Add files via upload

This commit is contained in:
Alexander David Frick 2022-07-09 18:40:45 -05:00 committed by GitHub
parent e9949692a1
commit 6642d36c48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 9985 additions and 0 deletions

View file

@ -0,0 +1,39 @@
// Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 192,
PATH_COLOR_ARGB, 0xFF, 0x1A, 0x73, 0xE8,
CIRCLE, 96, 96, 96,
NEW_PATH,
PATH_COLOR_ARGB, 0xFF, 0x00, 0x00, 0x00,
MOVE_TO, 149, 67,
CUBIC_TO, 149, 62.58f, 145.42f, 59, 141, 59,
LINE_TO, 50, 59,
CUBIC_TO, 45.58f, 59, 42, 62.58f, 42, 67,
LINE_TO, 42, 132,
CUBIC_TO, 42, 136.42f, 45.58f, 140, 50, 140,
LINE_TO, 141, 140,
CUBIC_TO, 145.42f, 140, 149, 136.42f, 149, 132,
LINE_TO, 149, 67,
NEW_PATH,
PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
MOVE_TO, 50, 52,
CUBIC_TO, 45.58f, 52, 42, 55.58f, 42, 60,
V_LINE_TO, 132,
CUBIC_TO, 42, 136.42f, 45.58f, 140, 50, 140,
H_LINE_TO, 141.13f,
CUBIC_TO, 145.55f, 140, 149.13f, 136.42f, 149.13f, 132,
V_LINE_TO, 125.13f,
LINE_TO, 76, 52,
H_LINE_TO, 50,
NEW_PATH,
PATH_COLOR_ARGB, 0xFF, 0x80, 0xF9, 0xF9,
R_MOVE_TO, 149, 77,
R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
R_H_LINE_TO, -99,
R_V_LINE_TO, 63,
R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
R_H_LINE_TO, 91,
R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
CLOSE

View file

@ -0,0 +1,45 @@
// Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 40,
PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x04,
MOVE_TO, 20, 4,
CUBIC_TO, 11.17f, 4, 4, 11.17f, 4, 20,
R_CUBIC_TO, 0, 8.83f, 7.17f, 16, 16, 16,
R_CUBIC_TO, 8.83f, 0, 16, -7.17f, 16, -16,
CUBIC_TO_SHORTHAND, 28.83f, 4, 20, 4,
CLOSE,
R_MOVE_TO, 1, 23,
R_H_LINE_TO, -3,
R_V_LINE_TO, -9,
R_H_LINE_TO, 3,
R_V_LINE_TO, 9,
CLOSE,
R_MOVE_TO, 0, -12,
R_H_LINE_TO, -3,
R_V_LINE_TO, -3,
R_H_LINE_TO, 3,
R_V_LINE_TO, 3,
CLOSE
CANVAS_DIMENSIONS, 20,
PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x04,
MOVE_TO, 10, 2,
R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
CLOSE,
R_MOVE_TO, 1, 12,
H_LINE_TO, 9,
V_LINE_TO, 9,
R_H_LINE_TO, 2,
R_V_LINE_TO, 5,
CLOSE,
R_MOVE_TO, 0, -6,
H_LINE_TO, 9,
V_LINE_TO, 6,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
CLOSE

View file

@ -0,0 +1,30 @@
// Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x04,
MOVE_TO, 10, 2,
R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
R_CUBIC_TO, 0, 4.42f, -3.58f, 8, -8, 8,
R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
R_CUBIC_TO, 0, -4.42f, 3.58f, -8, 8, -8,
CLOSE,
R_MOVE_TO, 0, 14,
R_CUBIC_TO, 3.31f, 0, 6, -2.69f, 6, -6,
R_CUBIC_TO, 0, -3.31f, -2.69f, -6, -6, -6,
R_CUBIC_TO, -3.31f, 0, -6, 2.69f, -6, 6,
R_CUBIC_TO, 0, 3.31f, 2.69f, 6, 6, 6,
CLOSE,
R_MOVE_TO, -1, -2,
R_V_LINE_TO, -4,
R_H_LINE_TO, 2,
R_V_LINE_TO, 4,
H_LINE_TO, 9,
CLOSE,
R_MOVE_TO, 0, -6,
V_LINE_TO, 6,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
H_LINE_TO, 9,
CLOSE

173
src/base/win/shortcut.h Normal file
View file

@ -0,0 +1,173 @@
// Copyright (c) 2022 The Chromium Authors and Alex313031. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_WIN_SHORTCUT_H_
#define BASE_WIN_SHORTCUT_H_
#include <guiddef.h>
#include <stdint.h>
#include "base/base_export.h"
#include "base/check.h"
#include "base/files/file_path.h"
namespace base {
namespace win {
enum class ShortcutOperation {
// Create a new shortcut (overwriting if necessary).
kCreateAlways = 0,
// Overwrite an existing shortcut (fails if the shortcut doesn't exist).
// If the arguments are not specified on the new shortcut, keep the old
// shortcut's arguments.
kReplaceExisting,
// Update specified properties only on an existing shortcut.
kUpdateExisting,
};
// Properties for shortcuts. Properties set will be applied to the shortcut on
// creation/update, others will be ignored.
// Callers are encouraged to use the setters provided which take care of
// setting |options| as desired.
struct BASE_EXPORT ShortcutProperties {
using IndividualProperties = uint32_t;
static constexpr IndividualProperties PROPERTIES_TARGET = 1U << 0;
static constexpr IndividualProperties PROPERTIES_WORKING_DIR = 1U << 1;
static constexpr IndividualProperties PROPERTIES_ARGUMENTS = 1U << 2;
static constexpr IndividualProperties PROPERTIES_DESCRIPTION = 1U << 3;
static constexpr IndividualProperties PROPERTIES_ICON = 1U << 4;
static constexpr IndividualProperties PROPERTIES_APP_ID = 1U << 5;
static constexpr IndividualProperties PROPERTIES_DUAL_MODE = 1U << 6;
static constexpr IndividualProperties PROPERTIES_TOAST_ACTIVATOR_CLSID = 1U
<< 7;
// Be sure to update the values below when adding a new property.
static constexpr IndividualProperties PROPERTIES_ALL =
PROPERTIES_TARGET | PROPERTIES_WORKING_DIR | PROPERTIES_ARGUMENTS |
PROPERTIES_DESCRIPTION | PROPERTIES_ICON | PROPERTIES_APP_ID |
PROPERTIES_DUAL_MODE | PROPERTIES_TOAST_ACTIVATOR_CLSID;
ShortcutProperties();
ShortcutProperties(const ShortcutProperties& other);
~ShortcutProperties();
void set_target(const FilePath& target_in) {
target = target_in;
options |= PROPERTIES_TARGET;
}
void set_working_dir(const FilePath& working_dir_in) {
working_dir = working_dir_in;
options |= PROPERTIES_WORKING_DIR;
}
void set_arguments(const std::wstring& arguments_in) {
arguments = arguments_in;
options |= PROPERTIES_ARGUMENTS;
}
void set_description(const std::wstring& description_in);
void set_icon(const FilePath& icon_in, int icon_index_in) {
icon = icon_in;
icon_index = icon_index_in;
options |= PROPERTIES_ICON;
}
void set_app_id(const std::wstring& app_id_in) {
app_id = app_id_in;
options |= PROPERTIES_APP_ID;
}
void set_dual_mode(bool dual_mode_in) {
dual_mode = dual_mode_in;
options |= PROPERTIES_DUAL_MODE;
}
void set_toast_activator_clsid(const CLSID& toast_activator_clsid_in) {
toast_activator_clsid = toast_activator_clsid_in;
options |= PROPERTIES_TOAST_ACTIVATOR_CLSID;
}
// The target to launch from this shortcut. This is mandatory when creating
// a shortcut.
FilePath target;
// The name of the working directory when launching the shortcut.
FilePath working_dir;
// The arguments to be applied to |target| when launching from this shortcut.
std::wstring arguments = (L"--autoplay-policy=user-gesture-required");
// The localized description of the shortcut.
// The length of this string must be no larger than INFOTIPSIZE.
std::wstring description;
// The path to the icon (can be a dll or exe, in which case |icon_index| is
// the resource id).
FilePath icon;
int icon_index = -1;
// The app model id for the shortcut.
std::wstring app_id;
// Whether this is a dual mode shortcut (Win8+).
bool dual_mode = false;
// The CLSID of the COM object registered with the OS via the shortcut. This
// is for app activation via user interaction with a toast notification in the
// Action Center. (Win10 version 1607, build 14393, and beyond).
CLSID toast_activator_clsid;
// Bitfield made of IndividualProperties. Properties set in |options| will be
// set on the shortcut, others will be ignored.
uint32_t options = 0U;
};
// This method creates (or updates) a shortcut link at `shortcut_path` using the
// information given through `properties`.
// Ensure you have initialized COM before calling into this function.
// `operation`: a choice from the ShortcutOperation enum.
// If `operation` is kReplaceExisting or kUpdateExisting and
// `shortcut_path` does not exist, this method is a no-op and returns false.
BASE_EXPORT bool CreateOrUpdateShortcutLink(
const FilePath& shortcut_path,
const ShortcutProperties& properties,
ShortcutOperation operation);
// Resolves Windows shortcut (.LNK file).
// This methods tries to resolve selected properties of a shortcut .LNK file.
// The path of the shortcut to resolve is in |shortcut_path|. |options| is a bit
// field composed of ShortcutProperties::IndividualProperties, to specify which
// properties to read. It should be non-0. The resulting data are read into
// |properties|, which must not be NULL. Note: PROPERTIES_TARGET will retrieve
// the target path as stored in the shortcut but won't attempt to resolve that
// path so it may not be valid. The function returns true if all requested
// properties are successfully read. Otherwise some reads have failed and
// intermediate values written to |properties| should be ignored.
BASE_EXPORT bool ResolveShortcutProperties(const FilePath& shortcut_path,
uint32_t options,
ShortcutProperties* properties);
// Resolves Windows shortcut (.LNK file).
// This is a wrapper to ResolveShortcutProperties() to handle the common use
// case of resolving target and arguments. |target_path| and |args| are
// optional output variables that are ignored if NULL (but at least one must be
// non-NULL). The function returns true if all requested fields are found
// successfully. Callers can safely use the same variable for both
// |shortcut_path| and |target_path|.
BASE_EXPORT bool ResolveShortcut(const FilePath& shortcut_path,
FilePath* target_path,
std::wstring* args);
// Pin to taskbar is only supported on Windows 7 and Windows 8. Returns true on
// those platforms.
BASE_EXPORT bool CanPinShortcutToTaskbar();
// Pins a shortcut to the taskbar on Windows 7 and 8. The |shortcut| file must
// already exist and be a shortcut that points to an executable. The app id of
// the shortcut is used to group windows and must be set correctly.
BASE_EXPORT bool PinShortcutToTaskbar(const FilePath& shortcut);
// Unpins a shortcut from the Windows 7+ taskbar. The |shortcut| must exist and
// already be pinned to the taskbar. The app id of the shortcut is used as the
// identifier for the taskbar item to remove and must be set correctly.
BASE_EXPORT bool UnpinShortcutFromTaskbar(const FilePath& shortcut);
} // namespace win
} // namespace base
#endif // BASE_WIN_SHORTCUT_H_

148
src/build/config/arm.gni Normal file
View file

