From 935c4d79c188b8f84b8d694b16bd0f3a43b15b3a Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Fri, 23 Feb 2024 22:36:34 -0500 Subject: [PATCH 1/5] Update chromium sample and clarify READMEs [skip ci] A chromium sample has been updated to a version that uses C++17 stuff READMEs of samples have been clarified regarding licensing Two licenses have also been updated Skip CI because I amended a typo in the commit message --- samples/boost-sample/README.md | 4 +- samples/chromium-sample/LICENSE | 27 + samples/chromium-sample/README.md | 4 +- .../src/chrome_content_renderer_client.cc | 2227 ++++++++++------- samples/codelite-sample/README.md | 3 +- samples/protobuf-sample/README.md | 4 +- samples/v8-sample/LICENSE | 3 +- samples/v8-sample/README.md | 4 +- samples/vlc-sample/README.md | 4 +- 9 files changed, 1363 insertions(+), 917 deletions(-) create mode 100644 samples/chromium-sample/LICENSE diff --git a/samples/boost-sample/README.md b/samples/boost-sample/README.md index 6266a4a..dca6b56 100644 --- a/samples/boost-sample/README.md +++ b/samples/boost-sample/README.md @@ -1,3 +1 @@ -# VLC sample - -code taken for regression testing from https://github.com/boostorg +Code under include/ and src/ taken from https://github.com/boostorg, licensed under the Boost license. diff --git a/samples/chromium-sample/LICENSE b/samples/chromium-sample/LICENSE new file mode 100644 index 0000000..2249a28 --- /dev/null +++ b/samples/chromium-sample/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2015 The Chromium Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/samples/chromium-sample/README.md b/samples/chromium-sample/README.md index f0c852d..29e9a44 100644 --- a/samples/chromium-sample/README.md +++ b/samples/chromium-sample/README.md @@ -1,3 +1 @@ -# VLC sample - -code taken for regression testing from https://github.com/chromium/chromium +Code under src/ taken from https://github.com/chromium/chromium, licensed under the BSD 3-clause. diff --git a/samples/chromium-sample/src/chrome_content_renderer_client.cc b/samples/chromium-sample/src/chrome_content_renderer_client.cc index ed78c48..04a7dbd 100644 --- a/samples/chromium-sample/src/chrome_content_renderer_client.cc +++ b/samples/chromium-sample/src/chrome_content_renderer_client.cc @@ -1,158 +1,263 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/renderer/chrome_content_renderer_client.h" +#include #include +#include #include +#include "base/check_op.h" #include "base/command_line.h" #include "base/debug/crash_logging.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram.h" +#include "base/functional/bind.h" +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics_action.h" +#include "base/no_destructor.h" +#include "base/notreached.h" +#include "base/process/current_process.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" +#include "chrome/common/buildflags.h" #include "chrome/common/channel_info.h" +#include "chrome/common/chrome_content_client.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_isolated_world_ids.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/crash_keys.h" +#include "chrome/common/pdf_util.h" #include "chrome/common/pepper_permission_util.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/secure_origin_whitelist.h" +#include "chrome/common/ppapi_utils.h" +#include "chrome/common/profiler/thread_profiler.h" +#include "chrome/common/profiler/unwind_util.h" +#include "chrome/common/secure_origin_allowlist.h" #include "chrome/common/url_constants.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/branded_strings.h" #include "chrome/grit/generated_resources.h" -#include "chrome/grit/locale_settings.h" #include "chrome/grit/renderer_resources.h" -#include "chrome/renderer/banners/app_banner_client.h" #include "chrome/renderer/benchmarking_extension.h" +#include "chrome/renderer/browser_exposed_renderer_interfaces.h" +#include "chrome/renderer/cart/commerce_hint_agent.h" +#include "chrome/renderer/chrome_content_settings_agent_delegate.h" #include "chrome/renderer/chrome_render_frame_observer.h" #include "chrome/renderer/chrome_render_thread_observer.h" -#include "chrome/renderer/chrome_render_view_observer.h" -#include "chrome/renderer/content_settings_observer.h" -#include "chrome/renderer/external_extension.h" +#include "chrome/renderer/controlled_frame/controlled_frame_extensions_renderer_api_provider.h" +#include "chrome/renderer/google_accounts_private_api_extension.h" #include "chrome/renderer/loadtimes_extension_bindings.h" -#include "chrome/renderer/media/chrome_key_systems.h" +#include "chrome/renderer/media/flash_embed_rewrite.h" +#include "chrome/renderer/media/webrtc_logging_agent_impl.h" #include "chrome/renderer/net/net_error_helper.h" #include "chrome/renderer/net_benchmarking_extension.h" -#include "chrome/renderer/page_load_histograms.h" -#include "chrome/renderer/pepper/pepper_helper.h" #include "chrome/renderer/plugins/non_loadable_plugin_placeholder.h" -#include "chrome/renderer/plugins/plugin_preroller.h" +#include "chrome/renderer/plugins/pdf_plugin_placeholder.h" #include "chrome/renderer/plugins/plugin_uma.h" -#include "chrome/renderer/prerender/prerender_dispatcher.h" -#include "chrome/renderer/prerender/prerender_helper.h" -#include "chrome/renderer/prerender/prerenderer_client.h" -#include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h" -#include "chrome/renderer/safe_browsing/threat_dom_details.h" -#include "chrome/renderer/searchbox/search_bouncer.h" -#include "chrome/renderer/searchbox/searchbox.h" -#include "chrome/renderer/searchbox/searchbox_extension.h" -#include "chrome/renderer/tts_dispatcher.h" -#include "chrome/renderer/worker_content_settings_client_proxy.h" +#include "chrome/renderer/trusted_vault_encryption_keys_extension.h" +#include "chrome/renderer/url_loader_throttle_provider_impl.h" +#include "chrome/renderer/v8_unwinder.h" +#include "chrome/renderer/websocket_handshake_throttle_provider_impl.h" +#include "chrome/renderer/worker_content_settings_client.h" +#include "chrome/services/speech/buildflags/buildflags.h" #include "components/autofill/content/renderer/autofill_agent.h" #include "components/autofill/content/renderer/password_autofill_agent.h" #include "components/autofill/content/renderer/password_generation_agent.h" +#include "components/autofill/core/common/autofill_features.h" +#include "components/commerce/content/renderer/commerce_web_extractor.h" +#include "components/commerce/core/commerce_feature_list.h" +#include "components/content_capture/common/content_capture_features.h" +#include "components/content_capture/renderer/content_capture_sender.h" #include "components/content_settings/core/common/content_settings_pattern.h" -#include "components/contextual_search/renderer/overlay_js_render_frame_observer.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" +#include "components/continuous_search/renderer/search_result_extractor_impl.h" #include "components/dom_distiller/content/renderer/distillability_agent.h" #include "components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h" +#include "components/dom_distiller/core/dom_distiller_features.h" +#include "components/dom_distiller/core/dom_distiller_switches.h" #include "components/dom_distiller/core/url_constants.h" +#include "components/error_page/common/error.h" #include "components/error_page/common/localized_error.h" -#include "components/network_hints/renderer/prescient_networking_dispatcher.h" +#include "components/feed/buildflags.h" +#include "components/grit/components_scaled_resources.h" +#include "components/heap_profiling/in_process/heap_profiler_controller.h" +#include "components/history_clusters/core/config.h" +#include "components/metrics/call_stacks/call_stack_profile_builder.h" +#include "components/network_hints/renderer/web_prescient_networking_impl.h" +#include "components/no_state_prefetch/renderer/no_state_prefetch_client.h" +#include "components/no_state_prefetch/renderer/no_state_prefetch_helper.h" +#include "components/no_state_prefetch/renderer/no_state_prefetch_utils.h" +#include "components/no_state_prefetch/renderer/prerender_render_frame_observer.h" +#include "components/optimization_guide/core/optimization_guide_features.h" #include "components/page_load_metrics/renderer/metrics_render_frame_observer.h" -#include "components/password_manager/content/renderer/credential_manager_client.h" -#include "components/pdf/renderer/pepper_pdf_host.h" -#include "components/plugins/renderer/mobile_youtube_plugin.h" -#include "components/signin/core/common/profile_management_switches.h" -#include "components/startup_metric_utils/common/startup_metric_messages.h" +#include "components/paint_preview/buildflags/buildflags.h" +#include "components/password_manager/core/common/password_manager_features.h" +#include "components/pdf/common/constants.h" +#include "components/permissions/features.h" +#include "components/safe_browsing/buildflags.h" +#include "components/safe_browsing/content/renderer/threat_dom_details.h" +#include "components/spellcheck/spellcheck_buildflags.h" +#include "components/subresource_filter/content/renderer/subresource_filter_agent.h" +#include "components/subresource_filter/content/renderer/unverified_ruleset_dealer.h" +#include "components/subresource_filter/core/common/common_features.h" +#include "components/supervised_user/core/common/buildflags.h" +#include "components/variations/net/variations_http_headers.h" +#include "components/variations/variations_switches.h" #include "components/version_info/version_info.h" -#include "components/visitedlink/renderer/visitedlink_slave.h" +#include "components/visitedlink/renderer/visitedlink_reader.h" #include "components/web_cache/renderer/web_cache_impl.h" +#include "components/webapps/renderer/web_page_metadata_agent.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_switches.h" +#include "content/public/common/page_visibility_state.h" #include "content/public/common/url_constants.h" -#include "content/public/renderer/plugin_instance_throttler.h" +#include "content/public/common/webplugininfo.h" #include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_thread.h" -#include "content/public/renderer/render_view.h" -#include "content/public/renderer/render_view_visitor.h" -#include "extensions/common/constants.h" +#include "content/public/renderer/render_frame_visitor.h" +#include "extensions/buildflags/buildflags.h" +#include "extensions/renderer/extensions_renderer_api_provider.h" +#include "extensions/renderer/worker_script_context_set.h" #include "ipc/ipc_sync_channel.h" +#include "media/base/media_switches.h" +#include "media/media_buildflags.h" +#include "mojo/public/cpp/bindings/generic_pending_receiver.h" +#include "mojo/public/cpp/bindings/remote.h" #include "net/base/net_errors.h" -#include "ppapi/c/private/ppb_pdf.h" -#include "ppapi/shared_impl/ppapi_switches.h" -#include "third_party/WebKit/public/platform/URLConversion.h" -#include "third_party/WebKit/public/platform/WebCachePolicy.h" -#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" -#include "third_party/WebKit/public/platform/WebURL.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "third_party/WebKit/public/web/WebCache.h" -#include "third_party/WebKit/public/web/WebDataSource.h" -#include "third_party/WebKit/public/web/WebDocument.h" -#include "third_party/WebKit/public/web/WebElement.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebPluginContainer.h" -#include "third_party/WebKit/public/web/WebPluginParams.h" -#include "third_party/WebKit/public/web/WebSecurityPolicy.h" +#include "pdf/buildflags.h" +#include "ppapi/buildflags/buildflags.h" +#include "printing/buildflags/buildflags.h" +#include "services/network/public/cpp/is_potentially_trustworthy.h" +#include "services/service_manager/public/cpp/interface_provider.h" +#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h" +#include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/platform/scheduler/web_renderer_process_type.h" +#include "third_party/blink/public/platform/url_conversion.h" +#include "third_party/blink/public/platform/web_cache.h" +#include "third_party/blink/public/platform/web_content_security_policy_struct.h" +#include "third_party/blink/public/platform/web_runtime_features.h" +#include "third_party/blink/public/platform/web_security_origin.h" +#include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/public/platform/web_url.h" +#include "third_party/blink/public/platform/web_url_error.h" +#include "third_party/blink/public/platform/web_url_request.h" +#include "third_party/blink/public/platform/web_url_response.h" +#include "third_party/blink/public/web/web_document.h" +#include "third_party/blink/public/web/web_element.h" +#include "third_party/blink/public/web/web_heap.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_origin_trials.h" +#include "third_party/blink/public/web/web_plugin.h" +#include "third_party/blink/public/web/web_plugin_container.h" +#include "third_party/blink/public/web/web_plugin_params.h" +#include "third_party/blink/public/web/web_script_controller.h" +#include "third_party/blink/public/web/web_security_policy.h" +#include "third_party/blink/public/web/web_view.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/layout.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" -#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. +#include "url/origin.h" +#include "v8/include/v8-isolate.h" + +#if BUILDFLAG(IS_ANDROID) +#include "chrome/renderer/sandbox_status_extension_android.h" +#include "chrome/renderer/wallet/boarding_pass_extractor.h" +#include "components/facilitated_payments/content/renderer/facilitated_payments_agent.h" +#include "components/facilitated_payments/core/features/features.h" +#else +#include "chrome/renderer/searchbox/searchbox.h" +#include "chrome/renderer/searchbox/searchbox_extension.h" +#include "components/search/ntp_features.h" // nogncheck +#endif + +#if BUILDFLAG(ENABLE_SPEECH_SERVICE) +#include "chrome/renderer/media/chrome_speech_recognition_client.h" +#endif // BUILDFLAG(ENABLE_SPEECH_SERVICE) -#if !defined(DISABLE_NACL) +#if BUILDFLAG(IS_WIN) +#include "chrome/renderer/render_frame_font_family_accessor.h" +#endif + +#if BUILDFLAG(ENABLE_FEED_V2) +#include "components/feed/content/renderer/rss_link_reader.h" +#include "components/feed/feed_feature_list.h" +#endif + +#if BUILDFLAG(ENABLE_NACL) #include "components/nacl/common/nacl_constants.h" #include "components/nacl/renderer/nacl_helper.h" #endif -#if defined(ENABLE_EXTENSIONS) -#include "chrome/common/extensions/chrome_extensions_client.h" +#if BUILDFLAG(ENABLE_EXTENSIONS) +#include "chrome/common/controlled_frame/controlled_frame.h" +#include "chrome/common/initialize_extensions_client.h" #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h" +#include "extensions/common/constants.h" +#include "extensions/common/context_data.h" #include "extensions/common/extension_urls.h" +#include "extensions/common/manifest_handlers/csp_info.h" +#include "extensions/common/manifest_handlers/web_accessible_resources_info.h" #include "extensions/common/switches.h" #include "extensions/renderer/dispatcher.h" +#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h" #include "extensions/renderer/renderer_extension_registry.h" +#include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom.h" +#include "third_party/blink/public/web/web_settings.h" #endif -#if defined(ENABLE_IPC_FUZZER) -#include "chrome/common/external_ipc_dumper.h" -#endif +#if BUILDFLAG(ENABLE_PDF) +#include "chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.h" +#include "components/pdf/renderer/internal_plugin_renderer_helpers.h" +#endif // BUILDFLAG(ENABLE_PDF) -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) #include "chrome/renderer/plugins/chrome_plugin_placeholder.h" -#include "chrome/renderer/plugins/power_saver_info.h" +#endif // BUILDFLAG(ENABLE_PLUGINS) + +#if BUILDFLAG(ENABLE_PPAPI) +#include "chrome/renderer/pepper/pepper_helper.h" +#include "ppapi/shared_impl/ppapi_switches.h" // nogncheck crbug.com/1125897 #endif -#if defined(ENABLE_PRINTING) -#include "chrome/common/chrome_content_client.h" -#include "chrome/renderer/printing/chrome_print_web_view_helper_delegate.h" -#include "components/printing/renderer/print_web_view_helper.h" -#include "printing/print_settings.h" +#if BUILDFLAG(ENABLE_PRINTING) +#include "chrome/renderer/printing/chrome_print_render_frame_helper_delegate.h" +#include "components/printing/renderer/print_render_frame_helper.h" // nogncheck +#include "printing/metafile_agent.h" // nogncheck #endif -#if defined(ENABLE_PRINT_PREVIEW) -#include "chrome/renderer/pepper/chrome_pdf_print_client.h" +#if BUILDFLAG(ENABLE_PAINT_PREVIEW) +#include "components/paint_preview/renderer/paint_preview_recorder_impl.h" // nogncheck +#endif + +#if BUILDFLAG(ENABLE_SPELLCHECK) +#include "components/spellcheck/renderer/spellcheck.h" +#include "components/spellcheck/renderer/spellcheck_provider.h" + +#if BUILDFLAG(HAS_SPELLCHECK_PANEL) +#include "components/spellcheck/renderer/spellcheck_panel.h" +#endif // BUILDFLAG(HAS_SPELLCHECK_PANEL) +#endif // BUILDFLAG(ENABLE_SPELLCHECK) + +#if BUILDFLAG(ENABLE_SUPERVISED_USERS) +#include "chrome/renderer/supervised_user/supervised_user_error_page_controller_delegate_impl.h" #endif -#if defined(ENABLE_SPELLCHECK) -#include "chrome/renderer/spellchecker/spellcheck.h" -#include "chrome/renderer/spellchecker/spellcheck_provider.h" +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) +#include "chrome/renderer/media/chrome_key_systems.h" #endif -#if defined(ENABLE_WEBRTC) -#include "chrome/renderer/media/webrtc_logging_message_filter.h" +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) +#include "chrome/renderer/cco/multiline_detector.h" #endif using autofill::AutofillAgent; @@ -161,9 +266,7 @@ using autofill::PasswordGenerationAgent; using base::ASCIIToUTF16; using base::UserMetricsAction; using blink::WebCache; -using blink::WebCachePolicy; using blink::WebConsoleMessage; -using blink::WebDataSource; using blink::WebDocument; using blink::WebFrame; using blink::WebLocalFrame; @@ -177,37 +280,37 @@ using blink::WebURLError; using blink::WebURLRequest; using blink::WebURLResponse; using blink::WebVector; -using content::PluginInstanceThrottler; +using blink::mojom::FetchCacheMode; using content::RenderFrame; using content::RenderThread; using content::WebPluginInfo; -using extensions::Extension; +using content::WebPluginMimeType; +using ExtractAllDatalists = autofill::AutofillAgent::ExtractAllDatalists; +using FocusRequiresScroll = autofill::AutofillAgent::FocusRequiresScroll; +using QueryPasswordSuggestions = + autofill::AutofillAgent::QueryPasswordSuggestions; +using SecureContextRequired = autofill::AutofillAgent::SecureContextRequired; +using UserGestureRequired = autofill::AutofillAgent::UserGestureRequired; +using UsesKeyboardAccessoryForSuggestions = + autofill::AutofillAgent::UsesKeyboardAccessoryForSuggestions; namespace { -// Whitelist PPAPI for Android Runtime for Chromium. (See crbug.com/383937) -#if defined(ENABLE_PLUGINS) +// Allow PPAPI for Android Runtime for Chromium. (See crbug.com/383937) +#if BUILDFLAG(ENABLE_PLUGINS) const char* const kPredefinedAllowedCameraDeviceOrigins[] = { - "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", - "4EB74897CB187C7633357C2FE832E0AD6A44883A" -}; - -const char* const kPredefinedAllowedCompositorOrigins[] = { - "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", - "4EB74897CB187C7633357C2FE832E0AD6A44883A" -}; -#endif - -#if defined(ENABLE_PLUGINS) -void AppendParams(const std::vector& additional_names, - const std::vector& additional_values, - WebVector* existing_names, - WebVector* existing_values) { - DCHECK(additional_names.size() == additional_values.size()); - DCHECK(existing_names->size() == existing_values->size()); + "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", + "4EB74897CB187C7633357C2FE832E0AD6A44883A"}; +#endif +#if BUILDFLAG(ENABLE_PLUGINS) +void AppendParams( + const std::vector& additional_params, + WebVector* existing_names, + WebVector* existing_values) { + DCHECK(existing_names->size() == existing_values->size()); size_t existing_size = existing_names->size(); - size_t total_size = existing_size + additional_names.size(); + size_t total_size = existing_size + additional_params.size(); WebVector names(total_size); WebVector values(total_size); @@ -217,348 +320,572 @@ void AppendParams(const std::vector& additional_names, values[i] = (*existing_values)[i]; } - for (size_t i = 0; i < additional_names.size(); ++i) { - names[existing_size + i] = additional_names[i]; - values[existing_size + i] = additional_values[i]; + for (size_t i = 0; i < additional_params.size(); ++i) { + names[existing_size + i] = WebString::FromUTF16(additional_params[i].name); + values[existing_size + i] = + WebString::FromUTF16(additional_params[i].value); } existing_names->swap(names); existing_values->swap(values); } +#endif // BUILDFLAG(ENABLE_PLUGINS) -// For certain sandboxed Pepper plugins, use the JavaScript Content Settings. -bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) { - if (plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS && - plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS) { - return false; - } - -#if !defined(DISABLE_NACL) - // Treat Native Client invocations like JavaScript. - if (plugin.name == ASCIIToUTF16(nacl::kNaClPluginName)) - return true; -#endif - -#if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) - // Treat CDM invocations like JavaScript. - if (plugin.name == ASCIIToUTF16(kWidevineCdmDisplayName)) { - DCHECK(plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS); - return true; - } -#endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) - +bool IsStandaloneContentExtensionProcess() { +#if !BUILDFLAG(ENABLE_EXTENSIONS) return false; +#else + return base::CommandLine::ForCurrentProcess()->HasSwitch( + extensions::switches::kExtensionProcess); +#endif } -#endif // defined(ENABLE_PLUGINS) -#if defined(ENABLE_SPELLCHECK) -class SpellCheckReplacer : public content::RenderViewVisitor { - public: - explicit SpellCheckReplacer(SpellCheck* spellcheck) - : spellcheck_(spellcheck) {} - bool Visit(content::RenderView* render_view) override; - - private: - SpellCheck* spellcheck_; // New shared spellcheck for all views. Weak Ptr. - DISALLOW_COPY_AND_ASSIGN(SpellCheckReplacer); -}; - -bool SpellCheckReplacer::Visit(content::RenderView* render_view) { - SpellCheckProvider* provider = SpellCheckProvider::Get(render_view); - DCHECK(provider); - provider->set_spellcheck(spellcheck_); - return true; +std::unique_ptr CreateV8Unwinder(v8::Isolate* isolate) { + return std::make_unique(isolate); } + +// Web Share is conditionally enabled here in chrome/, to avoid it being +// made available in other clients of content/ that do not have a Web Share +// Mojo implementation (e.g. WebView). +void MaybeEnableWebShare() { +#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) + if (base::FeatureList::IsEnabled(features::kWebShare)) +#endif +#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || \ + BUILDFLAG(IS_ANDROID) + blink::WebRuntimeFeatures::EnableWebShare(true); #endif +} -#if defined(ENABLE_EXTENSIONS) -bool IsStandaloneExtensionProcess() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - extensions::switches::kExtensionProcess); +#if BUILDFLAG(ENABLE_NACL) && BUILDFLAG(ENABLE_EXTENSIONS) && \ + BUILDFLAG(IS_CHROMEOS_ASH) +bool IsTerminalSystemWebAppNaClPage(GURL url) { + GURL::Replacements replacements; + replacements.ClearQuery(); + replacements.ClearRef(); + url = url.ReplaceComponents(replacements); + return url == "chrome-untrusted://terminal/html/terminal_ssh.html"; } #endif -// Defers media player loading in background pages until they're visible. -// TODO(dalecurtis): Include an idle listener too. http://crbug.com/509135 -class MediaLoadDeferrer : public content::RenderFrameObserver { - public: - MediaLoadDeferrer(content::RenderFrame* render_frame, - const base::Closure& continue_loading_cb) - : content::RenderFrameObserver(render_frame), - continue_loading_cb_(continue_loading_cb) {} - ~MediaLoadDeferrer() override {} - - private: - // content::RenderFrameObserver implementation: - void WasShown() override { - continue_loading_cb_.Run(); - delete this; - } - - const base::Closure continue_loading_cb_; - - DISALLOW_COPY_AND_ASSIGN(MediaLoadDeferrer); -}; - } // namespace ChromeContentRendererClient::ChromeContentRendererClient() - : main_entry_time_(base::TimeTicks::Now()) { -#if defined(ENABLE_EXTENSIONS) - extensions::ExtensionsClient::Set( - extensions::ChromeExtensionsClient::GetInstance()); + : +#if BUILDFLAG(IS_WIN) + remote_module_watcher_(nullptr, base::OnTaskRunnerDeleter(nullptr)), +#endif + main_thread_profiler_( +#if BUILDFLAG(IS_CHROMEOS) + // The profiler can't start before the sandbox is initialized on + // ChromeOS due to ChromeOS's sandbox initialization code's use of + // AssertSingleThreaded(). + nullptr +#else + ThreadProfiler::CreateAndStartOnMainThread() +#endif + ) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + EnsureExtensionsClientInitialized( + controlled_frame::CreateAvailabilityCheckMap()); extensions::ExtensionsRendererClient::Set( ChromeExtensionsRendererClient::GetInstance()); #endif -#if defined(ENABLE_PLUGINS) - for (size_t i = 0; i < arraysize(kPredefinedAllowedCameraDeviceOrigins); ++i) - allowed_camera_device_origins_.insert( - kPredefinedAllowedCameraDeviceOrigins[i]); - for (size_t i = 0; i < arraysize(kPredefinedAllowedCompositorOrigins); ++i) - allowed_compositor_origins_.insert(kPredefinedAllowedCompositorOrigins[i]); -#endif -#if defined(ENABLE_PRINTING) - printing::SetAgent(GetUserAgent()); +#if BUILDFLAG(ENABLE_PLUGINS) + for (const char* origin : kPredefinedAllowedCameraDeviceOrigins) + allowed_camera_device_origins_.insert(origin); #endif } -ChromeContentRendererClient::~ChromeContentRendererClient() { -} +ChromeContentRendererClient::~ChromeContentRendererClient() {} void ChromeContentRendererClient::RenderThreadStarted() { RenderThread* thread = RenderThread::Get(); - thread->Send(new StartupMetricHostMsg_RecordRendererMainEntryTime( - main_entry_time_)); + main_thread_profiler_->SetAuxUnwinderFactory(base::BindRepeating( + &CreateV8Unwinder, base::Unretained(v8::Isolate::GetCurrent()))); - chrome_observer_.reset(new ChromeRenderThreadObserver()); - web_cache_impl_.reset(new web_cache::WebCacheImpl()); + // In the case of single process mode, the v8 unwinding will not work. + tracing::TracingSamplerProfiler::SetAuxUnwinderFactoryOnMainThread( + base::BindRepeating(&CreateV8Unwinder, + base::Unretained(v8::Isolate::GetCurrent()))); -#if defined(ENABLE_EXTENSIONS) - ChromeExtensionsRendererClient::GetInstance()->RenderThreadStarted(); -#endif + const bool is_extension = IsStandaloneContentExtensionProcess(); + + thread->SetRendererProcessType( + is_extension + ? blink::scheduler::WebRendererProcessType::kExtensionRenderer + : blink::scheduler::WebRendererProcessType::kRenderer); - prescient_networking_dispatcher_.reset( - new network_hints::PrescientNetworkingDispatcher()); -#if defined(ENABLE_SPELLCHECK) - // ChromeRenderViewTest::SetUp() creates a Spellcheck and injects it using - // SetSpellcheck(). Don't overwrite it. - if (!spellcheck_) { - spellcheck_.reset(new SpellCheck()); - thread->AddObserver(spellcheck_.get()); + if (is_extension) { + // The process name was set to "Renderer" in RendererMain(). Update it to + // "Extension Renderer" to highlight that it's hosting an extension. + base::CurrentProcess::GetInstance().SetProcessType( + base::CurrentProcessType::PROCESS_RENDERER_EXTENSION); } -#endif - visited_link_slave_.reset(new visitedlink::VisitedLinkSlave()); -#if defined(FULL_SAFE_BROWSING) - phishing_classifier_.reset(safe_browsing::PhishingClassifierFilter::Create()); -#endif - prerender_dispatcher_.reset(new prerender::PrerenderDispatcher()); -#if defined(ENABLE_WEBRTC) - webrtc_logging_message_filter_ = new WebRtcLoggingMessageFilter( - thread->GetIOMessageLoopProxy()); + +#if BUILDFLAG(IS_WIN) + mojo::PendingRemote module_event_sink; + thread->BindHostReceiver(module_event_sink.InitWithNewPipeAndPassReceiver()); + remote_module_watcher_ = RemoteModuleWatcher::Create( + thread->GetIOTaskRunner(), std::move(module_event_sink)); #endif - thread->AddObserver(chrome_observer_.get()); -#if defined(FULL_SAFE_BROWSING) - thread->AddObserver(phishing_classifier_.get()); + browser_interface_broker_ = + blink::Platform::Current()->GetBrowserInterfaceBroker(); + + chrome_observer_ = std::make_unique(); + web_cache_impl_ = std::make_unique(); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient* chrome_extensions_renderer_client = + ChromeExtensionsRendererClient::GetInstance(); + chrome_extensions_renderer_client->AddAPIProvider( + std::make_unique< + controlled_frame::ControlledFrameExtensionsRendererAPIProvider>()); + chrome_extensions_renderer_client->RenderThreadStarted(); + WebSecurityPolicy::RegisterURLSchemeAsExtension( + WebString::FromASCII(extensions::kExtensionScheme)); + WebSecurityPolicy::RegisterURLSchemeAsCodeCacheWithHashing( + WebString::FromASCII(extensions::kExtensionScheme)); #endif - thread->AddObserver(visited_link_slave_.get()); - thread->AddObserver(prerender_dispatcher_.get()); - thread->AddObserver(SearchBouncer::GetInstance()); -#if defined(ENABLE_WEBRTC) - thread->AddFilter(webrtc_logging_message_filter_.get()); +#if BUILDFLAG(ENABLE_SPELLCHECK) + if (!spellcheck_) + InitSpellCheck(); #endif - thread->RegisterExtension(extensions_v8::ExternalExtension::Get()); - thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get()); + subresource_filter_ruleset_dealer_ = + std::make_unique(); + + phishing_model_setter_ = + std::make_unique(); + + thread->AddObserver(chrome_observer_.get()); + thread->AddObserver(subresource_filter_ruleset_dealer_.get()); + thread->AddObserver(phishing_model_setter_.get()); + + blink::WebScriptController::RegisterExtension( + extensions_v8::LoadTimesExtension::Get()); base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kEnableBenchmarking)) - thread->RegisterExtension(extensions_v8::BenchmarkingExtension::Get()); - if (command_line->HasSwitch(switches::kEnableNetBenchmarking)) - thread->RegisterExtension(extensions_v8::NetBenchmarkingExtension::Get()); - if (command_line->HasSwitch(switches::kInstantProcess)) - thread->RegisterExtension(extensions_v8::SearchBoxExtension::Get()); + if (command_line->HasSwitch(variations::switches::kEnableBenchmarking)) { + blink::WebScriptController::RegisterExtension( + extensions_v8::BenchmarkingExtension::Get()); + } + + if (command_line->HasSwitch(switches::kEnableNetBenchmarking)) { + blink::WebScriptController::RegisterExtension( + extensions_v8::NetBenchmarkingExtension::Get()); + } + + // chrome: is also to be permitted to embeds https:// things and have them + // treated as first-party. + // See + // ChromeContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel + WebString chrome_scheme(WebString::FromASCII(content::kChromeUIScheme)); + WebSecurityPolicy::RegisterURLSchemeAsFirstPartyWhenTopLevelEmbeddingSecure( + chrome_scheme); + + // chrome-native: is a scheme used for placeholder navigations that allow + // UIs to be drawn with platform native widgets instead of HTML. These pages + // should not be accessible. No code should be runnable in these pages, + // so it should not need to access anything nor should it allow javascript + // URLs since it should never be visible to the user. + // See also ChromeContentClient::AddAdditionalSchemes that adds it as an + // empty document scheme. + WebString native_scheme(WebString::FromASCII(chrome::kChromeNativeScheme)); + WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(native_scheme); + WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs( + native_scheme); // chrome-search: and chrome-distiller: pages should not be accessible by // normal content, and should also be unable to script anything but themselves // (to help limit the damage that a corrupt page could cause). - WebString chrome_search_scheme(ASCIIToUTF16(chrome::kChromeSearchScheme)); + WebString chrome_search_scheme( + WebString::FromASCII(chrome::kChromeSearchScheme)); + + // IWAs can be enabled by either the feature flag or by enterprise + // policy. In either case the kEnableIsolatedWebAppsInRenderer flag is passed + // to the renderer process. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableIsolatedWebAppsInRenderer)) { + // isolated-app: is the scheme used for Isolated Web Apps, which are web + // applications packaged in Signed Web Bundles. + WebString isolated_app_scheme( + WebString::FromASCII(chrome::kIsolatedAppScheme)); + // Resources contained in Isolated Web Apps are HTTP-like and safe to expose + // to the fetch API. + WebSecurityPolicy::RegisterURLSchemeAsSupportingFetchAPI( + isolated_app_scheme); + WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers( + isolated_app_scheme); + WebSecurityPolicy::RegisterURLSchemeAsAllowedForReferrer( + isolated_app_scheme); + } // The Instant process can only display the content but not read it. Other // processes can't display it or read it. if (!command_line->HasSwitch(switches::kInstantProcess)) - WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(chrome_search_scheme); + WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(chrome_search_scheme); WebString dom_distiller_scheme( - ASCIIToUTF16(dom_distiller::kDomDistillerScheme)); + WebString::FromASCII(dom_distiller::kDomDistillerScheme)); // TODO(nyquist): Add test to ensure this happens when the flag is set. - WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(dom_distiller_scheme); - -#if defined(OS_CHROMEOS) - WebSecurityPolicy::registerURLSchemeAsLocal( - WebString::fromUTF8(content::kExternalFileScheme)); -#endif - -#if defined(OS_ANDROID) - WebSecurityPolicy::registerURLSchemeAsAllowedForReferrer( - WebString::fromUTF8(chrome::kAndroidAppScheme)); -#endif + WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(dom_distiller_scheme); -#if defined(ENABLE_IPC_FUZZER) - if (command_line->HasSwitch(switches::kIpcDumpDirectory)) { - base::FilePath dump_directory = - command_line->GetSwitchValuePath(switches::kIpcDumpDirectory); - IPC::ChannelProxy::OutgoingMessageFilter* filter = - LoadExternalIPCDumper(dump_directory); - thread->GetChannel()->set_outgoing_message_filter(filter); - } +#if BUILDFLAG(IS_ANDROID) + WebSecurityPolicy::RegisterURLSchemeAsAllowedForReferrer( + WebString::FromUTF8(content::kAndroidAppScheme)); #endif // chrome-search: pages should not be accessible by bookmarklets // or javascript: URLs typed in the omnibox. - WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs( + WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs( chrome_search_scheme); - // chrome-search: resources shouldn't trigger insecure content warnings. Note - // that chrome-extension: and chrome-extension-resource: schemes are taken - // care of in extensions::Dispatcher. - WebSecurityPolicy::registerURLSchemeAsSecure(chrome_search_scheme); - -#if defined(ENABLE_PRINT_PREVIEW) - pdf_print_client_.reset(new ChromePDFPrintClient()); - pdf::PepperPDFHost::SetPrintClient(pdf_print_client_.get()); -#endif - - std::set origins; - GetSecureOriginWhitelist(&origins); - for (const GURL& origin : origins) { - WebSecurityPolicy::addOriginTrustworthyWhiteList( - WebSecurityOrigin::create(origin)); + for (auto& scheme : + secure_origin_allowlist::GetSchemesBypassingSecureContextCheck()) { + WebSecurityPolicy::AddSchemeToSecureContextSafelist( + WebString::FromASCII(scheme)); } - std::set schemes; - GetSchemesBypassingSecureContextCheckWhitelist(&schemes); - for (const std::string& scheme : schemes) { - WebSecurityPolicy::addSchemeToBypassSecureContextWhitelist( - WebString::fromUTF8(scheme)); + // This doesn't work in single-process mode. + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSingleProcess)) { + using HeapProfilerController = heap_profiling::HeapProfilerController; + // The HeapProfilerController should have been created in + // ChromeMainDelegate::PostEarlyInitialization. + DCHECK_NE(HeapProfilerController::GetProfilingEnabled(), + HeapProfilerController::ProfilingEnabled::kNoController); + if (ThreadProfiler::ShouldCollectProfilesForChildProcess() || + HeapProfilerController::GetProfilingEnabled() == + HeapProfilerController::ProfilingEnabled::kEnabled) { + ThreadProfiler::SetMainThreadTaskRunner( + base::SingleThreadTaskRunner::GetCurrentDefault()); + mojo::PendingRemote collector; + thread->BindHostReceiver(collector.InitWithNewPipeAndPassReceiver()); + metrics::CallStackProfileBuilder:: + SetParentProfileCollectorForChildProcess(std::move(collector)); + } } } +void ChromeContentRendererClient::ExposeInterfacesToBrowser( + mojo::BinderMap* binders) { + // NOTE: Do not add binders directly within this method. Instead, modify the + // definition of |ExposeChromeRendererInterfacesToBrowser()| to ensure + // security review coverage. + ExposeChromeRendererInterfacesToBrowser(this, binders); +} + void ChromeContentRendererClient::RenderFrameCreated( content::RenderFrame* render_frame) { - new ChromeRenderFrameObserver(render_frame); + ChromeRenderFrameObserver* render_frame_observer = + new ChromeRenderFrameObserver(render_frame, web_cache_impl_.get()); + service_manager::BinderRegistry* registry = render_frame_observer->registry(); + + new prerender::PrerenderRenderFrameObserver(render_frame); - bool should_whitelist_for_content_settings = + bool should_allow_for_content_settings = base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kInstantProcess); - extensions::Dispatcher* ext_dispatcher = NULL; -#if defined(ENABLE_EXTENSIONS) - ext_dispatcher = - ChromeExtensionsRendererClient::GetInstance()->extension_dispatcher(); + auto content_settings_delegate = + std::make_unique(render_frame); +#if BUILDFLAG(ENABLE_EXTENSIONS) + content_settings_delegate->SetExtensionDispatcher( + ChromeExtensionsRendererClient::GetInstance()->extension_dispatcher()); #endif - ContentSettingsObserver* content_settings = new ContentSettingsObserver( - render_frame, ext_dispatcher, should_whitelist_for_content_settings); + content_settings::ContentSettingsAgentImpl* content_settings = + new content_settings::ContentSettingsAgentImpl( + render_frame, should_allow_for_content_settings, + std::move(content_settings_delegate)); if (chrome_observer_.get()) { - content_settings->SetContentSettingRules( - chrome_observer_->content_setting_rules()); + if (chrome_observer_->content_settings_manager()) { + mojo::Remote manager; + chrome_observer_->content_settings_manager()->Clone( + manager.BindNewPipeAndPassReceiver()); + content_settings->SetContentSettingsManager(std::move(manager)); + } } -#if defined(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_EXTENSIONS) ChromeExtensionsRendererClient::GetInstance()->RenderFrameCreated( - render_frame); + render_frame, registry); #endif -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PPAPI) new PepperHelper(render_frame); #endif -#if !defined(DISABLE_NACL) +#if BUILDFLAG(ENABLE_NACL) new nacl::NaClHelper(render_frame); #endif -#if defined(FULL_SAFE_BROWSING) - safe_browsing::ThreatDOMDetails::Create(render_frame); +#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL) || BUILDFLAG(SAFE_BROWSING_DB_REMOTE) + safe_browsing::ThreatDOMDetails::Create(render_frame, registry); +#endif + +#if BUILDFLAG(ENABLE_PRINTING) + new printing::PrintRenderFrameHelper( + render_frame, std::make_unique()); +#endif + +#if BUILDFLAG(ENABLE_PAINT_PREVIEW) + new paint_preview::PaintPreviewRecorderImpl(render_frame); #endif +#if BUILDFLAG(IS_ANDROID) + SandboxStatusExtension::Create(render_frame); +#endif + + TrustedVaultEncryptionKeysExtension::Create(render_frame); + GoogleAccountsPrivateApiExtension::Create(render_frame); + + if (render_frame->IsMainFrame()) + new webapps::WebPageMetadataAgent(render_frame); + + const bool search_result_extractor_enabled = + render_frame->IsMainFrame() && + optimization_guide::features::IsPageContentAnnotationEnabled(); + if (search_result_extractor_enabled) { + continuous_search::SearchResultExtractorImpl::Create(render_frame); + } + new NetErrorHelper(render_frame); - if (render_frame->IsMainFrame()) { - // Only attach MainRenderFrameObserver to the main frame, since - // we only want to log page load metrics for the main frame. - new page_load_metrics::MetricsRenderFrameObserver(render_frame); - } else { - // Avoid any race conditions from having the browser tell subframes that - // they're prerendering. - if (prerender::PrerenderHelper::IsPrerendering( - render_frame->GetRenderView()->GetMainRenderFrame())) { - new prerender::PrerenderHelper(render_frame); +#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + new SupervisedUserErrorPageControllerDelegateImpl(render_frame); +#endif + + if (!render_frame->IsMainFrame()) { + auto* main_frame_no_state_prefetch_helper = + prerender::NoStatePrefetchHelper::Get( + render_frame->GetMainRenderFrame()); + if (main_frame_no_state_prefetch_helper) { + // Avoid any race conditions from having the browser tell subframes that + // they're no-state prefetching. + new prerender::NoStatePrefetchHelper( + render_frame, + main_frame_no_state_prefetch_helper->histogram_prefix()); } } - // Set up a mojo service to test if this page is a distiller page. + // Set up a render frame observer to test if this page is a distiller page. new dom_distiller::DistillerJsRenderFrameObserver( - render_frame, chrome::ISOLATED_WORLD_ID_CHROME_INTERNAL); + render_frame, ISOLATED_WORLD_ID_CHROME_INTERNAL); - // Create DistillabilityAgent to send distillability updates to - // DistillabilityDriver in the browser process. - new dom_distiller::DistillabilityAgent(render_frame); + if (dom_distiller::ShouldStartDistillabilityService()) { + // Create DistillabilityAgent to send distillability updates to + // DistillabilityDriver in the browser process. + new dom_distiller::DistillabilityAgent(render_frame, DCHECK_IS_ON()); + } - // Set up a mojo service to test if this page is a contextual search page. - new contextual_search::OverlayJsRenderFrameObserver(render_frame); + blink::AssociatedInterfaceRegistry* associated_interfaces = + render_frame_observer->associated_interfaces(); + + if (!render_frame->IsInFencedFrameTree() || + base::FeatureList::IsEnabled(blink::features::kFencedFramesAPIChanges)) { + auto password_autofill_agent = std::make_unique( + render_frame, associated_interfaces); + auto password_generation_agent = std::make_unique( + render_frame, password_autofill_agent.get(), associated_interfaces); + new AutofillAgent( + render_frame, + {ExtractAllDatalists(false), FocusRequiresScroll(true), + QueryPasswordSuggestions(false), SecureContextRequired(false), + UserGestureRequired(true), + UsesKeyboardAccessoryForSuggestions(BUILDFLAG(IS_ANDROID))}, + std::move(password_autofill_agent), + std::move(password_generation_agent), associated_interfaces); + +#if BUILDFLAG(IS_ANDROID) + if (render_frame->IsMainFrame() && + base::FeatureList::IsEnabled( + payments::facilitated::kEnablePixDetection)) { + new payments::facilitated::FacilitatedPaymentsAgent( + render_frame, associated_interfaces); + } +#endif + } - PasswordAutofillAgent* password_autofill_agent = - new PasswordAutofillAgent(render_frame); - PasswordGenerationAgent* password_generation_agent = - new PasswordGenerationAgent(render_frame, password_autofill_agent); - new AutofillAgent(render_frame, password_autofill_agent, - password_generation_agent); -} + if (content_capture::features::IsContentCaptureEnabled()) { + new content_capture::ContentCaptureSender(render_frame, + associated_interfaces); + } + +#if BUILDFLAG(ENABLE_EXTENSIONS) + associated_interfaces + ->AddInterface( + base::BindRepeating( + &extensions::MimeHandlerViewContainerManager::BindReceiver, + base::Unretained(render_frame))); +#endif + + // Owned by |render_frame|. + new page_load_metrics::MetricsRenderFrameObserver(render_frame); + // There is no render thread, thus no UnverifiedRulesetDealer in + // ChromeRenderViewTests. + if (subresource_filter_ruleset_dealer_) { + auto* subresource_filter_agent = + new subresource_filter::SubresourceFilterAgent( + render_frame, subresource_filter_ruleset_dealer_.get()); + subresource_filter_agent->Initialize(); + } -void ChromeContentRendererClient::RenderViewCreated( - content::RenderView* render_view) { -#if defined(ENABLE_EXTENSIONS) - ChromeExtensionsRendererClient::GetInstance()->RenderViewCreated(render_view); +#if !BUILDFLAG(IS_ANDROID) + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kInstantProcess) && + render_frame->IsMainFrame()) { + new SearchBox(render_frame); + } #endif - new PageLoadHistograms(render_view); -#if defined(ENABLE_PRINTING) - new printing::PrintWebViewHelper( - render_view, std::unique_ptr( - new ChromePrintWebViewHelperDelegate())); + +// We should create CommerceHintAgent only for a main frame except a fenced +// frame that is the main frame as well, so we should check if |render_frame| +// is the fenced frame. +#if !BUILDFLAG(IS_ANDROID) + if (command_line->HasSwitch(commerce::switches::kEnableChromeCart) && +#else + if (base::FeatureList::IsEnabled(commerce::kCommerceHintAndroid) && +#endif // !BUILDFLAG(IS_ANDROID) + render_frame->GetWebFrame()->IsOutermostMainFrame()) { + new cart::CommerceHintAgent(render_frame); + } + +#if BUILDFLAG(ENABLE_SPELLCHECK) + new SpellCheckProvider(render_frame, spellcheck_.get()); + +#if BUILDFLAG(HAS_SPELLCHECK_PANEL) + new SpellCheckPanel(render_frame, registry, this); +#endif // BUILDFLAG(HAS_SPELLCHECK_PANEL) #endif -#if defined(ENABLE_SPELLCHECK) - new SpellCheckProvider(render_view, spellcheck_.get()); +#if BUILDFLAG(ENABLE_FEED_V2) + if (render_frame->IsMainFrame() && + base::FeatureList::IsEnabled(feed::kWebFeed)) { + new feed::RssLinkReader(render_frame, registry); + } #endif - new prerender::PrerendererClient(render_view); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kInstantProcess)) - new SearchBox(render_view); +#if BUILDFLAG(IS_WIN) + if (render_frame->IsMainFrame()) { + associated_interfaces + ->AddInterface( + base::BindRepeating(&RenderFrameFontFamilyAccessor::Bind, + render_frame)); + } +#endif - new ChromeRenderViewObserver(render_view, web_cache_impl_.get()); +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) + MultilineDetector::InstallIfNecessary(render_frame); +#endif + + if (render_frame->IsMainFrame()) { + new commerce::CommerceWebExtractor(render_frame, registry); + } - new password_manager::CredentialManagerClient(render_view); +#if BUILDFLAG(IS_ANDROID) + if (base::FeatureList::IsEnabled(features::kBoardingPassDetector) && + render_frame->IsMainFrame()) { + new wallet::BoardingPassExtractor(render_frame, registry); + } +#endif } +void ChromeContentRendererClient::WebViewCreated( + blink::WebView* web_view, + bool was_created_by_renderer, + const url::Origin* outermost_origin) { + new prerender::NoStatePrefetchClient(web_view); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance()->WebViewCreated( + web_view, outermost_origin); +#endif +} SkBitmap* ChromeContentRendererClient::GetSadPluginBitmap() { - return const_cast(ResourceBundle::GetSharedInstance(). - GetImageNamed(IDR_SAD_PLUGIN).ToSkBitmap()); + return const_cast(ui::ResourceBundle::GetSharedInstance() + .GetImageNamed(IDR_SAD_PLUGIN) + .ToSkBitmap()); } SkBitmap* ChromeContentRendererClient::GetSadWebViewBitmap() { - return const_cast(ResourceBundle::GetSharedInstance(). - GetImageNamed(IDR_SAD_WEBVIEW).ToSkBitmap()); + return const_cast(ui::ResourceBundle::GetSharedInstance() + .GetImageNamed(IDR_SAD_WEBVIEW) + .ToSkBitmap()); +} + +bool ChromeContentRendererClient::IsPluginHandledExternally( + content::RenderFrame* render_frame, + const blink::WebElement& plugin_element, + const GURL& original_url, + const std::string& mime_type) { +#if BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS) + DCHECK(plugin_element.HasHTMLTagName("object") || + plugin_element.HasHTMLTagName("embed")); + + mojo::AssociatedRemote plugin_info_host; + render_frame->GetRemoteAssociatedInterfaces()->GetInterface( + &plugin_info_host); + // Blink will next try to load a WebPlugin which would end up in + // OverrideCreatePlugin, sending another IPC only to find out the plugin is + // not supported. Here it suffices to return false but there should perhaps be + // a more unified approach to avoid sending the IPC twice. + chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New(); + plugin_info_host->GetPluginInfo( + original_url, render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), + mime_type, &plugin_info); + // TODO(ekaramad): Not continuing here due to a disallowed status should take + // us to CreatePlugin. See if more in depths investigation of |status| is + // necessary here (see https://crbug.com/965747). For now, returning false + // should take us to CreatePlugin after HTMLPlugInElement which is called + // through HTMLPlugInElement::LoadPlugin code path. + if (plugin_info->status != chrome::mojom::PluginStatus::kAllowed && + plugin_info->status != + chrome::mojom::PluginStatus::kPlayImportantContent) { + // We could get here when a MimeHandlerView is loaded inside a + // which is using permissions API (see WebViewPluginTests). + ChromeExtensionsRendererClient::DidBlockMimeHandlerViewForDisallowedPlugin( + plugin_element); + return false; + } +#if BUILDFLAG(ENABLE_PDF) + if (plugin_info->actual_mime_type == pdf::kInternalPluginMimeType) { + // Only actually treat the internal PDF plugin as externally handled if + // used within an origin allowed to create the internal PDF plugin; + // otherwise, let Blink try to create the in-process PDF plugin. + if (IsPdfInternalPluginAllowedOrigin( + render_frame->GetWebFrame()->GetSecurityOrigin())) { + return true; + } + } +#endif // BUILDFLAG(ENABLE_PDF) + return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView( + plugin_element, original_url, plugin_info->actual_mime_type, + plugin_info->plugin); +#else // !(BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS)) + return false; +#endif // BUILDFLAG(ENABLE_EXTENSIONS) && BUILDFLAG(ENABLE_PLUGINS) +} + +v8::Local ChromeContentRendererClient::GetScriptableObject( + const blink::WebElement& plugin_element, + v8::Isolate* isolate) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + return ChromeExtensionsRendererClient::GetInstance()->GetScriptableObject( + plugin_element, isolate); +#else + return v8::Local(); +#endif } bool ChromeContentRendererClient::OverrideCreatePlugin( content::RenderFrame* render_frame, - WebLocalFrame* frame, const WebPluginParams& params, WebPlugin** plugin) { - std::string orig_mime_type = params.mimeType.utf8(); -#if defined(ENABLE_EXTENSIONS) + std::string orig_mime_type = params.mime_type.Utf8(); +#if BUILDFLAG(ENABLE_EXTENSIONS) if (!ChromeExtensionsRendererClient::GetInstance()->OverrideCreatePlugin( render_frame, params)) { return false; @@ -566,135 +893,136 @@ bool ChromeContentRendererClient::OverrideCreatePlugin( #endif GURL url(params.url); -#if defined(ENABLE_PLUGINS) - ChromeViewHostMsg_GetPluginInfo_Output output; - WebString top_origin = frame->top()->getSecurityOrigin().toString(); - render_frame->Send(new ChromeViewHostMsg_GetPluginInfo( - render_frame->GetRoutingID(), url, blink::WebStringToGURL(top_origin), - orig_mime_type, &output)); - *plugin = CreatePlugin(render_frame, frame, params, output); -#else // !defined(ENABLE_PLUGINS) - -#if defined(OS_ANDROID) - if (plugins::MobileYouTubePlugin::IsYouTubeURL(url, orig_mime_type)) { - base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_MOBILE_YOUTUBE_PLUGIN_HTML)); - *plugin = (new plugins::MobileYouTubePlugin(render_frame, frame, params, - template_html))->plugin(); +#if BUILDFLAG(ENABLE_PLUGINS) + mojo::AssociatedRemote plugin_info_host; + render_frame->GetRemoteAssociatedInterfaces()->GetInterface( + &plugin_info_host); + + chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New(); + plugin_info_host->GetPluginInfo( + url, render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), + orig_mime_type, &plugin_info); + *plugin = CreatePlugin(render_frame, params, *plugin_info); +#else // !BUILDFLAG(ENABLE_PLUGINS) + PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url); + if (orig_mime_type == pdf::kPDFMimeType) { + ReportPDFLoadStatus( + PDFLoadStatus::kShowedDisabledPluginPlaceholderForEmbeddedPdf); + + PDFPluginPlaceholder* placeholder = + PDFPluginPlaceholder::CreatePDFPlaceholder(render_frame, params); + *plugin = placeholder->plugin(); return true; } -#endif // defined(OS_ANDROID) - - PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url); - *plugin = NonLoadablePluginPlaceholder::CreateNotSupportedPlugin( - render_frame, frame, params)->plugin(); + auto* placeholder = NonLoadablePluginPlaceholder::CreateNotSupportedPlugin( + render_frame, params); + *plugin = placeholder->plugin(); -#endif // defined(ENABLE_PLUGINS) +#endif // BUILDFLAG(ENABLE_PLUGINS) return true; } +#if BUILDFLAG(ENABLE_PLUGINS) WebPlugin* ChromeContentRendererClient::CreatePluginReplacement( content::RenderFrame* render_frame, const base::FilePath& plugin_path) { - return NonLoadablePluginPlaceholder::CreateErrorPlugin(render_frame, - plugin_path)->plugin(); + auto* placeholder = NonLoadablePluginPlaceholder::CreateErrorPlugin( + render_frame, plugin_path); + return placeholder->plugin(); } +#endif // BUILDFLAG(ENABLE_PLUGINS) -void ChromeContentRendererClient::DeferMediaLoad( +bool ChromeContentRendererClient::DeferMediaLoad( content::RenderFrame* render_frame, bool has_played_media_before, - const base::Closure& closure) { - // Don't allow autoplay/autoload of media resources in a RenderFrame that is - // hidden and has never played any media before. We want to allow future - // loads even when hidden to allow playlist-like functionality. - // - // NOTE: This is also used to defer media loading for prerender. - // NOTE: Switch can be used to allow autoplay, unless frame is prerendered. - // - // TODO(dalecurtis): Include an idle check too. http://crbug.com/509135 - if ((render_frame->IsHidden() && !has_played_media_before && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGestureRequirementForMediaPlayback)) || - prerender::PrerenderHelper::IsPrerendering(render_frame)) { - new MediaLoadDeferrer(render_frame, closure); - return; - } - - closure.Run(); + base::OnceClosure closure) { + return prerender::DeferMediaLoad(render_frame, has_played_media_before, + std::move(closure)); } -#if defined(ENABLE_PLUGINS) +#if BUILDFLAG(ENABLE_PLUGINS) + +// static WebPlugin* ChromeContentRendererClient::CreatePlugin( content::RenderFrame* render_frame, - WebLocalFrame* frame, const WebPluginParams& original_params, - const ChromeViewHostMsg_GetPluginInfo_Output& output) { - const WebPluginInfo& info = output.plugin; - const std::string& actual_mime_type = output.actual_mime_type; - const base::string16& group_name = output.group_name; - const std::string& identifier = output.group_identifier; - ChromeViewHostMsg_GetPluginInfo_Status status = output.status; + const chrome::mojom::PluginInfo& plugin_info) { + const WebPluginInfo& info = plugin_info.plugin; + const std::string& actual_mime_type = plugin_info.actual_mime_type; + const std::u16string& group_name = plugin_info.group_name; + const std::string& identifier = plugin_info.group_identifier; + chrome::mojom::PluginStatus status = plugin_info.status; GURL url(original_params.url); - std::string orig_mime_type = original_params.mimeType.utf8(); - ChromePluginPlaceholder* placeholder = NULL; + std::string orig_mime_type = original_params.mime_type.Utf8(); + ChromePluginPlaceholder* placeholder = nullptr; // If the browser plugin is to be enabled, this should be handled by the // renderer, so the code won't reach here due to the early exit in // OverrideCreatePlugin. - if (status == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound || + if (status == chrome::mojom::PluginStatus::kNotFound || orig_mime_type == content::kBrowserPluginMimeType) { - PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url); - placeholder = ChromePluginPlaceholder::CreateLoadableMissingPlugin( - render_frame, frame, original_params); + // Flash has been thoroughly removed in M88+, so we need to have a special + // case here to display a deprecated message instead of a generic + // plugin-missing message. + if (orig_mime_type == "application/x-shockwave-flash" || + orig_mime_type == "application/futuresplash") { + return NonLoadablePluginPlaceholder::CreateFlashDeprecatedPlaceholder( + render_frame, original_params) + ->plugin(); + } else { + PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, + url); + placeholder = ChromePluginPlaceholder::CreateLoadableMissingPlugin( + render_frame, original_params); + } } else { // TODO(bauerb): This should be in content/. WebPluginParams params(original_params); - for (size_t i = 0; i < info.mime_types.size(); ++i) { - if (info.mime_types[i].mime_type == actual_mime_type) { - AppendParams(info.mime_types[i].additional_param_names, - info.mime_types[i].additional_param_values, - ¶ms.attributeNames, ¶ms.attributeValues); + for (const auto& mime_type : info.mime_types) { + if (mime_type.mime_type == actual_mime_type) { + AppendParams(mime_type.additional_params, ¶ms.attribute_names, + ¶ms.attribute_values); break; } } - if (params.mimeType.isNull() && (actual_mime_type.size() > 0)) { + if (params.mime_type.IsNull() && (actual_mime_type.size() > 0)) { // Webkit might say that mime type is null while we already know the // actual mime type via ChromeViewHostMsg_GetPluginInfo. In that case // we should use what we know since WebpluginDelegateProxy does some // specific initializations based on this information. - params.mimeType = WebString::fromUTF8(actual_mime_type.c_str()); + params.mime_type = WebString::FromUTF8(actual_mime_type); } - ContentSettingsObserver* observer = - ContentSettingsObserver::Get(render_frame); + auto* content_settings_agent = + content_settings::ContentSettingsAgentImpl::Get(render_frame); + auto* content_settings_agent_delegate = + ChromeContentSettingsAgentDelegate::Get(render_frame); - const ContentSettingsType content_type = - ShouldUseJavaScriptSettingForPlugin(info) - ? CONTENT_SETTINGS_TYPE_JAVASCRIPT - : CONTENT_SETTINGS_TYPE_PLUGINS; + const ContentSettingsType content_type = ContentSettingsType::JAVASCRIPT; - if ((status == ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized || - status == ChromeViewHostMsg_GetPluginInfo_Status::kBlocked) && - observer->IsPluginTemporarilyAllowed(identifier)) { - status = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; + if ((status == chrome::mojom::PluginStatus::kUnauthorized || + status == chrome::mojom::PluginStatus::kBlocked) && + content_settings_agent_delegate->IsPluginTemporarilyAllowed( + identifier)) { + status = chrome::mojom::PluginStatus::kAllowed; } - auto create_blocked_plugin = [&render_frame, &frame, ¶ms, &info, - &identifier, &group_name]( - int template_id, const base::string16& message) { + auto create_blocked_plugin = [&render_frame, ¶ms, &info, &identifier, + &group_name](int template_id, + const std::u16string& message) { return ChromePluginPlaceholder::CreateBlockedPlugin( - render_frame, frame, params, info, identifier, group_name, - template_id, message, PowerSaverInfo()); + render_frame, params, info, identifier, group_name, template_id, + message); }; switch (status) { - case ChromeViewHostMsg_GetPluginInfo_Status::kNotFound: { + case chrome::mojom::PluginStatus::kNotFound: { NOTREACHED(); break; } - case ChromeViewHostMsg_GetPluginInfo_Status::kAllowed: - case ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent: { -#if !defined(DISABLE_NACL) && defined(ENABLE_EXTENSIONS) + case chrome::mojom::PluginStatus::kAllowed: + case chrome::mojom::PluginStatus::kPlayImportantContent: { +#if BUILDFLAG(ENABLE_NACL) && BUILDFLAG(ENABLE_EXTENSIONS) + WebLocalFrame* frame = render_frame->GetWebFrame(); const bool is_nacl_plugin = info.name == ASCIIToUTF16(nacl::kNaClPluginName); const bool is_nacl_mime_type = @@ -702,154 +1030,160 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( const bool is_pnacl_mime_type = actual_mime_type == nacl::kPnaclPluginMimeType; if (is_nacl_plugin || is_nacl_mime_type || is_pnacl_mime_type) { - bool is_nacl_unrestricted = false; - if (is_nacl_mime_type) { - is_nacl_unrestricted = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableNaCl); - } else if (is_pnacl_mime_type) { - is_nacl_unrestricted = true; - } + bool has_enable_nacl_switch = + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNaCl); + bool is_nacl_unrestricted = + has_enable_nacl_switch || is_pnacl_mime_type; GURL manifest_url; GURL app_url; if (is_nacl_mime_type || is_pnacl_mime_type) { // Normal NaCl/PNaCl embed. The app URL is the page URL. manifest_url = url; - app_url = frame->top()->document().url(); + app_url = frame->GetDocument().Url(); } else { // NaCl is being invoked as a content handler. Look up the NaCl // module using the MIME type. The app URL is the manifest URL. manifest_url = GetNaClContentHandlerURL(actual_mime_type, info); app_url = manifest_url; } - const Extension* extension = + bool is_module_allowed = false; + const extensions::Extension* extension = extensions::RendererExtensionRegistry::Get() ->GetExtensionOrAppByURL(manifest_url); - if (!IsNaClAllowed(manifest_url, - app_url, - is_nacl_unrestricted, - extension, - ¶ms)) { + if (IsNaclAllowed()) { + if (extension) { + is_module_allowed = + IsNativeNaClAllowed(app_url, is_nacl_unrestricted, extension); +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Allow Terminal System App to load the SSH extension NaCl + // module. + } else if (IsTerminalSystemWebAppNaClPage(app_url)) { + is_module_allowed = true; +#endif + } else { + WebDocument document = frame->GetDocument(); + is_module_allowed = + has_enable_nacl_switch || + (is_pnacl_mime_type && + blink::WebOriginTrials::isTrialEnabled(&document, "PNaCl")); + } + } + if (!is_module_allowed) { WebString error_message; - if (is_nacl_mime_type) { + if (!IsNaclAllowed()) { + error_message = "NaCl is disabled."; + } else if (is_nacl_mime_type) { error_message = "Only unpacked extensions and apps installed from the Chrome " "Web Store can load NaCl modules without enabling Native " "Client in about:flags."; } else if (is_pnacl_mime_type) { error_message = - "Portable Native Client must not be disabled in about:flags."; + "PNaCl modules can only be used on the open web (non-app/" + "extension) when the PNaCl Origin Trial is enabled"; } - frame->addMessageToConsole( - WebConsoleMessage(WebConsoleMessage::LevelError, - error_message)); + frame->AddMessageToConsole(WebConsoleMessage( + blink::mojom::ConsoleMessageLevel::kError, error_message)); placeholder = create_blocked_plugin( IDR_BLOCKED_PLUGIN_HTML, -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS_ASH) l10n_util::GetStringUTF16(IDS_NACL_PLUGIN_BLOCKED)); #else l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); #endif break; } + ReportNaClAppType(is_pnacl_mime_type, extension); + } +#endif // BUILDFLAG(ENABLE_NACL) && BUILDFLAG(ENABLE_EXTENSIONS) + + if (info.path.value() == ChromeContentClient::kPDFExtensionPluginPath) { + // Report PDF load metrics. Since the PDF plugin is comprised of an + // extension that loads a second plugin, avoid double counting by + // ignoring the creation of the second plugin. + bool is_main_frame_plugin_document = + render_frame->IsMainFrame() && + render_frame->GetWebFrame()->GetDocument().IsPluginDocument(); + ReportPDFLoadStatus( + is_main_frame_plugin_document + ? PDFLoadStatus::kLoadedFullPagePdfWithPdfium + : PDFLoadStatus::kLoadedEmbeddedPdfWithPdfium); } -#endif // !defined(DISABLE_NACL) && defined(ENABLE_EXTENSIONS) - // Delay loading plugins if prerendering. - // TODO(mmenke): In the case of prerendering, feed into + // Delay loading plugins if no-state prefetching. + // TODO(mmenke): In the case of NoStatePrefetch, feed into // ChromeContentRendererClient::CreatePlugin instead, to // reduce the chance of future regressions. - bool is_prerendering = - prerender::PrerenderHelper::IsPrerendering(render_frame); - - bool power_saver_setting_on = - status == - ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent; - PowerSaverInfo power_saver_info = - PowerSaverInfo::Get(render_frame, power_saver_setting_on, params, - info, frame->document().url()); - if (power_saver_info.blocked_for_background_tab || is_prerendering || - !power_saver_info.poster_attribute.empty()) { + bool is_no_state_prefetching = + prerender::NoStatePrefetchHelper::IsPrefetching(render_frame); + + if (is_no_state_prefetching) { placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( - render_frame, frame, params, info, identifier, group_name, - power_saver_info.poster_attribute.empty() - ? IDR_BLOCKED_PLUGIN_HTML - : IDR_PLUGIN_POSTER_HTML, - l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name), - power_saver_info); - placeholder->set_blocked_for_prerendering(is_prerendering); + render_frame, params, info, identifier, group_name, + IDR_BLOCKED_PLUGIN_HTML, + l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); + placeholder->set_blocked_for_prerendering(is_no_state_prefetching); placeholder->AllowLoading(); break; } - std::unique_ptr throttler; - if (power_saver_info.power_saver_enabled) { - throttler = PluginInstanceThrottler::Create(); - // PluginPreroller manages its own lifetime. - new PluginPreroller( - render_frame, frame, params, info, identifier, group_name, - l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name), - throttler.get()); +#if BUILDFLAG(ENABLE_PDF) + if (info.path.value() == ChromeContentClient::kPDFInternalPluginPath) { + return pdf::CreateInternalPlugin( + std::move(params), render_frame, + std::make_unique()); } +#endif // BUILDFLAG(ENABLE_PDF) - return render_frame->CreatePlugin(frame, info, params, - std::move(throttler)); + return render_frame->CreatePlugin(info, params); } - case ChromeViewHostMsg_GetPluginInfo_Status::kDisabled: { + case chrome::mojom::PluginStatus::kDisabled: { PluginUMAReporter::GetInstance()->ReportPluginDisabled(orig_mime_type, url); + if (info.path.value() == ChromeContentClient::kPDFExtensionPluginPath) { + ReportPDFLoadStatus( + PDFLoadStatus::kShowedDisabledPluginPlaceholderForEmbeddedPdf); + + return PDFPluginPlaceholder::CreatePDFPlaceholder(render_frame, + params) + ->plugin(); + } + placeholder = create_blocked_plugin( IDR_DISABLED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_DISABLED, group_name)); break; } - case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked: { -#if defined(ENABLE_PLUGIN_INSTALLATION) - placeholder = create_blocked_plugin( - IDR_BLOCKED_PLUGIN_HTML, - l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name)); - placeholder->AllowLoading(); - render_frame->Send(new ChromeViewHostMsg_BlockedOutdatedPlugin( - render_frame->GetRoutingID(), placeholder->CreateRoutingId(), - identifier)); -#else - NOTREACHED(); -#endif - break; - } - case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed: { - placeholder = create_blocked_plugin( - IDR_BLOCKED_PLUGIN_HTML, - l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name)); - break; - } - case ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized: { + case chrome::mojom::PluginStatus::kUnauthorized: { placeholder = create_blocked_plugin( IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, group_name)); placeholder->AllowLoading(); - render_frame->Send(new ChromeViewHostMsg_BlockedUnauthorizedPlugin( - render_frame->GetRoutingID(), group_name, identifier)); - observer->DidBlockContentType(content_type, group_name); + mojo::AssociatedRemote plugin_auth_host; + render_frame->GetRemoteAssociatedInterfaces()->GetInterface( + plugin_auth_host.BindNewEndpointAndPassReceiver()); + plugin_auth_host->BlockedUnauthorizedPlugin(group_name, identifier); + content_settings_agent->DidBlockContentType(content_type); break; } - case ChromeViewHostMsg_GetPluginInfo_Status::kBlocked: { + case chrome::mojom::PluginStatus::kBlocked: { placeholder = create_blocked_plugin( IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); placeholder->AllowLoading(); RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Blocked")); - observer->DidBlockContentType(content_type, group_name); + content_settings_agent->DidBlockContentType(content_type); break; } - case ChromeViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy: { + case chrome::mojom::PluginStatus::kBlockedByPolicy: { placeholder = create_blocked_plugin( IDR_BLOCKED_PLUGIN_HTML, l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED_BY_POLICY, group_name)); RenderThread::Get()->RecordAction( UserMetricsAction("Plugin_BlockedByPolicy")); - observer->DidBlockContentType(content_type, group_name); + content_settings_agent->DidBlockContentType(content_type); break; } } @@ -857,7 +1191,7 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( placeholder->SetStatus(status); return placeholder->plugin(); } -#endif // defined(ENABLE_PLUGINS) +#endif // BUILDFLAG(ENABLE_PLUGINS) // For NaCl content handling plugins, the NaCl manifest is stored in an // additonal 'nacl' param associated with the MIME type. @@ -866,14 +1200,11 @@ GURL ChromeContentRendererClient::GetNaClContentHandlerURL( const std::string& actual_mime_type, const content::WebPluginInfo& plugin) { // Look for the manifest URL among the MIME type's additonal parameters. - const char kNaClPluginManifestAttribute[] = "nacl"; - base::string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute); - for (size_t i = 0; i < plugin.mime_types.size(); ++i) { - if (plugin.mime_types[i].mime_type == actual_mime_type) { - const content::WebPluginMimeType& content_type = plugin.mime_types[i]; - for (size_t i = 0; i < content_type.additional_param_names.size(); ++i) { - if (content_type.additional_param_names[i] == nacl_attr) - return GURL(content_type.additional_param_values[i]); + for (const auto& mime_type : plugin.mime_types) { + if (mime_type.mime_type == actual_mime_type) { + for (const auto& p : mime_type.additional_params) { + if (p.name == u"nacl") + return GURL(p.value); } break; } @@ -881,314 +1212,295 @@ GURL ChromeContentRendererClient::GetNaClContentHandlerURL( return GURL(); } -#if !defined(DISABLE_NACL) +void ChromeContentRendererClient::GetInterface( + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + // TODO(crbug.com/977637): Get rid of the use of this implementation of + // |service_manager::LocalInterfaceProvider|. This was done only to avoid + // churning spellcheck code while eliminting the "chrome" and + // "chrome_renderer" services. Spellcheck is (and should remain) the only + // consumer of this implementation. + RenderThread::Get()->BindHostReceiver( + mojo::GenericPendingReceiver(interface_name, std::move(interface_pipe))); +} + +#if BUILDFLAG(ENABLE_NACL) // static -bool ChromeContentRendererClient::IsNaClAllowed( - const GURL& manifest_url, +bool ChromeContentRendererClient::IsNativeNaClAllowed( const GURL& app_url, bool is_nacl_unrestricted, - const Extension* extension, - WebPluginParams* params) { - // Temporarily allow these whitelisted apps and WebUIs to use NaCl. - std::string app_url_host = app_url.host(); - std::string manifest_url_path = manifest_url.path(); - - bool is_whitelisted_web_ui = - app_url.spec() == chrome::kChromeUIAppListStartPageURL; - - bool is_photo_app = - // Whitelisted apps must be served over https. - app_url.SchemeIsCryptographic() && manifest_url.SchemeIsCryptographic() && - (base::EndsWith(app_url_host, "plus.google.com", - base::CompareCase::INSENSITIVE_ASCII) || - base::EndsWith(app_url_host, "plus.sandbox.google.com", - base::CompareCase::INSENSITIVE_ASCII)) && - manifest_url.DomainIs("ssl.gstatic.com") && - (manifest_url_path.find("s2/oz/nacl/") == 1 || - manifest_url_path.find("photos/nacl/") == 1); - - std::string manifest_fs_host; - if (manifest_url.SchemeIsFileSystem() && manifest_url.inner_url()) { - manifest_fs_host = manifest_url.inner_url()->host(); - } - bool is_hangouts_app = - // Whitelisted apps must be served over secure scheme. - app_url.SchemeIsCryptographic() && manifest_url.SchemeIsFileSystem() && - manifest_url.inner_url()->SchemeIsCryptographic() && - (base::EndsWith(app_url_host, "talkgadget.google.com", - base::CompareCase::INSENSITIVE_ASCII) || - base::EndsWith(app_url_host, "plus.google.com", - base::CompareCase::INSENSITIVE_ASCII) || - base::EndsWith(app_url_host, "plus.sandbox.google.com", - base::CompareCase::INSENSITIVE_ASCII) || - base::EndsWith(app_url_host, "hangouts.google.com", - base::CompareCase::INSENSITIVE_ASCII)) && - // The manifest must be loaded from the host's FileSystem. - (manifest_fs_host == app_url_host); - - bool is_whitelisted_app = is_photo_app || is_hangouts_app; - + const extensions::Extension* extension) { bool is_invoked_by_webstore_installed_extension = false; bool is_extension_unrestricted = false; bool is_extension_force_installed = false; -#if defined(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_EXTENSIONS) bool is_extension_from_webstore = extension && extension->from_webstore(); - bool is_invoked_by_extension = app_url.SchemeIs("chrome-extension"); - bool is_invoked_by_hosted_app = extension && - extension->is_hosted_app() && - extension->web_extent().MatchesURL(app_url); + bool is_invoked_by_extension = app_url.SchemeIs(extensions::kExtensionScheme); + bool is_invoked_by_hosted_app = extension && extension->is_hosted_app() && + extension->web_extent().MatchesURL(app_url); - is_invoked_by_webstore_installed_extension = is_extension_from_webstore && + is_invoked_by_webstore_installed_extension = + is_extension_from_webstore && (is_invoked_by_extension || is_invoked_by_hosted_app); // Allow built-in extensions and developer mode extensions. - is_extension_unrestricted = extension && - (extensions::Manifest::IsUnpackedLocation(extension->location()) || - extensions::Manifest::IsComponentLocation(extension->location())); + is_extension_unrestricted = + extension && + (extensions::Manifest::IsUnpackedLocation(extension->location()) || + extensions::Manifest::IsComponentLocation(extension->location())); // Allow extensions force installed by admin policy. - is_extension_force_installed = extension && - extensions::Manifest::IsPolicyLocation(extension->location()); -#endif // defined(ENABLE_EXTENSIONS) + is_extension_force_installed = + extension && + extensions::Manifest::IsPolicyLocation(extension->location()); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) // Allow NaCl under any of the following circumstances: - // 1) An app or URL is explictly whitelisted above. - // 2) An extension is loaded unpacked or built-in (component) to Chrome. - // 3) An extension is force installed by policy. - // 4) An extension is installed from the webstore, and invoked in that + // 1) An extension is loaded unpacked or built-in (component) to Chrome. + // 2) An extension is force installed by policy. + // 3) An extension is installed from the webstore, and invoked in that // context (hosted app URL or chrome-extension:// scheme). - // 5) --enable-nacl is set. - bool is_nacl_allowed_by_location = - is_whitelisted_web_ui || - is_whitelisted_app || - is_extension_unrestricted || - is_extension_force_installed || - is_invoked_by_webstore_installed_extension; + // 4) --enable-nacl is set. + bool is_nacl_allowed_by_location = is_extension_unrestricted || + is_extension_force_installed || + is_invoked_by_webstore_installed_extension; bool is_nacl_allowed = is_nacl_allowed_by_location || is_nacl_unrestricted; - if (is_nacl_allowed) { - // Make sure that PPAPI 'dev' interfaces are only available for unpacked - // and component extensions. Also allow dev interfaces when --enable-nacl - // is set, but do not allow --enable-nacl to provide dev interfaces to - // webstore installed and other normally allowed URLs. - WebString dev_attribute = WebString::fromUTF8("@dev"); - if (is_extension_unrestricted || - (is_nacl_unrestricted && !is_nacl_allowed_by_location)) { - // Add the special '@dev' attribute. - std::vector param_names; - std::vector param_values; - param_names.push_back(dev_attribute); - param_values.push_back(WebString()); - AppendParams( - param_names, - param_values, - ¶ms->attributeNames, - ¶ms->attributeValues); - } else { - // If the params somehow contain '@dev', remove it. - size_t attribute_count = params->attributeNames.size(); - for (size_t i = 0; i < attribute_count; ++i) { - if (params->attributeNames[i].equals(dev_attribute)) - params->attributeNames[i] = WebString(); - } - } - } return is_nacl_allowed; } -#endif // defined(DISABLE_NACL) -bool ChromeContentRendererClient::HasErrorPage(int http_status_code, - std::string* error_domain) { - // Use an internal error page, if we have one for the status code. - if (!error_page::LocalizedError::HasStrings( - error_page::LocalizedError::kHttpErrorDomain, http_status_code)) { - return false; +// static +void ChromeContentRendererClient::ReportNaClAppType( + bool is_pnacl, + const extensions::Extension* extension) { + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class NaClAppType { + kPNaClOpenWeb = 0, + kPNaClHostedApp = 1, + kPNaClPlatformApp = 2, + kPNaClLegacyPackagedApp = 3, + kPNaClMv2Extension = 4, + kPNaClMv3Extension = 5, + kPNaClLoginScreenMv2Extension = 6, + kPNaClLoginScreenMv3Extension = 7, + kNaClOpenWeb = 8, + kNaClHostedApp = 9, + kNaClPlatformApp = 10, + kNaClLegacyPackagedApp = 11, + kNaClMv2Extension = 12, + kNaClMv3Extension = 13, + kNaClLoginScreenMv2Extension = 14, + kNaClLoginScreenMv3Extension = 15, + kMaxValue = kNaClLoginScreenMv3Extension + }; + + // Not all combinations are allowed by default (e.g. kNaClOpenWeb), but they + // can be used with the --enable-nacl flag. + NaClAppType app_type = + is_pnacl ? NaClAppType::kPNaClOpenWeb : NaClAppType::kNaClOpenWeb; + if (extension) { + if (extension->is_extension()) { + if (extension->manifest_version() >= 3) { + app_type = is_pnacl ? NaClAppType::kPNaClMv3Extension + : NaClAppType::kNaClMv3Extension; + } else { + app_type = is_pnacl ? NaClAppType::kPNaClMv2Extension + : NaClAppType::kNaClMv2Extension; + } + } else if (extension->is_hosted_app()) { + app_type = + is_pnacl ? NaClAppType::kPNaClHostedApp : NaClAppType::kNaClHostedApp; + } else if (extension->is_legacy_packaged_app()) { + app_type = is_pnacl ? NaClAppType::kPNaClLegacyPackagedApp + : NaClAppType::kNaClLegacyPackagedApp; + } else if (extension->is_platform_app()) { + app_type = is_pnacl ? NaClAppType::kPNaClPlatformApp + : NaClAppType::kNaClPlatformApp; + } else if (extension->is_login_screen_extension()) { + if (extension->manifest_version() >= 3) { + app_type = is_pnacl ? NaClAppType::kPNaClLoginScreenMv3Extension + : NaClAppType::kNaClLoginScreenMv3Extension; + } else { + app_type = is_pnacl ? NaClAppType::kPNaClLoginScreenMv2Extension + : NaClAppType::kNaClLoginScreenMv2Extension; + } + } else { + // We found an extension that is not covered by any metric + NOTREACHED() << "Invalid NaCl usage in extension. Extension name: " + << extension->name() << ", type: " << extension->GetType(); + } } - *error_domain = error_page::LocalizedError::kHttpErrorDomain; - return true; + base::UmaHistogramEnumeration("NaCl.EmbedderType", app_type); } +#endif // BUILDFLAG(ENABLE_NACL) -bool ChromeContentRendererClient::ShouldSuppressErrorPage( +void ChromeContentRendererClient::PrepareErrorPage( content::RenderFrame* render_frame, - const GURL& url) { - // Unit tests for ChromeContentRendererClient pass a NULL RenderFrame here. - // Unfortunately it's very difficult to construct a mock RenderView, so skip - // this functionality in this case. - if (render_frame && - NetErrorHelper::Get(render_frame)->ShouldSuppressErrorPage(url)) { - return true; - } - // Do not flash an error page if the Instant new tab page fails to load. - return SearchBouncer::GetInstance()->IsNewTabPage(url); + const blink::WebURLError& web_error, + const std::string& http_method, + content::mojom::AlternativeErrorPageOverrideInfoPtr + alternative_error_page_info, + std::string* error_html) { + NetErrorHelper::Get(render_frame) + ->PrepareErrorPage( + error_page::Error::NetError( + web_error.url(), web_error.reason(), web_error.extended_reason(), + web_error.resolve_error_info(), web_error.has_copy_in_cache()), + http_method == "POST", std::move(alternative_error_page_info), + error_html); + +#if BUILDFLAG(ENABLE_SUPERVISED_USERS) + SupervisedUserErrorPageControllerDelegateImpl::Get(render_frame) + ->PrepareForErrorPage(); +#endif } -void ChromeContentRendererClient::GetNavigationErrorStrings( +void ChromeContentRendererClient::PrepareErrorPageForHttpStatusError( content::RenderFrame* render_frame, - const WebURLRequest& failed_request, - const WebURLError& error, - std::string* error_html, - base::string16* error_description) { - const GURL failed_url = error.unreachableURL; - - bool is_post = base::EqualsASCII( - base::StringPiece16(failed_request.httpMethod()), "POST"); - bool is_ignoring_cache = - failed_request.getCachePolicy() == WebCachePolicy::BypassingCache; - if (error_html) { - NetErrorHelper::Get(render_frame) - ->GetErrorHTML(error, is_post, is_ignoring_cache, error_html); - } + const blink::WebURLError& error, + const std::string& http_method, + int http_status, + content::mojom::AlternativeErrorPageOverrideInfoPtr + alternative_error_page_info, + std::string* error_html) { + NetErrorHelper::Get(render_frame) + ->PrepareErrorPage(error_page::Error::HttpError(error.url(), http_status), + http_method == "POST", + std::move(alternative_error_page_info), error_html); +} - if (error_description) { - *error_description = error_page::LocalizedError::GetErrorDetails( - error.domain.utf8(), error.reason, is_post); - } +void ChromeContentRendererClient::PostSandboxInitialized() { +#if BUILDFLAG(IS_CHROMEOS) + DCHECK(!main_thread_profiler_); + main_thread_profiler_ = ThreadProfiler::CreateAndStartOnMainThread(); +#endif // BUILDFLAG(IS_CHROMEOS) } -bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() { -#if defined(ENABLE_EXTENSIONS) - return !IsStandaloneExtensionProcess(); -#else - return true; -#endif +void ChromeContentRendererClient::PostIOThreadCreated( + base::SingleThreadTaskRunner* io_thread_task_runner) { + io_thread_task_runner->PostTask( + FROM_HERE, base::BindOnce(&ThreadProfiler::StartOnChildThread, + metrics::CallStackProfileParams::Thread::kIo)); } -bool ChromeContentRendererClient:: - AllowTimerSuspensionWhenProcessBackgrounded() { -#if defined(OS_ANDROID) - return true; +void ChromeContentRendererClient::PostCompositorThreadCreated( + base::SingleThreadTaskRunner* compositor_thread_task_runner) { + compositor_thread_task_runner->PostTask( + FROM_HERE, + base::BindOnce(&ThreadProfiler::StartOnChildThread, + metrics::CallStackProfileParams::Thread::kCompositor)); + // Enable stack sampling for tracing. + // We pass in CreateCoreUnwindersFactory here since it lives in the chrome/ + // layer while TracingSamplerProfiler is outside of chrome/. + compositor_thread_task_runner->PostTask( + FROM_HERE, + base::BindOnce(&tracing::TracingSamplerProfiler:: + CreateOnChildThreadWithCustomUnwinders, +#if BUILDFLAG(IS_ANDROID) + base::BindRepeating(&CreateCoreUnwindersFactory, false))); #else - return false; -#endif + base::BindRepeating(&CreateCoreUnwindersFactory))); +#endif // BUILDFLAG(IS_ANDROID) +} + +bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() { + return !IsStandaloneContentExtensionProcess(); } bool ChromeContentRendererClient::AllowPopup() { -#if defined(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_EXTENSIONS) return ChromeExtensionsRendererClient::GetInstance()->AllowPopup(); #else return false; #endif } -bool ChromeContentRendererClient::ShouldFork(WebLocalFrame* frame, - const GURL& url, - const std::string& http_method, - bool is_initial_navigation, - bool is_server_redirect, - bool* send_referrer) { - DCHECK(!frame->parent()); - - // If this is the Instant process, fork all navigations originating from the - // renderer. The destination page will then be bucketed back to this Instant - // process if it is an Instant url, or to another process if not. Conversely, - // fork if this is a non-Instant process navigating to an Instant url, so that - // such navigations can also be bucketed into an Instant renderer. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kInstantProcess) || - SearchBouncer::GetInstance()->ShouldFork(url)) { - *send_referrer = true; - return true; - } - - // For now, we skip the rest for POST submissions. This is because - // http://crbug.com/101395 is more likely to cause compatibility issues - // with hosted apps and extensions than WebUI pages. We will remove this - // check when cross-process POST submissions are supported. - if (http_method != "GET") - return false; +bool ChromeContentRendererClient::ShouldNotifyServiceWorkerOnWebSocketActivity( + v8::Local context) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + extensions::ScriptContext* script_context = + ChromeExtensionsRendererClient::GetInstance() + ->extension_dispatcher() + ->GetWorkerScriptContextSet() + ->GetContextByV8Context(context); + // Only notify on web socket activity if the service worker is the background + // service worker for an extension. + return script_context && + ChromeExtensionsRendererClient::GetInstance() + ->ExtensionAPIEnabledForServiceWorkerScript( + script_context->service_worker_scope(), script_context->url()); +#else + return false; +#endif +} - // If |url| matches one of the prerendered URLs, stop this navigation and try - // to swap in the prerendered page on the browser process. If the prerendered - // page no longer exists by the time the OpenURL IPC is handled, a normal - // navigation is attempted. - if (prerender_dispatcher_.get() && - prerender_dispatcher_->IsPrerenderURL(url)) { - *send_referrer = true; - return true; +blink::ProtocolHandlerSecurityLevel +ChromeContentRendererClient::GetProtocolHandlerSecurityLevel( + const url::Origin& origin) { + if (origin.scheme() == chrome::kIsolatedAppScheme) { + return blink::ProtocolHandlerSecurityLevel::kSameOrigin; } - -#if defined(ENABLE_EXTENSIONS) - bool should_fork = ChromeExtensionsRendererClient::ShouldFork( - frame, url, is_initial_navigation, is_server_redirect, send_referrer); - if (should_fork) - return true; -#endif // defined(ENABLE_EXTENSIONS) - - return false; +#if BUILDFLAG(ENABLE_EXTENSIONS) + return ChromeExtensionsRendererClient::GetInstance() + ->GetProtocolHandlerSecurityLevel(); +#else + return blink::ProtocolHandlerSecurityLevel::kStrict; +#endif } -bool ChromeContentRendererClient::WillSendRequest( - WebFrame* frame, +void ChromeContentRendererClient::WillSendRequest( + WebLocalFrame* frame, ui::PageTransition transition_type, - const GURL& url, - const GURL& first_party_for_cookies, + const blink::WebURL& url, + const net::SiteForCookies& site_for_cookies, + const url::Origin* initiator_origin, GURL* new_url) { +#if BUILDFLAG(ENABLE_EXTENSIONS) // Check whether the request should be allowed. If not allowed, we reset the // URL to something invalid to prevent the request and cause an error. -#if defined(ENABLE_EXTENSIONS) - if (ChromeExtensionsRendererClient::GetInstance()->WillSendRequest( - frame, transition_type, url, new_url)) { - return true; - } + ChromeExtensionsRendererClient::GetInstance()->WillSendRequest( + frame, transition_type, url, site_for_cookies, initiator_origin, new_url); + if (!new_url->is_empty()) + return; #endif - const content::RenderView* render_view = - content::RenderView::FromWebView(frame->view()); - SearchBox* search_box = SearchBox::Get(render_view); - if (search_box && url.SchemeIs(chrome::kChromeSearchScheme)) { - SearchBox::ImageSourceType type = SearchBox::NONE; - if (url.host() == chrome::kChromeUIFaviconHost) - type = SearchBox::FAVICON; - else if (url.host() == chrome::kChromeUILargeIconHost) - type = SearchBox::LARGE_ICON; - else if (url.host() == chrome::kChromeUIFallbackIconHost) - type = SearchBox::FALLBACK_ICON; - else if (url.host() == chrome::kChromeUIThumbnailHost) - type = SearchBox::THUMB; - - if (type != SearchBox::NONE) - return search_box->GenerateImageURLFromTransientURL(url, type, new_url); - } - - return false; -} + if (!url.ProtocolIs(chrome::kChromeSearchScheme)) + return; -unsigned long long ChromeContentRendererClient::VisitedLinkHash( - const char* canonical_url, size_t length) { - return visited_link_slave_->ComputeURLFingerprint(canonical_url, length); +#if !BUILDFLAG(IS_ANDROID) + SearchBox* search_box = + SearchBox::Get(content::RenderFrame::FromWebFrame(frame->LocalRoot())); + if (search_box) { + // Note: this GURL copy could be avoided if host() were added to WebURL. + GURL gurl(url); + if (gurl.host_piece() == chrome::kChromeUIFaviconHost) + search_box->GenerateImageURLFromTransientURL(url, new_url); + } +#endif // !BUILDFLAG(IS_ANDROID) } -bool ChromeContentRendererClient::IsLinkVisited(unsigned long long link_hash) { - return visited_link_slave_->IsVisited(link_hash); +bool ChromeContentRendererClient::IsPrefetchOnly( + content::RenderFrame* render_frame) { + return prerender::NoStatePrefetchHelper::IsPrefetching(render_frame); } -blink::WebPrescientNetworking* -ChromeContentRendererClient::GetPrescientNetworking() { - return prescient_networking_dispatcher_.get(); +uint64_t ChromeContentRendererClient::VisitedLinkHash( + std::string_view canonical_url) { + return chrome_observer_->visited_link_reader()->ComputeURLFingerprint( + canonical_url); } -bool ChromeContentRendererClient::ShouldOverridePageVisibilityState( - const content::RenderFrame* render_frame, - blink::WebPageVisibilityState* override_state) { - if (!prerender::PrerenderHelper::IsPrerendering(render_frame)) - return false; - - *override_state = blink::WebPageVisibilityStatePrerender; - return true; +bool ChromeContentRendererClient::IsLinkVisited(uint64_t link_hash) { + return chrome_observer_->visited_link_reader()->IsVisited(link_hash); } -#if defined(ENABLE_SPELLCHECK) -void ChromeContentRendererClient::SetSpellcheck(SpellCheck* spellcheck) { - RenderThread* thread = RenderThread::Get(); - if (spellcheck_.get() && thread) - thread->RemoveObserver(spellcheck_.get()); - spellcheck_.reset(spellcheck); - SpellCheckReplacer replacer(spellcheck_.get()); - content::RenderView::ForEach(&replacer); - if (thread) - thread->AddObserver(spellcheck_.get()); +std::unique_ptr +ChromeContentRendererClient::CreatePrescientNetworking( + content::RenderFrame* render_frame) { + return std::make_unique( + render_frame); } -#endif bool ChromeContentRendererClient::IsExternalPepperPlugin( const std::string& module_name) { @@ -1198,211 +1510,250 @@ bool ChromeContentRendererClient::IsExternalPepperPlugin( return module_name == "Native Client"; } -#if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS) -bool ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted( - const GURL& url, const std::set& whitelist) { +bool ChromeContentRendererClient::IsOriginIsolatedPepperPlugin( + const base::FilePath& plugin_path) { + // Hosting plugins in-process is inherently incompatible with attempting to + // process-isolate plugins from different origins. + auto* cmdline = base::CommandLine::ForCurrentProcess(); + if (cmdline->HasSwitch(switches::kPpapiInProcess)) { + // The kPpapiInProcess switch should only be used by tests. In particular, + // we expect that the PDF plugin should always be isolated in the product + // (and that the switch won't interfere with PDF isolation). + CHECK_NE(ChromeContentClient::kPDFInternalPluginPath, plugin_path.value()); + + return false; + } + +#if BUILDFLAG(ENABLE_NACL) + // Don't isolate the NaCl plugin (preserving legacy behavior). + if (plugin_path.value() == nacl::kInternalNaClPluginFileName) + return false; +#endif + + // Isolate all the other plugins (including the PDF plugin + test plugins). + return true; +} + +#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_EXTENSIONS) +bool ChromeContentRendererClient::IsExtensionOrSharedModuleAllowed( + const GURL& url, + const std::set& allowlist) { const extensions::ExtensionSet* extension_set = extensions::RendererExtensionRegistry::Get()->GetMainThreadExtensionSet(); - return chrome::IsExtensionOrSharedModuleWhitelisted(url, extension_set, - whitelist); + return ::IsExtensionOrSharedModuleAllowed(url, extension_set, allowlist); } #endif -blink::WebSpeechSynthesizer* -ChromeContentRendererClient::OverrideSpeechSynthesizer( - blink::WebSpeechSynthesizerClient* client) { - return new TtsDispatcher(client); +#if BUILDFLAG(ENABLE_SPELLCHECK) +void ChromeContentRendererClient::InitSpellCheck() { + spellcheck_ = std::make_unique(this); } +#endif -bool ChromeContentRendererClient::AllowPepperMediaStreamAPI( - const GURL& url) { -#if !defined(OS_ANDROID) - // 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. - std::string url_host = url.host(); - if (url.SchemeIs("https") && - (base::EndsWith(url_host, "talkgadget.google.com", - base::CompareCase::INSENSITIVE_ASCII) || - base::EndsWith(url_host, "plus.google.com", - base::CompareCase::INSENSITIVE_ASCII) || - base::EndsWith(url_host, "plus.sandbox.google.com", - base::CompareCase::INSENSITIVE_ASCII)) && - base::StartsWith(url.path(), "/hangouts/", - base::CompareCase::INSENSITIVE_ASCII)) { - return true; - } - // Allow access for tests. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnablePepperTesting)) { - return true; +ChromeRenderThreadObserver* ChromeContentRendererClient::GetChromeObserver() + const { + return chrome_observer_.get(); +} + +web_cache::WebCacheImpl* ChromeContentRendererClient::GetWebCache() { + return web_cache_impl_.get(); +} + +chrome::WebRtcLoggingAgentImpl* +ChromeContentRendererClient::GetWebRtcLoggingAgent() { + if (!webrtc_logging_agent_impl_) { + webrtc_logging_agent_impl_ = + std::make_unique(); } -#endif // !defined(OS_ANDROID) - return false; + return webrtc_logging_agent_impl_.get(); } -void ChromeContentRendererClient::AddSupportedKeySystems( - std::vector>* key_systems) { - AddChromeKeySystems(key_systems); +#if BUILDFLAG(ENABLE_SPELLCHECK) +SpellCheck* ChromeContentRendererClient::GetSpellCheck() { + return spellcheck_.get(); } +#endif // BUILDFLAG(ENABLE_SPELLCHECK) -bool ChromeContentRendererClient::ShouldReportDetailedMessageForSource( - const base::string16& source) const { -#if defined(ENABLE_EXTENSIONS) - return extensions::IsSourceFromAnExtension(source); +std::unique_ptr +ChromeContentRendererClient::CreateWebSocketHandshakeThrottleProvider() { + return std::make_unique( + browser_interface_broker_.get()); +} + +void ChromeContentRendererClient::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) + GetChromeKeySystems(std::move(cb)); #else - return false; + std::move(cb).Run({}); #endif } -bool ChromeContentRendererClient::ShouldGatherSiteIsolationStats() const { - // Site isolation stats are gathered currently for non-extension renderer - // processes running a normal web page from the Internet. - // TODO(nick): https://crbug.com/268640 Gather stats for extension processes - // too; we would need to check the extension's manifest to know which sites - // it's allowed to access. -#if defined(ENABLE_EXTENSIONS) - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - return !command_line->HasSwitch(extensions::switches::kExtensionProcess); +bool ChromeContentRendererClient::ShouldReportDetailedMessageForSource( + const std::u16string& source) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + return extensions::IsSourceFromAnExtension(source); #else - return true; + return false; #endif } -blink::WebWorkerContentSettingsClientProxy* -ChromeContentRendererClient::CreateWorkerContentSettingsClientProxy( - content::RenderFrame* render_frame, - WebFrame* frame) { - return new WorkerContentSettingsClientProxy(render_frame, frame); +std::unique_ptr +ChromeContentRendererClient::CreateWorkerContentSettingsClient( + content::RenderFrame* render_frame) { + return std::make_unique(render_frame); } -bool ChromeContentRendererClient::IsPluginAllowedToUseDevChannelAPIs() { -#if defined(ENABLE_PLUGINS) - // Allow access for tests. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnablePepperTesting)) { - return true; - } - - version_info::Channel channel = chrome::GetChannel(); - // Allow dev channel APIs to be used on "Canary", "Dev", and "Unknown" - // releases of Chrome. Permitting "Unknown" allows these APIs to be used on - // Chromium builds as well. - return channel <= version_info::Channel::DEV; -#else - return false; -#endif +#if BUILDFLAG(ENABLE_SPEECH_SERVICE) +std::unique_ptr +ChromeContentRendererClient::CreateSpeechRecognitionClient( + content::RenderFrame* render_frame) { + return std::make_unique(render_frame); } +#endif // BUILDFLAG(ENABLE_SPEECH_SERVICE) bool ChromeContentRendererClient::IsPluginAllowedToUseCameraDeviceAPI( const GURL& url) { -#if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_PPAPI) if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnablePepperTesting)) return true; +#endif // BUILDFLAG(ENABLE_PPAPI) - if (IsExtensionOrSharedModuleWhitelisted(url, allowed_camera_device_origins_)) + if (IsExtensionOrSharedModuleAllowed(url, allowed_camera_device_origins_)) return true; #endif return false; } -bool ChromeContentRendererClient::IsPluginAllowedToUseCompositorAPI( - const GURL& url) { -#if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnablePepperTesting)) - return true; - if (IsExtensionOrSharedModuleWhitelisted(url, allowed_compositor_origins_)) - return true; +void ChromeContentRendererClient::RunScriptsAtDocumentStart( + content::RenderFrame* render_frame) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentStart( + render_frame); + // |render_frame| might be dead by now. +#endif +} - version_info::Channel channel = chrome::GetChannel(); - return channel <= version_info::Channel::DEV; -#else - return false; +void ChromeContentRendererClient::RunScriptsAtDocumentEnd( + content::RenderFrame* render_frame) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentEnd( + render_frame); + // |render_frame| might be dead by now. #endif } -content::BrowserPluginDelegate* -ChromeContentRendererClient::CreateBrowserPluginDelegate( - content::RenderFrame* render_frame, - const std::string& mime_type, - const GURL& original_url) { -#if defined(ENABLE_EXTENSIONS) - return ChromeExtensionsRendererClient::CreateBrowserPluginDelegate( - render_frame, mime_type, original_url); -#else - return nullptr; +void ChromeContentRendererClient::RunScriptsAtDocumentIdle( + content::RenderFrame* render_frame) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentIdle( + render_frame); + // |render_frame| might be dead by now. #endif } -void ChromeContentRendererClient::RecordRappor(const std::string& metric, - const std::string& sample) { - RenderThread::Get()->Send(new ChromeViewHostMsg_RecordRappor(metric, sample)); +void ChromeContentRendererClient:: + SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() { + // The performance manager service interfaces are provided by the chrome + // embedder only. + blink::WebRuntimeFeatures::EnablePerformanceManagerInstrumentation(true); + + MaybeEnableWebShare(); + + if (base::FeatureList::IsEnabled( + autofill::features::kAutofillSharedAutofill)) { + blink::WebRuntimeFeatures::EnableSharedAutofill(true); + } + + if (base::FeatureList::IsEnabled(subresource_filter::kAdTagging)) + blink::WebRuntimeFeatures::EnableAdTagging(true); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + // WebHID and WebUSB on service workers is only available in extensions. + if (IsStandaloneContentExtensionProcess()) { + if (base::FeatureList::IsEnabled( + features::kEnableWebUsbOnExtensionServiceWorker)) { + blink::WebRuntimeFeatures::EnableWebUSBOnServiceWorkers(true); + } +#if !BUILDFLAG(IS_ANDROID) + if (base::FeatureList::IsEnabled( + features::kEnableWebHidOnExtensionServiceWorker)) { + blink::WebRuntimeFeatures::EnableWebHIDOnServiceWorkers(true); + } +#endif // !BUILDFLAG(IS_ANDROID) + } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) } -void ChromeContentRendererClient::RecordRapporURL(const std::string& metric, - const GURL& url) { - RenderThread::Get()->Send(new ChromeViewHostMsg_RecordRapporURL(metric, url)); +bool ChromeContentRendererClient::AllowScriptExtensionForServiceWorker( + const url::Origin& script_origin) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + return script_origin.scheme() == extensions::kExtensionScheme; +#else + return false; +#endif } -std::unique_ptr -ChromeContentRendererClient::CreateAppBannerClient( - content::RenderFrame* render_frame) { - return std::unique_ptr( - new AppBannerClient(render_frame)); -} - -void ChromeContentRendererClient::AddImageContextMenuProperties( - const WebURLResponse& response, - std::map* properties) { - DCHECK(properties); - WebString header_key(ASCIIToUTF16( - data_reduction_proxy::chrome_proxy_header())); - if (!response.httpHeaderField(header_key).isNull() && - response.httpHeaderField(header_key).utf8().find( - data_reduction_proxy::chrome_proxy_lo_fi_directive()) != - std::string::npos) { - (*properties)[data_reduction_proxy::chrome_proxy_header()] = - data_reduction_proxy::chrome_proxy_lo_fi_directive(); - } +void ChromeContentRendererClient:: + WillInitializeServiceWorkerContextOnWorkerThread() { + // This is called on the service worker thread. + ThreadProfiler::StartOnChildThread( + metrics::CallStackProfileParams::Thread::kServiceWorker); } -void ChromeContentRendererClient::RunScriptsAtDocumentStart( - content::RenderFrame* render_frame) { -#if defined(ENABLE_EXTENSIONS) - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentStart( - render_frame); - // |render_frame| might be dead by now. +void ChromeContentRendererClient:: + DidInitializeServiceWorkerContextOnWorkerThread( + blink::WebServiceWorkerContextProxy* context_proxy, + const GURL& service_worker_scope, + const GURL& script_url) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance() + ->extension_dispatcher() + ->DidInitializeServiceWorkerContextOnWorkerThread( + context_proxy, service_worker_scope, script_url); #endif } -void ChromeContentRendererClient::RunScriptsAtDocumentEnd( - content::RenderFrame* render_frame) { -#if defined(ENABLE_EXTENSIONS) - ChromeExtensionsRendererClient::GetInstance()->RunScriptsAtDocumentEnd( - render_frame); - // |render_frame| might be dead by now. +void ChromeContentRendererClient::WillEvaluateServiceWorkerOnWorkerThread( + blink::WebServiceWorkerContextProxy* context_proxy, + v8::Local v8_context, + int64_t service_worker_version_id, + const GURL& service_worker_scope, + const GURL& script_url) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance() + ->extension_dispatcher() + ->WillEvaluateServiceWorkerOnWorkerThread( + context_proxy, v8_context, service_worker_version_id, + service_worker_scope, script_url); #endif } -void -ChromeContentRendererClient::DidInitializeServiceWorkerContextOnWorkerThread( - v8::Local context, - const GURL& url) { -#if defined(ENABLE_EXTENSIONS) - extensions::Dispatcher::DidInitializeServiceWorkerContextOnWorkerThread( - context, url); +void ChromeContentRendererClient::DidStartServiceWorkerContextOnWorkerThread( + int64_t service_worker_version_id, + const GURL& service_worker_scope, + const GURL& script_url) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance() + ->extension_dispatcher() + ->DidStartServiceWorkerContextOnWorkerThread( + service_worker_version_id, service_worker_scope, script_url); #endif } void ChromeContentRendererClient::WillDestroyServiceWorkerContextOnWorkerThread( v8::Local context, - const GURL& url) { -#if defined(ENABLE_EXTENSIONS) - extensions::Dispatcher::WillDestroyServiceWorkerContextOnWorkerThread(context, - url); + int64_t service_worker_version_id, + const GURL& service_worker_scope, + const GURL& script_url) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + ChromeExtensionsRendererClient::GetInstance() + ->extension_dispatcher() + ->WillDestroyServiceWorkerContextOnWorkerThread( + context, service_worker_version_id, service_worker_scope, script_url); #endif } @@ -1411,9 +1762,89 @@ void ChromeContentRendererClient::WillDestroyServiceWorkerContextOnWorkerThread( // information. Also, the enforcement of sending and binding UDP is already done // by chrome extension permission model. bool ChromeContentRendererClient::ShouldEnforceWebRTCRoutingPreferences() { -#if defined(ENABLE_EXTENSIONS) - return !IsStandaloneExtensionProcess(); + return !IsStandaloneContentExtensionProcess(); +} + +GURL ChromeContentRendererClient::OverrideFlashEmbedWithHTML(const GURL& url) { + if (!url.is_valid()) + return GURL(); + + return FlashEmbedRewrite::RewriteFlashEmbedURL(url); +} + +std::unique_ptr +ChromeContentRendererClient::CreateURLLoaderThrottleProvider( + blink::URLLoaderThrottleProviderType provider_type) { + return URLLoaderThrottleProviderImpl::Create(provider_type, this, + browser_interface_broker_.get()); +} + +blink::WebFrame* ChromeContentRendererClient::FindFrame( + blink::WebLocalFrame* relative_to_frame, + const std::string& name) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + return ChromeExtensionsRendererClient::FindFrame(relative_to_frame, name); #else + return nullptr; +#endif // BUILDFLAG(ENABLE_EXTENSIONS) +} + +bool ChromeContentRendererClient::IsSafeRedirectTarget(const GURL& from_url, + const GURL& to_url) { +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (to_url.SchemeIs(extensions::kExtensionScheme)) { + const extensions::Extension* extension = + extensions::RendererExtensionRegistry::Get()->GetByID(to_url.host()); + if (!extension) + return false; + // TODO(solomonkinard): Use initiator_origin and add tests. + if (extensions::WebAccessibleResourcesInfo::IsResourceWebAccessible( + extension, to_url.path(), nullptr)) { + return true; + } + return extension->guid() == from_url.host(); + } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) return true; +} + +void ChromeContentRendererClient::DidSetUserAgent( + const std::string& user_agent) { +#if BUILDFLAG(ENABLE_PRINTING) + printing::SetAgent(user_agent); +#endif +} + +void ChromeContentRendererClient::AppendContentSecurityPolicy( + const blink::WebURL& url, + blink::WebVector* csp) { +#if BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_PDF) + // Don't apply default CSP to PDF renderers. + // TODO(crbug.com/1252096): Lock down the CSP once style and script are no + // longer injected inline by `pdf::PluginResponseWriter`. That class may be a + // better place to define such CSP, or we may continue doing so here. + if (pdf::IsPdfRenderer()) + return; +#endif // BUILDFLAG(ENABLE_PDF) + + DCHECK(csp); + GURL gurl(url); + const extensions::Extension* extension = + extensions::RendererExtensionRegistry::Get()->GetExtensionOrAppByURL( + gurl); + if (!extension) + return; + + // Append a minimum CSP to ensure the extension can't relax the default + // applied CSP through means like Service Worker. + const std::string* default_csp = + extensions::CSPInfo::GetMinimumCSPToAppend(*extension, gurl.path()); + if (!default_csp) + return; + + csp->push_back({blink::WebString::FromUTF8(*default_csp), + network::mojom::ContentSecurityPolicyType::kEnforce, + network::mojom::ContentSecurityPolicySource::kHTTP}); #endif } diff --git a/samples/codelite-sample/README.md b/samples/codelite-sample/README.md index 5cd1b36..7c1e4b9 100644 --- a/samples/codelite-sample/README.md +++ b/samples/codelite-sample/README.md @@ -1,2 +1 @@ -Canary sample taken from codelite https://github.com/eranif/codelite -License applies as per LICENSE file in this folder +Code under src/ taken from https://github.com/eranif/codelite, licensed under the GPL2. diff --git a/samples/protobuf-sample/README.md b/samples/protobuf-sample/README.md index 9e5b335..564eab9 100644 --- a/samples/protobuf-sample/README.md +++ b/samples/protobuf-sample/README.md @@ -1,3 +1 @@ -# VLC sample - -code taken for regression testing from https://github.com/protocolbuffers/protobuf +Code under src/ taken from https://github.com/protocolbuffers/protobuf. Rights except redistribution reserved to Google. See LICENSE. diff --git a/samples/v8-sample/LICENSE b/samples/v8-sample/LICENSE index 4d04acd..bbad266 100644 --- a/samples/v8-sample/LICENSE +++ b/samples/v8-sample/LICENSE @@ -1,4 +1,4 @@ -Copyright 2006-2011, the V8 project authors. All rights reserved. +Copyright 2014, the V8 project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -24,4 +24,3 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/samples/v8-sample/README.md b/samples/v8-sample/README.md index 7cf07c7..96c5274 100644 --- a/samples/v8-sample/README.md +++ b/samples/v8-sample/README.md @@ -1,3 +1 @@ -# V8 sample - -code taken for regression testing from https://github.com/v8/v8 +Code under src/ taken from https://github.com/v8/v8. Rights except redistribution reserved to the V8 project authors. See LICENSE. diff --git a/samples/vlc-sample/README.md b/samples/vlc-sample/README.md index f9177bc..d36093e 100644 --- a/samples/vlc-sample/README.md +++ b/samples/vlc-sample/README.md @@ -1,3 +1 @@ -# VLC sample - -code taken for regression testing from https://github.com/videolan/vlc +Code under src/ taken from https://github.com/videolan/vlc, licensed under the GPL2. From 01d6baa9936f696bba84ff31f8b892872bbb60e7 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Sat, 24 Feb 2024 11:21:52 -0500 Subject: [PATCH 2/5] Update .def --- samples/chromium-sample/simple.def | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/samples/chromium-sample/simple.def b/samples/chromium-sample/simple.def index 6d0351d..ba2ab4d 100644 --- a/samples/chromium-sample/simple.def +++ b/samples/chromium-sample/simple.def @@ -5,15 +5,11 @@ Done processing src/chrome_content_renderer_client.cc Done processing src/chrome_content_renderer_client.h Done processing src/io_thread.cc Done processing src/io_thread.h -Total errors found: 21 +Total errors found: 17 -src/chrome_content_renderer_client.cc:113: Include the directory when naming header files [build/include_subdir] [4] -src/chrome_content_renderer_client.cc:1156: Use int16/int64/etc, rather than the C type long [runtime/int] [4] -src/chrome_content_renderer_client.cc:1161: Use int16/int64/etc, rather than the C type long [runtime/int] [4] -src/chrome_content_renderer_client.cc:1203: Add #include for set<> [build/include_what_you_use] [4] -src/chrome_content_renderer_client.cc:1245: Add #include for vector<> [build/include_what_you_use] [4] -src/chrome_content_renderer_client.cc:1359: Add #include for map<> [build/include_what_you_use] [4] -src/chrome_content_renderer_client.cc:1366: Add #include for string [build/include_what_you_use] [4] +src/chrome_content_renderer_client.cc:308: Add #include for vector<> [build/include_what_you_use] [4] +src/chrome_content_renderer_client.cc:1540: Add #include for set<> [build/include_what_you_use] [4] +src/chrome_content_renderer_client.cc:1841: Add #include for string [build/include_what_you_use] [4] src/chrome_content_renderer_client.cc:5: samples/chromium-sample/src/chrome_content_renderer_client.cc should include its header file samples/chromium-sample/src/chrome_content_renderer_client.h [build/include] [5] src/chrome_content_renderer_client.h:5: #ifndef header guard has wrong style, please use: SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_ [build/header_guard] [5] src/chrome_content_renderer_client.h:225: #endif line should be "#endif // SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_" [build/header_guard] [5] From a1583e28e8cecd2a563fff97798064ab89b8a1f8 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Sun, 17 Mar 2024 15:20:19 -0400 Subject: [PATCH 3/5] Add support for [[likely]] and misc brace bugfixes 1. Fixes #212 2. else statements that have braces on both sides but have the second-to-last } on a separate line will no longer claim we need braces on both sides 3. Fix single-line if statements being yelled at to split their lines, something contradictory to the style guide 4. Fixes relevant tests, including adding the new "TestLintContains" and "TestLintNotContains" methods. (ik the latter may have a grammar error but who cares, this is consistent with the former's name) 5. Add a todo for "This exception does not apply to multi-keyword statements like if ... else or do ... while." --- cpplint.py | 36 ++++++--- cpplint_unittest.py | 83 ++++++++++++++------ samples/cfg-file/simple.def | 3 +- samples/silly-sample/filters.def | 5 +- samples/silly-sample/includeorder_cfirst.def | 3 +- samples/silly-sample/sed.def | 1 - samples/silly-sample/simple.def | 3 +- test-requirements | 1 + 8 files changed, 87 insertions(+), 48 deletions(-) diff --git a/cpplint.py b/cpplint.py index a2c5b6b..46ae715 100755 --- a/cpplint.py +++ b/cpplint.py @@ -4291,11 +4291,13 @@ def CheckBraces(filename, clean_lines, linenum, error): '{ should almost always be at the end of the previous line') # An else clause should be on the same line as the preceding closing brace. - if re.match(r'\s*else\b\s*(?:if\b|\{|$)', line): + if lastWrong := re.match(r'\s*else\b\s*(?:if\b|\{|$)', line): prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] if re.match(r'\s*}\s*$', prevline): error(filename, linenum, 'whitespace/newline', 4, 'An else should appear on the same line as the preceding }') + else: + lastWrong = False # If braces come on one side of an else, they should be on both. # However, we have to worry about "else if" that spans multiple lines! @@ -4310,19 +4312,29 @@ def CheckBraces(filename, clean_lines, linenum, error): if brace_on_left != brace_on_right: # must be brace after if error(filename, linenum, 'readability/braces', 5, 'If an else has a brace on one side, it should have it on both') - elif re.search(r'}\s*else[^{]*$', line) or re.match(r'[^}]*else\s*{', line): + # Prevent detection if statement has { and we detected an improper newline after } + elif re.search(r'}\s*else[^{]*$', line) or (re.match(r'[^}]*else\s*{', line) and not lastWrong): error(filename, linenum, 'readability/braces', 5, 'If an else has a brace on one side, it should have it on both') - # Likewise, an else should never have the else clause on the same line - if re.search(r'\belse [^\s{]', line) and not re.search(r'\belse if\b', line): - error(filename, linenum, 'whitespace/newline', 4, - 'Else clause should never be on same line as else (use 2 lines)') - - # In the same way, a do/while should never be on one line - if re.match(r'\s*do [^\s{]', line): - error(filename, linenum, 'whitespace/newline', 4, - 'do/while clauses should not be on a single line') + # No control clauses with braces should have its contents on the same line + # Exclude } which will be covered by empty-block detect + # Exclude ; which may be used by while in a do-while + if keyword := re.search( + r'\b(else if|if|while|for|switch)' # These have parens + r'\s*\(.*\)\s*(?:\[\[(?:un)?likely\]\]\s*)?{\s*[^\s\\};]', line): + error(filename, linenum, 'whitespace/newline', 5, + f'Controlled statements inside brackets of {keyword.group(1)} clause' + ' should be on a separate line') + elif keyword := re.search( + r'\b(else|do|try)' # These don't have parens + r'\s*(?:\[\[(?:un)?likely\]\]\s*)?{\s*[^\s\\}]', line): + error(filename, linenum, 'whitespace/newline', 5, + f'Controlled statements inside brackets of {keyword.group(1)} clause' + ' should be on a separate line') + + # TODO: Err on if...else and do...while statements without braces; + # style guide has changed since the below comment was written # Check single-line if/else bodies. The style guide says 'curly braces are not # required for single-line statements'. We additionally allow multi-line, @@ -4342,7 +4354,7 @@ def CheckBraces(filename, clean_lines, linenum, error): (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos) # Check for an opening brace, either directly after the if or on the next # line. If found, this isn't a single-statement conditional. - if (not re.match(r'\s*{', endline[endpos:]) + if (not re.match(r'\s*(?:\[\[(?:un)?likely\]\]\s*)?{', endline[endpos:]) and not (re.match(r'\s*$', endline[endpos:]) and endlinenum < (len(clean_lines.elided) - 1) and re.match(r'\s*{', clean_lines.elided[endlinenum + 1]))): diff --git a/cpplint_unittest.py b/cpplint_unittest.py index 11d28a1..7c2f3c0 100755 --- a/cpplint_unittest.py +++ b/cpplint_unittest.py @@ -43,7 +43,7 @@ import sys import tempfile import unittest - +from parameterized import parameterized import pytest import cpplint @@ -231,6 +231,12 @@ def PerformIncludeWhatYouUse(self, code, filename='foo.h', io=codecs): error_collector, io) return error_collector.Results() + # Perform lint and make sure one of the errors is what we want + def TestLintContains(self, code, expected_message): + self.assertTrue(expected_message in self.PerformSingleLineLint(code)) + def TestLintNotContains(self, code, expected_message): + self.assertFalse(expected_message in self.PerformSingleLineLint(code)) + # Perform lint and compare the error message with "expected_message". def TestLint(self, code, expected_message): self.assertEqual(expected_message, self.PerformSingleLineLint(code)) @@ -270,7 +276,6 @@ def doTestBlankLinesCheck(self, lines, start_errors, end_errors, extension): 'Redundant blank line at the end of a code block ' 'should be deleted. [whitespace/blank_line] [3]')) - class CpplintTest(CpplintTestBase): def GetNamespaceResults(self, lines): @@ -2122,6 +2127,14 @@ def testBraces(self): { { 1, 2 }, { 3, 4 } };""", '') + self.TestMultiLineLint( # should not claim else should have braces on both sides + """if (foo) { + bar; + } + else { + baz; + }""", + 'An else should appear on the same line as the preceding } [whitespace/newline] [4]') # CHECK/EXPECT_TRUE/EXPECT_FALSE replacements def testCheckCheck(self): @@ -2363,7 +2376,9 @@ def testNonConstReference(self): operand_error_message % 'std::vector& p') # Returning an address of something is not prohibited. self.TestLint('return &something;', '') - self.TestLint('if (condition) {return &something; }', '') + self.TestLint('if (condition) {return &something; }', + 'Controlled statements inside brackets of if clause should be on a separate line' + ' [whitespace/newline] [5]') self.TestLint('if (condition) return &something;', '') self.TestLint('if (condition) address = &something;', '') self.TestLint('if (condition) result = lhs&rhs;', '') @@ -2561,8 +2576,8 @@ def testSpacingForFncall(self): self.TestLint('for (foo;bar;baz) {', 'Missing space after ;' ' [whitespace/semicolon] [3]') # we don't warn about this semicolon, at least for now - self.TestLint('if (condition) {return &something; }', - '') + self.TestLintNotContains('if (condition) { return &something; }', + 'Missing space after ; [whitespace/semicolon] [3]') # seen in some macros self.TestLint('DoSth();\\', '') # Test that there is no warning about semicolon here. @@ -2670,7 +2685,7 @@ def testSpacingBeforeBraces(self): '') def testSemiColonAfterBraces(self): - self.TestLint('if (cond) { func(); };', + self.TestLintContains('if (cond) { func(); };', 'You don\'t need a ; after a } [readability/braces] [4]') self.TestLint('void Func() {};', 'You don\'t need a ; after a } [readability/braces] [4]') @@ -2759,7 +2774,9 @@ def testBraceInitializerList(self): ' }\n' '};\n', '') self.TestMultiLineLint('if (true) {\n' - ' if (false){ func(); }\n' + ' if (false){\n' + ' func();\n' + ' }' '}\n', 'Missing space before { [whitespace/braces] [5]') self.TestMultiLineLint('MyClass::MyClass()\n' @@ -2909,8 +2926,12 @@ def testEmptyBlockBody(self): ' [whitespace/empty_if_body] [4]') self.TestMultiLineLint("""if (test) func();""", '') - self.TestLint('if (test) { hello; }', '') - self.TestLint('if (test({})) { hello; }', '') + self.TestLint('if (test) { hello; }', + 'Controlled statements inside brackets of if clause should be on a separate line' + ' [whitespace/newline] [5]') + self.TestLint('if (test({})) { hello; }', + 'Controlled statements inside brackets of if clause should be on a separate line' + ' [whitespace/newline] [5]') self.TestMultiLineLint("""if (test) { func(); }""", '') @@ -3614,16 +3635,6 @@ def testEndOfNamespaceComments(self): 'Namespace should be terminated with "// namespace no_warning"' ' [readability/namespace] [5]')) - def testElseClauseNotOnSameLineAsElse(self): - self.TestLint(' else DoSomethingElse();', - 'Else clause should never be on same line as else ' - '(use 2 lines) [whitespace/newline] [4]') - self.TestLint(' else ifDoSomethingElse();', - 'Else clause should never be on same line as else ' - '(use 2 lines) [whitespace/newline] [4]') - self.TestLint(' } else if (blah) {', '') - self.TestLint(' variable_ends_in_else = true;', '') - def testComma(self): self.TestLint('a = f(1,2);', 'Missing space after , [whitespace/comma] [3]') @@ -4001,13 +4012,6 @@ def testConditionals(self): }""", '{ should almost always be at the end of the previous line' ' [whitespace/braces] [4]') - self.TestMultiLineLint( - """ - if (foo) { \\ - bar; \\ - baz; \\ - }""", - '') self.TestMultiLineLint( """ void foo() { if (bar) baz; }""", @@ -4048,6 +4052,33 @@ def testConditionals(self): #endif""", '') + @parameterized.expand(['else if', 'if', 'while', 'for', 'switch']) + def testControlClauseWithParensNewline(self, keyword): + # The % 2 part is pseudorandom whitespace-support testing + self.TestLintContains( + f'{keyword}{["", " "][len(keyword) % 2]}(condition)' + f'{[" ", ""][len(keyword) % 2]}[[unlikely]]' + f'{[" ", ""][len(keyword) % 2]}{{' + f'{["", " "][len(keyword) % 2]}do_something(); }}', + f'Controlled statements inside brackets of {keyword} clause' + f' should be on a separate line [whitespace/newline] [5]' + ) + + @parameterized.expand(['else', 'do', 'try']) + def testControlClauseWithoutParensNewline(self, keyword): + # The % 2 part is pseudorandom whitespace-support testing + self.TestLintContains( + f'{keyword}{["", " "][len(keyword) % 2]}{{' + f'{[" ", ""][len(keyword) % 2]}do_something(); }}', + f'Controlled statements inside brackets of {keyword} clause' + f' should be on a separate line [whitespace/newline] [5]' + ) + + def testControlClauseNewlineNameFalsePositives(self): + self.TestLint(' else if_condition_do_something();', '') + self.TestLint(' } else if (blah) {', '') + self.TestLint(' variable_ends_in_else = true;', '') + def testTab(self): self.TestLint('\tint a;', 'Tab found; better to use spaces [whitespace/tab] [1]') diff --git a/samples/cfg-file/simple.def b/samples/cfg-file/simple.def index f3d9b18..2a9c3f2 100644 --- a/samples/cfg-file/simple.def +++ b/samples/cfg-file/simple.def @@ -2,7 +2,7 @@ src/*.cpp 1 3 Done processing src/sillycode.cpp -Total errors found: 19 +Total errors found: 18 src/sillycode.cpp:0: No copyright message found. You should have a line: "Copyright [year] " [legal/copyright] [5] src/sillycode.cpp:3: Found C system header after C++ system header. Should be: sillycode.h, c system, c++ system, other. [build/include_order] [4] @@ -18,7 +18,6 @@ src/sillycode.cpp:123: Is this a non-const reference? If so, make const or use src/sillycode.cpp:171: Do not use variable-length arrays. Use an appropriately named ('k' followed by CamelCase) compile-time constant for the size. [runtime/arrays] [1] src/sillycode.cpp:178: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:199: If an else has a brace on one side, it should have it on both [readability/braces] [5] -src/sillycode.cpp:202: If an else has a brace on one side, it should have it on both [readability/braces] [5] src/sillycode.cpp:208: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:227: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:228: Using C-style cast. Use reinterpret_cast(...) instead [readability/casting] [4] diff --git a/samples/silly-sample/filters.def b/samples/silly-sample/filters.def index e420e15..85f4150 100644 --- a/samples/silly-sample/filters.def +++ b/samples/silly-sample/filters.def @@ -4,9 +4,9 @@ Done processing src/sillycode.cpp Category 'build' errors found: 1 Category 'legal' errors found: 1 -Category 'readability' errors found: 5 +Category 'readability' errors found: 4 Category 'runtime' errors found: 12 -Total errors found: 19 +Total errors found: 18 src/sillycode.cpp:0: No copyright message found. You should have a line: "Copyright [year] " [legal/copyright] [5] src/sillycode.cpp:3: Found C system header after C++ system header. Should be: sillycode.h, c system, c++ system, other. [build/include_order] [4] @@ -22,7 +22,6 @@ src/sillycode.cpp:123: Is this a non-const reference? If so, make const or use src/sillycode.cpp:171: Do not use variable-length arrays. Use an appropriately named ('k' followed by CamelCase) compile-time constant for the size. [runtime/arrays] [1] src/sillycode.cpp:178: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:199: If an else has a brace on one side, it should have it on both [readability/braces] [5] -src/sillycode.cpp:202: If an else has a brace on one side, it should have it on both [readability/braces] [5] src/sillycode.cpp:208: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:227: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:228: Using C-style cast. Use reinterpret_cast(...) instead [readability/casting] [4] diff --git a/samples/silly-sample/includeorder_cfirst.def b/samples/silly-sample/includeorder_cfirst.def index f0e5ada..220f1a5 100644 --- a/samples/silly-sample/includeorder_cfirst.def +++ b/samples/silly-sample/includeorder_cfirst.def @@ -2,7 +2,7 @@ 1 3 Done processing src/sillycode.cpp -Total errors found: 111 +Total errors found: 110 src/sillycode.cpp:0: No copyright message found. You should have a line: "Copyright [year] " [legal/copyright] [5] src/sillycode.cpp:8: public: should be indented +1 space inside class Date [whitespace/indent] [3] @@ -79,7 +79,6 @@ src/sillycode.cpp:197: Tab found; better to use spaces [whitespace/tab] [1] src/sillycode.cpp:197: At least two spaces is best between code and comments [whitespace/comments] [2] src/sillycode.cpp:199: If an else has a brace on one side, it should have it on both [readability/braces] [5] src/sillycode.cpp:202: An else should appear on the same line as the preceding } [whitespace/newline] [4] -src/sillycode.cpp:202: If an else has a brace on one side, it should have it on both [readability/braces] [5] src/sillycode.cpp:208: Missing space before { [whitespace/braces] [5] src/sillycode.cpp:208: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:209: Tab found; better to use spaces [whitespace/tab] [1] diff --git a/samples/silly-sample/sed.def b/samples/silly-sample/sed.def index 47c910d..df0792e 100644 --- a/samples/silly-sample/sed.def +++ b/samples/silly-sample/sed.def @@ -79,7 +79,6 @@ sed -i '208s/\([^ ]\){/\1 {/' src/sillycode.cpp # Missing space before { [white # src/sillycode.cpp:197: "At least two spaces is best between code and comments" [whitespace/comments] [2] # src/sillycode.cpp:199: "If an else has a brace on one side, it should have it on both" [readability/braces] [5] # src/sillycode.cpp:202: "An else should appear on the same line as the preceding }" [whitespace/newline] [4] -# src/sillycode.cpp:202: "If an else has a brace on one side, it should have it on both" [readability/braces] [5] # src/sillycode.cpp:208: "Static/global string variables are not permitted." [runtime/string] [4] # src/sillycode.cpp:209: "Tab found; better to use spaces" [whitespace/tab] [1] # src/sillycode.cpp:209: "At least two spaces is best between code and comments" [whitespace/comments] [2] diff --git a/samples/silly-sample/simple.def b/samples/silly-sample/simple.def index 0e4b5a1..36126dc 100644 --- a/samples/silly-sample/simple.def +++ b/samples/silly-sample/simple.def @@ -2,7 +2,7 @@ src/*.cpp 1 3 Done processing src/sillycode.cpp -Total errors found: 112 +Total errors found: 111 src/sillycode.cpp:0: No copyright message found. You should have a line: "Copyright [year] " [legal/copyright] [5] src/sillycode.cpp:3: Found C system header after C++ system header. Should be: sillycode.h, c system, c++ system, other. [build/include_order] [4] @@ -80,7 +80,6 @@ src/sillycode.cpp:197: Tab found; better to use spaces [whitespace/tab] [1] src/sillycode.cpp:197: At least two spaces is best between code and comments [whitespace/comments] [2] src/sillycode.cpp:199: If an else has a brace on one side, it should have it on both [readability/braces] [5] src/sillycode.cpp:202: An else should appear on the same line as the preceding } [whitespace/newline] [4] -src/sillycode.cpp:202: If an else has a brace on one side, it should have it on both [readability/braces] [5] src/sillycode.cpp:208: Missing space before { [whitespace/braces] [5] src/sillycode.cpp:208: Static/global string variables are not permitted. [runtime/string] [4] src/sillycode.cpp:209: Tab found; better to use spaces [whitespace/tab] [1] diff --git a/test-requirements b/test-requirements index 20bbcf7..4ff32e3 100644 --- a/test-requirements +++ b/test-requirements @@ -5,3 +5,4 @@ tox<5.0.0 pytest pytest-cov testfixtures +parameterized From 0ae2017106b97fd634a718b8969fe2155a22e701 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Mon, 1 Jul 2024 16:42:17 -0400 Subject: [PATCH 4/5] Remove Python 3.7 (EOL) support and update changelog Needed to use the `:=` operator --- .github/workflows/ci.yml | 4 ++-- changelog.rst | 6 ++++-- setup.py | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f740d1d..0fcd906 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,8 +13,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - # Python 3.7 is the lowest available for actions/setup-python - python-version: ['3.7', 'pypy3.10', '3.12'] + # Python 3.8 is the last non-EOL version + python-version: ['3.8', 'pypy3.10', '3.12'] os: [ubuntu-latest, windows-latest] fail-fast: false diff --git a/changelog.rst b/changelog.rst index 7182d32..4d04e8e 100644 --- a/changelog.rst +++ b/changelog.rst @@ -7,17 +7,18 @@ Changelog A bunch of long-overdue modernizations of the codebase! -* Python 2 is no longer supported. Python 3.7 and 3.12 support was added, courtesy of @jayvdb +* Python 2 is no longer supported. Python 3.12 support was added along with fixed CI for 3.7 and 3.8, courtesy of @jayvdb * As a result of all this, setup.py's lint subcommand was removed. Please run the commands directly instead. * You can now specify blocks of code that exclude linting with NOLINTBEGIN and NOLINTEND, courtesy of @n3world (https://github.com/cpplint/cpplint/pull/213) * The `--filter` option can now be only applied to a specific file or even a specific line through utilizing colons, e.g. `-filter=-whitespace:foo.h,+whitespace/braces:foo.h:418`. Courtesy of @PhilLab (https://github.com/cpplint/cpplint/pull/171) * NOLINT and NOLINTNEXTLINE comments now support a comma-separated list of categories, courtesy of @n3world (https://github.com/cpplint/cpplint/pull/220) * NOLINT and NOLINTNEXTLINE will now ignore categories known to be from clang-tidy thanks to @xatier (https://github.com/cpplint/cpplint/pull/231) -* Fix behavior with nested source repositories by @groegeorg (https://github.com/cpplint/cpplint/pull/78) +* Fixed behavior with nested source repositories by @groegeorg (https://github.com/cpplint/cpplint/pull/78) * build/include-what-you-use no longer supports transitive headers from the header for the current module for parity with the style guide by @aaronliu0130 * build/include-what-you-use now supports a plethora of new functions, courtesy of @geoffviola (https://github.com/cpplint/cpplint/pull/94) * build/include-what-you-use will no longer err on similarly-named classes from other namespaces thanks to @geoffviola (https://github.com/cpplint/cpplint/pull/273) * Indented functions inside namespaces will now be correctly erred on, courtesy of @Yujinmon (https://github.com/cpplint/cpplint/pull/235) +* `[[(un)likely]]` no longer clouds readability/braces's super spy−scanning of braces, courtesy of @aaronliu0130 (https://github.com/cpplint/cpplint/pull/265) * C++20 headers will no longer be flagged as C headers thanks to @miker2 (https://github.com/cpplint/cpplint/pull/216) * Same goes for C++23 and C23 headers, thanks to @aaronliu0130 (https://github.com/cpplint/cpplint/pull/239) * "complex.h" will be treated as the C99 header instead of the legacy C++ header by @tkruse (https://github.com/cpplint/cpplint/pull/219) @@ -29,6 +30,7 @@ A bunch of long-overdue modernizations of the codebase! * You can now specify the name of the CPPLINT.cfg file through `--config` as long as it is in the same directory, thanks to @gedankenexperimenter (https://github.com/cpplint/cpplint/pull/198) * The new __VA_OPT__(,) will now be recognized by the Whitespace linter as a function thanks to @elrinor (https://github.com/cpplint/cpplint/pull/237) * The check for including a source file's header file will now scan all files with the same base name. Thanks to @crogre for figuring out what code needed to be changed and @aaronliu0130 for fixing it (https://github.com/cpplint/cpplint/pull/104) +* Fixed false positive when an if/else statement has braces everywhere but one of the closing braces before the final block is on a separate line by @aaronliu0130 (https://github.com/cpplint/cpplint/pull/265) * Usages of the deprecated sre_compile were refectored by @jspricke (https://github.com/cpplint/cpplint/pull/214) * Usages of deprecated unittest aliases were refactored by @tirkarthi (https://github.com/cpplint/cpplint/pull/182), @aaronliu0130 and @jayvdb * Typos in this changelog, comments and functions were fixed by @jayvdb (https://github.com/cpplint/cpplint/pull/245), @aaronliu0130 and @tkruse diff --git a/setup.py b/setup.py index a567f02..cf4dbe4 100755 --- a/setup.py +++ b/setup.py @@ -31,7 +31,6 @@ def read_without_comments(filename): 'License :: OSI Approved :: BSD License', 'Natural Language :: English', 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', From 36ca2407f2223ef8c1e77a53f171c08dd2ca3723 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Mon, 1 Jul 2024 16:44:02 -0400 Subject: [PATCH 5/5] Fix varname (again) ...to our varname style guide. Was previously 534a142 but I forgot to pull from my own branch. Darn... Early-onset dementia? *knocks on wood* --- cpplint.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpplint.py b/cpplint.py index 93b650b..7723d00 100755 --- a/cpplint.py +++ b/cpplint.py @@ -4371,13 +4371,13 @@ def CheckBraces(filename, clean_lines, linenum, error): '{ should almost always be at the end of the previous line') # An else clause should be on the same line as the preceding closing brace. - if lastWrong := re.match(r'\s*else\b\s*(?:if\b|\{|$)', line): + if last_wrong := re.match(r'\s*else\b\s*(?:if\b|\{|$)', line): prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] if re.match(r'\s*}\s*$', prevline): error(filename, linenum, 'whitespace/newline', 4, 'An else should appear on the same line as the preceding }') else: - lastWrong = False + last_wrong = False # If braces come on one side of an else, they should be on both. # However, we have to worry about "else if" that spans multiple lines! @@ -4393,7 +4393,7 @@ def CheckBraces(filename, clean_lines, linenum, error): error(filename, linenum, 'readability/braces', 5, 'If an else has a brace on one side, it should have it on both') # Prevent detection if statement has { and we detected an improper newline after } - elif re.search(r'}\s*else[^{]*$', line) or (re.match(r'[^}]*else\s*{', line) and not lastWrong): + elif re.search(r'}\s*else[^{]*$', line) or (re.match(r'[^}]*else\s*{', line) and not last_wrong): error(filename, linenum, 'readability/braces', 5, 'If an else has a brace on one side, it should have it on both')