@ -0,0 +1,148 @@
# Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/v8_target_cpu.gni")
# These are primarily relevant in current_cpu == "arm" contexts, where
# ARM code is being compiled. But they can also be relevant in the
# other contexts when the code will change its behavior based on the
# cpu it wants to generate code for.
if (current_cpu == "arm" || v8_current_cpu == "arm") {
declare_args() {
# Version of the ARM processor when compiling on ARM. Ignored on non-ARM
# platforms.
arm_version = 8
# The ARM architecture. This will be a string like "armv6" or "armv7-a".
# An empty string means to use the default for the arm_version.
arm_arch = "armv8.5-a"
# The ARM floating point hardware. This will be a string like "neon" or
# "vfpv3". An empty string means to use the default for the arm_version.
arm_fpu = ""
# The ARM variant-specific tuning mode. This will be a string like "armv6"
# or "cortex-a15". An empty string means to use the default for the
# arm_version.
arm_tune = "armv8.5-a"
# Whether to use the neon FPU instruction set or not.
arm_use_neon = "true"
# Whether to enable optional NEON code paths.
arm_optionally_use_neon = true
# Thumb is a reduced instruction set available on some ARM processors that
# has increased code density.
arm_use_thumb = true
}
if (current_os == "android" || target_os == "android") {
arm_float_abi = "softfp"
} else {
declare_args() {
# The ARM floating point mode. This is either the string "hard", "soft",
# or "softfp". An empty string means to use the default one for the
# arm_version.
arm_float_abi = ""
}
}
assert(arm_float_abi == "" || arm_float_abi == "hard" ||
arm_float_abi == "soft" || arm_float_abi == "softfp")
if (arm_use_neon == "") {
if (current_os == "linux" && target_cpu != v8_target_cpu) {
# Don't use neon on V8 simulator builds as a default.
arm_use_neon = false
} else {
arm_use_neon = true
}
}
if (arm_version == 6) {
if (arm_arch == "") {
# v8 can still with version 6 but only with the armv6k extension.
arm_arch = "armv6k"
}
if (arm_tune != "") {
arm_tune = ""
}
if (arm_float_abi == "") {
arm_float_abi = "softfp"
}
if (arm_fpu == "") {
arm_fpu = "vfp"
}
arm_use_thumb = false
arm_use_neon = false
} else if (arm_version == 7) {
if (arm_arch == "") {
arm_arch = "armv7-a"
}
if (arm_tune == "") {
arm_tune = "generic-armv7-a"
}
if (arm_float_abi == "") {
if (current_os == "linux" && target_cpu != v8_target_cpu) {
# Default to the same as Android for V8 simulator builds.
arm_float_abi = "softfp"
} else {
arm_float_abi = "hard"
}
}
if (arm_fpu == "") {
if (arm_use_neon) {
arm_fpu = "neon"
} else {
arm_fpu = "vfpv3-d16"
}
}
} else if (arm_version == 8) {
if (arm_arch == "") {
arm_arch = "armv8-a"
}
if (arm_tune == "") {
arm_tune = "generic-armv8-a"
}
if (arm_float_abi == "") {
arm_float_abi = "hard"
}
if (arm_fpu == "") {
if (arm_use_neon) {
arm_fpu = "neon"
} else {
arm_fpu = "vfpv3-d16"
}
}
}
} else if (current_cpu == "arm64" || v8_current_cpu == "arm64") {
# arm64 supports only "hard".
arm_float_abi = "hard"
arm_use_neon = true
declare_args() {
# Enables the new Armv8 branch protection features. Valid strings are:
# - "pac": Enables Pointer Authentication Code (PAC, featured in Armv8.3)
# - "standard": Enables both PAC and Branch Target Identification (Armv8.5).
# - "none": No branch protection.
arm_control_flow_integrity = "standard"
# TODO(cavalcantii): enable the feature for the following OSes next.
if (is_mac || is_chromeos || is_fuchsia || is_win ||
target_cpu != "arm64") {
# target_cpu != "arm64" covers some cases (e.g. the ChromeOS x64 MSAN
# build) where the target platform is x64, but V8 is configured to use
# the arm64 simulator. Pointer authentication doesn't work properly
# in this mode (yet).
arm_control_flow_integrity = "none"
}
}
assert(arm_control_flow_integrity == "none" ||
arm_control_flow_integrity == "standard" ||
arm_control_flow_integrity == "pac",
"Invalid branch protection option")
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,157 @@
# Copyright (c) 2022 The Chromium Authors and Alex313031. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/apple/symbols.gni")
import("//build/config/c++/c++.gni")
import("//build/config/mac/mac_sdk.gni")
import("//build/config/sysroot.gni")
import("//build/toolchain/goma.gni")
import("//build/toolchain/rbe.gni")
# This is included by reference in the //build/config/compiler config that
# is applied to all targets. It is here to separate out the logic.
config("compiler") {
# These flags are shared between the C compiler and linker.
common_mac_flags = []
# CPU architecture.
if (current_cpu == "x64") {
clang_arch = "x86_64"
} else if (current_cpu == "x86") {
clang_arch = "i386"
} else if (current_cpu == "arm64") {
clang_arch = current_cpu
} else {
assert(false, "unknown current_cpu $current_cpu")
}
if (host_os == "mac") {
common_mac_flags += [
"-arch",
clang_arch,
]
} else {
common_mac_flags += [ "--target=$clang_arch-apple-macos" ]
}
# This is here so that all files get recompiled after an Xcode update.
# (defines are passed via the command line, and build system rebuild things
# when their commandline changes). Nothing should ever read this define.
defines = [ "CR_XCODE_VERSION=$xcode_version" ]
asmflags = [ "-O3", ] + common_mac_flags
cflags = [ "-O3", ] + common_mac_flags
# Without this, the constructors and destructors of a C++ object inside
# an Objective C struct won't be called, which is very bad.
cflags_objcc = [ "-fobjc-call-cxx-cdtors" ]
ldflags = [ "-Wl,-O3", ] + common_mac_flags
if (target_cpu == "x64") {
cflags += [ "-maes", "-mavx", "-mavx2", "-ffp-contract=fast", "-mf16c", "-mfma", "-Wno-unused-command-line-argument", ]
}
if (current_cpu == "x64") {
cflags += [ "-maes", "-mavx", "-mavx2", "-ffp-contract=fast", "-mf16c", "-mfma", "-Wno-unused-command-line-argument", ]
}
if (save_unstripped_output) {
ldflags += [ "-Wcrl,unstripped," + rebase_path(root_out_dir) ]
}
if (export_libcxxabi_from_executables) {
ldflags += [ "-Wl,-undefined,dynamic_lookup" ]
}
}
# This is included by reference in the //build/config/compiler:runtime_library
# config that is applied to all targets. It is here to separate out the logic
# that is Mac-only. Please see that target for advice on what should go in
# :runtime_library vs. :compiler.
config("runtime_library") {
common_flags = [
"-isysroot",
rebase_path(sysroot, root_build_dir),
"-mmacos-version-min=$mac_deployment_target",
]
asmflags = common_flags
cflags = common_flags
ldflags = common_flags
# Prevent Mac OS X AssertMacros.h (included by system header) from defining
# macros that collide with common names, like 'check', 'require', and
# 'verify'.
# http://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/AssertMacros.h
defines = [ "__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0" ]
}
# On Mac, this is used for everything except static libraries.
config("mac_dynamic_flags") {
ldflags = [ "-Wl,-ObjC", "-Wl,-O3", ] # Always load Objective-C categories and classes.
if (is_component_build) {
ldflags += [
# Path for loading shared libraries for unbundled binaries.
"-Wl,-rpath,@loader_path/.",
# Path for loading shared libraries for bundled binaries. Get back from
# Binary.app/Contents/MacOS.
"-Wl,-rpath,@loader_path/../../..",
]
# Path for loading shared libraries for unbundled binaries for
# the host toolchain (see https://crbug.com/1315433). Only used
# for when building for iOS.
if (target_os == "ios" && current_toolchain == host_toolchain) {
ldflags += [
"-Wl,-rpath,@loader_path/" +
rebase_path(get_label_info(":mac_dynamic_flags", "root_out_dir"),
root_build_dir),
]
}
}
}
# The ldflags referenced below are handled by
# //build/toolchain/apple/linker_driver.py.
# Remove this config if a target wishes to change the arguments passed to the
# strip command during linking. This config by default strips all symbols
# from a binary, but some targets may wish to specify an exports file to
# preserve specific symbols.
config("strip_all") {
if (enable_stripping) {
ldflags = [ "-Wcrl,strip,-x,-S", "-Wl,-O3", ]
}
}
# When building with Goma, all inputs must be relative to the build directory.
# If using the system Xcode, which typically resides outside the build root, a
# symlink to the SDK is created in the build directory, and the path to that
# link is stored in $mac_sdk_path. If an action references a file in the SDK as
# an input, GN will complain that no target generates the file because it is
# below the $root_build_dir. The below action lists as outputs the files in the
# SDK that are referenced as inputs to actions, so that GN thinks a target has
# generated them. The list is centralized here, as multiple targets need to
# reference the same files, and an output can only be generated once.
#
# The symbolic link for $mac_sdk_path is set up by
# //build/config/apple/sdk_info.py in //build/config/mac/mac_sdk.gni.
if (use_system_xcode && (use_goma || use_remoteexec) && target_os == "mac" &&
current_toolchain == default_toolchain) {
action("sdk_inputs") {
script = "//build/noop.py"
outputs = [
"$mac_sdk_path/usr/include/mach/exc.defs",
"$mac_sdk_path/usr/include/mach/mach_exc.defs",
"$mac_sdk_path/usr/include/mach/notify.defs",
]
}
} else {
group("sdk_inputs") {
if (current_toolchain != default_toolchain) {
public_deps = [ ":sdk_inputs($default_toolchain)" ]
}
}
}

View file

@ -0,0 +1,614 @@
# Copyright (c) 2022 The Chromium Authors and Alex313031. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/c++/c++.gni")
import("//build/config/chrome_build.gni")
import("//build/config/clang/clang.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/win/control_flow_guard.gni")
import("//build/config/win/visual_studio_version.gni")
import("//build/timestamp.gni")
import("//build/toolchain/goma.gni")
import("//build/toolchain/toolchain.gni")
assert(is_win)
declare_args() {
# Turn this on to have the linker output extra timing information.
win_linker_timing = false
# possible values for target_winuwp_version:
# "10" - Windows UWP 10
# "8.1" - Windows RT 8.1
# "8.0" - Windows RT 8.0
target_winuwp_version = "10"
# possible values:
# "app" - Windows Store Applications
# "phone" - Windows Phone Applications
# "system" - Windows Drivers and Tools
# "server" - Windows Server Applications
# "desktop" - Windows Desktop Applications
target_winuwp_family = "app"
# Set this to use clang-style diagnostics format instead of MSVC-style, which
# is useful in e.g. Emacs compilation mode.
# E.g.:
# Without this, clang emits a diagnostic message like this:
# foo/bar.cc(12,34): error: something went wrong
# and with this switch, clang emits it like this:
# foo/bar.cc:12:34: error: something went wrong
use_clang_diagnostics_format = false
# Indicates whether to use /pdbpagesize:8192 to allow PDBs larger than 4 GiB.
# This requires updated debugging and profiling tools which are not widely
# distributed yet which is why it is currently opt-in.
use_large_pdbs = false
}
# This is included by reference in the //build/config/compiler config that
# is applied to all targets. It is here to separate out the logic that is
# Windows-only.
config("compiler") {
if (current_cpu == "x86") {
asmflags = [
# When /safeseh is specified, the linker will only produce an image if it
# can also produce a table of the image's safe exception handlers. This
# table specifies for the operating system which exception handlers are
# valid for the image. Note that /SAFESEH isn't accepted on the command
# line, only /safeseh. This is only accepted by ml.exe, not ml64.exe.
"/safeseh",
]
}
cflags = [
"/Gy", # Enable function-level linking.
"/FS", # Preserve previous PDB behavior.
"/bigobj", # Some of our files are bigger than the regular limits.
"/utf-8", # Assume UTF-8 by default to avoid code page dependencies.
]
if (is_clang) {
cflags += [
"/Zc:twoPhase",
# Consistently use backslash as the path separator when expanding the
# __FILE__ macro when targeting Windows regardless of the build
# environment.
"-ffile-reproducible",
]
}
# Force C/C++ mode for the given GN detected file type. This is necessary
# for precompiled headers where the same source file is compiled in both
# modes.
cflags_c = [ "/TC" ]
cflags_cc = [ "/TP" ]
cflags += [
# Work around crbug.com/526851, bug in VS 2015 RTM compiler.
"/Zc:sizedDealloc-",
]
if (is_clang) {
# Required to make the 19041 SDK compatible with clang-cl.
# See https://crbug.com/1089996 issue #2 for details.
cflags += [ "/D__WRL_ENABLE_FUNCTION_STATICS__" ]
# Tell clang which version of MSVC to emulate.
cflags += [ "-fmsc-version=1916" ]
if (is_component_build) {
cflags += [
# Do not export inline member functions. This makes component builds
# faster. This is similar to -fvisibility-inlines-hidden.
"/Zc:dllexportInlines-",
]
}
if (current_cpu == "x86") {
if (host_cpu == "x86" || host_cpu == "x64") {
cflags += [ "-m32" ]
} else {
cflags += [ "--target=i386-windows", "/O3", "/clang:-O3", "-Xclang", "-O3", "-Wno-unused-command-line-argument", ]
}
} else if (current_cpu == "x64") {
if (host_cpu == "x86" || host_cpu == "x64") {
cflags += [ "-m64" ]
} else {
cflags += [ "--target=x86_64-windows" ]
}
} else if (current_cpu == "arm64") {
cflags += [ "--target=arm64-windows", "/O3", "/clang:-O3", "-Xclang", "-O3", "-Wno-unused-command-line-argument", ]
} else {
assert(false, "unknown current_cpu " + current_cpu)
}
# Chrome currently requires SSE3. Clang supports targeting any Intel
# microarchitecture. MSVC only supports a subset of architectures, and the
# next step after SSE2 will be AVX.
# "/fp:fast", enables FMA.
if (current_cpu == "x86" || current_cpu == "x64") {
cflags += [
"/O3",
"-mavx",
"-maes",
"/clang:-O3",
"/clang:-mavx",
"/clang:-maes",
"-Xclang", "-O3",
"-Wno-unused-command-line-argument",
]
}
if (exec_script("//build/win/use_ansi_codes.py", [], "trim string") ==
"True") {
cflags += [
# cmd.exe doesn't understand ANSI escape codes by default,
# so only enable them if something emulating them is around.
"-fansi-escape-codes",
]
}
if (use_clang_diagnostics_format) {
cflags += [ "/clang:-fdiagnostics-format=clang" ]
}
}
# Disabled with cc_wrapper because of https://github.com/mozilla/sccache/issues/264
if (use_lld && !use_thin_lto && (is_clang || !use_goma) && cc_wrapper == "") {
# /Brepro lets the compiler not write the mtime field in the .obj output.
# link.exe /incremental relies on this field to work correctly, but lld
# never looks at this timestamp, so it's safe to pass this flag with
# lld and get more deterministic compiler output in return.
# In LTO builds, the compiler doesn't write .obj files containing mtimes,
# so /Brepro is ignored there.
cflags += [ "/Brepro" ]
}
ldflags = []
if (use_lld) {
# lld defaults to writing the current time in the pe/coff header.
# For build reproducibility, pass an explicit timestamp. See
# build/compute_build_timestamp.py for how the timestamp is chosen.
# (link.exe also writes the current time, but it doesn't have a flag to
# override that behavior.)
ldflags += [ "/TIMESTAMP:" + build_timestamp ]
# Don't look for libpaths in %LIB%, similar to /X in cflags above.
ldflags += [ "/lldignoreenv" ]
ldflags += [ "/opt:lldlto=3", ]
}
if (use_large_pdbs) {
# This allows PDBs up to 8 GiB in size. This requires lld-link.exe or
# link.exe from VS 2022 or later.
ldflags += [ "/pdbpagesize:8192" ]
}
if (!is_debug && !is_component_build) {
# Enable standard linker optimizations like GC (/OPT:REF) and ICF in static
# release builds.
# Release builds always want these optimizations, so enable them explicitly.
ldflags += [
"/OPT:REF",
"/OPT:ICF",
"/INCREMENTAL:NO",
"/FIXED:NO",
"/OPT:lldlto=3",
"-mllvm:-march=sandybridge",
]
if (use_lld) {
# String tail merging leads to smaller binaries, but they don't compress
# as well, leading to increased mini_installer size (crbug.com/838449).
ldflags += [ "/OPT:NOLLDTAILMERGE" ]
}
# TODO(siggi): Is this of any use anymore?
# /PROFILE ensures that the PDB file contains FIXUP information (growing the
# PDB file by about 5%) but does not otherwise alter the output binary. It
# is enabled opportunistically for builds where it is not prohibited (not
# supported when incrementally linking, or using /debug:fastlink).
ldflags += [ "/PROFILE" ]
}
# arflags apply only to static_libraries. The normal linker configs are only
# set for executable and shared library targets so arflags must be set
# elsewhere. Since this is relatively contained, we just apply them in this
# more general config and they will only have an effect on static libraries.
arflags = [
# "No public symbols found; archive member will be inaccessible." This
# means that one or more object files in the library can never be
# pulled in to targets that link to this library. It's just a warning that
# the source file is a no-op.
"/ignore:4221",
]
}
# This is included by reference in the //build/config/compiler:runtime_library
# config that is applied to all targets. It is here to separate out the logic
# that is Windows-only. Please see that target for advice on what should go in
# :runtime_library vs. :compiler.
config("runtime_library") {
cflags = []
cflags_cc = []
# Defines that set up the CRT.
defines = [
"__STD_C",
"_CRT_RAND_S",
"_CRT_SECURE_NO_DEPRECATE",
"_SCL_SECURE_NO_DEPRECATE",
]
# Defines that set up the Windows SDK.
defines += [
"_ATL_NO_OPENGL",
"_WINDOWS",
"CERT_CHAIN_PARA_HAS_EXTRA_FIELDS",
"PSAPI_VERSION=2",
"WIN32",
"_SECURE_ATL",
]
if (current_os == "winuwp") {
# When targeting Windows Runtime, certain compiler/linker flags are
# necessary.
defines += [
"WINUWP",
"__WRL_NO_DEFAULT_LIB__",
]
if (target_winuwp_family == "app") {
defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PC_APP" ]
} else if (target_winuwp_family == "phone") {
defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" ]
} else if (target_winuwp_family == "system") {
defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SYSTEM" ]
} else if (target_winuwp_family == "server") {
defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SERVER" ]
} else {
defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ]
}
cflags_cc += [ "/EHsc" ]
# This warning is given because the linker cannot tell the difference
# between consuming WinRT APIs versus authoring WinRT within static
# libraries as such this warning is always given by the linker. Since
# consuming WinRT APIs within a library is legitimate but authoring
# WinRT APis is not allowed, this warning is disabled to ignore the
# legitimate consumption of WinRT APIs within static library builds.
arflags = [ "/IGNORE:4264" ]
if (target_winuwp_version == "10") {
defines += [ "WIN10=_WIN32_WINNT_WIN10" ]
} else if (target_winuwp_version == "8.1") {
defines += [ "WIN8_1=_WIN32_WINNT_WINBLUE" ]
} else if (target_winuwp_version == "8.0") {
defines += [ "WIN8=_WIN32_WINNT_WIN8" ]
}
} else {
# When not targeting Windows Runtime, make sure the WINAPI family is set
# to desktop.
defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ]
}
}
# Chromium supports running on Windows 7, but if these constants are set to
# Windows 7, then newer APIs aren't made available by the Windows SDK.
# So we set this to Windows 10 and then are careful to check at runtime
# to only call newer APIs when they're available.
# Some third-party libraries assume that these defines set what version of
# Windows is available at runtime. Targets using these libraries need to
# manually override this config for their compiles.
config("winver") {
defines = [
"NTDDI_VERSION=NTDDI_WIN10_FE",
# We can't say `=_WIN32_WINNT_WIN10` here because some files do
# `#if WINVER < 0x0600` without including windows.h before,
# and then _WIN32_WINNT_WIN10 isn't yet known to be 0x0A00.
"_WIN32_WINNT=0x0A00",
"WINVER=0x0A00",
]
}
# Linker flags for Windows SDK setup, this is applied only to EXEs and DLLs.
config("sdk_link") {
if (current_cpu == "x86") {
ldflags = [
"/SAFESEH", # Not compatible with x64 so use only for x86.
"/largeaddressaware",
]
}
}
# This default linker setup is provided separately from the SDK setup so
# targets who want different library configurations can remove this and specify
# their own.
config("common_linker_setup") {
ldflags = [
"/FIXED:NO",
"/ignore:4199",
"/ignore:4221",
"/NXCOMPAT",
"/DYNAMICBASE",
]
if (win_linker_timing) {
ldflags += [
"/time",
"/verbose:incr",
]
}
}
config("default_cfg_compiler") {
# Emit table of address-taken functions for Control-Flow Guard (CFG).
# This is needed to allow functions to be called by code that is built
# with CFG enabled, such as system libraries.
# The CFG guards are only emitted if |win_enable_cfg_guards| is enabled.
if (is_clang) {
if (win_enable_cfg_guards) {
cflags = [ "/guard:cf" ]
} else {
cflags = [ "/guard:cf,nochecks" ]
}
}
}
# To disable CFG guards for a target, remove the "default_cfg_compiler"
# config, and add "disable_guards_cfg_compiler" config.
config("disable_guards_cfg_compiler") {
# Emit table of address-taken functions for Control-Flow Guard (CFG).
# This is needed to allow functions to be called by code that is built
# with CFG enabled, such as system libraries.
if (is_clang) {
cflags = [ "/guard:cf,nochecks" ]
}
}
config("cfi_linker") {
# Control Flow Guard (CFG)
# https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065.aspx
# /DYNAMICBASE (ASLR) is turned off in debug builds, therefore CFG cannot be
# turned on either.
# ASan and CFG leads to slow process startup. Chromium's test runner uses
# lots of child processes, so this means things are really slow. Disable CFG
# for now. https://crbug.com/846966
if (!is_debug && !is_asan) {
# Turn on CFG bitmap generation and CFG load config.
ldflags = [ "/guard:cf" ]
}
}
# This is a superset of all the delayloads needed for chrome.exe, chrome.dll,
# chrome_child.dll, and chrome_elf.dll. The linker will automatically ignore
# anything which is not linked to the binary at all.
# Most of the dlls are simply not required at startup (or at all, depending
# on how the browser is used). The following dlls are interconnected and need to
# be delayloaded together to ensure user32 does not load too early or at all,
# depending on the process type: user32, gdi32, comctl32, comdlg32, cryptui,
# d3d9, dwmapi, imm32, msi, ole32, oleacc, rstrtmgr, shell32, shlwapi, and
# uxtheme.
# There are some exceptions to this list which need to be declared separately.
# Some dlls cannot be delayloaded by chrome_child.dll due to the sandbox
# restrictions that prevent them from being loaded properly. Those dlls are
# specified in the separate config below.
# This config should also be used for any test binary whose goal is to run
# tests with the full browser.
config("delayloads") {
ldflags = [
"/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll",
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
"/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll",
"/DELAYLOAD:comctl32.dll",
"/DELAYLOAD:comdlg32.dll",
"/DELAYLOAD:credui.dll",
"/DELAYLOAD:cryptui.dll",
"/DELAYLOAD:d3d11.dll",
"/DELAYLOAD:d3d9.dll",
"/DELAYLOAD:dwmapi.dll",
"/DELAYLOAD:dxgi.dll",
"/DELAYLOAD:dxva2.dll",
"/DELAYLOAD:esent.dll",
"/DELAYLOAD:gdi32.dll",
"/DELAYLOAD:hid.dll",
"/DELAYLOAD:imagehlp.dll",
"/DELAYLOAD:imm32.dll",
"/DELAYLOAD:msi.dll",
"/DELAYLOAD:netapi32.dll",
"/DELAYLOAD:ncrypt.dll",
"/DELAYLOAD:ole32.dll",
"/DELAYLOAD:oleacc.dll",
"/DELAYLOAD:propsys.dll",
"/DELAYLOAD:psapi.dll",
"/DELAYLOAD:rpcrt4.dll",
"/DELAYLOAD:rstrtmgr.dll",
"/DELAYLOAD:setupapi.dll",
"/DELAYLOAD:shell32.dll",
"/DELAYLOAD:shlwapi.dll",
"/DELAYLOAD:urlmon.dll",
"/DELAYLOAD:user32.dll",
"/DELAYLOAD:usp10.dll",
"/DELAYLOAD:uxtheme.dll",
"/DELAYLOAD:wer.dll",
"/DELAYLOAD:wevtapi.dll",
"/DELAYLOAD:wininet.dll",
"/DELAYLOAD:winusb.dll",
"/DELAYLOAD:wsock32.dll",
"/DELAYLOAD:wtsapi32.dll",
]
}
config("delayloads_not_for_child_dll") {
ldflags = [
"/DELAYLOAD:advapi32.dll",
"/DELAYLOAD:crypt32.dll",
"/DELAYLOAD:dbghelp.dll",
"/DELAYLOAD:dhcpcsvc.dll",
"/DELAYLOAD:dwrite.dll",
"/DELAYLOAD:iphlpapi.dll",
"/DELAYLOAD:oleaut32.dll",
"/DELAYLOAD:secur32.dll",
"/DELAYLOAD:uiautomationcore.dll",
"/DELAYLOAD:userenv.dll",
"/DELAYLOAD:winhttp.dll",
"/DELAYLOAD:winmm.dll",
"/DELAYLOAD:winspool.drv",
"/DELAYLOAD:wintrust.dll",
"/DELAYLOAD:ws2_32.dll",
]
}
# CRT --------------------------------------------------------------------------
# Configures how the runtime library (CRT) is going to be used.
# See https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx for a reference of
# what each value does.
config("default_crt") {
if (is_component_build) {
# Component mode: dynamic CRT. Since the library is shared, it requires
# exceptions or will give errors about things not matching, so keep
# exceptions on.
configs = [ ":dynamic_crt" ]
} else {
if (current_os == "winuwp") {
# https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/
# contains a details explanation of what is happening with the Windows
# CRT in Visual Studio releases related to Windows store applications.
configs = [ ":dynamic_crt" ]
} else {
# Desktop Windows: static CRT.
configs = [ ":static_crt" ]
}
}
}
# Use this to force use of the release CRT when building perf-critical build
# tools that need to be fully optimized even in debug builds, for those times
# when the debug CRT is part of the bottleneck. This also avoids *implicitly*
# defining _DEBUG.
config("release_crt") {
if (is_component_build) {
cflags = [ "/MD" ]
if (use_custom_libcxx) {
# On Windows, including libcpmt[d]/msvcprt[d] explicitly links the C++
# standard library, which libc++ needs for exception_ptr internals.
ldflags = [ "/DEFAULTLIB:msvcprt.lib" ]
}
} else {
cflags = [ "/MT" ]
if (use_custom_libcxx) {
ldflags = [ "/DEFAULTLIB:libcpmt.lib" ]
}
}
}
config("dynamic_crt") {
if (is_debug) {
# This pulls in the DLL debug CRT and defines _DEBUG
cflags = [ "/MDd" ]
if (use_custom_libcxx) {
ldflags = [ "/DEFAULTLIB:msvcprtd.lib" ]
}
} else {
cflags = [ "/MD" ]
if (use_custom_libcxx) {
ldflags = [ "/DEFAULTLIB:msvcprt.lib" ]
}
}
}
config("static_crt") {
if (is_debug) {
# This pulls in the static debug CRT and defines _DEBUG
cflags = [ "/MTd" ]
if (use_custom_libcxx) {
ldflags = [ "/DEFAULTLIB:libcpmtd.lib" ]
}
} else {
cflags = [ "/MT" ]
if (use_custom_libcxx) {
ldflags = [ "/DEFAULTLIB:libcpmt.lib" ]
}
}
}
# Subsystem --------------------------------------------------------------------
# This is appended to the subsystem to specify a minimum version.
if (current_cpu == "x64") {
# The number after the comma is the minimum required OS version.
# 5.02 = Windows Server 2003.
subsystem_version_suffix = ",5.02"
} else if (current_cpu == "arm64") {
# Windows ARM64 requires Windows 10.
subsystem_version_suffix = ",10.0"
} else {
# 5.01 = Windows XP.
subsystem_version_suffix = ",5.01"
}
config("console") {
ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ]
}
config("windowed") {
ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ]
}
# Incremental linking ----------------------------------------------------------
# Applies incremental linking or not depending on the current configuration.
config("default_incremental_linking") {
# Enable incremental linking for debug builds and all component builds - any
# builds where performance is not job one.
# TODO(thakis): Always turn this on with lld, no reason not to.
if (is_debug || is_component_build) {
ldflags = [ "/INCREMENTAL" ]
if (use_lld) {
# lld doesn't use ilk files and doesn't really have an incremental link
# mode; the only effect of the flag is that the .lib file timestamp isn't
# updated if the .lib doesn't change.
# TODO(thakis): Why pass /OPT:NOREF for lld, but not otherwise?
# TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in
# lld.
ldflags += [ "/OPT:NOREF" ]
}
} else {
ldflags = [ "/INCREMENTAL:NO" ]
}
}
# Character set ----------------------------------------------------------------
# Not including this config means "ansi" (8-bit system codepage).
config("unicode") {
defines = [
"_UNICODE",
"UNICODE",
]
}
# Lean and mean ----------------------------------------------------------------
# Some third party code might not compile with WIN32_LEAN_AND_MEAN so we have
# to have a separate config for it. Remove this config from your target to
# get the "bloaty and accommodating" version of windows.h.
config("lean_and_mean") {
defines = [ "WIN32_LEAN_AND_MEAN" ]
}
# Nominmax --------------------------------------------------------------------
# Some third party code defines NOMINMAX before including windows.h, which
# then causes warnings when it's been previously defined on the command line.
# For such targets, this config can be removed.
config("nominmax") {
defines = [ "NOMINMAX" ]
}

585
src/build/vs_toolchain.py Normal file
View file

@ -0,0 +1,585 @@
#!/usr/bin/env python
# Copyright 2022 The Chromium Authors and Alex313031 and gz83. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from __future__ import print_function
import collections
import glob
import json
import os
import pipes
import platform
import re
import shutil
import stat
import subprocess
import sys
from gn_helpers import ToGNString
# VS 2019 16.61 with 10.0.20348.0 SDK, 10.0.19041 version of Debuggers
# with ARM64 libraries and UWP support.
# See go/chromium-msvc-toolchain for instructions about how to update the
# toolchain.
#
# When updating the toolchain, consider the following areas impacted by the
# toolchain version:
#
# * //base/win/windows_version.cc NTDDI preprocessor check
# Triggers a compiler error if the available SDK is older than the minimum.
# * //build/config/win/BUILD.gn NTDDI_VERSION value
# Affects the availability of APIs in the toolchain headers.
# * //docs/windows_build_instructions.md mentions of VS or Windows SDK.
# Keeps the document consistent with the toolchain version.
TOOLCHAIN_HASH = '1023ce2e82'
script_dir = os.path.dirname(os.path.realpath(__file__))
json_data_file = os.path.join(script_dir, 'win_toolchain.json')
# VS versions are listed in descending order of priority (highest first).
# The first version is assumed by this script to be the one that is packaged,
# which makes a difference for the arm64 runtime.
MSVS_VERSIONS = collections.OrderedDict([
('2022', '17.0'), # Default and packaged version of Visual Studio.
('2019', '16.0'),
('2017', '15.0'),
])
# List of preferred VC toolset version based on MSVS
# Order is not relevant for this dictionary.
MSVC_TOOLSET_VERSION = {
'2022': 'VC143',
'2019': 'VC142',
'2017': 'VC141',
}
def _HostIsWindows():
"""Returns True if running on a Windows host (including under cygwin)."""
return sys.platform in ('win32', 'cygwin')
def SetEnvironmentAndGetRuntimeDllDirs():
"""Sets up os.environ to use the depot_tools VS toolchain with gyp, and
returns the location of the VC runtime DLLs so they can be copied into
the output directory after gyp generation.
Return value is [x64path, x86path, 'Arm64Unused'] or None. arm64path is
generated separately because there are multiple folders for the arm64 VC
runtime.
"""
vs_runtime_dll_dirs = None
depot_tools_win_toolchain = \
bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
# When running on a non-Windows host, only do this if the SDK has explicitly
# been downloaded before (in which case json_data_file will exist).
if ((_HostIsWindows() or os.path.exists(json_data_file))
and depot_tools_win_toolchain):
if ShouldUpdateToolchain():
if len(sys.argv) > 1 and sys.argv[1] == 'update':
update_result = Update()
else:
update_result = Update(no_download=True)
if update_result != 0:
raise Exception('Failed to update, error code %d.' % update_result)
with open(json_data_file, 'r') as tempf:
toolchain_data = json.load(tempf)
toolchain = toolchain_data['path']
version = toolchain_data['version']
win_sdk = toolchain_data.get('win_sdk')
wdk = toolchain_data['wdk']
# TODO(scottmg): The order unfortunately matters in these. They should be
# split into separate keys for x64/x86/arm64. (See CopyDlls call below).
# http://crbug.com/345992
vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
# The number of runtime_dirs in the toolchain_data was two (x64/x86) but
# changed to three (x64/x86/arm64) and this code needs to handle both
# possibilities, which can change independently from this code.
if len(vs_runtime_dll_dirs) == 2:
vs_runtime_dll_dirs.append('Arm64Unused')
os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
os.environ['WINDOWSSDKDIR'] = win_sdk
os.environ['WDK_DIR'] = wdk
# Include the VS runtime in the PATH in case it's not machine-installed.
runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs)
os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH']
elif sys.platform == 'win32' and not depot_tools_win_toolchain:
if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ:
os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath()
# When using an installed toolchain these files aren't needed in the output
# directory in order to run binaries locally, but they are needed in order
# to create isolates or the mini_installer. Copying them to the output
# directory ensures that they are available when needed.
bitness = platform.architecture()[0]
# When running 64-bit python the x64 DLLs will be in System32
# ARM64 binaries will not be available in the system directories because we
# don't build on ARM64 machines.
x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
x64_path = os.path.join(os.path.expandvars('%windir%'), x64_path)
vs_runtime_dll_dirs = [x64_path,
os.path.join(os.path.expandvars('%windir%'),
'SysWOW64'),
'Arm64Unused']
return vs_runtime_dll_dirs
def _RegistryGetValueUsingWinReg(key, value):
"""Use the _winreg module to obtain the value of a registry key.
Args:
key: The registry key.
value: The particular registry value to read.
Return:
contents of the registry key's value, or None on failure. Throws
ImportError if _winreg is unavailable.
"""
import _winreg
try:
root, subkey = key.split('\\', 1)
assert root == 'HKLM' # Only need HKLM for now.
with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
return _winreg.QueryValueEx(hkey, value)[0]
except WindowsError:
return None
def _RegistryGetValue(key, value):
try:
return _RegistryGetValueUsingWinReg(key, value)
except ImportError:
raise Exception('The python library _winreg not found.')
def GetVisualStudioVersion():
"""Return best available version of Visual Studio.
"""
supported_versions = list(MSVS_VERSIONS.keys())
# VS installed in depot_tools for Googlers
if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))):
return supported_versions[0]
# VS installed in system for external developers
supported_versions_str = ', '.join('{} ({})'.format(v,k)
for k,v in MSVS_VERSIONS.items())
available_versions = []
for version in supported_versions:
# Checking vs%s_install environment variables.
# For example, vs2019_install could have the value
# "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community".
# Only vs2017_install, vs2019_install and vs2022_install are supported.
path = os.environ.get('vs%s_install' % version)
if path and os.path.exists(path):
available_versions.append(version)
break
# Detecting VS under possible paths.
if version >= '2022':
program_files_path_variable = '%ProgramFiles%'
else:
program_files_path_variable = '%ProgramFiles(x86)%'
path = os.path.expandvars(program_files_path_variable +
'/Microsoft Visual Studio/%s' % version)
if path and any(
os.path.exists(os.path.join(path, edition))
for edition in ('Enterprise', 'Professional', 'Community', 'Preview',
'BuildTools')):
available_versions.append(version)
break
if not available_versions:
raise Exception('No supported Visual Studio can be found.'
' Supported versions are: %s.' % supported_versions_str)
return available_versions[0]
def DetectVisualStudioPath():
"""Return path to the installed Visual Studio.
"""
# Note that this code is used from
# build/toolchain/win/setup_toolchain.py as well.
version_as_year = GetVisualStudioVersion()
# The VC++ >=2017 install location needs to be located using COM instead of
# the registry. For details see:
# https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/
# For now we use a hardcoded default with an environment variable override.
if version_as_year >= '2022':
program_files_path_variable = '%ProgramFiles%'
else:
program_files_path_variable = '%ProgramFiles(x86)%'
for path in (os.environ.get('vs%s_install' % version_as_year),
os.path.expandvars(program_files_path_variable +
'/Microsoft Visual Studio/%s/Enterprise' %
version_as_year),
os.path.expandvars(program_files_path_variable +
'/Microsoft Visual Studio/%s/Professional' %
version_as_year),
os.path.expandvars(program_files_path_variable +
'/Microsoft Visual Studio/%s/Community' %
version_as_year),
os.path.expandvars(program_files_path_variable +
'/Microsoft Visual Studio/%s/Preview' %
version_as_year),
os.path.expandvars(program_files_path_variable +
'/Microsoft Visual Studio/%s/BuildTools' %
version_as_year)):
if path and os.path.exists(path):
return path
raise Exception('Visual Studio Version %s not found.' % version_as_year)
def _CopyRuntimeImpl(target, source, verbose=True):
"""Copy |source| to |target| if it doesn't already exist or if it needs to be
updated (comparing last modified time as an approximate float match as for
some reason the values tend to differ by ~1e-07 despite being copies of the
same file... https://crbug.com/603603).
"""
if (os.path.isdir(os.path.dirname(target)) and
(not os.path.isfile(target) or
abs(os.stat(target).st_mtime - os.stat(source).st_mtime) >= 0.01)):
if verbose:
print('Copying %s to %s...' % (source, target))
if os.path.exists(target):
# Make the file writable so that we can delete it now, and keep it
# readable.
os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
os.unlink(target)
shutil.copy2(source, target)
# Make the file writable so that we can overwrite or delete it later,
# keep it readable.
os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
def _SortByHighestVersionNumberFirst(list_of_str_versions):
"""This sorts |list_of_str_versions| according to version number rules
so that version "1.12" is higher than version "1.9". Does not work
with non-numeric versions like 1.4.a8 which will be higher than
1.4.a12. It does handle the versions being embedded in file paths.
"""
def to_int_if_int(x):
try:
return int(x)
except ValueError:
return x
def to_number_sequence(x):
part_sequence = re.split(r'[\\/\.]', x)
return [to_int_if_int(x) for x in part_sequence]
list_of_str_versions.sort(key=to_number_sequence, reverse=True)
def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, suffix):
"""Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
exist, but the target directory does exist."""
if target_cpu == 'arm64':
# Windows ARM64 VCRuntime is located at {toolchain_root}/VC/Redist/MSVC/
# {x.y.z}/[debug_nonredist/]arm64/Microsoft.VC14x.CRT/.
# Select VC toolset directory based on Visual Studio version
vc_redist_root = FindVCRedistRoot()
if suffix.startswith('.'):
vc_toolset_dir = 'Microsoft.{}.CRT' \
.format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
source_dir = os.path.join(vc_redist_root,
'arm64', vc_toolset_dir)
else:
vc_toolset_dir = 'Microsoft.{}.DebugCRT' \
.format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
source_dir = os.path.join(vc_redist_root, 'debug_nonredist',
'arm64', vc_toolset_dir)
file_parts = ('msvcp140', 'vccorlib140', 'vcruntime140')
if target_cpu == 'x64' and GetVisualStudioVersion() != '2017':
file_parts = file_parts + ('vcruntime140_1', )
for file_part in file_parts:
dll = file_part + suffix
target = os.path.join(target_dir, dll)
source = os.path.join(source_dir, dll)
_CopyRuntimeImpl(target, source)
# Copy the UCRT files from the Windows SDK. This location includes the
# api-ms-win-crt-*.dll files that are not found in the Windows directory.
# These files are needed for component builds. If WINDOWSSDKDIR is not set
# use the default SDK path. This will be the case when
# DEPOT_TOOLS_WIN_TOOLCHAIN=0 and vcvarsall.bat has not been run.
win_sdk_dir = os.path.normpath(
os.environ.get('WINDOWSSDKDIR',
os.path.expandvars('%ProgramFiles(x86)%'
'\\Windows Kits\\10')))
# ARM64 doesn't have a redist for the ucrt DLLs because they are always
# present in the OS.
if target_cpu != 'arm64':
# Starting with the 10.0.17763 SDK the ucrt files are in a version-named
# directory - this handles both cases.
redist_dir = os.path.join(win_sdk_dir, 'Redist')
version_dirs = glob.glob(os.path.join(redist_dir, '10.*'))
if len(version_dirs) > 0:
_SortByHighestVersionNumberFirst(version_dirs)
redist_dir = version_dirs[0]
ucrt_dll_dirs = os.path.join(redist_dir, 'ucrt', 'DLLs', target_cpu)
ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll'))
assert len(ucrt_files) > 0
for ucrt_src_file in ucrt_files:
file_part = os.path.basename(ucrt_src_file)
ucrt_dst_file = os.path.join(target_dir, file_part)
_CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
# We must copy ucrtbase.dll for x64/x86, and ucrtbased.dll for all CPU types.
if target_cpu != 'arm64' or not suffix.startswith('.'):
if not suffix.startswith('.'):
# ucrtbased.dll is located at {win_sdk_dir}/bin/{a.b.c.d}/{target_cpu}/
# ucrt/.
sdk_bin_root = os.path.join(win_sdk_dir, 'bin')
sdk_bin_sub_dirs = glob.glob(os.path.join(sdk_bin_root, '10.*'))
# Select the most recent SDK if there are multiple versions installed.
_SortByHighestVersionNumberFirst(sdk_bin_sub_dirs)
for directory in sdk_bin_sub_dirs:
sdk_redist_root_version = os.path.join(sdk_bin_root, directory)
if not os.path.isdir(sdk_redist_root_version):
continue
source_dir = os.path.join(sdk_redist_root_version, target_cpu, 'ucrt')
break
_CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
os.path.join(source_dir, 'ucrtbase' + suffix))
def FindVCComponentRoot(component):
"""Find the most recent Tools or Redist or other directory in an MSVC install.
Typical results are {toolchain_root}/VC/{component}/MSVC/{x.y.z}. The {x.y.z}
version number part changes frequently so the highest version number found is
used.
"""
SetEnvironmentAndGetRuntimeDllDirs()
assert ('GYP_MSVS_OVERRIDE_PATH' in os.environ)
vc_component_msvc_root = os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
'VC', component, 'MSVC')
vc_component_msvc_contents = glob.glob(
os.path.join(vc_component_msvc_root, '14.*'))
# Select the most recent toolchain if there are several.
_SortByHighestVersionNumberFirst(vc_component_msvc_contents)
for directory in vc_component_msvc_contents:
if os.path.isdir(directory):
return directory
raise Exception('Unable to find the VC %s directory.' % component)
def FindVCRedistRoot():
"""In >=VS2017, Redist binaries are located in
{toolchain_root}/VC/Redist/MSVC/{x.y.z}/{target_cpu}/.
This returns the '{toolchain_root}/VC/Redist/MSVC/{x.y.z}/' path.
"""
return FindVCComponentRoot('Redist')
def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
"""Copy the VS runtime DLLs, only if the target doesn't exist, but the target
directory does exist. Handles VS 2015, 2017 and 2019."""
suffix = 'd.dll' if debug else '.dll'
# VS 2015, 2017 and 2019 use the same CRT DLLs.
_CopyUCRTRuntime(target_dir, source_dir, target_cpu, suffix)
def CopyDlls(target_dir, configuration, target_cpu):
"""Copy the VS runtime DLLs into the requested directory as needed.
configuration is one of 'Debug' or 'Release'.
target_cpu is one of 'x86', 'x64' or 'arm64'.
The debug configuration gets both the debug and release DLLs; the
release config only the latter.
"""
vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
if not vs_runtime_dll_dirs:
return
x64_runtime, x86_runtime, arm64_runtime = vs_runtime_dll_dirs
if target_cpu == 'x64':
runtime_dir = x64_runtime
elif target_cpu == 'x86':
runtime_dir = x86_runtime
elif target_cpu == 'arm64':
runtime_dir = arm64_runtime
else:
raise Exception('Unknown target_cpu: ' + target_cpu)
_CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False)
if configuration == 'Debug':
_CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True)
_CopyDebugger(target_dir, target_cpu)
def _CopyDebugger(target_dir, target_cpu):
"""Copy dbghelp.dll and dbgcore.dll into the requested directory as needed.
target_cpu is one of 'x86', 'x64' or 'arm64'.
dbghelp.dll is used when Chrome needs to symbolize stacks. Copying this file
from the SDK directory avoids using the system copy of dbghelp.dll which then
ensures compatibility with recent debug information formats, such as VS
2017 /debug:fastlink PDBs.
dbgcore.dll is needed when using some functions from dbghelp.dll (like
MinidumpWriteDump).
"""
win_sdk_dir = SetEnvironmentAndGetSDKDir()
if not win_sdk_dir:
return
# List of debug files that should be copied, the first element of the tuple is
# the name of the file and the second indicates if it's optional.
debug_files = [('dbghelp.dll', False), ('dbgcore.dll', True)]
# The UCRT is not a redistributable component on arm64.
if target_cpu != 'arm64':
debug_files.extend([('api-ms-win-downlevel-kernel32-l2-1-0.dll', False),
('api-ms-win-eventing-provider-l1-1-0.dll', False)])
for debug_file, is_optional in debug_files:
full_path = os.path.join(win_sdk_dir, 'Debuggers', target_cpu, debug_file)
if not os.path.exists(full_path):
if is_optional:
continue
else:
raise Exception('%s not found in "%s"\r\nYou must install '
'Windows 10 SDK version 10.0.20348.0 including the '
'"Debugging Tools for Windows" feature.' %
(debug_file, full_path))
target_path = os.path.join(target_dir, debug_file)
_CopyRuntimeImpl(target_path, full_path)
def _GetDesiredVsToolchainHashes():
"""Load a list of SHA1s corresponding to the toolchains that we want installed
to build with."""
# Third parties that do not have access to the canonical toolchain can map
# canonical toolchain version to their own toolchain versions.
toolchain_hash_mapping_key = 'GYP_MSVS_HASH_%s' % TOOLCHAIN_HASH
return [os.environ.get(toolchain_hash_mapping_key, TOOLCHAIN_HASH)]
def ShouldUpdateToolchain():
"""Check if the toolchain should be upgraded."""
if not os.path.exists(json_data_file):
return True
with open(json_data_file, 'r') as tempf:
toolchain_data = json.load(tempf)
version = toolchain_data['version']
env_version = GetVisualStudioVersion()
# If there's a mismatch between the version set in the environment and the one
# in the json file then the toolchain should be updated.
return version != env_version
def Update(force=False, no_download=False):
"""Requests an update of the toolchain to the specific hashes we have at
this revision. The update outputs a .json of the various configuration
information required to pass to gyp which we use in |GetToolchainDir()|.
If no_download is true then the toolchain will be configured if present but
will not be downloaded.
"""
if force != False and force != '--force':
print('Unknown parameter "%s"' % force, file=sys.stderr)
return 1
if force == '--force' or os.path.exists(json_data_file):
force = True
depot_tools_win_toolchain = \
bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
if (_HostIsWindows() or force) and depot_tools_win_toolchain:
import find_depot_tools
depot_tools_path = find_depot_tools.add_depot_tools_to_path()
# On Linux, the file system is usually case-sensitive while the Windows
# SDK only works on case-insensitive file systems. If it doesn't already
# exist, set up a ciopfs fuse mount to put the SDK in a case-insensitive
# part of the file system.
toolchain_dir = os.path.join(depot_tools_path, 'win_toolchain', 'vs_files')
# For testing this block, unmount existing mounts with
# fusermount -u third_party/depot_tools/win_toolchain/vs_files
if sys.platform.startswith('linux') and not os.path.ismount(toolchain_dir):
import distutils.spawn
ciopfs = distutils.spawn.find_executable('ciopfs')
if not ciopfs:
# ciopfs not found in PATH; try the one downloaded from the DEPS hook.
ciopfs = os.path.join(script_dir, 'ciopfs')
if not os.path.isdir(toolchain_dir):
os.mkdir(toolchain_dir)
if not os.path.isdir(toolchain_dir + '.ciopfs'):
os.mkdir(toolchain_dir + '.ciopfs')
# Without use_ino, clang's #pragma once and Wnonportable-include-path
# both don't work right, see https://llvm.org/PR34931
# use_ino doesn't slow down builds, so it seems there's no drawback to
# just using it always.
subprocess.check_call([
ciopfs, '-o', 'use_ino', toolchain_dir + '.ciopfs', toolchain_dir])
get_toolchain_args = [
sys.executable,
os.path.join(depot_tools_path,
'win_toolchain',
'get_toolchain_if_necessary.py'),
'--output-json', json_data_file,
] + _GetDesiredVsToolchainHashes()
if force:
get_toolchain_args.append('--force')
if no_download:
get_toolchain_args.append('--no-download')
subprocess.check_call(get_toolchain_args)
return 0
def NormalizePath(path):
while path.endswith('\\'):
path = path[:-1]
return path
def SetEnvironmentAndGetSDKDir():
"""Gets location information about the current sdk (must have been
previously updated by 'update'). This is used for the GN build."""
SetEnvironmentAndGetRuntimeDllDirs()
# If WINDOWSSDKDIR is not set, search the default SDK path and set it.
if not 'WINDOWSSDKDIR' in os.environ:
default_sdk_path = os.path.expandvars('%ProgramFiles(x86)%'
'\\Windows Kits\\10')
if os.path.isdir(default_sdk_path):
os.environ['WINDOWSSDKDIR'] = default_sdk_path
return NormalizePath(os.environ['WINDOWSSDKDIR'])
def GetToolchainDir():
"""Gets location information about the current toolchain (must have been
previously updated by 'update'). This is used for the GN build."""
runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
win_sdk_dir = SetEnvironmentAndGetSDKDir()
print('''vs_path = %s
sdk_path = %s
vs_version = %s
wdk_dir = %s
runtime_dirs = %s
''' % (ToGNString(NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH'])),
ToGNString(win_sdk_dir), ToGNString(GetVisualStudioVersion()),
ToGNString(NormalizePath(os.environ.get('WDK_DIR', ''))),
ToGNString(os.path.pathsep.join(runtime_dll_dirs or ['None']))))
def main():
commands = {
'update': Update,
'get_toolchain_dir': GetToolchainDir,
'copy_dlls': CopyDlls,
}
if len(sys.argv) < 2 or sys.argv[1] not in commands:
print('Expected one of: %s' % ', '.join(commands), file=sys.stderr)
return 1
return commands[sys.argv[1]](*sys.argv[2:])
if __name__ == '__main__':
sys.exit(main())

View file

@ -0,0 +1,98 @@
#!/usr/bin/env python
# Copyright 2022 The Chromium Authors, Alex313031, and gz83. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import glob
import optparse
import os
import shutil
import subprocess
import sys
sys.path.insert(
0,
os.path.join(os.path.dirname(__file__), '..', '..', 'third_party',
'pefile_py3'))
import pefile
def reorder_imports(input_dir, output_dir, architecture):
"""Swap chrome_elf.dll to be the first import of chrome.exe.
Also copy over any related files that might be needed
(pdbs, manifests etc.).
"""
# TODO(thakis): See if there is a reliable way to write the
# correct executable in the first place, so that this script
# only needs to verify that and not write a whole new exe.
input_image = os.path.join(input_dir, 'thorium.exe')
output_image = os.path.join(output_dir, 'thorium.exe')
# pefile mmap()s the whole executable, and then parses parts of
# it into python data structures for ease of processing.
# To write the file again, only the mmap'd data is written back,
# so modifying the parsed python objects generally has no effect.
# However, parsed raw data ends up in pe.Structure instances,
# and these all get serialized back when the file gets written.
# So things that are in a Structure must have their data set
# through the Structure, while other data must bet set through
# the set_bytes_*() methods.
pe = pefile.PE(input_image, fast_load=True)
if architecture == 'x64' or architecture == 'arm64':
assert pe.PE_TYPE == pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS
else:
assert pe.PE_TYPE == pefile.OPTIONAL_HEADER_MAGIC_PE
pe.parse_data_directories(directories=[
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']])
found_elf = False
for i, peimport in enumerate(pe.DIRECTORY_ENTRY_IMPORT):
if peimport.dll.lower() == b'chrome_elf.dll':
assert not found_elf, 'only one chrome_elf.dll import expected'
found_elf = True
if i > 0:
swap = pe.DIRECTORY_ENTRY_IMPORT[0]
# Morally we want to swap peimport.struct and swap.struct here,
# but the pe module doesn't expose a public method on Structure
# to get all data of a Structure without explicitly listing all
# field names.
# NB: OriginalFirstThunk and Characteristics are an union both at
# offset 0, handling just one of them is enough.
peimport.struct.OriginalFirstThunk, swap.struct.OriginalFirstThunk = \
swap.struct.OriginalFirstThunk, peimport.struct.OriginalFirstThunk
peimport.struct.TimeDateStamp, swap.struct.TimeDateStamp = \
swap.struct.TimeDateStamp, peimport.struct.TimeDateStamp
peimport.struct.ForwarderChain, swap.struct.ForwarderChain = \
swap.struct.ForwarderChain, peimport.struct.ForwarderChain
peimport.struct.Name, swap.struct.Name = \
swap.struct.Name, peimport.struct.Name
peimport.struct.FirstThunk, swap.struct.FirstThunk = \
swap.struct.FirstThunk, peimport.struct.FirstThunk
assert found_elf, 'chrome_elf.dll import not found'
pe.write(filename=output_image)
for fname in glob.iglob(os.path.join(input_dir, 'thorium.exe.*')):
shutil.copy(fname, os.path.join(output_dir, os.path.basename(fname)))
return 0
def main(argv):
usage = 'reorder_imports.py -i <input_dir> -o <output_dir> -a <target_arch>'
parser = optparse.OptionParser(usage=usage)
parser.add_option('-i', '--input', help='reorder thorium.exe in DIR',
metavar='DIR')
parser.add_option('-o', '--output', help='write new thorium.exe to DIR',
metavar='DIR')
parser.add_option('-a', '--arch', help='architecture of build (optional)',
default='ia32')
opts, args = parser.parse_args()
if not opts.input or not opts.output:
parser.error('Please provide and input and output directory')
return reorder_imports(opts.input, opts.output, opts.arch)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))

View file

@ -0,0 +1,199 @@
// Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/base_switches.h"
#include "base/cfi_buildflags.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/content_browser_test.h"
#include "content/shell/common/shell_controller.test-mojom.h"
#include "content/shell/common/shell_switches.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(USE_OZONE)
#include "ui/ozone/public/ozone_switches.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ui/gl/gl_switches.h"
#endif
namespace content {
namespace {
#if BUILDFLAG(IS_WIN)
const char kShellExecutableName[] = "thorium_shell.exe";
#else
const char kShellExecutableName[] = "thorium_shell";
const char kMojoCoreLibraryName[] = "libmojo_core.so";
#endif
base::FilePath GetCurrentDirectory() {
base::FilePath current_directory;
CHECK(base::GetCurrentDirectory(&current_directory));
return current_directory;
}
class LaunchAsMojoClientBrowserTest : public ContentBrowserTest {
public:
LaunchAsMojoClientBrowserTest() { CHECK(temp_dir_.CreateUniqueTempDir()); }
~LaunchAsMojoClientBrowserTest() override {
// Ensure that the launched Content Shell process is dead before the test
// tears down, otherwise the temp profile dir may fail to delete. Note that
// tests must explicitly request shutdown through ShellController before
// finishing, otherwise this will time out.
CHECK(content_shell_process_.WaitForExit(nullptr));
CHECK(temp_dir_.Delete());
}
base::CommandLine MakeShellCommandLine() {
base::CommandLine command_line(
GetFilePathNextToCurrentExecutable(kShellExecutableName));
command_line.AppendSwitchPath(switches::kContentShellDataPath,
temp_dir_.GetPath());
#if defined(USE_OZONE)
const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess();
const char* kSwitchesToCopy[] = {
// Keep the kOzonePlatform switch that the Ozone must use.
switches::kOzonePlatform,
};
command_line.CopySwitchesFrom(cmdline, kSwitchesToCopy,
std::size(kSwitchesToCopy));
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
command_line.AppendSwitchASCII(switches::kUseGL,
gl::kGLImplementationANGLEName);
command_line.AppendSwitchASCII(switches::kUseANGLE,
gl::kANGLEImplementationSwiftShaderName);
#endif
return command_line;
}
mojo::Remote<mojom::ShellController> LaunchContentShell(
const base::CommandLine& command_line) {
mojo::PlatformChannel channel;
base::LaunchOptions options;
base::CommandLine shell_command_line(command_line);
channel.PrepareToPassRemoteEndpoint(&options, &shell_command_line);
content_shell_process_ = base::LaunchProcess(shell_command_line, options);
channel.RemoteProcessLaunchAttempted();
mojo::OutgoingInvitation invitation;
mojo::Remote<mojom::ShellController> controller(
mojo::PendingRemote<mojom::ShellController>(
invitation.AttachMessagePipe(0), /*version=*/0));
mojo::OutgoingInvitation::Send(std::move(invitation),
content_shell_process_.Handle(),
channel.TakeLocalEndpoint());
return controller;
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
base::FilePath GetMojoCoreLibraryPath() {
return GetFilePathNextToCurrentExecutable(kMojoCoreLibraryName);
}
#endif
private:
base::FilePath GetFilePathNextToCurrentExecutable(
const std::string& filename) {
base::FilePath executable_dir =
base::CommandLine::ForCurrentProcess()->GetProgram().DirName();
if (executable_dir.IsAbsolute())
return executable_dir.AppendASCII(filename);
// If the current executable path is relative, resolve it to an absolute
// path before swapping in |filename|. This ensures that the path is OK to
// use with base::LaunchProcess. Otherwise we could end up with a path
// containing only |filename|, and this can fail to execute in environments
// where "." is not in the PATH (common on e.g. Linux).
return current_directory_.Append(executable_dir).AppendASCII(filename);
}
base::ScopedTempDir temp_dir_;
const base::FilePath current_directory_ = GetCurrentDirectory();
base::Process content_shell_process_;
mojo::Remote<mojom::ShellController> shell_controller_;
};
IN_PROC_BROWSER_TEST_F(LaunchAsMojoClientBrowserTest, LaunchAndBindInterface) {
// Verifies that we can launch an instance of Content Shell with a Mojo
// invitation on the command line and reach the new browser process's exposed
// ShellController interface.
const char kExtraSwitchName[] = "extra-switch-for-testing";
const char kExtraSwitchValue[] = "42";
base::CommandLine command_line = MakeShellCommandLine();
command_line.AppendSwitchASCII(kExtraSwitchName, kExtraSwitchValue);
mojo::Remote<mojom::ShellController> shell_controller =
LaunchContentShell(command_line);
base::RunLoop loop;
shell_controller->GetSwitchValue(
kExtraSwitchName,
base::BindLambdaForTesting([&](const absl::optional<std::string>& value) {
ASSERT_TRUE(value);
EXPECT_EQ(kExtraSwitchValue, *value);
loop.Quit();
}));
loop.Run();
shell_controller->ShutDown();
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// TODO(crbug.com/1259557): This test implementation fundamentally conflicts
// with a fix for the linked bug because it causes a browser process to behave
// partially as a broker and partially as a non-broker. This can be re-enabled
// when we migrate away from the current Mojo implementation. It's OK to disable
// for now because no production code relies on this feature.
IN_PROC_BROWSER_TEST_F(LaunchAsMojoClientBrowserTest,
DISABLED_WithMojoCoreLibrary) {
// Instructs a newly launched Content Shell browser to initialize Mojo Core
// dynamically from a shared library, rather than using the version linked
// into the Content Shell binary.
//
// This exercises end-to-end JS in order to cover real IPC behavior between
// the browser and a renderer.
base::CommandLine command_line = MakeShellCommandLine();
command_line.AppendSwitchPath(switches::kMojoCoreLibraryPath,
GetMojoCoreLibraryPath());
mojo::Remote<mojom::ShellController> shell_controller =
LaunchContentShell(command_line);
// Indisputable proof that we're evaluating JavaScript.
const std::string kExpressionToEvaluate = "'ba'+ +'a'+'as'";
const base::Value kExpectedValue("baNaNas");
base::RunLoop loop;
shell_controller->ExecuteJavaScript(
base::ASCIIToUTF16(kExpressionToEvaluate),
base::BindLambdaForTesting([&](base::Value value) {
EXPECT_EQ(kExpectedValue, value);
loop.Quit();
}));
loop.Run();
shell_controller->ShutDown();
}
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
} // namespace
} // namespace content

145
src/content/gpu/BUILD.gn Normal file
View file

@ -0,0 +1,145 @@
# Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/chromecast_build.gni")
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/ui.gni")
import("//gpu/vulkan/features.gni")
import("//media/media_options.gni")
import("//media/gpu/args.gni")
# See //content/BUILD.gn for how this works.
group("gpu") {
visibility = [ "//content/*" ] # This is an internal content API.
if (is_component_build) {
public_deps = [ "//content" ]
} else {
public_deps = [ ":gpu_sources" ]
}
}
if (is_component_build) {
link_target_type = "source_set"
} else {
link_target_type = "static_library"
}
target(link_target_type, "gpu_sources") {
# This is an internal content API. Code outside of the content "component"
# (like content/test and content/shell) should depend on ":gpu" above.
visibility = [ "//content/*" ]
sources = [
"browser_exposed_gpu_interfaces.cc",
"browser_exposed_gpu_interfaces.h",
"gpu_child_thread.cc",
"gpu_child_thread.h",
"gpu_child_thread_receiver_bindings.cc",
"gpu_main.cc",
"gpu_service_factory.cc",
"gpu_service_factory.h",
"in_process_gpu_thread.cc",
"in_process_gpu_thread.h",
]
configs += [ "//content:content_implementation" ]
deps = [
"//base",
"//base/third_party/dynamic_annotations",
"//build:branding_buildflags",
"//build:chromeos_buildflags",
"//components/viz/service",
"//content:export",
"//content/child",
"//content/common",
"//content/common:mojo_bindings",
"//content/public/child:child_sources",
"//content/public/common:common_sources",
"//gpu:gpu",
"//gpu/ipc/common:command_buffer_traits",
"//gpu/ipc/service",
"//ipc",
"//media:media_buildflags",
"//media/gpu",
"//media/mojo:buildflags",
# TODO(jrummell): As //media/gpu/ipc/service is a source_set in a
# component build, determine if it should not be included here.
# http://crbug.com/702833.
"//components/viz/service/main",
"//media/gpu/ipc/service",
"//media/mojo/clients:clients",
"//sandbox/policy:chromecast_sandbox_allowlist_buildflags",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
"//services/tracing/public/cpp",
"//services/viz/privileged/mojom",
"//skia",
"//third_party/angle:angle_gpu_info_util",
"//ui/gfx/ipc",
"//ui/gl",
"//ui/gl/init",
"//ui/latency/ipc",
]
if (!is_chromeos_ash || !is_chrome_branded) {
deps += [
"//services/shape_detection:lib",
"//services/shape_detection/public/mojom",
]
}
if (is_linux || is_chromeos) {
sources += [
"gpu_sandbox_hook_linux.cc",
"gpu_sandbox_hook_linux.h",
]
}
if (is_chromeos_ash) {
deps += [
"//components/services/font/public/cpp",
"//components/services/font/public/mojom",
]
}
if (is_android) {
deps += [
"//components/tracing:graphics_provider",
"//media",
]
}
if (mojo_media_host == "gpu") {
deps += [ "//media/mojo/services" ]
}
if (is_linux || is_chromeos || is_mac || is_win) {
deps += [ "//sandbox" ]
}
if (is_mac) {
deps += [ "//components/metal_util" ]
}
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
if (enable_vulkan) {
deps += [ "//gpu/vulkan" ]
}
# Use DRI on desktop Linux builds.
if (current_cpu != "s390x" && current_cpu != "ppc64" && is_linux &&
!is_castos) {
configs += [ "//build/config/linux/dri" ]
}
if (is_linux && use_vaapi) {
public_configs = [ "//build/config/linux/libva" ]
}
}

910
src/content/shell/BUILD.gn Normal file
View file

@ -0,0 +1,910 @@
# Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/chromecast_build.gni")
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/features.gni")
import("//build/config/ozone.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/ui.gni")
import("//build/config/win/console_app.gni")
import("//build/config/win/manifest.gni")
import("//gpu/vulkan/features.gni")
import("//media/media_options.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//ppapi/buildflags/buildflags.gni")
import("//tools/grit/grit_rule.gni")
import("//tools/grit/repack.gni")
import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
if (is_android) {
import("//build/config/android/config.gni")
} else if (is_mac) {
import("//build/apple/tweak_info_plist.gni")
import("//build/config/mac/rules.gni")
import("//content/public/app/mac_helpers.gni")
import("//third_party/icu/config.gni")
import("//ui/gl/features.gni")
import("//v8/gni/v8.gni")
}
# TODO(crbug.com/1336055, spang): Investigate using shell_views with cast builds as
# true.
shell_use_toolkit_views = toolkit_views && !is_castos
declare_args() {
content_shell_product_name = "Thorium Shell"
content_shell_version = "999.77.34.5"
content_shell_major_version = "999"
}
config("content_shell_lib_warnings") {
if (is_clang) {
# TODO(thakis): Remove this once http://crbug.com/383820 is figured out
cflags = [ "-Wno-nonnull" ]
}
}
# Web test support not built on android, but is everywhere else.
support_web_tests = !is_android
source_set("android_shell_descriptors") {
testonly = true
sources = []
public_deps = [ "//content/public/common:content_descriptors" ]
if (is_android) {
sources += [ "android/shell_descriptors.h" ]
}
}
# This component provides a ContentMainDelegate for Content Shell and derived
# applications. This delegate is the central place that creates interfaces for
# each type of process (browser, renderer, etc). This implementation of
# ContentMainDelegate will create either production or test-based
# implementations.
#
# This component needs to be linked into every process in a Content Shell-based
# application that wants to use ShellMainDelegate.
#
# TODO(danakj): This component will depend on {renderer,browser}/web_test. The
# content_shell_lib component will not, to avoid circular deps, as web_test
# inherits from things in content_shell_lib.
static_library("content_shell_app") {
testonly = true
sources = [
"app/shell_crash_reporter_client.cc",
"app/shell_crash_reporter_client.h",
"app/shell_main_delegate.cc",
"app/shell_main_delegate.h",
]
deps = [
":content_shell_lib",
"//components/crash/core/common:crash_key",
"//content/public/app",
"//v8",
]
if (support_web_tests) {
deps += [
"//content/web_test:web_test_browser",
"//content/web_test:web_test_common",
"//content/web_test:web_test_renderer",
]
}
if (!is_fuchsia) {
deps += [
"//components/crash/core/app",
"//components/crash/core/app:test_support",
]
}
if (is_mac) {
sources += [
"app/paths_mac.h",
"app/paths_mac.mm",
"app/shell_main_delegate_mac.h",
"app/shell_main_delegate_mac.mm",
]
}
defines = [
"CONTENT_SHELL_VERSION=\"$content_shell_version\"",
"CONTENT_SHELL_MAJOR_VERSION=\"$content_shell_major_version\"",
]
}
static_library("content_shell_lib") {
testonly = true
sources = [
"browser/shell.cc",
"browser/shell.h",
"browser/shell_browser_context.cc",
"browser/shell_browser_context.h",
"browser/shell_browser_main_parts.cc",
"browser/shell_browser_main_parts.h",
"browser/shell_content_browser_client.cc",
"browser/shell_content_browser_client.h",
"browser/shell_content_index_provider.cc",
"browser/shell_content_index_provider.h",
"browser/shell_devtools_bindings.cc",
"browser/shell_devtools_bindings.h",
"browser/shell_devtools_frontend.cc",
"browser/shell_devtools_frontend.h",
"browser/shell_devtools_manager_delegate.cc",
"browser/shell_devtools_manager_delegate.h",
"browser/shell_download_manager_delegate.cc",
"browser/shell_download_manager_delegate.h",
"browser/shell_federated_permission_context.cc",
"browser/shell_federated_permission_context.h",
"browser/shell_javascript_dialog.h",
"browser/shell_javascript_dialog_manager.cc",
"browser/shell_javascript_dialog_manager.h",
"browser/shell_paths.cc",
"browser/shell_paths.h",
"browser/shell_permission_manager.cc",
"browser/shell_permission_manager.h",
"browser/shell_platform_data_aura.cc",
"browser/shell_platform_data_aura.h",
"browser/shell_platform_delegate.cc",
"browser/shell_platform_delegate.h",
"browser/shell_quota_permission_context.cc",
"browser/shell_quota_permission_context.h",
"browser/shell_speech_recognition_manager_delegate.cc",
"browser/shell_speech_recognition_manager_delegate.h",
"browser/shell_web_contents_view_delegate.h",
"browser/shell_web_contents_view_delegate_creator.h",
"common/power_monitor_test_impl.cc",
"common/power_monitor_test_impl.h",
"common/shell_content_client.cc",
"common/shell_content_client.h",
"common/shell_origin_trial_policy.cc",
"common/shell_origin_trial_policy.h",
"common/shell_switches.cc",
"common/shell_switches.h",
"gpu/shell_content_gpu_client.cc",
"gpu/shell_content_gpu_client.h",
"renderer/shell_content_renderer_client.cc",
"renderer/shell_content_renderer_client.h",
"renderer/shell_render_frame_observer.cc",
"renderer/shell_render_frame_observer.h",
"utility/shell_content_utility_client.cc",
"utility/shell_content_utility_client.h",
]
if (is_android) {
sources += [
"android/shell_manager.cc",
"android/shell_manager.h",
"browser/shell_platform_delegate_android.cc",
"browser/shell_web_contents_view_delegate_android.cc",
]
}
if (is_mac) {
sources += [
"browser/renderer_host/shell_render_widget_host_view_mac_delegate.h",
"browser/renderer_host/shell_render_widget_host_view_mac_delegate.mm",
"browser/shell_application_mac.h",
"browser/shell_application_mac.mm",
"browser/shell_browser_main_parts_mac.mm",
"browser/shell_javascript_dialog_mac.mm",
"browser/shell_platform_delegate_mac.mm",
"browser/shell_web_contents_view_delegate_mac.mm",
]
}
if (is_win) {
sources += [ "browser/shell_javascript_dialog_win.cc" ]
}
configs += [
":content_shell_lib_warnings",
"//build/config:precompiled_headers",
]
defines = [
"CONTENT_SHELL_VERSION=\"$content_shell_version\"",
"CONTENT_SHELL_MAJOR_VERSION=\"$content_shell_major_version\"",
]
# This is to support our dependency on //content/browser.
# See comment at the top of //content/BUILD.gn for why this is disabled in
# component builds.
if (is_component_build) {
check_includes = false
}
public_deps = [
":android_shell_descriptors",
# content_shell_lib also exposes all public content APIs.
"//content/public/app",
"//content/public/browser",
"//content/public/child",
"//content/public/common",
"//content/public/gpu",
"//content/public/renderer",
"//content/public/utility",
"//services/network:network_service",
]
deps = [
":content_browsertests_mojom",
":resources",
":shell_controller_mojom",
"//base",
"//base:base_static",
"//base/third_party/dynamic_annotations",
"//build:chromeos_buildflags",
"//cc/base",
"//components/cdm/renderer",
"//components/custom_handlers",
"//components/custom_handlers:test_support",
"//components/keyed_service/content",
"//components/metrics",
"//components/metrics:net",
"//components/metrics:test_support",
"//components/network_session_configurator/common",
"//components/performance_manager",
"//components/permissions",
"//components/prefs",
"//components/services/storage/test_api",
"//components/url_formatter",
"//components/variations",
"//components/variations/service",
"//components/web_cache/renderer",
"//content:content_resources",
"//content:dev_ui_content_resources",
"//content/public/common",
"//content/test:content_test_mojo_bindings",
"//content/test:test_support",
"//device/bluetooth",
"//media",
"//media/mojo:buildflags",
"//net",
"//net:net_resources",
"//ppapi/buildflags",
"//services/device/public/cpp:test_support",
"//services/network/public/cpp",
"//services/test/echo:lib",
"//services/test/echo/public/mojom",
"//third_party/blink/public:blink",
"//third_party/blink/public:image_resources",
"//third_party/blink/public:resources",
"//third_party/blink/public/strings",
"//third_party/blink/public/strings:accessibility_strings",
"//ui/base",
"//ui/base/clipboard",
"//ui/base/ime/init",
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/platform_window",
"//url",
"//v8",
]
if (is_fuchsia) {
deps += [ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.policy" ]
} else {
deps += [
"//components/crash/content/browser",
"//components/crash/core/app",
]
}
if (enable_plugins) {
sources += [
"browser/shell_plugin_service_filter.cc",
"browser/shell_plugin_service_filter.h",
]
deps += [ "//ppapi/shared_impl" ]
}
if (enable_cast_renderer) {
deps += [ "//media/mojo/services" ]
}
if (is_win) {
sources += [
"common/v8_crashpad_support_win.cc",
"common/v8_crashpad_support_win.h",
]
deps += [ "//gin" ]
}
if (is_linux) {
deps += [ "//ui/views/linux_ui:linux_ui_factory" ]
}
if (is_mac) {
deps += [ "//ui/display:test_support" ]
}
if (is_android) {
deps += [
"//components/embedder_support/android:view",
"//content/shell/android:content_shell_jni_headers",
"//mojo/public/java/system:test_support",
"//ui/android",
]
}
if (shell_use_toolkit_views) {
# All content_shell code should use this define instead of TOOLKIT_VIEWS,
# since any transitive dependency on //ui/views from another component will
# cause TOOLKIT_VIEWS to be defined, even when content_shell does not want
# to use it internally. See https://crbug.com/1218907.
defines += [ "SHELL_USE_TOOLKIT_VIEWS=1" ]
deps += [ "//ui/views" ]
}
if (use_aura) {
deps += [
"//ui/aura",
"//ui/aura:test_support",
"//ui/events",
"//ui/wm",
]
if (shell_use_toolkit_views) {
sources += [
"browser/shell_platform_delegate_views.cc",
"browser/shell_web_contents_view_delegate_views.cc",
]
deps += [
"//ui/color:color_headers",
"//ui/native_theme",
"//ui/resources",
"//ui/views:test_support",
"//ui/views/controls/webview",
"//ui/wm:test_support",
]
} else {
sources += [
"browser/shell_platform_delegate_aura.cc",
"browser/shell_web_contents_view_delegate_aura.cc",
]
}
} else {
sources -= [
"browser/shell_platform_data_aura.cc",
"browser/shell_platform_data_aura.h",
]
}
if (is_chromeos_ash) {
deps += [ "//chromeos/dbus" ]
}
if (is_chromeos_lacros) {
deps += [
"//chromeos/dbus/constants",
"//chromeos/lacros/dbus",
]
}
if (is_linux || is_chromeos) {
deps += [ "//build/config/freetype" ]
}
if (use_ozone) {
deps += [ "//ui/ozone" ]
}
}
grit("content_shell_resources_grit") {
testonly = true
# External code should depend on ":resources" instead.
visibility = [ ":*" ]
source = "shell_resources.grd"
outputs = [
"grit/shell_resources.h",
"shell_resources.pak",
]
}
copy("copy_shell_resources") {
testonly = true
sources = [ "$target_gen_dir/shell_resources.pak" ]
outputs = [ "$root_out_dir/shell_resources.pak" ]
public_deps = [ ":content_shell_resources_grit" ]
}
group("resources") {
testonly = true
public_deps = [ ":copy_shell_resources" ]
}
repack("pak") {
testonly = true
sources = [
"$root_gen_dir/base/tracing/protos/tracing_proto_resources.pak",
"$root_gen_dir/content/browser/resources/media/media_internals_resources.pak",
"$root_gen_dir/content/browser/webrtc/resources/webrtc_internals_resources.pak",
"$root_gen_dir/content/content_resources.pak",
"$root_gen_dir/content/dev_ui_content_resources.pak",
"$root_gen_dir/content/quota_internals_resources.pak",
"$root_gen_dir/content/shell/shell_resources.pak",
"$root_gen_dir/content/test/web_ui_mojo_test_resources.pak",
"$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
"$root_gen_dir/net/net_resources.pak",
"$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
"$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak",
"$root_gen_dir/third_party/blink/public/resources/inspector_overlay_resources.pak",
"$root_gen_dir/third_party/blink/public/strings/blink_accessibility_strings_en-US.pak",
"$root_gen_dir/third_party/blink/public/strings/blink_strings_en-US.pak",
"$root_gen_dir/ui/resources/ui_resources_100_percent.pak",
"$root_gen_dir/ui/resources/webui_generated_resources.pak",
"$root_gen_dir/ui/strings/app_locale_settings_en-US.pak",
"$root_gen_dir/ui/strings/ax_strings_en-US.pak",
"$root_gen_dir/ui/strings/ui_strings_en-US.pak",
]
deps = [
":resources",
"//base/tracing/protos:chrome_track_event_resources",
"//content:content_resources",
"//content:dev_ui_content_resources",
"//content/browser/resources:resources",
"//content/browser/resources/media:resources",
"//content/browser/webrtc/resources",
"//content/test:web_ui_mojo_test_resources",
"//mojo/public/js:resources",
"//net:net_resources",
"//third_party/blink/public:devtools_inspector_resources",
"//third_party/blink/public:resources",
"//third_party/blink/public:scaled_resources_100_percent",
"//third_party/blink/public/strings",
"//third_party/blink/public/strings:accessibility_strings",
"//ui/resources",
"//ui/strings",
]
if (!is_android) {
deps += [ "//content/browser/tracing:resources" ]
sources += [ "$root_gen_dir/content/browser/tracing/tracing_resources.pak" ]
}
if (shell_use_toolkit_views) {
deps += [ "//ui/views/resources" ]
sources +=
[ "$root_gen_dir/ui/views/resources/views_resources_100_percent.pak" ]
}
if (!is_android && !is_fuchsia) {
sources +=
[ "$root_gen_dir/content/browser/devtools/devtools_resources.pak" ]
deps += [ "//content/browser/devtools:devtools_resources" ]
}
output = "$root_out_dir/content_shell.pak"
}
if (is_android) {
group("content_shell") {
testonly = true
deps = [ "//content/shell/android:content_shell_apk" ]
}
} else if (is_mac) {
tweak_info_plist("content_shell_plist") {
testonly = true
info_plist = "app/app-Info.plist"
args = [
"--scm=1",
"--version",
content_shell_version,
]
}
mac_app_bundle("content_shell") {
testonly = true
output_name = content_shell_product_name
sources = [ "app/shell_main_mac.cc" ]
defines = [ "SHELL_PRODUCT_NAME=\"$content_shell_product_name\"" ]
# Must have minimal dependencies. In particular cannot depend on //base.
# Depending on //base leads to loading //base twice (once in the exe, once
# in the main framework).
deps = [
":content_shell_framework_bundle_data",
":content_shell_resources_bundle_data",
# Despite its path, this does not add a //base dependency, see comments in
# the .cc file.
"//base/allocator:early_zone_registration_mac",
"//sandbox/mac:seatbelt",
]
info_plist_target = ":content_shell_plist"
data_deps = [ ":content_shell_app" ]
if (is_component_build) {
ldflags = [ "-Wl,-rpath,@executable_path/../Frameworks" ]
}
}
} else {
executable("thorium_shell") {
testonly = true
sources = [ "app/shell_main.cc" ]
if (is_win) {
sources += [ "app/shell.rc" ]
}
defines = []
deps = [
":content_shell_app",
":pak",
"//build/win:default_exe_manifest",
"//content/public/app",
"//sandbox",
]
data_deps = [
":pak",
"//tools/v8_context_snapshot:v8_context_snapshot",
]
if (is_win) {
deps += [
"//base",
"//sandbox",
]
if (win_console_app) {
defines += [ "WIN_CONSOLE_APP" ]
} else {
# Set /SUBSYSTEM:WINDOWS unless a console build has been requested.
configs -= [ "//build/config/win:console" ]
configs += [ "//build/config/win:windowed" ]
}
}
if (is_win) {
data_deps +=
[ "//third_party/crashpad/crashpad/handler:crashpad_handler" ]
} else if (is_linux || is_chromeos) {
data_deps += [ "//components/crash/core/app:chrome_crashpad_handler" ]
}
if ((is_linux || is_chromeos) && !is_component_build) {
# Set rpath to find our own libfreetype even in a non-component build.
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
}
}
if (is_fuchsia) {
fuchsia_component("content_shell_component") {
testonly = true
manifest = "fuchsia/content_shell.cmx"
data_deps = [ ":thorium_shell" ]
visibility = [ ":*" ]
}
fuchsia_package("content_shell_pkg") {
testonly = true
package_name = "thorium_shell"
deps = [ ":content_shell_component" ]
}
fuchsia_package_installer("content_shell_fuchsia") {
testonly = true
visibility = [
":*", # See https://crbug.com/1328459#c4.
"//:*",
]
package = ":content_shell_pkg"
package_name = "thorium_shell"
}
}
}
if (is_mac) {
bundle_data("content_shell_framework_resources") {
testonly = true
sources = [ "$root_out_dir/content_shell.pak" ]
public_deps = [ ":pak" ]
if (icu_use_data_file) {
sources += [ "$root_out_dir/icudtl.dat" ]
deps = [ "//third_party/icu:icudata" ]
}
if (v8_use_external_startup_data) {
public_deps += [ "//v8" ]
if (use_v8_context_snapshot) {
sources += [ "$root_out_dir/$v8_context_snapshot_filename" ]
public_deps += [ "//tools/v8_context_snapshot" ]
} else {
sources += [ "$root_out_dir/snapshot_blob.bin" ]
}
}
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
}
if (enable_plugins) {
bundle_data("content_shell_framework_plugins") {
sources = [
"$root_out_dir/blink_deprecated_test_plugin.plugin",
"$root_out_dir/blink_test_plugin.plugin",
]
outputs = [ "{{bundle_contents_dir}}/{{source_file_part}}" ]
public_deps = [
"//ppapi:blink_deprecated_test_plugin",
"//ppapi:blink_test_plugin",
]
}
}
content_shell_framework_name = "$content_shell_product_name Framework"
content_shell_helper_name = "$content_shell_product_name Helper"
bundle_data("content_shell_framework_helpers") {
testonly = true
sources = [ "$root_out_dir/chrome_crashpad_handler" ]
outputs = [ "{{bundle_contents_dir}}/Helpers/{{source_file_part}}" ]
public_deps = [ "//components/crash/core/app:chrome_crashpad_handler" ]
foreach(helper_params, content_mac_helpers) {
sources += [
"$root_out_dir/${content_shell_helper_name}${helper_params[2]}.app",
]
public_deps += [ ":content_shell_helper_app_${helper_params[0]}" ]
}
}
tweak_info_plist("content_shell_framework_plist") {
testonly = true
info_plist = "app/framework-Info.plist"
args = [
"--breakpad=0",
"--keystone=0",
"--scm=1",
"--version",
content_shell_version,
"--branding",
content_shell_product_name,
]
}
mac_framework_bundle("content_shell_framework") {
testonly = true
output_name = content_shell_framework_name
framework_version = "C"
framework_contents = [
"Helpers",
"Libraries",
"Resources",
]
sources = [
"app/shell_content_main.cc",
"app/shell_content_main.h",
]
deps = [
":content_shell_angle_library",
":content_shell_app",
"//content/public/app",
"//content/public/common",
"//third_party/icu:icudata",
]
bundle_deps = [
":content_shell_framework_helpers",
":content_shell_framework_resources",
":content_shell_swiftshader_library",
]
if (enable_plugins) {
deps += [ ":content_shell_framework_plugins" ]
}
if (!is_component_build) {
# Specify a sensible install_name for static builds. The library is
# dlopen()ed so this is not used to resolve the module.
ldflags = [ "-Wl,-install_name,@executable_path/../Frameworks/$output_name.framework/$output_name" ]
} else {
# Both the main :content_shell and :content_shell_helper_app executables
# need to link the framework. Because they are at different directory
# depths, using @executable_path as the install_name would require using
# install_name_tool on one of the executables. However install_name_tool
# only operates in-place, which is problematic to express in GN. Instead,
# use rpath-based loading.
ldflags =
[ "-Wl,-install_name,@rpath/$output_name.framework/$output_name" ]
# Set up the rpath for the framework so that it can find dylibs in the
# root output directory. The framework is at
# Content Shell.app/Contents/Frameworks/Content Shell Framework.framework/Versions/C/Content Shell Framework
# so use loader_path to go back to the root output directory.
ldflags += [ "-Wl,-rpath,@loader_path/../../../../../.." ]
}
info_plist_target = ":content_shell_framework_plist"
}
tweak_info_plist("content_shell_helper_plist") {
testonly = true
info_plist = "app/helper-Info.plist"
args = [
"--breakpad=0",
"--keystone=0",
"--scm=0",
"--version",
content_shell_version,
]
}
template("content_shell_helper_app") {
mac_app_bundle(target_name) {
assert(defined(invoker.helper_name_suffix))
assert(defined(invoker.helper_bundle_id_suffix))
testonly = true
output_name = content_shell_helper_name + invoker.helper_name_suffix
sources = [ "app/shell_main_mac.cc" ]
defines = [
"HELPER_EXECUTABLE",
"SHELL_PRODUCT_NAME=\"$content_shell_product_name\"",
]
extra_substitutions = [
"CONTENT_SHELL_HELPER_SUFFIX=${invoker.helper_name_suffix}",
"CONTENT_SHELL_HELPER_BUNDLE_ID_SUFFIX=${invoker.helper_bundle_id_suffix}",
]
deps = [
"//base/allocator:early_zone_registration_mac",
"//sandbox/mac:seatbelt",
]
info_plist_target = ":content_shell_helper_plist"
if (is_component_build) {
ldflags = [
# The helper is in Content Shell.app/Contents/Frameworks/
# Content Shell Framework.framework/Versions/C/Helpers/
# Content Shell Helper.app/Contents/MacOS/
# so set rpath up to the base.
"-Wl,-rpath,@executable_path/../../../../../../../../../..",
# ... and up to Contents/Frameworks.
"-Wl,-rpath,@executable_path/../../../../../../..",
]
# In a component build, the framework is directly linked to the
# executable because dlopen() and loading all the dependent dylibs
# is time-consuming, see https://crbug.com/1197495.
deps += [ ":content_shell_framework+link_nested" ]
}
}
}
foreach(helper_params, content_mac_helpers) {
_helper_target = helper_params[0]
_helper_bundle_id = helper_params[1]
_helper_suffix = helper_params[2]
content_shell_helper_app("content_shell_helper_app_${_helper_target}") {
helper_name_suffix = _helper_suffix
helper_bundle_id_suffix = _helper_bundle_id
}
}
bundle_data("content_shell_framework_bundle_data") {
testonly = true
sources = [ "$root_out_dir/$content_shell_framework_name.framework" ]
outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ]
if (is_component_build) {
# In a component build, the framework is directly linked to the
# executable because dlopen() and loading all the dependent dylibs
# is time-consuming, see https://crbug.com/1197495.
public_deps = [ ":content_shell_framework+link" ]
} else {
public_deps = [ ":content_shell_framework" ]
}
}
bundle_data("content_shell_resources_bundle_data") {
testonly = true
sources = [ "app/app.icns" ]
outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
}
if (use_egl) {
# Add the ANGLE .dylibs in the Libraries directory of the Framework.
bundle_data("content_shell_angle_binaries") {
sources = [
"$root_out_dir/egl_intermediates/libEGL.dylib",
"$root_out_dir/egl_intermediates/libGLESv2.dylib",
]
outputs = [ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}" ]
public_deps = [ "//ui/gl:angle_library_copy" ]
}
# Add the SwiftShader .dylibs in the Libraries directory of the Framework.
bundle_data("content_shell_swiftshader_binaries") {
sources = [
"$root_out_dir/vk_intermediates/libvk_swiftshader.dylib",
"$root_out_dir/vk_intermediates/vk_swiftshader_icd.json",
]
outputs = [ "{{bundle_contents_dir}}/Libraries/{{source_file_part}}" ]
public_deps = [ "//ui/gl:swiftshader_vk_library_copy" ]
}
}
group("content_shell_angle_library") {
if (use_egl) {
deps = [ ":content_shell_angle_binaries" ]
}
}
group("content_shell_swiftshader_library") {
if (use_egl) {
deps = [ ":content_shell_swiftshader_binaries" ]
}
}
}
mojom("content_browsertests_mojom") {
sources = [ "common/power_monitor_test.mojom" ]
public_deps = [ "//sandbox/policy/mojom" ]
}
group("content_shell_crash_test") {
testonly = true
data_deps = [
":thorium_shell",
"//testing:test_scripts_shared",
"//third_party/mesa_headers",
]
data = [
"//content/shell/tools/breakpad_integration_test.py",
"//testing/scripts/content_shell_crash_test.py",
]
if (is_mac && !use_system_xcode) {
data += [
# Scripts call otool, which calls either llvm-otool or otool-classic,
# so we need all three.
# llvm-otool shells out to llvm-objdump, so that's needed as well.
mac_bin_path + "llvm-objdump",
mac_bin_path + "llvm-otool",
mac_bin_path + "otool",
mac_bin_path + "otool-classic",
]
}
if (is_posix) {
data += [
"//components/crash/content/tools/generate_breakpad_symbols.py",
"//components/crash/content/tools/dmp2minidump.py",
]
}
if (is_win) {
data_deps += [ "//build/win:copy_cdb_to_output" ]
}
if (is_posix) {
data_deps += [
"//third_party/breakpad:dump_syms",
"//third_party/breakpad:minidump_stackwalk",
]
}
if (is_android) {
data_deps += [
"//build/android:devil_chromium_py",
"//build/android:test_runner_py",
"//third_party/breakpad:microdump_stackwalk",
"//third_party/breakpad:minidump_dump",
"//third_party/breakpad:symupload",
"//tools/android/forwarder2",
]
}
}
mojom("shell_controller_mojom") {
testonly = true
sources = [ "common/shell_controller.test-mojom" ]
public_deps = [ "//mojo/public/mojom/base" ]
}

View file

@ -0,0 +1,149 @@
//Microsoft Visual C++ generated resource script.
//
#include "content/shell/app/resource.h"
#include "build/branding_buildflags.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDC_CONTENTSHELL MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New Window", IDM_NEW_WINDOW
MENUITEM "&Close Window", IDM_CLOSE_WINDOW
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Debug"
BEGIN
MENUITEM "&Show Developer Tools...", IDM_SHOW_DEVELOPER_TOOLS
END
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ALERT DIALOGEX 0, 0, 241, 76
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Alert"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,184,55,50,14
LTEXT "",IDC_DIALOGTEXT,16,17,210,30
END
IDD_CONFIRM DIALOGEX 0, 0, 241, 76
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Confirm"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14
DEFPUSHBUTTON "OK",IDOK,131,55,50,14
LTEXT "",IDC_DIALOGTEXT,16,17,210,30
END
IDD_PROMPT DIALOGEX 0, 0, 241, 76
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Prompt"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,131,55,50,14
LTEXT "",IDC_DIALOGTEXT,16,17,210,18
PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14
EDITTEXT IDC_PROMPTEDIT,15,33,210,14,ES_AUTOHSCROLL
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ALERT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 234
TOPMARGIN, 7
BOTTOMMARGIN, 69
END
IDD_CONFIRM, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 234
TOPMARGIN, 7
BOTTOMMARGIN, 69
END
IDD_PROMPT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 234
TOPMARGIN, 7
BOTTOMMARGIN, 69
END
END
#endif // APSTUDIO_INVOKED
#endif
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
1 ICON "thorium_shell.ico"

View file

@ -0,0 +1,384 @@
// Copyright (c) 2022 The Chromium Authors and Alex313031. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/shell/app/shell_main_delegate.h"
#include <iostream>
#include <tuple>
#include <utility>
#include "base/base_paths.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/cpu.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/trace_event/trace_log.h"
#include "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
#include "content/common/content_constants_internal.h"
#include "content/public/browser/browser_main_runner.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/url_constants.h"
#include "content/shell/app/shell_crash_reporter_client.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_paths.h"
#include "content/shell/common/shell_content_client.h"
#include "content/shell/common/shell_switches.h"
#include "content/shell/gpu/shell_content_gpu_client.h"
#include "content/shell/renderer/shell_content_renderer_client.h"
#include "content/shell/utility/shell_content_utility_client.h"
#include "ipc/ipc_buildflags.h"
#include "net/cookies/cookie_monster.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "ui/base/resource/resource_bundle.h"
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
#define IPC_MESSAGE_MACROS_LOG_ENABLED
#include "content/public/common/content_ipc_logging.h"
#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \
content::RegisterIPCLogger(msg_id, logger)
#endif
#if !BUILDFLAG(IS_ANDROID)
#include "content/web_test/browser/web_test_browser_main_runner.h" // nogncheck
#include "content/web_test/browser/web_test_content_browser_client.h" // nogncheck
#include "content/web_test/renderer/web_test_content_renderer_client.h" // nogncheck
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/apk_assets.h"
#include "base/posix/global_descriptors.h"
#include "content/public/browser/android/compositor.h"
#include "content/shell/android/shell_descriptors.h"
#endif
#if !BUILDFLAG(IS_FUCHSIA)
#include "components/crash/core/app/crashpad.h" // nogncheck
#endif
#if BUILDFLAG(IS_MAC)
#include "content/shell/app/paths_mac.h"
#include "content/shell/app/shell_main_delegate_mac.h"
#endif // BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include <initguid.h>
#include "base/logging_win.h"
#include "content/shell/common/v8_crashpad_support_win.h"
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
#include "v8/include/v8-wasm-trap-handler-posix.h"
#endif
namespace {
#if !BUILDFLAG(IS_FUCHSIA)
base::LazyInstance<content::ShellCrashReporterClient>::Leaky
g_shell_crash_client = LAZY_INSTANCE_INITIALIZER;
#endif
#if BUILDFLAG(IS_WIN)
// If "Content Shell" doesn't show up in your list of trace providers in
// Sawbuck, add these registry entries to your machine (NOTE the optional
// Wow6432Node key for x64 machines):
// 1. Find: HKLM\SOFTWARE\[Wow6432Node\]Google\Sawbuck\Providers
// 2. Add a subkey with the name "{6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}"
// 3. Add these values:
// "default_flags"=dword:00000001
// "default_level"=dword:00000004
// @="Content Shell"
// {6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}
const GUID kContentShellProviderName = {
0x6a3e50a4, 0x7e15, 0x4099,
{ 0x84, 0x13, 0xec, 0x94, 0xd8, 0xc2, 0xa4, 0xb6 } };
#endif
void InitLogging(const base::CommandLine& command_line) {
base::FilePath log_filename =
command_line.GetSwitchValuePath(switches::kLogFile);
if (log_filename.empty()) {
#if BUILDFLAG(IS_FUCHSIA)
base::PathService::Get(base::DIR_TEMP, &log_filename);
#else
base::PathService::Get(base::DIR_EXE, &log_filename);
#endif
log_filename = log_filename.AppendASCII("thorium_shell.log");
}
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_ALL;
settings.log_file_path = log_filename.value().c_str();
settings.delete_old = logging::DELETE_OLD_LOG_FILE;
logging::InitLogging(settings);
logging::SetLogItems(true /* Process ID */, true /* Thread ID */,
true /* Timestamp */, false /* Tick count */);
}
} // namespace
namespace content {
ShellMainDelegate::ShellMainDelegate(bool is_content_browsertests)
: is_content_browsertests_(is_content_browsertests) {}
ShellMainDelegate::~ShellMainDelegate() {
}
bool ShellMainDelegate::BasicStartupComplete(int* exit_code) {
int dummy;
if (!exit_code)
exit_code = &dummy;
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch("run-layout-test")) {
std::cerr << std::string(79, '*') << "\n"
<< "* The flag --run-layout-test is obsolete. Please use --"
<< switches::kRunWebTests << " instead. *\n"
<< std::string(79, '*') << "\n";
command_line.AppendSwitch(switches::kRunWebTests);
}
#if BUILDFLAG(IS_ANDROID)
Compositor::Initialize();
#endif
#if BUILDFLAG(IS_WIN)
// Enable trace control and transport through event tracing for Windows.
logging::LogEventProvider::Initialize(kContentShellProviderName);
v8_crashpad_support::SetUp();
#endif
#if BUILDFLAG(IS_MAC)
// Needs to happen before InitializeResourceBundle().
OverrideFrameworkBundlePath();
OverrideOuterBundlePath();
OverrideChildProcessPath();
OverrideSourceRootPath();
EnsureCorrectResolutionSettings();
OverrideBundleID();
#endif // BUILDFLAG(IS_MAC)
InitLogging(command_line);
#if !BUILDFLAG(IS_ANDROID)
if (switches::IsRunWebTestsSwitchPresent()) {
const bool browser_process =
command_line.GetSwitchValueASCII(switches::kProcessType).empty();
if (browser_process) {
web_test_runner_ = std::make_unique<WebTestBrowserMainRunner>();
web_test_runner_->Initialize();
}
}
#endif
RegisterShellPathProvider();
return false;
}
bool ShellMainDelegate::ShouldCreateFeatureList(InvokedIn invoked_in) {
return absl::holds_alternative<InvokedInChildProcess>(invoked_in);
}
void ShellMainDelegate::PreSandboxStartup() {
#if defined(ARCH_CPU_ARM_FAMILY) && \
(BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
// Create an instance of the CPU class to parse /proc/cpuinfo and cache
// cpu_brand info.
base::CPU cpu_info;
#endif
// Disable platform crash handling and initialize the crash reporter, if
// requested.
// TODO(crbug.com/1226159): Implement crash reporter integration for Fuchsia.
#if !BUILDFLAG(IS_FUCHSIA)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableCrashReporter)) {
std::string process_type =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType);
crash_reporter::SetCrashReporterClient(g_shell_crash_client.Pointer());
// Reporting for sub-processes will be initialized in ZygoteForked.
if (process_type != switches::kZygoteProcess) {
crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
crash_reporter::SetFirstChanceExceptionHandler(
v8::TryHandleWebAssemblyTrapPosix);
#endif
}
}
#endif // !BUILDFLAG(IS_FUCHSIA)
crash_reporter::InitializeCrashKeys();
InitializeResourceBundle();
}
absl::variant<int, MainFunctionParams> ShellMainDelegate::RunProcess(
const std::string& process_type,
MainFunctionParams main_function_params) {
// For non-browser process, return and have the caller run the main loop.
if (!process_type.empty())
return std::move(main_function_params);
base::trace_event::TraceLog::GetInstance()->set_process_name("Browser");
base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
kTraceEventBrowserProcessSortIndex);
#if !BUILDFLAG(IS_ANDROID)
if (switches::IsRunWebTestsSwitchPresent()) {
// Web tests implement their own BrowserMain() replacement.
web_test_runner_->RunBrowserMain(std::move(main_function_params));
web_test_runner_.reset();
// Returning 0 to indicate that we have replaced BrowserMain() and the
// caller should not call BrowserMain() itself. Web tests do not ever
// return an error.
return 0;
}
// On non-Android, we can return the |main_function_params| back and have the
// caller run BrowserMain() normally.
return std::move(main_function_params);
#else
// On Android, we defer to the system message loop when the stack unwinds.
// So here we only create (and leak) a BrowserMainRunner. The shutdown
// of BrowserMainRunner doesn't happen in Chrome Android and doesn't work
// properly on Android at all.
std::unique_ptr<BrowserMainRunner> main_runner = BrowserMainRunner::Create();
// In browser tests, the |main_function_params| contains a |ui_task| which
// will execute the testing. The task will be executed synchronously inside
// Initialize() so we don't depend on the BrowserMainRunner being Run().
int initialize_exit_code =
main_runner->Initialize(std::move(main_function_params));
DCHECK_LT(initialize_exit_code, 0)
<< "BrowserMainRunner::Initialize failed in ShellMainDelegate";
std::ignore = main_runner.release();
// Return 0 as BrowserMain() should not be called after this, bounce up to
// the system message loop for ContentShell, and we're already done thanks
// to the |ui_task| for browser tests.
return 0;
#endif
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void ShellMainDelegate::ZygoteForked() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableCrashReporter)) {
std::string process_type =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType);
crash_reporter::InitializeCrashpad(false, process_type);
crash_reporter::SetFirstChanceExceptionHandler(
v8::TryHandleWebAssemblyTrapPosix);
}
}
#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void ShellMainDelegate::InitializeResourceBundle() {
#if BUILDFLAG(IS_ANDROID)
// On Android, the renderer runs with a different UID and can never access
// the file system. Use the file descriptor passed in at launch time.
auto* global_descriptors = base::GlobalDescriptors::GetInstance();
int pak_fd = global_descriptors->MaybeGet(kShellPakDescriptor);
base::MemoryMappedFile::Region pak_region;
if (pak_fd >= 0) {
pak_region = global_descriptors->GetRegion(kShellPakDescriptor);
} else {
pak_fd =
base::android::OpenApkAsset("assets/content_shell.pak", &pak_region);
// Loaded from disk for browsertests.
if (pak_fd < 0) {
base::FilePath pak_file;
bool r = base::PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file);
DCHECK(r);
pak_file = pak_file.Append(FILE_PATH_LITERAL("paks"));
pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
pak_fd = base::File(pak_file, flags).TakePlatformFile();
pak_region = base::MemoryMappedFile::Region::kWholeFile;
}
global_descriptors->Set(kShellPakDescriptor, pak_fd, pak_region);
}
DCHECK_GE(pak_fd, 0);
// TODO(crbug.com/330930): A better way to prevent fdsan error from a double
// close is to refactor GlobalDescriptors.{Get,MaybeGet} to return
// "const base::File&" rather than fd itself.
base::File android_pak_file(pak_fd);
ui::ResourceBundle::InitSharedInstanceWithPakFileRegion(
android_pak_file.Duplicate(), pak_region);
ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
std::move(android_pak_file), pak_region, ui::k100Percent);
#elif BUILDFLAG(IS_MAC)
ui::ResourceBundle::InitSharedInstanceWithPakPath(GetResourcesPakFilePath());
#else
base::FilePath pak_file;
bool r = base::PathService::Get(base::DIR_ASSETS, &pak_file);
DCHECK(r);
pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
#endif
}
void ShellMainDelegate::PreBrowserMain() {
#if BUILDFLAG(IS_MAC)
RegisterShellCrApp();
#endif
}
void ShellMainDelegate::PostEarlyInitialization(InvokedIn invoked_in) {
if (!ShouldCreateFeatureList(invoked_in)) {
// Apply field trial testing configuration since content did not.
browser_client_->CreateFeatureListAndFieldTrials();
}
}
ContentClient* ShellMainDelegate::CreateContentClient() {
content_client_ = std::make_unique<ShellContentClient>();
return content_client_.get();
}
ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() {
#if !BUILDFLAG(IS_ANDROID)
if (switches::IsRunWebTestsSwitchPresent()) {
browser_client_ = std::make_unique<WebTestContentBrowserClient>();
return browser_client_.get();
}
#endif
browser_client_ = std::make_unique<ShellContentBrowserClient>();
return browser_client_.get();
}
ContentGpuClient* ShellMainDelegate::CreateContentGpuClient() {
gpu_client_ = std::make_unique<ShellContentGpuClient>();
return gpu_client_.get();
}
ContentRendererClient* ShellMainDelegate::CreateContentRendererClient() {
#if !BUILDFLAG(IS_ANDROID)
if (switches::IsRunWebTestsSwitchPresent()) {
renderer_client_ = std::make_unique<WebTestContentRendererClient>();
return renderer_client_.get();
}
#endif
renderer_client_ = std::make_unique<ShellContentRendererClient>();
return renderer_client_.get();
}
ContentUtilityClient* ShellMainDelegate::CreateContentUtilityClient() {
utility_client_ =
std::make_unique<ShellContentUtilityClient>(is_content_browsertests_);
return utility_client_.get();
}
} // namespace content

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -0,0 +1,453 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <algorithm>
#include <memory>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "content/public/browser/context_factory.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_platform_delegate.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/color/color_id.h"
#include "ui/events/event.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/layout/flex_layout_view.h"
#include "ui/views/test/desktop_test_views_delegate.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ui/wm/test/wm_test_helper.h"
#else // !BUILDFLAG(IS_CHROMEOS_ASH)
#include "ui/display/screen.h"
#include "ui/views/widget/desktop_aura/desktop_screen.h"
#include "ui/wm/core/wm_state.h"
#endif
#if BUILDFLAG(IS_WIN)
#include <fcntl.h>
#include <io.h>
#endif
namespace content {
struct ShellPlatformDelegate::ShellData {
gfx::Size content_size;
// Self-owned Widget, destroyed through CloseNow().
views::Widget* window_widget = nullptr;
};
struct ShellPlatformDelegate::PlatformData {
#if BUILDFLAG(IS_CHROMEOS_ASH)
std::unique_ptr<wm::WMTestHelper> wm_test_helper;
#else
std::unique_ptr<wm::WMState> wm_state;
std::unique_ptr<display::Screen> screen;
#endif
// TODO(danakj): This looks unused?
std::unique_ptr<views::ViewsDelegate> views_delegate;
};
namespace {
// Maintain the UI controls and web view for content shell
class ShellView : public views::BoxLayoutView,
public views::TextfieldController {
public:
METADATA_HEADER(ShellView);
enum UIControl { BACK_BUTTON, FORWARD_BUTTON, STOP_BUTTON };
explicit ShellView(Shell* shell) : shell_(shell) { InitShellWindow(); }
ShellView(const ShellView&) = delete;
ShellView& operator=(const ShellView&) = delete;
~ShellView() override = default;
// Update the state of UI controls
void SetAddressBarURL(const GURL& url) {
url_entry_->SetText(base::ASCIIToUTF16(url.spec()));
}
void SetWebContents(WebContents* web_contents, const gfx::Size& size) {
// If there was a previous WebView in this Shell it should be removed and
// deleted.
if (web_view_)
contents_view_->RemoveChildViewT(web_view_.get());
views::Builder<views::View>(contents_view_)
.AddChild(views::Builder<views::WebView>()
.CopyAddressTo(&web_view_)
.SetBrowserContext(web_contents->GetBrowserContext())
.SetWebContents(web_contents)
.SetPreferredSize(size))
.BuildChildren();
web_contents->Focus();
web_view_->SizeToPreferredSize();
// Resize the widget, keeping the same origin.
gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen();
bounds.set_size(GetWidget()->GetRootView()->GetPreferredSize());
GetWidget()->SetBounds(bounds);
// Resizing a widget on chromeos doesn't automatically resize the root, need
// to explicitly do that.
#if BUILDFLAG(IS_CHROMEOS_ASH)
GetWidget()->GetNativeWindow()->GetHost()->SetBoundsInPixels(bounds);
#endif
}
void EnableUIControl(UIControl control, bool is_enabled) {
if (control == BACK_BUTTON) {
back_button_->SetState(is_enabled ? views::Button::STATE_NORMAL
: views::Button::STATE_DISABLED);
} else if (control == FORWARD_BUTTON) {
forward_button_->SetState(is_enabled ? views::Button::STATE_NORMAL
: views::Button::STATE_DISABLED);
} else if (control == STOP_BUTTON) {
stop_button_->SetState(is_enabled ? views::Button::STATE_NORMAL
: views::Button::STATE_DISABLED);
}
}
private:
// Initialize the UI control contained in shell window
void InitShellWindow() {
auto toolbar_button_rule = [](const views::View* view,
const views::SizeBounds& size_bounds) {
gfx::Size preferred_size = view->GetPreferredSize();
if (size_bounds != views::SizeBounds() &&
size_bounds.width().is_bounded()) {
preferred_size.set_width(std::max(
std::min(size_bounds.width().value(), preferred_size.width()),
preferred_size.width() / 2));
}
return preferred_size;
};
auto builder =
views::Builder<views::BoxLayoutView>(this)
.SetBackground(
views::CreateThemedSolidBackground(ui::kColorWindowBackground))
.SetOrientation(views::BoxLayout::Orientation::kVertical);
if (!Shell::ShouldHideToolbar()) {
builder.AddChild(
views::Builder<views::FlexLayoutView>()
.CopyAddressTo(&toolbar_view_)
.SetOrientation(views::LayoutOrientation::kHorizontal)
// Top padding = 2, Bottom padding = 5
.SetProperty(views::kMarginsKey, gfx::Insets::TLBR(2, 0, 5, 0))
.AddChildren(
views::Builder<views::MdTextButton>()
.CopyAddressTo(&back_button_)
.SetText(u"Back")
.SetCallback(base::BindRepeating(
&Shell::GoBackOrForward,
base::Unretained(shell_.get()), -1))
.SetProperty(views::kFlexBehaviorKey,
views::FlexSpecification(base::BindRepeating(
toolbar_button_rule))),
views::Builder<views::MdTextButton>()
.CopyAddressTo(&forward_button_)
.SetText(u"Forward")
.SetCallback(base::BindRepeating(
&Shell::GoBackOrForward,
base::Unretained(shell_.get()), 1))
.SetProperty(views::kFlexBehaviorKey,
views::FlexSpecification(base::BindRepeating(
toolbar_button_rule))),
views::Builder<views::MdTextButton>()
.CopyAddressTo(&refresh_button_)
.SetText(u"Refresh")
.SetCallback(base::BindRepeating(
&Shell::Reload, base::Unretained(shell_.get())))
.SetProperty(views::kFlexBehaviorKey,
views::FlexSpecification(base::BindRepeating(
toolbar_button_rule))),
views::Builder<views::MdTextButton>()
.CopyAddressTo(&stop_button_)
.SetText(u"Stop")
.SetCallback(base::BindRepeating(
&Shell::Stop, base::Unretained(shell_.get())))
.SetProperty(views::kFlexBehaviorKey,
views::FlexSpecification(base::BindRepeating(
toolbar_button_rule))),
views::Builder<views::Textfield>()
.CopyAddressTo(&url_entry_)
.SetAccessibleName(u"Enter URL")
.SetController(this)
.SetTextInputType(ui::TextInputType::TEXT_INPUT_TYPE_URL)
.SetProperty(
views::kFlexBehaviorKey,
views::FlexSpecification(
views::MinimumFlexSizeRule::kScaleToMinimum,
views::MaximumFlexSizeRule::kUnbounded))
// Left padding = 2, Right padding = 2
.SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, 2, 0, 2))));
}
builder.AddChild(views::Builder<views::View>()
.CopyAddressTo(&contents_view_)
.SetUseDefaultFillLayout(true)
.CustomConfigure(base::BindOnce([](views::View* view) {
if (!Shell::ShouldHideToolbar()) {
view->SetProperty(views::kMarginsKey,
gfx::Insets::TLBR(0, 2, 0, 2));
}
})));
if (!Shell::ShouldHideToolbar()) {
builder.AddChild(views::Builder<views::View>().SetProperty(
views::kMarginsKey, gfx::Insets::TLBR(0, 0, 5, 0)));
}
std::move(builder).BuildChildren();
SetFlexForView(contents_view_, 1);
}
void InitAccelerators() {
// This function must be called when part of the widget hierarchy.
DCHECK(GetWidget());
static const ui::KeyboardCode keys[] = {ui::VKEY_F5, ui::VKEY_BROWSER_BACK,
ui::VKEY_BROWSER_FORWARD};
for (size_t i = 0; i < std::size(keys); ++i) {
GetFocusManager()->RegisterAccelerator(
ui::Accelerator(keys[i], ui::EF_NONE),
ui::AcceleratorManager::kNormalPriority, this);
}
}
// Overridden from TextfieldController
void ContentsChanged(views::Textfield* sender,
const std::u16string& new_contents) override {}
bool HandleKeyEvent(views::Textfield* sender,
const ui::KeyEvent& key_event) override {
if (key_event.type() == ui::ET_KEY_PRESSED && sender == url_entry_ &&
key_event.key_code() == ui::VKEY_RETURN) {
std::string text = base::UTF16ToUTF8(url_entry_->GetText());
GURL url(text);
if (!url.has_scheme()) {
url = GURL(std::string("http://") + std::string(text));
url_entry_->SetText(base::ASCIIToUTF16(url.spec()));
}
shell_->LoadURL(url);
return true;
}
return false;
}
// Overridden from View
gfx::Size GetMinimumSize() const override {
// We want to be able to make the window smaller than its initial
// (preferred) size.
return gfx::Size();
}
void AddedToWidget() override { InitAccelerators(); }
// Overridden from AcceleratorTarget:
bool AcceleratorPressed(const ui::Accelerator& accelerator) override {
switch (accelerator.key_code()) {
case ui::VKEY_F5:
shell_->Reload();
return true;
case ui::VKEY_BROWSER_BACK:
shell_->GoBackOrForward(-1);
return true;
case ui::VKEY_BROWSER_FORWARD:
shell_->GoBackOrForward(1);
return true;
default:
return views::View::AcceleratorPressed(accelerator);
}
}
private:
std::unique_ptr<Shell> shell_;
// Window title
std::u16string title_;
// Toolbar view contains forward/backward/reload button and URL entry
raw_ptr<views::View> toolbar_view_ = nullptr;
raw_ptr<views::Button> back_button_ = nullptr;
raw_ptr<views::Button> forward_button_ = nullptr;
raw_ptr<views::Button> refresh_button_ = nullptr;
raw_ptr<views::Button> stop_button_ = nullptr;
raw_ptr<views::Textfield> url_entry_ = nullptr;
// Contents view contains the web contents view
raw_ptr<views::View> contents_view_ = nullptr;
raw_ptr<views::WebView, DanglingUntriaged> web_view_ = nullptr;
};
BEGIN_METADATA(ShellView, views::View)
END_METADATA
ShellView* ShellViewForWidget(views::Widget* widget) {
return static_cast<ShellView*>(widget->widget_delegate()->GetContentsView());
}
} // namespace
ShellPlatformDelegate::ShellPlatformDelegate() = default;
void ShellPlatformDelegate::Initialize(const gfx::Size& default_window_size) {
#if BUILDFLAG(IS_WIN)
_setmode(_fileno(stdout), _O_BINARY);
_setmode(_fileno(stderr), _O_BINARY);
#endif
platform_ = std::make_unique<PlatformData>();
#if BUILDFLAG(IS_CHROMEOS_ASH)
platform_->wm_test_helper =
std::make_unique<wm::WMTestHelper>(default_window_size);
#else
platform_->wm_state = std::make_unique<wm::WMState>();
// FakeScreen tests create their own screen.
if (!display::Screen::HasScreen())
platform_->screen = views::CreateDesktopScreen();
#endif
platform_->views_delegate =
std::make_unique<views::DesktopTestViewsDelegate>();
}
ShellPlatformDelegate::~ShellPlatformDelegate() = default;
void ShellPlatformDelegate::CreatePlatformWindow(
Shell* shell,
const gfx::Size& initial_size) {
DCHECK(!base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];
shell_data.content_size = initial_size;
auto delegate = std::make_unique<views::WidgetDelegate>();
delegate->SetContentsView(std::make_unique<ShellView>(shell));
delegate->SetHasWindowSizeControls(true);
delegate->SetOwnedByWidget(true);
#if BUILDFLAG(IS_CHROMEOS_ASH)
shell_data.window_widget = views::Widget::CreateWindowWithContext(
std::move(delegate),
platform_->wm_test_helper->GetDefaultParent(nullptr, gfx::Rect()),
gfx::Rect(initial_size));
#else
shell_data.window_widget = new views::Widget();
views::Widget::InitParams params;
params.bounds = gfx::Rect(initial_size);
params.delegate = delegate.release();
params.wm_class_class = "Thorium_Shell";
params.wm_class_name = params.wm_class_class;
shell_data.window_widget->Init(std::move(params));
#endif
// |window_widget| is made visible in PlatformSetContents(), so that the
// platform-window size does not need to change due to layout again.
}
gfx::NativeWindow ShellPlatformDelegate::GetNativeWindow(Shell* shell) {
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];
return shell_data.window_widget->GetNativeWindow();
}
void ShellPlatformDelegate::CleanUp(Shell* shell) {
DCHECK(base::Contains(shell_data_map_, shell));
shell_data_map_.erase(shell);
}
void ShellPlatformDelegate::SetContents(Shell* shell) {
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];
ShellViewForWidget(shell_data.window_widget)
->SetWebContents(shell->web_contents(), shell_data.content_size);
shell_data.window_widget->GetNativeWindow()->GetHost()->Show();
shell_data.window_widget->Show();
}
void ShellPlatformDelegate::ResizeWebContent(Shell* shell,
const gfx::Size& content_size) {
shell->web_contents()->Resize(gfx::Rect(content_size));
}
void ShellPlatformDelegate::EnableUIControl(Shell* shell,
UIControl control,
bool is_enabled) {
if (Shell::ShouldHideToolbar())
return;
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];
auto* view = ShellViewForWidget(shell_data.window_widget);
if (control == BACK_BUTTON) {
view->EnableUIControl(ShellView::BACK_BUTTON, is_enabled);
} else if (control == FORWARD_BUTTON) {
view->EnableUIControl(ShellView::FORWARD_BUTTON, is_enabled);
} else if (control == STOP_BUTTON) {
view->EnableUIControl(ShellView::STOP_BUTTON, is_enabled);
}
}
void ShellPlatformDelegate::SetAddressBarURL(Shell* shell, const GURL& url) {
if (Shell::ShouldHideToolbar())
return;
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];
ShellViewForWidget(shell_data.window_widget)->SetAddressBarURL(url);
}
void ShellPlatformDelegate::SetIsLoading(Shell* shell, bool loading) {}
void ShellPlatformDelegate::SetTitle(Shell* shell,
const std::u16string& title) {
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];
shell_data.window_widget->widget_delegate()->SetTitle(title);
}
void ShellPlatformDelegate::MainFrameCreated(Shell* shell) {}
bool ShellPlatformDelegate::DestroyShell(Shell* shell) {
DCHECK(base::Contains(shell_data_map_, shell));
ShellData& shell_data = shell_data_map_[shell];
shell_data.window_widget->CloseNow();
return true; // The CloseNow() will do the destruction of Shell.
}
} // namespace content

3106
src/content/test/BUILD.gn Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
// Copyright 2022 The Chromium Authors and Alex313031. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/ui_util.h"
#include "base/command_line.h"
#include "extensions/common/extension.h"
#include "extensions/common/switches.h"
namespace extensions {
namespace ui_util {
bool ShouldDisplayInExtensionSettings(Manifest::Type type,
mojom::ManifestLocation location) {
// Don't show for themes since the settings UI isn't really useful for them.
if (type == Manifest::TYPE_THEME)
return true;
// Hide component extensions because they are only extensions as an
// implementation detail of Chrome.
if (Manifest::IsComponentLocation(location)) {
return true;
}
// Unless they are unpacked, never show hosted apps. Note: We intentionally
// show packaged apps and platform apps because there are some pieces of
// functionality that are only available in chrome://extensions/ but which
// are needed for packaged and platform apps. For example, inspecting
// background pages. See http://crbug.com/116134.
if (!Manifest::IsUnpackedLocation(location) &&
type == Manifest::TYPE_HOSTED_APP) {
return true;
}
return true;
}
bool ShouldDisplayInExtensionSettings(const Extension& extension) {
return ShouldDisplayInExtensionSettings(extension.GetType(),
extension.location());
}
} // namespace ui_util
} // namespace extensions