diff --git a/.gitignore b/.gitignore index 689792c..c2ab5fb 100644 --- a/.gitignore +++ b/.gitignore
@@ -77,6 +77,7 @@ /build/linux/bin/eu-strip /build/linux/debian_*-sysroot/ /build/linux/ubuntu_*-sysroot/ +/build/ios_files /build/mac_files /buildtools # The Chrome OS build creates a /c symlink due to http://crbug.com/54866.
diff --git a/DEPS b/DEPS index 1ea71c3c..01c9bcf 100644 --- a/DEPS +++ b/DEPS
@@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'd71b47153f165d7c823deadc02a0c3b5102630ce', + 'catapult_revision': '6377613b1a29bc80e2077bf4e956b9b921ebdab3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -356,7 +356,7 @@ Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '43555c66627f6ed44817855a0f6d465f559d30e0', 'src/ios/third_party/material_components_ios/src': - Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'b1eb638d70792b7aa06118b128e3518c20e2aaae', + Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '43c7f9494f171baaf08d75cf3646eeb98a03252f', 'src/ios/third_party/material_font_disk_loader_ios/src': Var('chromium_git') + '/external/github.com/material-foundation/material-font-disk-loader-ios.git' + '@' + '93acc021e3034898716028822cb802a3a816be7e',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 2284a0f..36afa36 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -2278,8 +2278,10 @@ """Checks that all source files use SYSLOG properly.""" syslog_files = [] for f in input_api.AffectedSourceFiles(source_file_filter): - if 'SYSLOG' in input_api.ReadFile(f, 'rb'): - syslog_files.append(f.LocalPath()) + for line_number, line in f.ChangedContents(): + if 'SYSLOG' in line: + syslog_files.append(f.LocalPath() + ':' + str(line_number)) + if syslog_files: return [output_api.PresubmitPromptWarning( 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
diff --git a/build/mac_toolchain.py b/build/mac_toolchain.py index c0e5e7f..c4de86f9 100755 --- a/build/mac_toolchain.py +++ b/build/mac_toolchain.py
@@ -40,34 +40,34 @@ GCLIENT_CONFIG = os.path.join(os.path.dirname(REPO_ROOT), '.gclient') BASE_DIR = os.path.abspath(os.path.dirname(__file__)) -TOOLCHAIN_BUILD_DIR = os.path.join(BASE_DIR, 'mac_files', 'Xcode.app') -STAMP_FILE = os.path.join(BASE_DIR, 'mac_files', 'toolchain_build_revision') +TOOLCHAIN_BUILD_DIR = os.path.join(BASE_DIR, '%s_files', 'Xcode.app') +STAMP_FILE = os.path.join(BASE_DIR, '%s_files', 'toolchain_build_revision') TOOLCHAIN_URL = 'gs://chrome-mac-sdk/' -def IsIOSPlatform(): +def GetPlatforms(): + default_target_os = ["mac"] try: env = {} execfile(GCLIENT_CONFIG, env, env) - if 'ios' in env.get('target_os', []): - return True + return env.get('target_os', default_target_os) except: pass - return False + return default_target_os -def ReadStampFile(): +def ReadStampFile(target_os): """Return the contents of the stamp file, or '' if it doesn't exist.""" try: - with open(STAMP_FILE, 'r') as f: + with open(STAMP_FILE % target_os, 'r') as f: return f.read().rstrip() except IOError: return '' -def WriteStampFile(s): +def WriteStampFile(target_os, s): """Write s to the stamp file.""" - EnsureDirExists(os.path.dirname(STAMP_FILE)) - with open(STAMP_FILE, 'w') as f: + EnsureDirExists(os.path.dirname(STAMP_FILE % target_os)) + with open(STAMP_FILE % target_os, 'w') as f: f.write(s) f.write('\n') @@ -101,6 +101,7 @@ proc.communicate() return proc.returncode == 0 + def LoadPlist(path): """Loads Plist at |path| and returns it as a dictionary.""" fd, name = tempfile.mkstemp() @@ -112,7 +113,7 @@ os.unlink(name) -def AcceptLicense(): +def AcceptLicense(target_os): """Use xcodebuild to accept new toolchain license if necessary. Don't accept the license if a newer license has already been accepted. This only works if xcodebuild and xcode-select are passwordless in sudoers.""" @@ -120,7 +121,7 @@ # Check old license try: target_license_plist_path = \ - os.path.join(TOOLCHAIN_BUILD_DIR, + os.path.join(TOOLCHAIN_BUILD_DIR % target_os, *['Contents','Resources','LicenseInfo.plist']) target_license_plist = LoadPlist(target_license_plist_path) build_type = target_license_plist['licenseType'] @@ -147,17 +148,17 @@ old_path = subprocess.Popen(['/usr/bin/xcode-select', '-p'], stdout=subprocess.PIPE).communicate()[0].strip() try: - build_dir = os.path.join(TOOLCHAIN_BUILD_DIR, 'Contents/Developer') + build_dir = os.path.join( + TOOLCHAIN_BUILD_DIR % target_os, 'Contents/Developer') subprocess.check_call(['sudo', '/usr/bin/xcode-select', '-s', build_dir]) subprocess.check_call(['sudo', '/usr/bin/xcodebuild', '-license', 'accept']) finally: subprocess.check_call(['sudo', '/usr/bin/xcode-select', '-s', old_path]) -def _UseHermeticToolchain(): +def _UseHermeticToolchain(target_os): current_dir = os.path.dirname(os.path.realpath(__file__)) script_path = os.path.join(current_dir, 'mac/should_use_hermetic_xcode.py') - target_os = 'ios' if IsIOSPlatform() else 'mac' proc = subprocess.Popen([script_path, target_os], stdout=subprocess.PIPE) return '1' in proc.stdout.readline() @@ -186,27 +187,17 @@ sys.exit(1) -def main(): - if sys.platform != 'darwin': +def DownloadHermeticBuild(target_os, default_version, toolchain_filename): + if not _UseHermeticToolchain(target_os): + print 'Using local toolchain for %s.' % target_os return 0 - if not _UseHermeticToolchain(): - print 'Using local toolchain.' - return 0 - - if IsIOSPlatform(): - default_version = IOS_TOOLCHAIN_VERSION - toolchain_filename = 'ios-toolchain-%s.tgz' - else: - default_version = MAC_TOOLCHAIN_VERSION - toolchain_filename = 'toolchain-%s.tgz' - toolchain_version = os.environ.get('MAC_TOOLCHAIN_REVISION', default_version) - if ReadStampFile() == toolchain_version: + if ReadStampFile(target_os) == toolchain_version: print 'Toolchain (%s) is already up to date.' % toolchain_version - AcceptLicense() + AcceptLicense(target_os) return 0 if not CanAccessToolchainBucket(): @@ -214,7 +205,7 @@ return 1 # Reset the stamp file in case the build is unsuccessful. - WriteStampFile('') + WriteStampFile(target_os, '') toolchain_file = '%s.tgz' % toolchain_version toolchain_full_url = TOOLCHAIN_URL + toolchain_file @@ -223,11 +214,11 @@ try: toolchain_file = toolchain_filename % toolchain_version toolchain_full_url = TOOLCHAIN_URL + toolchain_file - DownloadAndUnpack(toolchain_full_url, TOOLCHAIN_BUILD_DIR) - AcceptLicense() + DownloadAndUnpack(toolchain_full_url, TOOLCHAIN_BUILD_DIR % target_os) + AcceptLicense(target_os) print 'Toolchain %s unpacked.' % toolchain_version - WriteStampFile(toolchain_version) + WriteStampFile(target_os, toolchain_version) return 0 except Exception as e: print 'Failed to download toolchain %s.' % toolchain_file @@ -235,5 +226,26 @@ print 'Exiting.' return 1 + +def main(): + if sys.platform != 'darwin': + return 0 + + for target_os in GetPlatforms(): + if target_os == 'ios': + default_version = IOS_TOOLCHAIN_VERSION + toolchain_filename = 'ios-toolchain-%s.tgz' + else: + default_version = MAC_TOOLCHAIN_VERSION + toolchain_filename = 'toolchain-%s.tgz' + + return_value = DownloadHermeticBuild( + target_os, default_version, toolchain_filename) + if return_value: + return return_value + + return 0 + + if __name__ == '__main__': sys.exit(main())
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni index b89733b1..48e3671 100644 --- a/build/toolchain/toolchain.gni +++ b/build/toolchain/toolchain.gni
@@ -45,7 +45,7 @@ # The path to the hermetic install of Xcode. Only relevant when # use_system_xcode = false. hermetic_xcode_path = - rebase_path("//build/mac_files/Xcode.app", "", root_build_dir) + rebase_path("//build/${target_os}_files/Xcode.app", "", root_build_dir) declare_args() { if (is_clang) {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 65053020..fdcbecf 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -263,6 +263,8 @@ "arc/fileapi/arc_file_system_instance_util.h", "arc/fileapi/arc_file_system_service.cc", "arc/fileapi/arc_file_system_service.h", + "arc/fileapi/arc_media_view_util.cc", + "arc/fileapi/arc_media_view_util.h", "arc/intent_helper/arc_external_protocol_dialog.cc", "arc/intent_helper/arc_external_protocol_dialog.h", "arc/intent_helper/arc_navigation_throttle.cc",
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.cc index 8068a7f..26c3db5 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.cc
@@ -14,11 +14,48 @@ namespace arc { +// This is based on net/base/escape.cc: net::(anonymous namespace)::Escape. +// TODO(nya): Consider consolidating this function with EscapeFileSystemId() in +// chrome/browser/chromeos/file_system_provider/mount_path_util.cc. +// This version differs from the other one in the point that dots are not always +// escaped because authorities often contain harmless dots. +std::string EscapePathComponent(const std::string& name) { + std::string escaped; + // Escape dots only when they forms a special file name. + if (name == "." || name == "..") { + base::ReplaceChars(name, ".", "%2E", &escaped); + return escaped; + } + // Escape % and / only. + for (size_t i = 0; i < name.size(); ++i) { + const char c = name[i]; + if (c == '%' || c == '/') + base::StringAppendF(&escaped, "%%%02X", c); + else + escaped.push_back(c); + } + return escaped; +} + +std::string UnescapePathComponent(const std::string& escaped) { + return net::UnescapeURLComponent( + escaped, net::UnescapeRule::PATH_SEPARATORS | + net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); +} + const char kDocumentsProviderMountPointName[] = "arc-documents-provider"; const base::FilePath::CharType kDocumentsProviderMountPointPath[] = "/special/arc-documents-provider"; const char kAndroidDirectoryMimeType[] = "vnd.android.document/directory"; +base::FilePath GetDocumentsProviderMountPath( + const std::string& authority, + const std::string& root_document_id) { + return base::FilePath(kDocumentsProviderMountPointPath) + .Append(EscapePathComponent(authority)) + .Append(EscapePathComponent(root_document_id)); +} + bool ParseDocumentsProviderUrl(const storage::FileSystemURL& url, std::string* authority, std::string* root_document_id, @@ -39,12 +76,11 @@ if (components.size() < 5) return false; - *authority = components[3]; - *root_document_id = components[4]; + *authority = UnescapePathComponent(components[3]); + *root_document_id = UnescapePathComponent(components[4]); - base::FilePath root_path = base::FilePath(kDocumentsProviderMountPointPath) - .Append(*authority) - .Append(*root_document_id); + base::FilePath root_path = + GetDocumentsProviderMountPath(*authority, *root_document_id); // Special case: AppendRelativePath() fails for identical paths. if (url_path_stripped == root_path) { path->clear();
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h index 38ae3c86..1ba3583 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h
@@ -29,7 +29,28 @@ // Defined as DocumentsContract.Document.MIME_TYPE_DIR in Android. extern const char kAndroidDirectoryMimeType[]; +// Escapes a string so it can be used as a file/directory name. +// [%/.] are escaped with percent-encoding. +// NOTE: This function is visible only for unit testing. Usually you should not +// call this function directly. +std::string EscapePathComponent(const std::string& name); + +// Unescapes a string escaped by EscapePathComponent(). +// NOTE: This function is visible only for unit testing. Usually you should not +// call this function directly. +std::string UnescapePathComponent(const std::string& escaped); + +// Returns the path of a directory where the specified DocumentsProvider is +// mounted. +// Appropriate escaping is done to embed |authority| and |root_document_id| in +// a file path. +base::FilePath GetDocumentsProviderMountPath( + const std::string& authority, + const std::string& root_document_id); + // Parses a FileSystemURL pointing to ARC documents provider file system. +// Appropriate unescaping is done to extract |authority| and |root_document_id| +// from |url|. // On success, true is returned. All arguments must not be nullptr. bool ParseDocumentsProviderUrl(const storage::FileSystemURL& url, std::string* authority,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util_unittest.cc index 3374aaf..496bdd4e 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util_unittest.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util_unittest.cc
@@ -12,6 +12,45 @@ namespace { +TEST(ArcDocumentsProviderUtilTest, EscapePathComponent) { + EXPECT_EQ("", EscapePathComponent("")); + EXPECT_EQ("%2E", EscapePathComponent(".")); + EXPECT_EQ("%2E%2E", EscapePathComponent("..")); + EXPECT_EQ("...", EscapePathComponent("...")); + EXPECT_EQ("example.com", EscapePathComponent("example.com")); + EXPECT_EQ("%2F%2F%2F", EscapePathComponent("///")); + EXPECT_EQ("100%25", EscapePathComponent("100%")); + EXPECT_EQ("a b", EscapePathComponent("a b")); + EXPECT_EQ("ねこ", EscapePathComponent("ねこ")); +} + +TEST(ArcDocumentsProviderUtilTest, UnescapePathComponent) { + EXPECT_EQ("", UnescapePathComponent("")); + EXPECT_EQ(".", UnescapePathComponent("%2E")); + EXPECT_EQ("..", UnescapePathComponent("%2E%2E")); + EXPECT_EQ("...", UnescapePathComponent("...")); + EXPECT_EQ("example.com", UnescapePathComponent("example.com")); + EXPECT_EQ("///", UnescapePathComponent("%2F%2F%2F")); + EXPECT_EQ("100%", UnescapePathComponent("100%25")); + EXPECT_EQ("a b", UnescapePathComponent("a b")); + EXPECT_EQ("ねこ", UnescapePathComponent("ねこ")); +} + +TEST(ArcDocumentsProviderUtilTest, GetDocumentsProviderMountPath) { + EXPECT_EQ("/special/arc-documents-provider/authority/document_id", + GetDocumentsProviderMountPath("authority", "document_id").value()); + EXPECT_EQ("/special/arc-documents-provider/a b/a b", + GetDocumentsProviderMountPath("a b", "a b").value()); + EXPECT_EQ("/special/arc-documents-provider/a%2Fb/a%2Fb", + GetDocumentsProviderMountPath("a/b", "a/b").value()); + EXPECT_EQ("/special/arc-documents-provider/%2E/%2E", + GetDocumentsProviderMountPath(".", ".").value()); + EXPECT_EQ("/special/arc-documents-provider/%2E%2E/%2E%2E", + GetDocumentsProviderMountPath("..", "..").value()); + EXPECT_EQ("/special/arc-documents-provider/.../...", + GetDocumentsProviderMountPath("...", "...").value()); +} + TEST(ArcDocumentsProviderUtilTest, ParseDocumentsProviderUrl) { std::string authority; std::string root_document_id; @@ -118,6 +157,22 @@ &authority, &root_document_id, &path)); } +TEST(ArcDocumentsProviderUtilTest, ParseDocumentsProviderUrlUnescape) { + std::string authority; + std::string root_document_id; + base::FilePath path; + + EXPECT_TRUE(ParseDocumentsProviderUrl( + storage::FileSystemURL::CreateForTest( + GURL(), storage::kFileSystemTypeArcDocumentsProvider, + base::FilePath( + "/special/arc-documents-provider/cats/ro%2Fot/home/calico.jpg")), + &authority, &root_document_id, &path)); + EXPECT_EQ("cats", authority); + EXPECT_EQ("ro/ot", root_document_id); + EXPECT_EQ(FILE_PATH_LITERAL("home/calico.jpg"), path.value()); +} + TEST(ArcDocumentsProviderUtilTest, ParseDocumentsProviderUrlUtf8) { std::string authority; std::string root_document_id; @@ -135,8 +190,13 @@ } TEST(ArcDocumentsProviderUtilTest, BuildDocumentUrl) { - EXPECT_EQ("content://Cat%20Provider/document/C%2B%2B", - BuildDocumentUrl("Cat Provider", "C++").spec()); + EXPECT_EQ("content://authority/document/document_id", + BuildDocumentUrl("authority", "document_id").spec()); + EXPECT_EQ("content://a%20b/document/a%20b", + BuildDocumentUrl("a b", "a b").spec()); + EXPECT_EQ("content://a%2Fb/document/a%2Fb", + BuildDocumentUrl("a/b", "a/b").spec()); + EXPECT_EQ("content://../document/..", BuildDocumentUrl("..", "..").spec()); } } // namespace
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.cc index 11e0290..5697ea4 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.h" #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" #include "components/arc/arc_bridge_service.h" +#include "components/arc/file_system/arc_file_system_observer.h" #include "content/public/browser/browser_thread.h" #include "storage/browser/fileapi/external_mount_points.h" @@ -15,6 +16,10 @@ namespace arc { +// static +const char ArcFileSystemService::kArcServiceName[] = + "arc::ArcFileSystemService"; + ArcFileSystemService::ArcFileSystemService(ArcBridgeService* bridge_service) : ArcService(bridge_service) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -31,11 +36,15 @@ storage::kFileSystemTypeArcDocumentsProvider, storage::FileSystemMountOption(), base::FilePath(kDocumentsProviderMountPointPath)); + + arc_bridge_service()->file_system()->AddObserver(this); } ArcFileSystemService::~ArcFileSystemService() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + arc_bridge_service()->file_system()->RemoveObserver(this); + storage::ExternalMountPoints* mount_points = storage::ExternalMountPoints::GetSystemInstance(); @@ -43,4 +52,22 @@ mount_points->RevokeFileSystem(kDocumentsProviderMountPointPath); } +void ArcFileSystemService::AddObserver(ArcFileSystemObserver* observer) { + observer_list_.AddObserver(observer); +} + +void ArcFileSystemService::RemoveObserver(ArcFileSystemObserver* observer) { + observer_list_.RemoveObserver(observer); +} + +void ArcFileSystemService::OnInstanceReady() { + for (auto& observer : observer_list_) + observer.OnFileSystemsReady(); +} + +void ArcFileSystemService::OnInstanceClosed() { + for (auto& observer : observer_list_) + observer.OnFileSystemsClosed(); +} + } // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.h index 11be0ce..9080004 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_service.h
@@ -6,19 +6,37 @@ #define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_FILE_SYSTEM_SERVICE_H_ #include "base/macros.h" +#include "base/observer_list.h" #include "components/arc/arc_service.h" +#include "components/arc/common/file_system.mojom.h" +#include "components/arc/instance_holder.h" namespace arc { class ArcBridgeService; +class ArcFileSystemObserver; // ArcFileSystemService registers ARC file systems to the system. -class ArcFileSystemService : public ArcService { +class ArcFileSystemService + : public ArcService, + public InstanceHolder<mojom::FileSystemInstance>::Observer { public: explicit ArcFileSystemService(ArcBridgeService* bridge_service); ~ArcFileSystemService() override; + void AddObserver(ArcFileSystemObserver* observer); + void RemoveObserver(ArcFileSystemObserver* observer); + + // InstanceHolder<mojom::FileSystemInstance>::Observer overrides: + void OnInstanceReady() override; + void OnInstanceClosed() override; + + // For supporting ArcServiceManager::GetService<T>(). + static const char kArcServiceName[]; + private: + base::ObserverList<ArcFileSystemObserver> observer_list_; + DISALLOW_COPY_AND_ASSIGN(ArcFileSystemService); };
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.cc new file mode 100644 index 0000000..261516ff --- /dev/null +++ b/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.cc
@@ -0,0 +1,29 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/arc/fileapi/arc_media_view_util.h" + +namespace arc { + +namespace { + +constexpr char kMediaViewVolumeIdPrefix[] = "media_view:"; + +} // namespace + +const base::Feature kMediaViewFeature{"ArcMediaView", + base::FEATURE_DISABLED_BY_DEFAULT}; + +const char kMediaDocumentsProviderAuthority[] = + "com.android.providers.media.documents"; + +const char kImagesRootDocumentId[] = "images_root"; +const char kVideosRootDocumentId[] = "videos_root"; +const char kAudioRootDocumentId[] = "audio_root"; + +std::string GetMediaViewVolumeId(const std::string& root_document_id) { + return std::string(kMediaViewVolumeIdPrefix) + root_document_id; +} + +} // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.h b/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.h new file mode 100644 index 0000000..f5cb581 --- /dev/null +++ b/chrome/browser/chromeos/arc/fileapi/arc_media_view_util.h
@@ -0,0 +1,32 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Utilities for ARC Media View. + +#ifndef CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_MEDIA_VIEW_UTIL_H_ +#define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_MEDIA_VIEW_UTIL_H_ + +#include <string> + +#include "base/feature_list.h" + +namespace arc { + +// base::FeatureList feature for ARC media view. +extern const base::Feature kMediaViewFeature; + +// Authority of MediaDocumentsProvider in Android. +extern const char kMediaDocumentsProviderAuthority[]; + +// Document IDs of file system roots in MediaDocumentsProvider. +extern const char kImagesRootDocumentId[]; +extern const char kVideosRootDocumentId[]; +extern const char kAudioRootDocumentId[]; + +// Returns an ID of a Media View volume. +std::string GetMediaViewVolumeId(const std::string& root_document_id); + +} // namespace arc + +#endif // CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_MEDIA_VIEW_UTIL_H_
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc index ee08fae..cc9fb9fc 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -242,6 +242,10 @@ case VOLUME_TYPE_MTP: volume_metadata->volume_type = file_manager_private::VOLUME_TYPE_MTP; break; + case VOLUME_TYPE_MEDIA_VIEW: + volume_metadata->volume_type = + file_manager_private::VOLUME_TYPE_MEDIA_VIEW; + break; case VOLUME_TYPE_TESTING: volume_metadata->volume_type = file_manager_private::VOLUME_TYPE_TESTING;
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc index 4464bb60..392914fa 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.cc +++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" @@ -16,6 +17,10 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chromeos/arc/arc_session_manager.h" +#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" +#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_service.h" +#include "chrome/browser/chromeos/arc/fileapi/arc_media_view_util.h" #include "chrome/browser/chromeos/drive/drive_integration_service.h" #include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/file_manager/path_util.h" @@ -29,6 +34,7 @@ #include "chrome/common/pref_names.h" #include "chromeos/chromeos_switches.h" #include "chromeos/disks/disk_mount_manager.h" +#include "components/arc/arc_service_manager.h" #include "components/drive/chromeos/file_system_interface.h" #include "components/drive/file_system_core_util.h" #include "components/prefs/pref_service.h" @@ -111,6 +117,8 @@ return "provided"; case VOLUME_TYPE_MTP: return "mtp"; + case VOLUME_TYPE_MEDIA_VIEW: + return "media_view"; case VOLUME_TYPE_TESTING: return "testing"; case NUM_VOLUME_TYPE: @@ -271,6 +279,22 @@ } // static +Volume* Volume::CreateForMediaView(const std::string& root_document_id) { + Volume* const volume = new Volume; + volume->type_ = VOLUME_TYPE_MEDIA_VIEW; + volume->device_type_ = chromeos::DEVICE_TYPE_UNKNOWN; + volume->source_ = SOURCE_SYSTEM; + volume->mount_path_ = arc::GetDocumentsProviderMountPath( + arc::kMediaDocumentsProviderAuthority, root_document_id); + volume->mount_condition_ = chromeos::disks::MOUNT_CONDITION_NONE; + volume->volume_label_ = root_document_id; + volume->is_read_only_ = true; + volume->watchable_ = false; + volume->volume_id_ = arc::GetMediaViewVolumeId(root_document_id); + return volume; +} + +// static Volume* Volume::CreateForTesting(const base::FilePath& path, VolumeType volume_type, chromeos::DeviceType device_type, @@ -382,6 +406,13 @@ base::Bind(&VolumeManager::OnStorageMonitorInitialized, weak_ptr_factory_.GetWeakPtr())); } + + // Subscribe to ARC file system events. + if (base::FeatureList::IsEnabled(arc::kMediaViewFeature) && + arc::ArcSessionManager::IsAllowedForProfile(profile_)) { + arc::ArcServiceManager::GetGlobalService<arc::ArcFileSystemService>() + ->AddObserver(this); + } } void VolumeManager::Shutdown() { @@ -398,6 +429,17 @@ if (file_system_provider_service_) file_system_provider_service_->RemoveObserver(this); + + // Unsubscribe from ARC file system events. + if (base::FeatureList::IsEnabled(arc::kMediaViewFeature) && + arc::ArcSessionManager::IsAllowedForProfile(profile_)) { + arc::ArcFileSystemService* file_system_service = + arc::ArcServiceManager::GetGlobalService<arc::ArcFileSystemService>(); + // TODO(crbug.com/672829): We need nullptr check here because + // ArcServiceManager may or may not be alive at this point. + if (file_system_service) + file_system_service->RemoveObserver(this); + } } void VolumeManager::AddObserver(VolumeManagerObserver* observer) { @@ -702,6 +744,38 @@ weak_ptr_factory_.GetWeakPtr())); } +void VolumeManager::OnFileSystemsReady() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(base::FeatureList::IsEnabled(arc::kMediaViewFeature)); + DCHECK(arc::ArcSessionManager::IsAllowedForProfile(profile_)); + + DoMountEvent(chromeos::MOUNT_ERROR_NONE, + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kImagesRootDocumentId))); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kVideosRootDocumentId))); + DoMountEvent(chromeos::MOUNT_ERROR_NONE, + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kAudioRootDocumentId))); +} + +void VolumeManager::OnFileSystemsClosed() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(base::FeatureList::IsEnabled(arc::kMediaViewFeature)); + DCHECK(arc::ArcSessionManager::IsAllowedForProfile(profile_)); + + DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kImagesRootDocumentId))); + DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kVideosRootDocumentId))); + DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, + linked_ptr<Volume>( + Volume::CreateForMediaView(arc::kAudioRootDocumentId))); +} + void VolumeManager::OnExternalStorageDisabledChanged() { // If the policy just got disabled we have to unmount every device currently // mounted. The opposite is fine - we can let the user re-plug their device to
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.h b/chrome/browser/chromeos/file_manager/volume_manager.h index f78be05..da2b0cd 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.h +++ b/chrome/browser/chromeos/file_manager/volume_manager.h
@@ -22,6 +22,7 @@ #include "chrome/browser/chromeos/file_system_provider/service.h" #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/disks/disk_mount_manager.h" +#include "components/arc/file_system/arc_file_system_observer.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" #include "components/storage_monitor/removable_storage_observer.h" @@ -51,6 +52,7 @@ VOLUME_TYPE_MOUNTED_ARCHIVE_FILE, VOLUME_TYPE_PROVIDED, // File system provided by the FileSystemProvider API. VOLUME_TYPE_MTP, + VOLUME_TYPE_MEDIA_VIEW, // The enum values must be kept in sync with FileManagerVolumeType in // tools/metrics/histograms/histograms.xml. Since enums for histograms are // append-only (for keeping the number consistent across versions), new values @@ -90,6 +92,7 @@ static Volume* CreateForMTP(const base::FilePath& mount_path, const std::string& label, bool read_only); + static Volume* CreateForMediaView(const std::string& root_document_id); static Volume* CreateForTesting(const base::FilePath& path, VolumeType volume_type, chromeos::DeviceType device_type, @@ -211,6 +214,7 @@ // for a device). // - Mounted zip archives. class VolumeManager : public KeyedService, + public arc::ArcFileSystemObserver, public drive::DriveIntegrationServiceObserver, public chromeos::disks::DiskMountManager::Observer, public chromeos::file_system_provider::Observer, @@ -297,6 +301,10 @@ file_system_info, base::File::Error error) override; + // arc::ArcFileSystemObserver overrides. + void OnFileSystemsReady() override; + void OnFileSystemsClosed() override; + // Called on change to kExternalStorageDisabled pref. void OnExternalStorageDisabledChanged();
diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc index 9992f28..299f128 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend.cc +++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc
@@ -11,12 +11,14 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" #include "chrome/browser/chromeos/fileapi/file_access_permissions.h" #include "chrome/browser/chromeos/fileapi/file_system_backend_delegate.h" #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" #include "chrome/common/url_constants.h" #include "chromeos/chromeos_switches.h" #include "chromeos/dbus/cros_disks_client.h" +#include "net/base/escape.h" #include "storage/browser/fileapi/async_file_util.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_stream_reader.h" @@ -26,6 +28,7 @@ #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/common/fileapi/file_system_mount_option.h" +#include "storage/common/fileapi/file_system_util.h" namespace chromeos { namespace { @@ -156,6 +159,27 @@ std::string inner_mount_name = components[1]; root_url += inner_mount_name + "/"; name = inner_mount_name; + } else if (id == arc::kDocumentsProviderMountPointName) { + // For ARC documents provider file system, volumes are mounted per document + // provider root, so we need to fix up |root_url| to point to an individual + // root. + std::string authority; + std::string root_document_id; + base::FilePath unused_path; + if (!arc::ParseDocumentsProviderUrl(url, &authority, &root_document_id, + &unused_path)) { + callback.Run(GURL(root_url), std::string(), + base::File::FILE_ERROR_SECURITY); + return; + } + base::FilePath mount_path = + arc::GetDocumentsProviderMountPath(authority, root_document_id); + base::FilePath relative_mount_path; + base::FilePath(arc::kDocumentsProviderMountPointPath) + .AppendRelativePath(mount_path, &relative_mount_path); + root_url += + net::EscapePath(storage::FilePathToString(relative_mount_path)) + "/"; + name = authority + ":" + root_document_id; } else { name = id; }
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 76e1de1..8faf6fb 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -100,308 +100,452 @@ // List of policy types to preference names. This is used for simple policies // that directly map to a single preference. +// clang-format off const PolicyToPreferenceMapEntry kSimplePolicyMap[] = { - {key::kHomepageLocation, prefs::kHomePage, base::Value::Type::STRING}, - {key::kHomepageIsNewTabPage, prefs::kHomePageIsNewTabPage, - base::Value::Type::BOOLEAN}, - {key::kRestoreOnStartupURLs, prefs::kURLsToRestoreOnStartup, - base::Value::Type::LIST}, - {key::kAlternateErrorPagesEnabled, prefs::kAlternateErrorPagesEnabled, - base::Value::Type::BOOLEAN}, - {key::kSearchSuggestEnabled, prefs::kSearchSuggestEnabled, - base::Value::Type::BOOLEAN}, - {key::kBuiltInDnsClientEnabled, prefs::kBuiltInDnsClientEnabled, - base::Value::Type::BOOLEAN}, - {key::kWPADQuickCheckEnabled, prefs::kQuickCheckEnabled, - base::Value::Type::BOOLEAN}, - {key::kPacHttpsUrlStrippingEnabled, prefs::kPacHttpsUrlStrippingEnabled, - base::Value::Type::BOOLEAN}, - {key::kQuicAllowed, prefs::kQuicAllowed, base::Value::Type::BOOLEAN}, - {key::kSafeBrowsingEnabled, prefs::kSafeBrowsingEnabled, - base::Value::Type::BOOLEAN}, - {key::kForceGoogleSafeSearch, prefs::kForceGoogleSafeSearch, - base::Value::Type::BOOLEAN}, - {key::kForceYouTubeRestrict, prefs::kForceYouTubeRestrict, - base::Value::Type::INTEGER}, - {key::kPasswordManagerEnabled, - password_manager::prefs::kPasswordManagerSavingEnabled, - base::Value::Type::BOOLEAN}, - {key::kPrintingEnabled, prefs::kPrintingEnabled, - base::Value::Type::BOOLEAN}, - {key::kDisablePrintPreview, prefs::kPrintPreviewDisabled, - base::Value::Type::BOOLEAN}, - {key::kDefaultPrinterSelection, - prefs::kPrintPreviewDefaultDestinationSelectionRules, - base::Value::Type::STRING}, - {key::kApplicationLocaleValue, prefs::kApplicationLocale, - base::Value::Type::STRING}, - {key::kAlwaysOpenPdfExternally, prefs::kPluginsAlwaysOpenPdfExternally, - base::Value::Type::BOOLEAN}, - {key::kShowHomeButton, prefs::kShowHomeButton, base::Value::Type::BOOLEAN}, - {key::kSavingBrowserHistoryDisabled, prefs::kSavingBrowserHistoryDisabled, - base::Value::Type::BOOLEAN}, - {key::kAllowDeletingBrowserHistory, prefs::kAllowDeletingBrowserHistory, - base::Value::Type::BOOLEAN}, - {key::kDeveloperToolsDisabled, prefs::kDevToolsDisabled, - base::Value::Type::BOOLEAN}, - {key::kBlockThirdPartyCookies, prefs::kBlockThirdPartyCookies, - base::Value::Type::BOOLEAN}, - {key::kDefaultCookiesSetting, prefs::kManagedDefaultCookiesSetting, - base::Value::Type::INTEGER}, - {key::kDefaultImagesSetting, prefs::kManagedDefaultImagesSetting, - base::Value::Type::INTEGER}, - {key::kDefaultPluginsSetting, prefs::kManagedDefaultPluginsSetting, - base::Value::Type::INTEGER}, - {key::kDefaultPopupsSetting, prefs::kManagedDefaultPopupsSetting, - base::Value::Type::INTEGER}, - {key::kAutoSelectCertificateForUrls, - prefs::kManagedAutoSelectCertificateForUrls, base::Value::Type::LIST}, - {key::kCookiesAllowedForUrls, prefs::kManagedCookiesAllowedForUrls, - base::Value::Type::LIST}, - {key::kCookiesBlockedForUrls, prefs::kManagedCookiesBlockedForUrls, - base::Value::Type::LIST}, - {key::kCookiesSessionOnlyForUrls, prefs::kManagedCookiesSessionOnlyForUrls, - base::Value::Type::LIST}, - {key::kImagesAllowedForUrls, prefs::kManagedImagesAllowedForUrls, - base::Value::Type::LIST}, - {key::kImagesBlockedForUrls, prefs::kManagedImagesBlockedForUrls, - base::Value::Type::LIST}, - {key::kJavaScriptAllowedForUrls, prefs::kManagedJavaScriptAllowedForUrls, - base::Value::Type::LIST}, - {key::kJavaScriptBlockedForUrls, prefs::kManagedJavaScriptBlockedForUrls, - base::Value::Type::LIST}, - {key::kPluginsAllowedForUrls, prefs::kManagedPluginsAllowedForUrls, - base::Value::Type::LIST}, - {key::kPluginsBlockedForUrls, prefs::kManagedPluginsBlockedForUrls, - base::Value::Type::LIST}, - {key::kPopupsAllowedForUrls, prefs::kManagedPopupsAllowedForUrls, - base::Value::Type::LIST}, - {key::kPopupsBlockedForUrls, prefs::kManagedPopupsBlockedForUrls, - base::Value::Type::LIST}, - {key::kNotificationsAllowedForUrls, - prefs::kManagedNotificationsAllowedForUrls, base::Value::Type::LIST}, - {key::kNotificationsBlockedForUrls, - prefs::kManagedNotificationsBlockedForUrls, base::Value::Type::LIST}, - {key::kDefaultNotificationsSetting, - prefs::kManagedDefaultNotificationsSetting, base::Value::Type::INTEGER}, - {key::kDefaultGeolocationSetting, prefs::kManagedDefaultGeolocationSetting, - base::Value::Type::INTEGER}, - {key::kSigninAllowed, prefs::kSigninAllowed, base::Value::Type::BOOLEAN}, - {key::kEnableOnlineRevocationChecks, - ssl_config::prefs::kCertRevocationCheckingEnabled, - base::Value::Type::BOOLEAN}, - {key::kRequireOnlineRevocationChecksForLocalAnchors, - ssl_config::prefs::kCertRevocationCheckingRequiredLocalAnchors, - base::Value::Type::BOOLEAN}, - {key::kEnableSha1ForLocalAnchors, - ssl_config::prefs::kCertEnableSha1LocalAnchors, - base::Value::Type::BOOLEAN}, - {key::kAuthSchemes, prefs::kAuthSchemes, base::Value::Type::STRING}, - {key::kDisableAuthNegotiateCnameLookup, - prefs::kDisableAuthNegotiateCnameLookup, base::Value::Type::BOOLEAN}, - {key::kEnableAuthNegotiatePort, prefs::kEnableAuthNegotiatePort, - base::Value::Type::BOOLEAN}, - {key::kAuthServerWhitelist, prefs::kAuthServerWhitelist, - base::Value::Type::STRING}, - {key::kAuthNegotiateDelegateWhitelist, - prefs::kAuthNegotiateDelegateWhitelist, base::Value::Type::STRING}, - {key::kGSSAPILibraryName, prefs::kGSSAPILibraryName, - base::Value::Type::STRING}, - {key::kAllowCrossOriginAuthPrompt, prefs::kAllowCrossOriginAuthPrompt, - base::Value::Type::BOOLEAN}, - {key::kDisable3DAPIs, prefs::kDisable3DAPIs, base::Value::Type::BOOLEAN}, - {key::kDisablePluginFinder, prefs::kDisablePluginFinder, - base::Value::Type::BOOLEAN}, - {key::kDiskCacheSize, prefs::kDiskCacheSize, base::Value::Type::INTEGER}, - {key::kMediaCacheSize, prefs::kMediaCacheSize, base::Value::Type::INTEGER}, - {key::kPolicyRefreshRate, policy_prefs::kUserPolicyRefreshRate, - base::Value::Type::INTEGER}, - {key::kDevicePolicyRefreshRate, prefs::kDevicePolicyRefreshRate, - base::Value::Type::INTEGER}, - {key::kDefaultBrowserSettingEnabled, prefs::kDefaultBrowserSettingEnabled, - base::Value::Type::BOOLEAN}, - {key::kCloudPrintProxyEnabled, prefs::kCloudPrintProxyEnabled, - base::Value::Type::BOOLEAN}, - {key::kCloudPrintSubmitEnabled, prefs::kCloudPrintSubmitEnabled, - base::Value::Type::BOOLEAN}, - {key::kTranslateEnabled, prefs::kEnableTranslate, - base::Value::Type::BOOLEAN}, - {key::kAllowOutdatedPlugins, prefs::kPluginsAllowOutdated, - base::Value::Type::BOOLEAN}, - {key::kAlwaysAuthorizePlugins, prefs::kPluginsAlwaysAuthorize, - base::Value::Type::BOOLEAN}, - {key::kBookmarkBarEnabled, bookmarks::prefs::kShowBookmarkBar, - base::Value::Type::BOOLEAN}, - {key::kEditBookmarksEnabled, bookmarks::prefs::kEditBookmarksEnabled, - base::Value::Type::BOOLEAN}, - {key::kShowAppsShortcutInBookmarkBar, - bookmarks::prefs::kShowAppsShortcutInBookmarkBar, - base::Value::Type::BOOLEAN}, - {key::kAllowFileSelectionDialogs, prefs::kAllowFileSelectionDialogs, - base::Value::Type::BOOLEAN}, - {key::kImportBookmarks, prefs::kImportBookmarks, - base::Value::Type::BOOLEAN}, - {key::kImportHistory, prefs::kImportHistory, base::Value::Type::BOOLEAN}, - {key::kImportHomepage, prefs::kImportHomepage, base::Value::Type::BOOLEAN}, - {key::kImportSearchEngine, prefs::kImportSearchEngine, - base::Value::Type::BOOLEAN}, - {key::kImportSavedPasswords, prefs::kImportSavedPasswords, - base::Value::Type::BOOLEAN}, - {key::kImportAutofillFormData, prefs::kImportAutofillFormData, - base::Value::Type::BOOLEAN}, - {key::kMaxConnectionsPerProxy, prefs::kMaxConnectionsPerProxy, - base::Value::Type::INTEGER}, - {key::kURLWhitelist, policy_prefs::kUrlWhitelist, base::Value::Type::LIST}, - {key::kRestrictSigninToPattern, prefs::kGoogleServicesUsernamePattern, - base::Value::Type::STRING}, - {key::kDefaultWebBluetoothGuardSetting, - prefs::kManagedDefaultWebBluetoothGuardSetting, - base::Value::Type::INTEGER}, - {key::kDefaultMediaStreamSetting, prefs::kManagedDefaultMediaStreamSetting, - base::Value::Type::INTEGER}, - {key::kDisableSafeBrowsingProceedAnyway, - prefs::kSafeBrowsingProceedAnywayDisabled, base::Value::Type::BOOLEAN}, - {key::kSafeBrowsingExtendedReportingOptInAllowed, - prefs::kSafeBrowsingExtendedReportingOptInAllowed, - base::Value::Type::BOOLEAN}, - {key::kSSLErrorOverrideAllowed, prefs::kSSLErrorOverrideAllowed, - base::Value::Type::BOOLEAN}, - {key::kHardwareAccelerationModeEnabled, - prefs::kHardwareAccelerationModeEnabled, base::Value::Type::BOOLEAN}, - {key::kAllowDinosaurEasterEgg, prefs::kAllowDinosaurEasterEgg, - base::Value::Type::BOOLEAN}, - {key::kAllowedDomainsForApps, prefs::kAllowedDomainsForApps, - base::Value::Type::STRING}, - {key::kComponentUpdatesEnabled, prefs::kComponentUpdatesEnabled, - base::Value::Type::BOOLEAN}, + { key::kHomepageLocation, + prefs::kHomePage, + base::Value::Type::STRING }, + { key::kHomepageIsNewTabPage, + prefs::kHomePageIsNewTabPage, + base::Value::Type::BOOLEAN }, + { key::kRestoreOnStartupURLs, + prefs::kURLsToRestoreOnStartup, + base::Value::Type::LIST }, + { key::kAlternateErrorPagesEnabled, + prefs::kAlternateErrorPagesEnabled, + base::Value::Type::BOOLEAN }, + { key::kSearchSuggestEnabled, + prefs::kSearchSuggestEnabled, + base::Value::Type::BOOLEAN }, + { key::kBuiltInDnsClientEnabled, + prefs::kBuiltInDnsClientEnabled, + base::Value::Type::BOOLEAN }, + { key::kWPADQuickCheckEnabled, + prefs::kQuickCheckEnabled, + base::Value::Type::BOOLEAN }, + { key::kPacHttpsUrlStrippingEnabled, + prefs::kPacHttpsUrlStrippingEnabled, + base::Value::Type::BOOLEAN }, + { key::kQuicAllowed, + prefs::kQuicAllowed, + base::Value::Type::BOOLEAN }, + { key::kSafeBrowsingEnabled, + prefs::kSafeBrowsingEnabled, + base::Value::Type::BOOLEAN }, + { key::kForceGoogleSafeSearch, + prefs::kForceGoogleSafeSearch, + base::Value::Type::BOOLEAN }, + { key::kForceYouTubeRestrict, + prefs::kForceYouTubeRestrict, + base::Value::Type::INTEGER}, + { key::kPasswordManagerEnabled, + password_manager::prefs::kPasswordManagerSavingEnabled, + base::Value::Type::BOOLEAN }, + { key::kPrintingEnabled, + prefs::kPrintingEnabled, + base::Value::Type::BOOLEAN }, + { key::kDisablePrintPreview, + prefs::kPrintPreviewDisabled, + base::Value::Type::BOOLEAN }, + { key::kDefaultPrinterSelection, + prefs::kPrintPreviewDefaultDestinationSelectionRules, + base::Value::Type::STRING }, + { key::kApplicationLocaleValue, + prefs::kApplicationLocale, + base::Value::Type::STRING }, + { key::kAlwaysOpenPdfExternally, + prefs::kPluginsAlwaysOpenPdfExternally, + base::Value::Type::BOOLEAN }, + { key::kShowHomeButton, + prefs::kShowHomeButton, + base::Value::Type::BOOLEAN }, + { key::kSavingBrowserHistoryDisabled, + prefs::kSavingBrowserHistoryDisabled, + base::Value::Type::BOOLEAN }, + { key::kAllowDeletingBrowserHistory, + prefs::kAllowDeletingBrowserHistory, + base::Value::Type::BOOLEAN }, + { key::kDeveloperToolsDisabled, + prefs::kDevToolsDisabled, + base::Value::Type::BOOLEAN }, + { key::kBlockThirdPartyCookies, + prefs::kBlockThirdPartyCookies, + base::Value::Type::BOOLEAN }, + { key::kDefaultCookiesSetting, + prefs::kManagedDefaultCookiesSetting, + base::Value::Type::INTEGER }, + { key::kDefaultImagesSetting, + prefs::kManagedDefaultImagesSetting, + base::Value::Type::INTEGER }, + { key::kDefaultPluginsSetting, + prefs::kManagedDefaultPluginsSetting, + base::Value::Type::INTEGER }, + { key::kDefaultPopupsSetting, + prefs::kManagedDefaultPopupsSetting, + base::Value::Type::INTEGER }, + { key::kAutoSelectCertificateForUrls, + prefs::kManagedAutoSelectCertificateForUrls, + base::Value::Type::LIST }, + { key::kCookiesAllowedForUrls, + prefs::kManagedCookiesAllowedForUrls, + base::Value::Type::LIST }, + { key::kCookiesBlockedForUrls, + prefs::kManagedCookiesBlockedForUrls, + base::Value::Type::LIST }, + { key::kCookiesSessionOnlyForUrls, + prefs::kManagedCookiesSessionOnlyForUrls, + base::Value::Type::LIST }, + { key::kImagesAllowedForUrls, + prefs::kManagedImagesAllowedForUrls, + base::Value::Type::LIST }, + { key::kImagesBlockedForUrls, + prefs::kManagedImagesBlockedForUrls, + base::Value::Type::LIST }, + { key::kJavaScriptAllowedForUrls, + prefs::kManagedJavaScriptAllowedForUrls, + base::Value::Type::LIST }, + { key::kJavaScriptBlockedForUrls, + prefs::kManagedJavaScriptBlockedForUrls, + base::Value::Type::LIST }, + { key::kPluginsAllowedForUrls, + prefs::kManagedPluginsAllowedForUrls, + base::Value::Type::LIST }, + { key::kPluginsBlockedForUrls, + prefs::kManagedPluginsBlockedForUrls, + base::Value::Type::LIST }, + { key::kPopupsAllowedForUrls, + prefs::kManagedPopupsAllowedForUrls, + base::Value::Type::LIST }, + { key::kPopupsBlockedForUrls, + prefs::kManagedPopupsBlockedForUrls, + base::Value::Type::LIST }, + { key::kNotificationsAllowedForUrls, + prefs::kManagedNotificationsAllowedForUrls, + base::Value::Type::LIST }, + { key::kNotificationsBlockedForUrls, + prefs::kManagedNotificationsBlockedForUrls, + base::Value::Type::LIST }, + { key::kDefaultNotificationsSetting, + prefs::kManagedDefaultNotificationsSetting, + base::Value::Type::INTEGER }, + { key::kDefaultGeolocationSetting, + prefs::kManagedDefaultGeolocationSetting, + base::Value::Type::INTEGER }, + { key::kSigninAllowed, + prefs::kSigninAllowed, + base::Value::Type::BOOLEAN }, + { key::kEnableOnlineRevocationChecks, + ssl_config::prefs::kCertRevocationCheckingEnabled, + base::Value::Type::BOOLEAN }, + { key::kRequireOnlineRevocationChecksForLocalAnchors, + ssl_config::prefs::kCertRevocationCheckingRequiredLocalAnchors, + base::Value::Type::BOOLEAN }, + { key::kEnableSha1ForLocalAnchors, + ssl_config::prefs::kCertEnableSha1LocalAnchors, + base::Value::Type::BOOLEAN }, + { key::kAuthSchemes, + prefs::kAuthSchemes, + base::Value::Type::STRING }, + { key::kDisableAuthNegotiateCnameLookup, + prefs::kDisableAuthNegotiateCnameLookup, + base::Value::Type::BOOLEAN }, + { key::kEnableAuthNegotiatePort, + prefs::kEnableAuthNegotiatePort, + base::Value::Type::BOOLEAN }, + { key::kAuthServerWhitelist, + prefs::kAuthServerWhitelist, + base::Value::Type::STRING }, + { key::kAuthNegotiateDelegateWhitelist, + prefs::kAuthNegotiateDelegateWhitelist, + base::Value::Type::STRING }, + { key::kGSSAPILibraryName, + prefs::kGSSAPILibraryName, + base::Value::Type::STRING }, + { key::kAllowCrossOriginAuthPrompt, + prefs::kAllowCrossOriginAuthPrompt, + base::Value::Type::BOOLEAN }, + { key::kDisable3DAPIs, + prefs::kDisable3DAPIs, + base::Value::Type::BOOLEAN }, + { key::kDisablePluginFinder, + prefs::kDisablePluginFinder, + base::Value::Type::BOOLEAN }, + { key::kDiskCacheSize, + prefs::kDiskCacheSize, + base::Value::Type::INTEGER }, + { key::kMediaCacheSize, + prefs::kMediaCacheSize, + base::Value::Type::INTEGER }, + { key::kPolicyRefreshRate, + policy_prefs::kUserPolicyRefreshRate, + base::Value::Type::INTEGER }, + { key::kDevicePolicyRefreshRate, + prefs::kDevicePolicyRefreshRate, + base::Value::Type::INTEGER }, + { key::kDefaultBrowserSettingEnabled, + prefs::kDefaultBrowserSettingEnabled, + base::Value::Type::BOOLEAN }, + { key::kCloudPrintProxyEnabled, + prefs::kCloudPrintProxyEnabled, + base::Value::Type::BOOLEAN }, + { key::kCloudPrintSubmitEnabled, + prefs::kCloudPrintSubmitEnabled, + base::Value::Type::BOOLEAN }, + { key::kTranslateEnabled, + prefs::kEnableTranslate, + base::Value::Type::BOOLEAN }, + { key::kAllowOutdatedPlugins, + prefs::kPluginsAllowOutdated, + base::Value::Type::BOOLEAN }, + { key::kAlwaysAuthorizePlugins, + prefs::kPluginsAlwaysAuthorize, + base::Value::Type::BOOLEAN }, + { key::kBookmarkBarEnabled, + bookmarks::prefs::kShowBookmarkBar, + base::Value::Type::BOOLEAN }, + { key::kEditBookmarksEnabled, + bookmarks::prefs::kEditBookmarksEnabled, + base::Value::Type::BOOLEAN }, + { key::kShowAppsShortcutInBookmarkBar, + bookmarks::prefs::kShowAppsShortcutInBookmarkBar, + base::Value::Type::BOOLEAN }, + { key::kAllowFileSelectionDialogs, + prefs::kAllowFileSelectionDialogs, + base::Value::Type::BOOLEAN }, + { key::kImportBookmarks, + prefs::kImportBookmarks, + base::Value::Type::BOOLEAN }, + { key::kImportHistory, + prefs::kImportHistory, + base::Value::Type::BOOLEAN }, + { key::kImportHomepage, + prefs::kImportHomepage, + base::Value::Type::BOOLEAN }, + { key::kImportSearchEngine, + prefs::kImportSearchEngine, + base::Value::Type::BOOLEAN }, + { key::kImportSavedPasswords, + prefs::kImportSavedPasswords, + base::Value::Type::BOOLEAN }, + { key::kImportAutofillFormData, + prefs::kImportAutofillFormData, + base::Value::Type::BOOLEAN }, + { key::kMaxConnectionsPerProxy, + prefs::kMaxConnectionsPerProxy, + base::Value::Type::INTEGER }, + { key::kURLWhitelist, + policy_prefs::kUrlWhitelist, + base::Value::Type::LIST }, + { key::kRestrictSigninToPattern, + prefs::kGoogleServicesUsernamePattern, + base::Value::Type::STRING }, + { key::kDefaultWebBluetoothGuardSetting, + prefs::kManagedDefaultWebBluetoothGuardSetting, + base::Value::Type::INTEGER }, + { key::kDefaultMediaStreamSetting, + prefs::kManagedDefaultMediaStreamSetting, + base::Value::Type::INTEGER }, + { key::kDisableSafeBrowsingProceedAnyway, + prefs::kSafeBrowsingProceedAnywayDisabled, + base::Value::Type::BOOLEAN }, + { key::kSafeBrowsingExtendedReportingOptInAllowed, + prefs::kSafeBrowsingExtendedReportingOptInAllowed, + base::Value::Type::BOOLEAN }, + { key::kSSLErrorOverrideAllowed, + prefs::kSSLErrorOverrideAllowed, + base::Value::Type::BOOLEAN }, + { key::kHardwareAccelerationModeEnabled, + prefs::kHardwareAccelerationModeEnabled, + base::Value::Type::BOOLEAN }, + { key::kAllowDinosaurEasterEgg, + prefs::kAllowDinosaurEasterEgg, + base::Value::Type::BOOLEAN }, + { key::kAllowedDomainsForApps, + prefs::kAllowedDomainsForApps, + base::Value::Type::STRING }, + { key::kComponentUpdatesEnabled, + prefs::kComponentUpdatesEnabled, + base::Value::Type::BOOLEAN }, #if BUILDFLAG(ENABLE_SPELLCHECK) - {key::kSpellCheckServiceEnabled, - spellcheck::prefs::kSpellCheckUseSpellingService, - base::Value::Type::BOOLEAN}, + { key::kSpellCheckServiceEnabled, + spellcheck::prefs::kSpellCheckUseSpellingService, + base::Value::Type::BOOLEAN }, #endif // BUILDFLAG(ENABLE_SPELLCHECK) - {key::kDisableScreenshots, prefs::kDisableScreenshots, - base::Value::Type::BOOLEAN}, - {key::kAudioCaptureAllowed, prefs::kAudioCaptureAllowed, - base::Value::Type::BOOLEAN}, - {key::kVideoCaptureAllowed, prefs::kVideoCaptureAllowed, - base::Value::Type::BOOLEAN}, - {key::kAudioCaptureAllowedUrls, prefs::kAudioCaptureAllowedUrls, - base::Value::Type::LIST}, - {key::kVideoCaptureAllowedUrls, prefs::kVideoCaptureAllowedUrls, - base::Value::Type::LIST}, - {key::kHideWebStoreIcon, prefs::kHideWebStoreIcon, - base::Value::Type::BOOLEAN}, - {key::kVariationsRestrictParameter, - variations::prefs::kVariationsRestrictParameter, - base::Value::Type::STRING}, - {key::kForceEphemeralProfiles, prefs::kForceEphemeralProfiles, - base::Value::Type::BOOLEAN}, - {key::kDHEEnabled, ssl_config::prefs::kDHEEnabled, - base::Value::Type::BOOLEAN}, - {key::kNTPContentSuggestionsEnabled, ntp_snippets::prefs::kEnableSnippets, - base::Value::Type::BOOLEAN}, + { key::kDisableScreenshots, + prefs::kDisableScreenshots, + base::Value::Type::BOOLEAN }, + { key::kAudioCaptureAllowed, + prefs::kAudioCaptureAllowed, + base::Value::Type::BOOLEAN }, + { key::kVideoCaptureAllowed, + prefs::kVideoCaptureAllowed, + base::Value::Type::BOOLEAN }, + { key::kAudioCaptureAllowedUrls, + prefs::kAudioCaptureAllowedUrls, + base::Value::Type::LIST }, + { key::kVideoCaptureAllowedUrls, + prefs::kVideoCaptureAllowedUrls, + base::Value::Type::LIST }, + { key::kHideWebStoreIcon, + prefs::kHideWebStoreIcon, + base::Value::Type::BOOLEAN }, + { key::kVariationsRestrictParameter, + variations::prefs::kVariationsRestrictParameter, + base::Value::Type::STRING }, + { key::kForceEphemeralProfiles, + prefs::kForceEphemeralProfiles, + base::Value::Type::BOOLEAN }, + { key::kDHEEnabled, + ssl_config::prefs::kDHEEnabled, + base::Value::Type::BOOLEAN }, + { key::kNTPContentSuggestionsEnabled, + ntp_snippets::prefs::kEnableSnippets, + base::Value::Type::BOOLEAN }, #if defined(ENABLE_MEDIA_ROUTER) - {key::kEnableMediaRouter, prefs::kEnableMediaRouter, - base::Value::Type::BOOLEAN}, + { key::kEnableMediaRouter, + prefs::kEnableMediaRouter, + base::Value::Type::BOOLEAN }, #endif // defined(ENABLE_MEDIA_ROUTER) #if BUILDFLAG(ENABLE_WEBRTC) - {key::kWebRtcUdpPortRange, prefs::kWebRTCUDPPortRange, - base::Value::Type::STRING}, + { key::kWebRtcUdpPortRange, + prefs::kWebRTCUDPPortRange, + base::Value::Type::STRING }, #endif // BUILDFLAG(ENABLE_WEBRTC) #if !defined(OS_MACOSX) - {key::kFullscreenAllowed, prefs::kFullscreenAllowed, - base::Value::Type::BOOLEAN}, + { key::kFullscreenAllowed, + prefs::kFullscreenAllowed, + base::Value::Type::BOOLEAN }, #if BUILDFLAG(ENABLE_EXTENSIONS) - {key::kFullscreenAllowed, extensions::pref_names::kAppFullscreenAllowed, - base::Value::Type::BOOLEAN}, + { key::kFullscreenAllowed, + extensions::pref_names::kAppFullscreenAllowed, + base::Value::Type::BOOLEAN }, #endif // BUILDFLAG(ENABLE_EXTENSIONS) #endif // !defined(OS_MACOSX) #if defined(OS_CHROMEOS) - {key::kChromeOsLockOnIdleSuspend, prefs::kEnableAutoScreenLock, - base::Value::Type::BOOLEAN}, - {key::kChromeOsReleaseChannel, prefs::kChromeOsReleaseChannel, - base::Value::Type::STRING}, - {key::kDriveDisabled, drive::prefs::kDisableDrive, - base::Value::Type::BOOLEAN}, - {key::kDriveDisabledOverCellular, drive::prefs::kDisableDriveOverCellular, - base::Value::Type::BOOLEAN}, - {key::kExternalStorageDisabled, prefs::kExternalStorageDisabled, - base::Value::Type::BOOLEAN}, - {key::kExternalStorageReadOnly, prefs::kExternalStorageReadOnly, - base::Value::Type::BOOLEAN}, - {key::kAudioOutputAllowed, chromeos::prefs::kAudioOutputAllowed, - base::Value::Type::BOOLEAN}, - {key::kShowLogoutButtonInTray, prefs::kShowLogoutButtonInTray, - base::Value::Type::BOOLEAN}, - {key::kShelfAutoHideBehavior, prefs::kShelfAutoHideBehaviorLocal, - base::Value::Type::STRING}, - {key::kSessionLengthLimit, prefs::kSessionLengthLimit, - base::Value::Type::INTEGER}, - {key::kWaitForInitialUserActivity, - prefs::kSessionWaitForInitialUserActivity, base::Value::Type::BOOLEAN}, - {key::kPowerManagementUsesAudioActivity, prefs::kPowerUseAudioActivity, - base::Value::Type::BOOLEAN}, - {key::kPowerManagementUsesVideoActivity, prefs::kPowerUseVideoActivity, - base::Value::Type::BOOLEAN}, - {key::kAllowScreenWakeLocks, prefs::kPowerAllowScreenWakeLocks, - base::Value::Type::BOOLEAN}, - {key::kWaitForInitialUserActivity, prefs::kPowerWaitForInitialUserActivity, - base::Value::Type::BOOLEAN}, - {key::kTermsOfServiceURL, prefs::kTermsOfServiceURL, - base::Value::Type::STRING}, - {key::kShowAccessibilityOptionsInSystemTrayMenu, - prefs::kShouldAlwaysShowAccessibilityMenu, base::Value::Type::BOOLEAN}, - {key::kLargeCursorEnabled, prefs::kAccessibilityLargeCursorEnabled, - base::Value::Type::BOOLEAN}, - {key::kSpokenFeedbackEnabled, prefs::kAccessibilitySpokenFeedbackEnabled, - base::Value::Type::BOOLEAN}, - {key::kHighContrastEnabled, prefs::kAccessibilityHighContrastEnabled, - base::Value::Type::BOOLEAN}, - {key::kVirtualKeyboardEnabled, prefs::kAccessibilityVirtualKeyboardEnabled, - base::Value::Type::BOOLEAN}, - {key::kDeviceLoginScreenDefaultLargeCursorEnabled, NULL, - base::Value::Type::BOOLEAN}, - {key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled, NULL, - base::Value::Type::BOOLEAN}, - {key::kDeviceLoginScreenDefaultHighContrastEnabled, NULL, - base::Value::Type::BOOLEAN}, - {key::kDeviceLoginScreenDefaultVirtualKeyboardEnabled, NULL, - base::Value::Type::BOOLEAN}, - {key::kRebootAfterUpdate, prefs::kRebootAfterUpdate, - base::Value::Type::BOOLEAN}, - {key::kAttestationEnabledForUser, prefs::kAttestationEnabled, - base::Value::Type::BOOLEAN}, - {key::kChromeOsMultiProfileUserBehavior, prefs::kMultiProfileUserBehavior, - base::Value::Type::STRING}, - {key::kKeyboardDefaultToFunctionKeys, prefs::kLanguageSendFunctionKeys, - base::Value::Type::BOOLEAN}, - {key::kTouchVirtualKeyboardEnabled, prefs::kTouchVirtualKeyboardEnabled, - base::Value::Type::BOOLEAN}, - {key::kEasyUnlockAllowed, prefs::kEasyUnlockAllowed, - base::Value::Type::BOOLEAN}, - {key::kCaptivePortalAuthenticationIgnoresProxy, - prefs::kCaptivePortalAuthenticationIgnoresProxy, - base::Value::Type::BOOLEAN}, - {key::kForceMaximizeOnFirstRun, prefs::kForceMaximizeOnFirstRun, - base::Value::Type::BOOLEAN}, - {key::kUnifiedDesktopEnabledByDefault, - prefs::kUnifiedDesktopEnabledByDefault, base::Value::Type::BOOLEAN}, - {key::kArcEnabled, prefs::kArcEnabled, base::Value::Type::BOOLEAN}, - {key::kArcBackupRestoreEnabled, prefs::kArcBackupRestoreEnabled, - base::Value::Type::BOOLEAN}, - {key::kReportArcStatusEnabled, prefs::kReportArcStatusEnabled, - base::Value::Type::BOOLEAN}, - {key::kNativePrinters, prefs::kRecommendedNativePrinters, - base::Value::Type::LIST}, + { key::kChromeOsLockOnIdleSuspend, + prefs::kEnableAutoScreenLock, + base::Value::Type::BOOLEAN }, + { key::kChromeOsReleaseChannel, + prefs::kChromeOsReleaseChannel, + base::Value::Type::STRING }, + { key::kDriveDisabled, + drive::prefs::kDisableDrive, + base::Value::Type::BOOLEAN }, + { key::kDriveDisabledOverCellular, + drive::prefs::kDisableDriveOverCellular, + base::Value::Type::BOOLEAN }, + { key::kExternalStorageDisabled, + prefs::kExternalStorageDisabled, + base::Value::Type::BOOLEAN }, + { key::kExternalStorageReadOnly, + prefs::kExternalStorageReadOnly, + base::Value::Type::BOOLEAN }, + { key::kAudioOutputAllowed, + chromeos::prefs::kAudioOutputAllowed, + base::Value::Type::BOOLEAN }, + { key::kShowLogoutButtonInTray, + prefs::kShowLogoutButtonInTray, + base::Value::Type::BOOLEAN }, + { key::kShelfAutoHideBehavior, + prefs::kShelfAutoHideBehaviorLocal, + base::Value::Type::STRING }, + { key::kSessionLengthLimit, + prefs::kSessionLengthLimit, + base::Value::Type::INTEGER }, + { key::kWaitForInitialUserActivity, + prefs::kSessionWaitForInitialUserActivity, + base::Value::Type::BOOLEAN }, + { key::kPowerManagementUsesAudioActivity, + prefs::kPowerUseAudioActivity, + base::Value::Type::BOOLEAN }, + { key::kPowerManagementUsesVideoActivity, + prefs::kPowerUseVideoActivity, + base::Value::Type::BOOLEAN }, + { key::kAllowScreenWakeLocks, + prefs::kPowerAllowScreenWakeLocks, + base::Value::Type::BOOLEAN }, + { key::kWaitForInitialUserActivity, + prefs::kPowerWaitForInitialUserActivity, + base::Value::Type::BOOLEAN }, + { key::kTermsOfServiceURL, + prefs::kTermsOfServiceURL, + base::Value::Type::STRING }, + { key::kShowAccessibilityOptionsInSystemTrayMenu, + prefs::kShouldAlwaysShowAccessibilityMenu, + base::Value::Type::BOOLEAN }, + { key::kLargeCursorEnabled, + prefs::kAccessibilityLargeCursorEnabled, + base::Value::Type::BOOLEAN }, + { key::kSpokenFeedbackEnabled, + prefs::kAccessibilitySpokenFeedbackEnabled, + base::Value::Type::BOOLEAN }, + { key::kHighContrastEnabled, + prefs::kAccessibilityHighContrastEnabled, + base::Value::Type::BOOLEAN }, + { key::kVirtualKeyboardEnabled, + prefs::kAccessibilityVirtualKeyboardEnabled, + base::Value::Type::BOOLEAN }, + { key::kDeviceLoginScreenDefaultLargeCursorEnabled, + NULL, + base::Value::Type::BOOLEAN }, + { key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled, + NULL, + base::Value::Type::BOOLEAN }, + { key::kDeviceLoginScreenDefaultHighContrastEnabled, + NULL, + base::Value::Type::BOOLEAN }, + { key::kDeviceLoginScreenDefaultVirtualKeyboardEnabled, + NULL, + base::Value::Type::BOOLEAN }, + { key::kRebootAfterUpdate, + prefs::kRebootAfterUpdate, + base::Value::Type::BOOLEAN }, + { key::kAttestationEnabledForUser, + prefs::kAttestationEnabled, + base::Value::Type::BOOLEAN }, + { key::kChromeOsMultiProfileUserBehavior, + prefs::kMultiProfileUserBehavior, + base::Value::Type::STRING }, + { key::kKeyboardDefaultToFunctionKeys, + prefs::kLanguageSendFunctionKeys, + base::Value::Type::BOOLEAN }, + { key::kTouchVirtualKeyboardEnabled, + prefs::kTouchVirtualKeyboardEnabled, + base::Value::Type::BOOLEAN }, + { key::kEasyUnlockAllowed, + prefs::kEasyUnlockAllowed, + base::Value::Type::BOOLEAN }, + { key::kCaptivePortalAuthenticationIgnoresProxy, + prefs::kCaptivePortalAuthenticationIgnoresProxy, + base::Value::Type::BOOLEAN }, + { key::kForceMaximizeOnFirstRun, + prefs::kForceMaximizeOnFirstRun, + base::Value::Type::BOOLEAN }, + { key::kUnifiedDesktopEnabledByDefault, + prefs::kUnifiedDesktopEnabledByDefault, + base::Value::Type::BOOLEAN }, + { key::kArcEnabled, + prefs::kArcEnabled, + base::Value::Type::BOOLEAN }, + { key::kArcBackupRestoreEnabled, + prefs::kArcBackupRestoreEnabled, + base::Value::Type::BOOLEAN }, + { key::kReportArcStatusEnabled, + prefs::kReportArcStatusEnabled, + base::Value::Type::BOOLEAN }, + { key::kNativePrinters, + prefs::kRecommendedNativePrinters, + base::Value::Type::LIST }, #endif // defined(OS_CHROMEOS) // Metrics reporting is controlled by a platform specific policy for ChromeOS #if defined(OS_CHROMEOS) - {key::kDeviceMetricsReportingEnabled, - metrics::prefs::kMetricsReportingEnabled, base::Value::Type::BOOLEAN}, + { key::kDeviceMetricsReportingEnabled, + metrics::prefs::kMetricsReportingEnabled, + base::Value::Type::BOOLEAN }, #else { key::kMetricsReportingEnabled, metrics::prefs::kMetricsReportingEnabled, @@ -409,71 +553,89 @@ #endif #if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) - {key::kBackgroundModeEnabled, prefs::kBackgroundModeEnabled, - base::Value::Type::BOOLEAN}, + { key::kBackgroundModeEnabled, + prefs::kBackgroundModeEnabled, + base::Value::Type::BOOLEAN }, #endif // !defined(OS_MACOSX) && !defined(OS_CHROMEOS) #if defined(OS_ANDROID) - {key::kDataCompressionProxyEnabled, prefs::kDataSaverEnabled, - base::Value::Type::BOOLEAN}, - {key::kAuthAndroidNegotiateAccountType, - prefs::kAuthAndroidNegotiateAccountType, base::Value::Type::STRING}, + { key::kDataCompressionProxyEnabled, + prefs::kDataSaverEnabled, + base::Value::Type::BOOLEAN }, + { key::kAuthAndroidNegotiateAccountType, + prefs::kAuthAndroidNegotiateAccountType, + base::Value::Type::STRING }, #endif // defined(OS_ANDROID) #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) - {key::kNativeMessagingUserLevelHosts, - extensions::pref_names::kNativeMessagingUserLevelHosts, - base::Value::Type::BOOLEAN}, - {key::kBrowserAddPersonEnabled, prefs::kBrowserAddPersonEnabled, - base::Value::Type::BOOLEAN}, + { key::kNativeMessagingUserLevelHosts, + extensions::pref_names::kNativeMessagingUserLevelHosts, + base::Value::Type::BOOLEAN }, + { key::kBrowserAddPersonEnabled, + prefs::kBrowserAddPersonEnabled, + base::Value::Type::BOOLEAN }, #endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID) - {key::kForceBrowserSignin, prefs::kForceBrowserSignin, - base::Value::Type::BOOLEAN}, + { key::kForceBrowserSignin, + prefs::kForceBrowserSignin, + base::Value::Type::BOOLEAN }, #if defined(OS_WIN) - {key::kWelcomePageOnOSUpgradeEnabled, prefs::kWelcomePageOnOSUpgradeEnabled, - base::Value::Type::BOOLEAN}, + { key::kWelcomePageOnOSUpgradeEnabled, + prefs::kWelcomePageOnOSUpgradeEnabled, + base::Value::Type::BOOLEAN }, #endif // OS_WIN #if !defined(OS_ANDROID) - {key::kSuppressUnsupportedOSWarning, prefs::kSuppressUnsupportedOSWarning, - base::Value::Type::BOOLEAN}, + { key::kSuppressUnsupportedOSWarning, + prefs::kSuppressUnsupportedOSWarning, + base::Value::Type::BOOLEAN }, #endif // !OS_ANDROID #if defined(OS_CHROMEOS) - {key::kSystemTimezoneAutomaticDetection, - prefs::kSystemTimezoneAutomaticDetectionPolicy, - base::Value::Type::INTEGER}, + { key::kSystemTimezoneAutomaticDetection, + prefs::kSystemTimezoneAutomaticDetectionPolicy, + base::Value::Type::INTEGER }, #endif - {key::kTaskManagerEndProcessEnabled, prefs::kTaskManagerEndProcessEnabled, - base::Value::Type::BOOLEAN}, + { key::kTaskManagerEndProcessEnabled, + prefs::kTaskManagerEndProcessEnabled, + base::Value::Type::BOOLEAN }, #if defined(OS_CHROMEOS) - {key::kNetworkThrottlingEnabled, prefs::kNetworkThrottlingEnabled, - base::Value::Type::DICTIONARY}, + { key::kNetworkThrottlingEnabled, + prefs::kNetworkThrottlingEnabled, + base::Value::Type::DICTIONARY }, - {key::kAllowScreenLock, prefs::kAllowScreenLock, - base::Value::Type::BOOLEAN}, + { key::kAllowScreenLock, + prefs::kAllowScreenLock, + base::Value::Type::BOOLEAN }, - {key::kQuickUnlockModeWhitelist, prefs::kQuickUnlockModeWhitelist, - base::Value::Type::LIST}, - {key::kQuickUnlockTimeout, prefs::kQuickUnlockTimeout, - base::Value::Type::INTEGER}, - {key::kPinUnlockMinimumLength, prefs::kPinUnlockMinimumLength, - base::Value::Type::INTEGER}, - {key::kPinUnlockMaximumLength, prefs::kPinUnlockMaximumLength, - base::Value::Type::INTEGER}, - {key::kPinUnlockWeakPinsAllowed, prefs::kPinUnlockWeakPinsAllowed, - base::Value::Type::BOOLEAN}, + { key::kQuickUnlockModeWhitelist, + prefs::kQuickUnlockModeWhitelist, + base::Value::Type::LIST }, + { key::kQuickUnlockTimeout, + prefs::kQuickUnlockTimeout, + base::Value::Type::INTEGER }, + { key::kPinUnlockMinimumLength, + prefs::kPinUnlockMinimumLength, + base::Value::Type::INTEGER }, + { key::kPinUnlockMaximumLength, + prefs::kPinUnlockMaximumLength, + base::Value::Type::INTEGER }, + { key::kPinUnlockWeakPinsAllowed, + prefs::kPinUnlockWeakPinsAllowed, + base::Value::Type::BOOLEAN }, #endif - {key::kRoamingProfileSupportEnabled, syncer::prefs::kEnableLocalSyncBackend, - base::Value::Type::BOOLEAN}, - {key::kRoamingProfileLocation, syncer::prefs::kLocalSyncBackendDir, - base::Value::Type::STRING}, + { key::kRoamingProfileSupportEnabled, + syncer::prefs::kEnableLocalSyncBackend, + base::Value::Type::BOOLEAN }, + { key::kRoamingProfileLocation, + syncer::prefs::kLocalSyncBackendDir, + base::Value::Type::STRING }, }; +// clang-format on class ForceSafeSearchPolicyHandler : public TypeCheckingPolicyHandler { public:
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl index bc76709..a2d0117 100644 --- a/chrome/common/extensions/api/file_manager_private.idl +++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -9,7 +9,7 @@ namespace fileManagerPrivate { // Type of the mounted volume. enum VolumeType { drive, downloads, removable, archive, provided, mtp, - testing }; + media_view, testing }; // Device type. Available if this is removable volume. enum DeviceType { usb, sd, optical, mobile, unknown };
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index 0423c4b..64e83491 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -21,6 +21,7 @@ "clipboard/arc_clipboard_bridge.h", "crash_collector/arc_crash_collector_bridge.cc", "crash_collector/arc_crash_collector_bridge.h", + "file_system/arc_file_system_observer.h", "ime/arc_ime_bridge.h", "ime/arc_ime_bridge_impl.cc", "ime/arc_ime_bridge_impl.h",
diff --git a/components/arc/file_system/arc_file_system_observer.h b/components/arc/file_system/arc_file_system_observer.h new file mode 100644 index 0000000..e3718aa --- /dev/null +++ b/components/arc/file_system/arc_file_system_observer.h
@@ -0,0 +1,23 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_ARC_FILE_SYSTEM_ARC_FILE_SYSTEM_OBSERVER_H_ +#define COMPONENTS_ARC_FILE_SYSTEM_ARC_FILE_SYSTEM_OBSERVER_H_ + +namespace arc { + +class ArcFileSystemObserver { + public: + virtual ~ArcFileSystemObserver() = default; + + // Called when ARC file systems are ready. + virtual void OnFileSystemsReady() = 0; + + // Called when ARC file systems are closed. + virtual void OnFileSystemsClosed() = 0; +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_FILE_SYSTEM_ARC_FILE_SYSTEM_OBSERVER_H_
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 18a61953..9ebda8a 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -293,6 +293,9 @@ base::FeatureList::IsEnabled( features::kExpensiveBackgroundTimerThrottling)); + if (base::FeatureList::IsEnabled(features::kHeapCompaction)) + WebRuntimeFeatures::enableHeapCompaction(true); + WebRuntimeFeatures::enableRenderingPipelineThrottling( base::FeatureList::IsEnabled(features::kRenderingPipelineThrottling));
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 3741185..51310700 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -105,6 +105,10 @@ const base::Feature kGuestViewCrossProcessFrames{ "GuestViewCrossProcessFrames", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables BlinkGC heap compaction. +const base::Feature kHeapCompaction{"HeapCompaction", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables lazily parsing css properties for performance. const base::Feature kLazyParseCSS{"LazyParseCSS", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index fad4b4ca..076c2803 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -35,6 +35,7 @@ CONTENT_EXPORT extern const base::Feature kGamepadExtensions; CONTENT_EXPORT extern const base::Feature kGenericSensor; CONTENT_EXPORT extern const base::Feature kGuestViewCrossProcessFrames; +CONTENT_EXPORT extern const base::Feature kHeapCompaction; CONTENT_EXPORT extern const base::Feature kLazyParseCSS; CONTENT_EXPORT extern const base::Feature kMediaDocumentDownloadButton; CONTENT_EXPORT extern const base::Feature kMemoryCoordinator;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 3291804..ebf13c2 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -3959,6 +3959,68 @@ WebDataSource* ds = frame->dataSource(); Send(new FrameHostMsg_DidFinishLoad(routing_id_, ds->getRequest().url())); + + if (RenderThreadImpl::current()) { + RenderThreadImpl::RendererMemoryMetrics memory_metrics; + RenderThreadImpl::current()->GetRendererMemoryMetrics(&memory_metrics); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.PartitionAlloc.DidFinishLoad", + memory_metrics.partition_alloc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.BlinkGC.DidFinishLoad", + memory_metrics.blink_gc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.Malloc.DidFinishLoad", + memory_metrics.malloc_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.Discardable.DidFinishLoad", + memory_metrics.discardable_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.V8MainThreadIsolate.DidFinishLoad", + memory_metrics.v8_main_thread_isolate_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocated.DidFinishLoad", + memory_metrics.total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.NonDiscardableTotalAllocated." + "DidFinishLoad", + memory_metrics.non_discardable_total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocatedPerRenderView." + "DidFinishLoad", + memory_metrics.total_allocated_per_render_view_mb); + if (IsMainFrame()) { + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.PartitionAlloc." + "MainFrameDidFinishLoad", + memory_metrics.partition_alloc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.BlinkGC.MainFrameDidFinishLoad", + memory_metrics.blink_gc_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.Malloc.MainFrameDidFinishLoad", + memory_metrics.malloc_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.Discardable.MainFrameDidFinishLoad", + memory_metrics.discardable_kb / 1024); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.V8MainThreadIsolate." + "MainFrameDidFinishLoad", + memory_metrics.v8_main_thread_isolate_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocated." + "MainFrameDidFinishLoad", + memory_metrics.total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.NonDiscardableTotalAllocated." + "MainFrameDidFinishLoad", + memory_metrics.non_discardable_total_allocated_mb); + UMA_HISTOGRAM_MEMORY_MB( + "Memory.Experimental.Renderer.TotalAllocatedPerRenderView." + "MainFrameDidFinishLoad", + memory_metrics.total_allocated_per_render_view_mb); + } + } } void RenderFrameImpl::didNavigateWithinPage(
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 5508305..8c32c5e 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1734,6 +1734,52 @@ } // namespace #endif +void RenderThreadImpl::GetRendererMemoryMetrics( + RendererMemoryMetrics* memory_metrics) const { + DCHECK(memory_metrics); + + blink::WebMemoryStatistics blink_stats = blink::WebMemoryStatistics::Get(); + memory_metrics->partition_alloc_kb = + blink_stats.partitionAllocTotalAllocatedBytes / 1024; + memory_metrics->blink_gc_kb = blink_stats.blinkGCTotalAllocatedBytes / 1024; +#if defined(OS_LINUX) || defined(OS_ANDROID) + struct mallinfo minfo = mallinfo(); +#if defined(USE_TCMALLOC) + size_t malloc_usage = minfo.uordblks; +#else + size_t malloc_usage = minfo.hblkhd + minfo.arena; +#endif +#else + size_t malloc_usage = GetMallocUsage(); +#endif + memory_metrics->malloc_mb = malloc_usage / 1024 / 1024; + + discardable_memory::ClientDiscardableSharedMemoryManager::Statistics + discardable_stats = discardable_shared_memory_manager_->GetStatistics(); + size_t discardable_usage = + discardable_stats.total_size - discardable_stats.freelist_size; + memory_metrics->discardable_kb = discardable_usage / 1024; + + size_t v8_usage = 0; + if (v8::Isolate* isolate = blink::mainThreadIsolate()) { + v8::HeapStatistics v8_heap_statistics; + isolate->GetHeapStatistics(&v8_heap_statistics); + v8_usage = v8_heap_statistics.total_heap_size(); + } + // TODO(tasak): Currently only memory usage of mainThreadIsolate() is + // reported. We should collect memory usages of all isolates using + // memory-infra. + memory_metrics->v8_main_thread_isolate_mb = v8_usage / 1024 / 1024; + size_t total_allocated = blink_stats.partitionAllocTotalAllocatedBytes + + blink_stats.blinkGCTotalAllocatedBytes + + malloc_usage + v8_usage + discardable_usage; + memory_metrics->total_allocated_mb = total_allocated / 1024 / 1024; + memory_metrics->non_discardable_total_allocated_mb = + (total_allocated - discardable_usage) / 1024 / 1024; + memory_metrics->total_allocated_per_render_view_mb = + total_allocated / RenderView::GetRenderViewCount() / 1024 / 1024; +} + // TODO(tasak): Once it is possible to use memory-infra without tracing, // we should collect the metrics using memory-infra. // TODO(tasak): We should also report a difference between the memory usages @@ -1745,47 +1791,20 @@ // TODO(tasak): Compare memory metrics between purge-enabled renderers and // purge-disabled renderers (A/B testing). - blink::WebMemoryStatistics blink_stats = blink::WebMemoryStatistics::Get(); + RendererMemoryMetrics memory_metrics; + GetRendererMemoryMetrics(&memory_metrics); UMA_HISTOGRAM_MEMORY_KB("PurgeAndSuspend.Memory.PartitionAllocKB", - blink_stats.partitionAllocTotalAllocatedBytes / 1024); + memory_metrics.partition_alloc_kb); UMA_HISTOGRAM_MEMORY_KB("PurgeAndSuspend.Memory.BlinkGCKB", - blink_stats.blinkGCTotalAllocatedBytes / 1024); -#if defined(OS_LINUX) || defined(OS_ANDROID) - struct mallinfo minfo = mallinfo(); -#if defined(USE_TCMALLOC) - size_t malloc_usage = minfo.uordblks; -#else - size_t malloc_usage = minfo.hblkhd + minfo.arena; -#endif -#else - size_t malloc_usage = GetMallocUsage(); -#endif + memory_metrics.blink_gc_kb); UMA_HISTOGRAM_MEMORY_MB("PurgeAndSuspend.Memory.MallocMB", - malloc_usage / 1024 / 1024); - - discardable_memory::ClientDiscardableSharedMemoryManager::Statistics - discardable_stats = discardable_shared_memory_manager_->GetStatistics(); - size_t discardable_usage = - discardable_stats.total_size - discardable_stats.freelist_size; + memory_metrics.malloc_mb); UMA_HISTOGRAM_MEMORY_KB("PurgeAndSuspend.Memory.DiscardableKB", - discardable_usage / 1024); - - size_t v8_usage = 0; - if (v8::Isolate* isolate = blink::mainThreadIsolate()) { - v8::HeapStatistics v8_heap_statistics; - isolate->GetHeapStatistics(&v8_heap_statistics); - v8_usage = v8_heap_statistics.total_heap_size(); - } - // TODO(tasak): Currently only memory usage of mainThreadIsolate() is - // reported. We should collect memory usages of all isolates using - // memory-infra. + memory_metrics.discardable_kb); UMA_HISTOGRAM_MEMORY_MB("PurgeAndSuspend.Memory.V8MainThreadIsolateMB", - v8_usage / 1024 / 1024); + memory_metrics.v8_main_thread_isolate_mb); UMA_HISTOGRAM_MEMORY_MB("PurgeAndSuspend.Memory.TotalAllocatedMB", - (blink_stats.partitionAllocTotalAllocatedBytes + - blink_stats.blinkGCTotalAllocatedBytes + - malloc_usage + v8_usage + discardable_usage) / - 1024 / 1024); + memory_metrics.total_allocated_mb); } void RenderThreadImpl::OnProcessResume() {
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index cf45d73..a4ff0885 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -482,6 +482,18 @@ // ChildMemoryCoordinatorDelegate implementation. void OnTrimMemoryImmediately() override; + struct RendererMemoryMetrics { + size_t partition_alloc_kb; + size_t blink_gc_kb; + size_t malloc_mb; + size_t discardable_kb; + size_t v8_main_thread_isolate_mb; + size_t total_allocated_mb; + size_t non_discardable_total_allocated_mb; + size_t total_allocated_per_render_view_mb; + }; + void GetRendererMemoryMetrics(RendererMemoryMetrics* memory_metrics) const; + protected: RenderThreadImpl( const InProcessChildThreadParams& params,
diff --git a/google_apis/gcm/engine/connection_event_tracker.cc b/google_apis/gcm/engine/connection_event_tracker.cc index cad77ebd..0ebd798 100644 --- a/google_apis/gcm/engine/connection_event_tracker.cc +++ b/google_apis/gcm/engine/connection_event_tracker.cc
@@ -4,6 +4,7 @@ #include "google_apis/gcm/engine/connection_event_tracker.h" +#include "base/metrics/histogram_macros.h" #include "base/time/time.h" #include "net/base/network_change_notifier.h" @@ -19,7 +20,10 @@ ConnectionEventTracker::ConnectionEventTracker() = default; -ConnectionEventTracker::~ConnectionEventTracker() = default; +ConnectionEventTracker::~ConnectionEventTracker() { + UMA_HISTOGRAM_ENUMERATION("GCM.PendingConnectionEventsAtShutdown", + completed_events_.size(), kMaxClientEvents + 1); +} void ConnectionEventTracker::StartConnectionAttempt() { // TODO(harkness): Can we dcheck here that there is not an in progress
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd index 04792e1a..c347380 100644 --- a/ios/chrome/app/strings/ios_chromium_strings.grd +++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -210,6 +210,9 @@ <message name="IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB_DETAILS" desc="The detailed description of an option to enable scanning for nearby devices broadcasting URLs."> Discover web pages sent by nearby objects. When Bluetooth is turned on, Chromium can gather web pages associated with objects around you and send them anonymously to Google to find the most useful ones. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> </message> + <message name="IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SIGNIN" desc="The title of the Import Data settings screen when signing in. [30em]"> + Sign in to Chromium + </message> <message name="IDS_IOS_OPTIONS_PRIVACY_FOOTER" desc="Footer for the clear browsing data dialog [Length: 300em] [iOS only]"> Chromium may use web services to improve your browsing experience. You may optionally disable these services. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> </message>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd index 4acd831..12aca122 100644 --- a/ios/chrome/app/strings/ios_google_chrome_strings.grd +++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -210,6 +210,9 @@ <message name="IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB_DETAILS" desc="The detailed description of an option to enable scanning for nearby devices broadcasting URLs."> Discover web pages sent by nearby objects. When Bluetooth is turned on, Chrome can gather web pages associated with objects around you and send them anonymously to Google to find the most useful ones. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> </message> + <message name="IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SIGNIN" desc="The title of the Import Data settings screen when signing in. [30em]"> + Sign in to Chrome + </message> <message name="IDS_IOS_OPTIONS_PRIVACY_FOOTER" desc="Footer for the clear browsing data dialog [Length: 300em] [iOS only]"> Google Chrome may use web services to improve your browsing experience. You may optionally disable these services. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> </message>
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index deb1a90..5b4ad58f 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -885,6 +885,9 @@ <message name="IDS_IOS_OPTIONS_IMPORT_DATA_KEEP_TITLE" desc="The title of the Keep Data Separate option on the Import Data settings screen. [60em]"> Keep my data separate </message> + <message name="IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SWITCH" desc="The title of the Import Data settings screen when switching accounts. [30em]"> + Switch Sync Account + </message> <message name="IDS_IOS_OPTIONS_PRELOAD_WEBPAGES" desc="Title for opening the setting for if/when to preload webpages. [Length: 20em] [iOS only]"> Preload Webpages </message>
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index 3a65342..4d8c453 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -10,9 +10,9 @@ "resources/distillation_success.png", "resources/distillation_success@2x.png", "resources/distillation_success@3x.png", - "resources/reading_list_icon.png", - "resources/reading_list_icon@2x.png", - "resources/reading_list_icon@3x.png", + "resources/reading_list_empty_state.png", + "resources/reading_list_empty_state@2x.png", + "resources/reading_list_empty_state@3x.png", "resources/reading_list_side_swipe.png", "resources/reading_list_side_swipe@2x.png", "resources/reading_list_side_swipe@3x.png",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm index 07473ac..6d78d91 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
@@ -47,7 +47,7 @@ namespace { -NSString* const kEmptyReadingListBackgroundIcon = @"reading_list_icon"; +NSString* const kEmptyReadingListBackgroundIcon = @"reading_list_empty_state"; NSString* const kBeginBoldMarker = @"BEGIN_BOLD_FONT"; NSString* const kEndBoldMarker = @"END_BOLD_FONT";
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state.png new file mode 100644 index 0000000..291570d --- /dev/null +++ b/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state.png Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state@2x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state@2x.png new file mode 100644 index 0000000..f686b5f --- /dev/null +++ b/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state@3x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state@3x.png new file mode 100644 index 0000000..3831f1b --- /dev/null +++ b/ios/chrome/browser/ui/reading_list/resources/reading_list_empty_state@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/import_data_collection_view_controller.mm b/ios/chrome/browser/ui/settings/import_data_collection_view_controller.mm index 0d126ef..cdef4a7 100644 --- a/ios/chrome/browser/ui/settings/import_data_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/import_data_collection_view_controller.mm
@@ -15,6 +15,7 @@ #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/settings/cells/card_multiline_item.h" #import "ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_cell.h" +#include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" #import "ios/third_party/material_components_ios/src/components/Collections/src/MaterialCollections.h" @@ -67,6 +68,10 @@ _isSignedIn = isSignedIn; _shouldClearData = isSignedIn ? SHOULD_CLEAR_DATA_CLEAR_DATA : SHOULD_CLEAR_DATA_MERGE_DATA; + self.title = + isSignedIn + ? l10n_util::GetNSString(IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SWITCH) + : l10n_util::GetNSString(IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SIGNIN); [self setShouldHideDoneButton:YES]; self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:l10n_util::GetNSString(
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn index 60396254..fd9cc38 100644 --- a/ios/third_party/material_components_ios/BUILD.gn +++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -170,9 +170,6 @@ "src/components/private/Application/src/MaterialApplication.h", "src/components/private/Application/src/UIApplication+AppExtensions.h", "src/components/private/Application/src/UIApplication+AppExtensions.m", - "src/components/private/Color/src/MaterialColor.h", - "src/components/private/Color/src/UIColor+MDC.h", - "src/components/private/Color/src/UIColor+MDC.m", "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h", "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m", "src/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h",
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index a7ea530c..7afbba1d 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2175,9 +2175,6 @@ # Added 2016-12-12 crbug.com/673539 [ Linux Win ] css3/filters/effect-contrast-hw.html [ Pass Failure ] -# Added 2016-12-14 -crbug.com/674048 [ Linux ] virtual/mojo-loading/http/tests/navigation/image-load-in-unload-handler.html [ Pass Timeout ] - # Added 2016-12-15 crbug.com/674466 [ Win10 ] fast/forms/select/menulist-appearance-rtl.html [ Pass Failure ] crbug.com/674720 [ Debug Trusty ] http/tests/loading/preload-img-test.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/custom-properties/registered-property-cssom.html b/third_party/WebKit/LayoutTests/custom-properties/registered-property-cssom.html index c704405..de03c531 100644 --- a/third_party/WebKit/LayoutTests/custom-properties/registered-property-cssom.html +++ b/third_party/WebKit/LayoutTests/custom-properties/registered-property-cssom.html
@@ -67,6 +67,8 @@ assert_equals(computedStyle.getPropertyValue('--length'), '10px'); sheetStyle.setProperty('--length', '20px'); assert_equals(computedStyle.getPropertyValue('--length'), '20px'); + sheetStyle.setProperty('--length', 'initial'); + assert_equals(computedStyle.getPropertyValue('--length'), '0px'); }, "Stylesheets can be modified by CSSOM"); test(function() { @@ -76,5 +78,8 @@ assert_equals(inlineStyle.getPropertyValue('--color'), 'pink'); assert_equals(computedStyle.getPropertyValue('--length'), '30px'); assert_equals(computedStyle.getPropertyValue('--color'), 'pink'); + inlineStyle.setProperty('--color', 'inherit'); + assert_equals(inlineStyle.getPropertyValue('--color'), 'inherit'); + assert_equals(computedStyle.getPropertyValue('--color'), 'blue'); }, "Valid values can be set on inline styles"); </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/streams/writable-streams/close.js b/third_party/WebKit/LayoutTests/http/tests/streams/writable-streams/close.js index fb15523..5c83a5e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/streams/writable-streams/close.js +++ b/third_party/WebKit/LayoutTests/http/tests/streams/writable-streams/close.js
@@ -170,4 +170,47 @@ }); }, 'releaseLock() should not change the result of async close()'); +promise_test(() => { + let resolveClose; + const ws = new WritableStream({ + close() { + const promise = new Promise(resolve => { + resolveClose = resolve; + }); + return promise; + } + }); + const writer = ws.getWriter(); + const closePromise = writer.close(); + writer.releaseLock(); + return delay(0).then(() => { + resolveClose(); + return closePromise.then(() => { + assert_equals(ws.getWriter().desiredSize, 0, 'desiredSize should be 0'); + }); + }); +}, 'close() should set state to CLOSED even if writer has detached'); + +promise_test(() => { + let resolveClose; + const ws = new WritableStream({ + close() { + const promise = new Promise(resolve => { + resolveClose = resolve; + }); + return promise; + } + }); + const writer = ws.getWriter(); + writer.close(); + writer.releaseLock(); + return delay(0).then(() => { + const abortingWriter = ws.getWriter(); + const abortPromise = abortingWriter.abort(); + abortingWriter.releaseLock(); + resolveClose(); + return abortPromise; + }); +}, 'the promise returned by async abort during close should resolve'); + done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/dom/reflection-embedded-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/html/dom/reflection-embedded-expected.txt index 3547a7da..8ef8584 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/html/dom/reflection-embedded-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/dom/reflection-embedded-expected.txt
@@ -173,20 +173,20 @@ FAIL object.typeMustMatch: setAttribute() to object "test-valueOf" assert_equals: IDL get expected (boolean) true but got (undefined) undefined FAIL object.typeMustMatch: setAttribute() to "typeMustMatch" assert_equals: IDL get expected (boolean) true but got (undefined) undefined FAIL object.typeMustMatch: IDL set to "" assert_equals: hasAttribute() expected false but got true -FAIL object.typeMustMatch: IDL set to " foo " assert_equals: IDL get expected (boolean) true but got (undefined) undefined +FAIL object.typeMustMatch: IDL set to " foo " assert_equals: IDL get expected (boolean) true but got (string) " foo " FAIL object.typeMustMatch: IDL set to undefined assert_equals: hasAttribute() expected false but got true FAIL object.typeMustMatch: IDL set to null assert_equals: hasAttribute() expected false but got true -FAIL object.typeMustMatch: IDL set to 7 assert_equals: IDL get expected (boolean) true but got (undefined) undefined -FAIL object.typeMustMatch: IDL set to 1.5 assert_equals: IDL get expected (boolean) true but got (undefined) undefined -FAIL object.typeMustMatch: IDL set to true assert_equals: IDL get expected (boolean) true but got (undefined) undefined +FAIL object.typeMustMatch: IDL set to 7 assert_equals: IDL get expected (boolean) true but got (number) 7 +FAIL object.typeMustMatch: IDL set to 1.5 assert_equals: IDL get expected (boolean) true but got (number) 1.5 +PASS object.typeMustMatch: IDL set to true FAIL object.typeMustMatch: IDL set to false assert_equals: hasAttribute() expected false but got true -FAIL object.typeMustMatch: IDL set to object "[object Object]" assert_equals: IDL get expected (boolean) true but got (undefined) undefined +FAIL object.typeMustMatch: IDL set to object "[object Object]" assert_equals: IDL get expected (boolean) true but got (object) object "[object Object]" FAIL object.typeMustMatch: IDL set to NaN assert_equals: hasAttribute() expected false but got true -FAIL object.typeMustMatch: IDL set to Infinity assert_equals: IDL get expected (boolean) true but got (undefined) undefined -FAIL object.typeMustMatch: IDL set to -Infinity assert_equals: IDL get expected (boolean) true but got (undefined) undefined -FAIL object.typeMustMatch: IDL set to "\0" assert_equals: IDL get expected (boolean) true but got (undefined) undefined -FAIL object.typeMustMatch: IDL set to object "test-toString" assert_equals: IDL get expected (boolean) true but got (undefined) undefined -FAIL object.typeMustMatch: IDL set to object "test-valueOf" assert_equals: IDL get expected (boolean) true but got (undefined) undefined +FAIL object.typeMustMatch: IDL set to Infinity assert_equals: IDL get expected (boolean) true but got (number) Infinity +FAIL object.typeMustMatch: IDL set to -Infinity assert_equals: IDL get expected (boolean) true but got (number) -Infinity +FAIL object.typeMustMatch: IDL set to "\0" assert_equals: IDL get expected (boolean) true but got (string) "\0" +FAIL object.typeMustMatch: IDL set to object "test-toString" assert_equals: IDL get expected (boolean) true but got (object) object "test-toString" +FAIL object.typeMustMatch: IDL set to object "test-valueOf" assert_equals: IDL get expected (boolean) true but got (object) object "test-valueOf" PASS object.name: 32 tests PASS object.useMap: 32 tests PASS object.width: 32 tests
diff --git a/third_party/WebKit/LayoutTests/plugins/simple-expando.html b/third_party/WebKit/LayoutTests/plugins/simple-expando.html new file mode 100644 index 0000000..3a5ef97 --- /dev/null +++ b/third_party/WebKit/LayoutTests/plugins/simple-expando.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> +test(function() { + var obj = document.createElement("object"); + obj.foo = 1; + assert_equals(obj.foo, 1, "Setting an expando on an <object> works"); +}, "setting an expando"); +</script>
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8HTMLPlugInElementCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8HTMLPlugInElementCustom.cpp index 6404f13..bb9a760 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8HTMLPlugInElementCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8HTMLPlugInElementCustom.cpp
@@ -82,22 +82,25 @@ HTMLPlugInElement* impl = ElementType::toImpl(info.Holder()); RefPtr<SharedPersistent<v8::Object>> wrapper = impl->pluginWrapper(); - v8::Local<v8::Object> instance; - if (wrapper) - instance = wrapper->newLocal(info.GetIsolate()); - if (!instance.IsEmpty()) { - // FIXME: The gTalk pepper plugin is the only plugin to make use of - // SetProperty and that is being deprecated. This can be removed as soon as - // it goes away. - // Call SetProperty on a pepper plugin's scriptable object. Note that we - // never set the return value here which would indicate that the plugin has - // intercepted the SetProperty call, which means that the property on the - // DOM element will also be set. For plugin's that don't intercept the call - // (all except gTalk) this makes no difference at all. For gTalk the fact - // that the property on the DOM element also gets set is inconsequential. - v8CallBoolean(instance->CreateDataProperty( - info.GetIsolate()->GetCurrentContext(), v8Name, value)); - } + if (!wrapper) + return; + + v8::Local<v8::Object> instance = wrapper->newLocal(info.GetIsolate()); + + if (instance.IsEmpty()) + return; + + // FIXME: The gTalk pepper plugin is the only plugin to make use of + // SetProperty and that is being deprecated. This can be removed as soon as + // it goes away. + // Call SetProperty on a pepper plugin's scriptable object. Note that we + // never set the return value here which would indicate that the plugin has + // intercepted the SetProperty call, which means that the property on the + // DOM element will also be set. For plugin's that don't intercept the call + // (all except gTalk) this makes no difference at all. For gTalk the fact + // that the property on the DOM element also gets set is inconsequential. + v8CallBoolean(instance->CreateDataProperty( + info.GetIsolate()->GetCurrentContext(), v8Name, value)); v8SetReturnValue(info, value); }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp index 56c252ed..a6549ff 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -81,7 +81,9 @@ bool didParse = false; bool didChange = false; if (!parser.m_parsedProperties.isEmpty()) { - if (registry) { + const CSSCustomPropertyDeclaration* parsedDeclaration = + toCSSCustomPropertyDeclaration(parser.m_parsedProperties[0].value()); + if (parsedDeclaration->value() && registry) { const PropertyRegistry::Registration* registration = registry->registration(propertyName); // TODO(timloh): This is a bit wasteful, we parse the registered property
diff --git a/third_party/WebKit/Source/core/dom/StyleEngine.cpp b/third_party/WebKit/Source/core/dom/StyleEngine.cpp index b225c09..a708c8a 100644 --- a/third_party/WebKit/Source/core/dom/StyleEngine.cpp +++ b/third_party/WebKit/Source/core/dom/StyleEngine.cpp
@@ -451,7 +451,9 @@ m_activeTreeScopes.clear(); m_viewportResolver = nullptr; m_mediaQueryEvaluator = nullptr; - clearFontCache(); + if (m_fontSelector) + m_fontSelector->fontFaceCache()->clearAll(); + m_fontSelector = nullptr; } void StyleEngine::clearFontCache() {
diff --git a/third_party/WebKit/Source/core/editing/CaretBase.cpp b/third_party/WebKit/Source/core/editing/CaretBase.cpp index 07e9ed7..57550300f 100644 --- a/third_party/WebKit/Source/core/editing/CaretBase.cpp +++ b/third_party/WebKit/Source/core/editing/CaretBase.cpp
@@ -47,10 +47,6 @@ DEFINE_TRACE(CaretBase) {} -void CaretBase::clearCaretRect() { - m_caretLocalRect = LayoutRect(); -} - static inline bool caretRendersInsideNode(Node* node) { return node && !isDisplayInsideTable(node) && !editingIgnoresContent(*node); } @@ -77,53 +73,50 @@ : layoutObject->containingBlock(); } -static void mapCaretRectToCaretPainter(LayoutItem caretLayoutItem, - LayoutBlockItem caretPainterItem, - LayoutRect& caretRect) { +static LayoutRect mapCaretRectToCaretPainter( + LayoutItem caretLayoutItem, + LayoutBlockItem caretPainterItem, + const LayoutRect& passedCaretRect) { // FIXME: This shouldn't be called on un-rooted subtrees. // FIXME: This should probably just use mapLocalToAncestor. // Compute an offset between the caretLayoutItem and the caretPainterItem. DCHECK(caretLayoutItem.isDescendantOf(caretPainterItem)); - bool unrooted = false; + LayoutRect caretRect = passedCaretRect; while (caretLayoutItem != caretPainterItem) { LayoutItem containerItem = caretLayoutItem.container(); - if (containerItem.isNull()) { - unrooted = true; - break; - } + if (containerItem.isNull()) + return LayoutRect(); caretRect.move(caretLayoutItem.offsetFromContainer(containerItem)); caretLayoutItem = containerItem; } - - if (unrooted) - caretRect = LayoutRect(); + return caretRect; } -void CaretBase::updateCaretRect(const PositionWithAffinity& caretPosition) { - m_caretLocalRect = LayoutRect(); - +LayoutRect CaretBase::computeCaretRect( + const PositionWithAffinity& caretPosition) { if (caretPosition.isNull()) - return; + return LayoutRect(); DCHECK(caretPosition.anchorNode()->layoutObject()); // First compute a rect local to the layoutObject at the selection start. LayoutObject* layoutObject; - m_caretLocalRect = localCaretRectOfPosition(caretPosition, layoutObject); + const LayoutRect& caretLocalRect = + localCaretRectOfPosition(caretPosition, layoutObject); // Get the layoutObject that will be responsible for painting the caret // (which is either the layoutObject we just found, or one of its containers). LayoutBlockItem caretPainterItem = LayoutBlockItem(caretLayoutObject(caretPosition.anchorNode())); - mapCaretRectToCaretPainter(LayoutItem(layoutObject), caretPainterItem, - m_caretLocalRect); + return mapCaretRectToCaretPainter(LayoutItem(layoutObject), caretPainterItem, + caretLocalRect); } -void CaretBase::updateCaretRect(const VisiblePosition& caretPosition) { - updateCaretRect(caretPosition.toPositionWithAffinity()); +LayoutRect CaretBase::computeCaretRect(const VisiblePosition& caretPosition) { + return computeCaretRect(caretPosition.toPositionWithAffinity()); } IntRect CaretBase::absoluteBoundsForLocalRect(Node* node, @@ -168,21 +161,24 @@ (node.parentNode() && hasEditableStyle(*node.parentNode())); } -void CaretBase::invalidateCaretRect(Node* node) { +void CaretBase::invalidateCaretRect(Node* node, + const LayoutRect& caretLocalRect) { node->document().updateStyleAndLayoutTree(); if (hasEditableStyle(*node)) - invalidateLocalCaretRect(node, localCaretRectWithoutUpdate()); + invalidateLocalCaretRect(node, caretLocalRect); } void CaretBase::paintCaret(Node* node, GraphicsContext& context, + const DisplayItemClient& client, + const LayoutRect& caretLocalRect, const LayoutPoint& paintOffset, - DisplayItem::Type displayItemType) const { - if (DrawingRecorder::useCachedDrawingIfPossible(context, *this, + DisplayItem::Type displayItemType) { + if (DrawingRecorder::useCachedDrawingIfPossible(context, client, displayItemType)) return; - LayoutRect drawingRect = localCaretRectWithoutUpdate(); + LayoutRect drawingRect = caretLocalRect; if (LayoutBlock* layoutObject = caretLayoutObject(node)) layoutObject->flipForWritingMode(drawingRect); drawingRect.moveBy(paintOffset); @@ -190,7 +186,7 @@ const Color caretColor = node->layoutObject()->resolveColor(CSSPropertyCaretColor); IntRect paintRect = pixelSnappedIntRect(drawingRect); - DrawingRecorder drawingRecorder(context, *this, DisplayItem::kCaret, + DrawingRecorder drawingRecorder(context, client, DisplayItem::kCaret, paintRect); context.fillRect(paintRect, caretColor); }
diff --git a/third_party/WebKit/Source/core/editing/CaretBase.h b/third_party/WebKit/Source/core/editing/CaretBase.h index 15cbba2..264bc57b 100644 --- a/third_party/WebKit/Source/core/editing/CaretBase.h +++ b/third_party/WebKit/Source/core/editing/CaretBase.h
@@ -48,23 +48,29 @@ CaretBase(); virtual ~CaretBase(); - void invalidateCaretRect(Node*); - void clearCaretRect(); + void invalidateCaretRect(Node*, const LayoutRect&); // Creating VisiblePosition causes synchronous layout so we should use the // PositionWithAffinity version if possible. // A position in HTMLTextFromControlElement is a typical example. - void updateCaretRect(const PositionWithAffinity& caretPosition); - void updateCaretRect(const VisiblePosition& caretPosition); - IntRect absoluteBoundsForLocalRect(Node*, const LayoutRect&) const; - bool shouldRepaintCaret(Node&) const; - void paintCaret(Node*, - GraphicsContext&, - const LayoutPoint&, - DisplayItem::Type) const; + static LayoutRect computeCaretRect(const PositionWithAffinity& caretPosition); - const LayoutRect& localCaretRectWithoutUpdate() const { - return m_caretLocalRect; - } + // TODO(yosin): We should move |computeCaretRect()| with |VisiblePosition| to + // "FrameCaret.cpp" as static file local function. + static LayoutRect computeCaretRect(const VisiblePosition& caretPosition); + + // TODO(yosin): We should move |absoluteBoundsForLocalRect()| with + // |VisiblePosition| to "FrameCaret.cpp" as static file local function. + IntRect absoluteBoundsForLocalRect(Node*, const LayoutRect&) const; + + // TODO(yosin): We should move |shouldRepaintCaret()| to "FrameCaret.cpp" as + // static file local function. + bool shouldRepaintCaret(Node&) const; + static void paintCaret(Node*, + GraphicsContext&, + const DisplayItemClient&, + const LayoutRect& caretLocalRect, + const LayoutPoint&, + DisplayItem::Type); static LayoutBlock* caretLayoutObject(Node*); void invalidateLocalCaretRect(Node*, const LayoutRect&); @@ -76,9 +82,6 @@ DECLARE_VIRTUAL_TRACE(); private: - // caret rect in coords local to the layoutObject responsible for painting the - // caret - LayoutRect m_caretLocalRect; LayoutRect m_visualRect; };
diff --git a/third_party/WebKit/Source/core/editing/DragCaretController.cpp b/third_party/WebKit/Source/core/editing/DragCaretController.cpp index e3f3300..61f9722 100644 --- a/third_party/WebKit/Source/core/editing/DragCaretController.cpp +++ b/third_party/WebKit/Source/core/editing/DragCaretController.cpp
@@ -61,20 +61,20 @@ DisableCompositingQueryAsserts disabler; if (Node* node = m_position.anchorNode()) - m_caretBase->invalidateCaretRect(node); + m_caretBase->invalidateCaretRect(node, m_caretLocalRect); m_position = createVisiblePosition(position).toPositionWithAffinity(); Document* document = nullptr; if (Node* node = m_position.anchorNode()) { - m_caretBase->invalidateCaretRect(node); + m_caretBase->invalidateCaretRect(node, m_caretLocalRect); document = &node->document(); setContext(document); } if (m_position.isNull()) { - m_caretBase->clearCaretRect(); + m_caretLocalRect = LayoutRect(); } else { DCHECK(!m_position.isOrphan()); document->updateStyleAndLayoutTree(); - m_caretBase->updateCaretRect(m_position); + m_caretLocalRect = CaretBase::computeCaretRect(m_position); } } @@ -112,8 +112,9 @@ GraphicsContext& context, const LayoutPoint& paintOffset) const { if (m_position.anchorNode()->document().frame() == frame) { - m_caretBase->paintCaret(m_position.anchorNode(), context, paintOffset, - DisplayItem::kDragCaret); + CaretBase::paintCaret(m_position.anchorNode(), context, *m_caretBase, + m_caretLocalRect, paintOffset, + DisplayItem::kDragCaret); } }
diff --git a/third_party/WebKit/Source/core/editing/DragCaretController.h b/third_party/WebKit/Source/core/editing/DragCaretController.h index 71d7f4bb..a001451 100644 --- a/third_party/WebKit/Source/core/editing/DragCaretController.h +++ b/third_party/WebKit/Source/core/editing/DragCaretController.h
@@ -63,6 +63,9 @@ void nodeWillBeRemoved(Node&) final; PositionWithAffinity m_position; + // caret rect in coords local to the layoutObject responsible for painting the + // caret + LayoutRect m_caretLocalRect; const Member<CaretBase> m_caretBase; };
diff --git a/third_party/WebKit/Source/core/editing/FrameCaret.cpp b/third_party/WebKit/Source/core/editing/FrameCaret.cpp index 85fc98a6..d207352 100644 --- a/third_party/WebKit/Source/core/editing/FrameCaret.cpp +++ b/third_party/WebKit/Source/core/editing/FrameCaret.cpp
@@ -209,6 +209,7 @@ m_previousCaretVisibility = m_caretVisibility; } +// TDOO(yosin): We should mark |FrameCaret::absoluteCaretBounds()| to |const|. IntRect FrameCaret::absoluteCaretBounds() { DCHECK_NE(m_frame->document()->lifecycle().state(), DocumentLifecycle::InPaintInvalidation); @@ -216,20 +217,18 @@ DocumentLifecycle::DisallowTransitionScope disallowTransition( m_frame->document()->lifecycle()); - if (!isActive()) { - clearCaretRect(); - } else { - if (enclosingTextControl(caretPosition().position())) { - if (isVisuallyEquivalentCandidate(caretPosition().position())) - updateCaretRect(caretPosition()); - else - updateCaretRect(createVisiblePosition(caretPosition())); - } else { - updateCaretRect(createVisiblePosition(caretPosition())); - } + Node* const caretNode = caretPosition().anchorNode(); + if (!isActive()) + return absoluteBoundsForLocalRect(caretNode, LayoutRect()); + // TODO(yosin): We should get rid of text control short path since layout + // tree is clean. + if (enclosingTextControl(caretPosition().position()) && + isVisuallyEquivalentCandidate(caretPosition().position())) { + return absoluteBoundsForLocalRect(caretNode, + computeCaretRect(caretPosition())); } - return absoluteBoundsForLocalRect(caretPosition().anchorNode(), - localCaretRectWithoutUpdate()); + return absoluteBoundsForLocalRect( + caretNode, computeCaretRect(createVisiblePosition(caretPosition()))); } void FrameCaret::setShouldShowBlockCursor(bool shouldShowBlockCursor) { @@ -248,9 +247,9 @@ if (!(isActive() && m_shouldPaintCaret)) return; - updateCaretRect(caretPosition()); - CaretBase::paintCaret(caretPosition().anchorNode(), context, paintOffset, - DisplayItem::kCaret); + const LayoutRect caretLocalRect = computeCaretRect(caretPosition()); + CaretBase::paintCaret(caretPosition().anchorNode(), context, *this, + caretLocalRect, paintOffset, DisplayItem::kCaret); } void FrameCaret::dataWillChange(const CharacterData& node) {
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp index 244af9b..4b7a190 100644 --- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -1972,6 +1972,9 @@ if (!enclosingAnchor) return original; } + + document().updateStyleAndLayoutIgnorePendingStylesheets(); + // Don't insert outside an anchor if doing so would skip over a line // break. It would probably be safe to move the line break so that we // could still avoid the anchor here. @@ -1984,8 +1987,6 @@ result = Position::inParentAfterNode(*enclosingAnchor); } - document().updateStyleAndLayoutIgnorePendingStylesheets(); - // If visually just before an anchor, insert *outside* the anchor unless // it's the first VisiblePosition in a paragraph, to match NSTextView. if (visiblePos.deepEquivalent() == firstInAnchor.deepEquivalent()) {
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp index 79fc3a5..4a6ad4eb 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -596,6 +596,8 @@ startPos = Position::beforeNode(placeholder); } + document().updateStyleAndLayoutIgnorePendingStylesheets(); + // Insert the list at a position visually equivalent to start of the // paragraph that is being moved into the list. // Try to avoid inserting it somewhere where it will be surrounded by
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp index 2e1a000..d8185db1 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -364,6 +364,8 @@ refNode = insertionPosition.anchorNode(); } + document().updateStyleAndLayoutIgnorePendingStylesheets(); + // find ending selection position easily before inserting the paragraph insertionPosition = mostForwardCaretPosition(insertionPosition);
diff --git a/third_party/WebKit/Source/core/streams/WritableStream.js b/third_party/WebKit/Source/core/streams/WritableStream.js index 5780fa8..e987cedd 100644 --- a/third_party/WebKit/Source/core/streams/WritableStream.js +++ b/third_party/WebKit/Source/core/streams/WritableStream.js
@@ -306,13 +306,16 @@ TEMP_ASSERT(state === CLOSING || state === ERRORED, 'state is "closing" or "errored"'); + const writer = stream[_writer]; if (state === CLOSING) { - v8.resolvePromise(stream[_writer][_closedPromise], undefined); + if (writer !== undefined) { + v8.resolvePromise(writer[_closedPromise], undefined); + } stream[_state] = CLOSED; - } else { + } else if (writer !== undefined) { TEMP_ASSERT(state === ERRORED, 'state is "errored"'); - v8.rejectPromise(stream[_writer][_closedPromise], stream[_storedError]); - v8.markPromiseAsHandled(stream[_writer][_closedPromise]); + v8.rejectPromise(writer[_closedPromise], stream[_storedError]); + v8.markPromiseAsHandled(writer[_closedPromise]); } if (stream[_pendingAbortRequest] !== undefined) {
diff --git a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp index c7bcaa1..f57c4be 100644 --- a/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp +++ b/third_party/WebKit/Source/web/WebRuntimeFeatures.cpp
@@ -150,6 +150,10 @@ RuntimeEnabledFeatures::setSensorEnabled(enable); } +void WebRuntimeFeatures::enableHeapCompaction(bool enable) { + RuntimeEnabledFeatures::setHeapCompactionEnabled(enable); +} + void WebRuntimeFeatures::enableInputMultipleFieldsUI(bool enable) { RuntimeEnabledFeatures::setInputMultipleFieldsUIEnabled(enable); }
diff --git a/third_party/WebKit/Source/wtf/Allocator.md b/third_party/WebKit/Source/wtf/Allocator.md index c034a8f..a08e00de 100644 --- a/third_party/WebKit/Source/wtf/Allocator.md +++ b/third_party/WebKit/Source/wtf/Allocator.md
@@ -19,7 +19,7 @@ * HeapVector<T>, HeapHashSet<T>, HeapHashMap<T, U> etc The implementation is in platform/heap/. -See [BlinkGCDesign.md](platform/heap/BlinkGCDesign.md) to learn the design. +See [BlinkGCDesign.md](../platform/heap/BlinkGCDesign.md) to learn the design. ### PartitionAlloc @@ -37,8 +37,9 @@ * Strings, Vectors, HashTables, ArrayBuffers and other primitive containers. -The implementation is in wtf/Partition*. -See [PartitionAlloc.md](wtf/PartitionAlloc.md) to learn the design. +The implementation is in /base/allocator/partition_allocator. +See [PartitionAlloc.md](/base/allocator/partition_allocator/PartitionAlloc.md) +to learn the design. ### Discardable memory @@ -73,7 +74,7 @@ * Use Oilpan if you want a GC to manage the lifetime of the object. You need to make the object inherit from GarbageCollected<T> or GarbageCollectedFinalized<T>. See -[BlinkGCAPIReference.md](platform/heap/BlinkGCAPIReference.md) to learn +[BlinkGCAPIReference.md](../platform/heap/BlinkGCAPIReference.md) to learn programming with Oilpan. ```c++
diff --git a/third_party/WebKit/public/web/WebRuntimeFeatures.h b/third_party/WebKit/public/web/WebRuntimeFeatures.h index 9ce38029..9fc53c46 100644 --- a/third_party/WebKit/public/web/WebRuntimeFeatures.h +++ b/third_party/WebKit/public/web/WebRuntimeFeatures.h
@@ -84,6 +84,7 @@ BLINK_EXPORT static void enableFileSystem(bool); BLINK_EXPORT static void enableGamepadExtensions(bool); BLINK_EXPORT static void enableGenericSensor(bool); + BLINK_EXPORT static void enableHeapCompaction(bool); BLINK_EXPORT static void enableInputMultipleFieldsUI(bool); BLINK_EXPORT static void enableLazyParseCSS(bool); BLINK_EXPORT static void enableMediaCapture(bool);
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 0d7e7e5..0f2cf42f 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -19458,6 +19458,16 @@ </summary> </histogram> +<histogram name="GCM.PendingConnectionEventsAtShutdown" units="events"> + <owner>harkness@chromium.org</owner> + <summary> + Number of connection events which have not been sent to GCM. This is + recorded only at the time of shutdown to capture the events which are being + lost due to shutdown. Because this is recorded at shutdown, this is not + guaranteed to be complete and should be treated as a best effort record. + </summary> +</histogram> + <histogram name="GCM.ReceivedDataMessageBurstSize" units="messages"> <owner>juyik@chromium.org</owner> <summary>Number of messages in a received GCM data message burst.</summary> @@ -26744,6 +26754,13 @@ </summary> </histogram> +<histogram base="true" name="Memory.Experimental.Renderer" units="MB"> +<!-- Name completed by histogram_suffixes name="RendererMemoryAllocator" --> + + <owner>keishi@chromium.org</owner> + <summary>The renderer process's memory usage after a page load.</summary> +</histogram> + <histogram name="Memory.Extension" units="KB"> <owner>hajimehoshi@chromium.org</owner> <owner>kenjibaheux@google.com</owner> @@ -115310,6 +115327,45 @@ <affected-histogram name="Event.Latency.RendererImpl"/> </histogram_suffixes> +<histogram_suffixes name="RendererMemoryAllocator" separator="."> + <suffix base="true" name="BlinkGC" + label="Constrained to the BlinkGC allocator"/> + <suffix base="true" name="Discardable" + label="Constrained to discardable memory usage"/> + <suffix base="true" name="Malloc" label="Constrained to malloc usage"/> + <suffix base="true" name="NonDiscardableTotalAllocated" + label="Summed over the PartitionAlloc, malloc, mainThreadIsolate() and + BlinkGC allocators"/> + <suffix base="true" name="PartitionAlloc" + label="Constrained to the PartitionAlloc allocator"/> + <suffix base="true" name="TotalAllocatedPerRenderView" + label="TotalAllocated divided by the number of RenderViews"/> + <suffix base="true" name="V8MainThreadIsolate" + label="Constrained to memory usage by mainThreadIsolate()"/> + <suffix base="true" name="TotalAllocated" + label="Summed over the PartitionAlloc, malloc, discardable memory, + mainThreadIsolate() and BlinkGC allocators"/> + <affected-histogram name="Memory.Experimental.Renderer"/> +</histogram_suffixes> + +<histogram_suffixes name="RendererMemoryTiming" separator="."> + <suffix name="DidFinishLoad" + label="Recorded each time DidFinishLoad is called for *any* frame + within the page."/> + <suffix name="MainFrameDidFinishLoad" + label="Recorded when DidFinishLoad is called for the main frame."/> + <affected-histogram name="Memory.Experimental.Renderer.BlinkGC"/> + <affected-histogram name="Memory.Experimental.Renderer.Discardable"/> + <affected-histogram name="Memory.Experimental.Renderer.Malloc"/> + <affected-histogram + name="Memory.Experimental.Renderer.NonDiscardableTotalAllocated"/> + <affected-histogram name="Memory.Experimental.Renderer.PartitionAlloc"/> + <affected-histogram name="Memory.Experimental.Renderer.TotalAllocated"/> + <affected-histogram + name="Memory.Experimental.Renderer.TotalAllocatedPerRenderView"/> + <affected-histogram name="Memory.Experimental.Renderer.V8MainThreadIsolate"/> +</histogram_suffixes> + <histogram_suffixes name="RequestMediaKeySystemAccessKeySystems" separator="."> <suffix name="ClearKey" label="Requests for the Clear Key key system."/> <suffix name="Unknown"
diff --git a/tools/perf/page_sets/blob_workshop.py b/tools/perf/page_sets/blob_workshop.py index a766293..8d873f9 100644 --- a/tools/perf/page_sets/blob_workshop.py +++ b/tools/perf/page_sets/blob_workshop.py
@@ -25,9 +25,8 @@ for size_bytes in self._blob_sizes: with action_runner.CreateInteraction('Action_CreateAndReadBlob', repeatable=True): - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript( - 'createAndRead(' + str(size_bytes) + ');') + 'createAndRead({{ size }});', size=size_bytes) action_runner.WaitForJavaScriptCondition( 'doneReading === true || errors', timeout_in_seconds=60) @@ -51,8 +50,8 @@ for size_bytes in self._blob_sizes: with action_runner.CreateInteraction('Action_CreateBlob', repeatable=True): - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - action_runner.ExecuteJavaScript('createBlob(' + str(size_bytes) + ');') + action_runner.ExecuteJavaScript( + 'createBlob({{ size }});', size=size_bytes) # Read blobs for _ in range(0, NUM_BLOB_MASS_CREATE_READS):
diff --git a/tools/perf/page_sets/google_pages.py b/tools/perf/page_sets/google_pages.py index d782a47..abdb76a 100644 --- a/tools/perf/page_sets/google_pages.py +++ b/tools/perf/page_sets/google_pages.py
@@ -6,6 +6,7 @@ from telemetry.page import page as page_module from telemetry.page import shared_page_state +from telemetry.util import js_template import os @@ -67,8 +68,8 @@ page_set=page_set, name='AdwordsCampaign', credentials_path='data/credentials.json', shared_page_state_class=shared_page_state.SharedDesktopPageState) - self.script_to_evaluate_on_commit = ( - 'console.time("%s");' % INTERACTION_NAME) + self.script_to_evaluate_on_commit = js_template.Render( + 'console.time({{ label }});', label=INTERACTION_NAME) def RunNavigateSteps(self, action_runner): google_login.LoginGoogleAccount(action_runner, 'google3', @@ -77,5 +78,5 @@ def RunPageInteractions(self, action_runner): action_runner.WaitForElement(text='Welcome to AdWords!') - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - action_runner.ExecuteJavaScript('console.timeEnd("%s");' % INTERACTION_NAME) + action_runner.ExecuteJavaScript( + 'console.timeEnd({{ label }});', label=INTERACTION_NAME)
diff --git a/tools/perf/page_sets/indexeddb_endure_page.py b/tools/perf/page_sets/indexeddb_endure_page.py index ada21bec..176d726 100644 --- a/tools/perf/page_sets/indexeddb_endure_page.py +++ b/tools/perf/page_sets/indexeddb_endure_page.py
@@ -15,9 +15,8 @@ self._subtest = subtest def RunPageInteractions(self, action_runner): - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - action_runner.ExecuteJavaScript('window.testFilter = "' + - self._subtest + '";') + action_runner.ExecuteJavaScript( + 'window.testFilter = {{ subtest }};', subtest=self._subtest) with action_runner.CreateInteraction('Action_Test'): action_runner.ExecuteJavaScript('window.test();') action_runner.WaitForJavaScriptCondition(
diff --git a/tools/perf/page_sets/key_silk_cases.py b/tools/perf/page_sets/key_silk_cases.py index 2023f2b..ee9395f 100644 --- a/tools/perf/page_sets/key_silk_cases.py +++ b/tools/perf/page_sets/key_silk_cases.py
@@ -418,9 +418,9 @@ def ScrollKnowledgeCardToTop(self, action_runner, card_id): # scroll until the knowledge card is at the top - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript( - "document.getElementById('%s').scrollIntoView()" % card_id) + "document.getElementById({{ card_id }}).scrollIntoView()", + card_id=card_id) def PerformPageInteractions(self, action_runner): self.ExpandKnowledgeCard(action_runner) @@ -648,20 +648,19 @@ first_name = profile + 'paper-input#first /deep/ input' action_runner.WaitForElement(selector=first_name) # Input First Name: - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript(''' - var fn = document.querySelector('%s'); + var fn = document.querySelector({{ first_name }}); fn.value = 'Chrome'; - fn.fire('input');''' % first_name) + fn.fire('input');''', + first_name=first_name) # Input Last Initial: - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript(''' - var li = document.querySelector('%s paper-input#last /deep/ input'); + var li = document.querySelector({{ selector }}); li.value = 'E'; - li.fire('input');''' % profile) + li.fire('input');''', + selector='%s paper-input#last /deep/ input' % profile) with action_runner.CreateInteraction('animation_interaction'): # Click the check-mark to login: - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript(''' window.topeka_page_transitions = 0; [].forEach.call(document.querySelectorAll( @@ -671,7 +670,8 @@ window.topeka_page_transitions++; }); }); - document.querySelector('%s paper-fab').fire('tap')''' % profile) + document.querySelector({{ selector }}).fire('tap')''', + selector='%s paper-fab' % profile) # Wait for category list to animate in: action_runner.WaitForJavaScriptCondition(''' window.topeka_page_transitions === 1''')
diff --git a/tools/perf/page_sets/login_helpers/dropbox_login.py b/tools/perf/page_sets/login_helpers/dropbox_login.py index fda3a3a..c4f81c4 100644 --- a/tools/perf/page_sets/login_helpers/dropbox_login.py +++ b/tools/perf/page_sets/login_helpers/dropbox_login.py
@@ -32,13 +32,13 @@ # Wait until the "Sign in" button is enabled and then click it. login_button_selector = '.login-form .login-button' - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.WaitForJavaScriptCondition(''' (function() { - var loginButton = document.querySelector("%s"); + var loginButton = document.querySelector({{ selector }}); if (!loginButton) return false; return !loginButton.disabled; - })();''' % login_button_selector) + })();''', + selector=login_button_selector) action_runner.ClickElement(selector=login_button_selector) action_runner.WaitForNavigate()
diff --git a/tools/perf/page_sets/login_helpers/google_login.py b/tools/perf/page_sets/login_helpers/google_login.py index 9c5a14e..a1108e4 100644 --- a/tools/perf/page_sets/login_helpers/google_login.py +++ b/tools/perf/page_sets/login_helpers/google_login.py
@@ -43,9 +43,8 @@ 'https%3A%2F%2Faccounts.google.com%2FManageAccount') # Wait until either the email or password input is visible. - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - action_runner.WaitForJavaScriptCondition('%s || %s' % ( - _EMAIL_INPUT_VISIBLE_CONDITION, _PASSWORD_INPUT_VISIBLE_CONDITION)) + action_runner.WaitForJavaScriptCondition('{{ @a }} || {{ @b }}', + a=_EMAIL_INPUT_VISIBLE_CONDITION, b=_PASSWORD_INPUT_VISIBLE_CONDITION) # If the email input is visible, this is the first Google login within the # browser session, so we must enter both email and password. Otherwise, only
diff --git a/tools/perf/page_sets/login_helpers/login_utils.py b/tools/perf/page_sets/login_helpers/login_utils.py index 296ed20..710c415 100644 --- a/tools/perf/page_sets/login_helpers/login_utils.py +++ b/tools/perf/page_sets/login_helpers/login_utils.py
@@ -45,10 +45,9 @@ possible exceptions. """ action_runner.WaitForElement(selector=input_selector) - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript( - 'document.querySelector("%s").value = "%s";' % - (input_selector, input_text)) + 'document.querySelector({{ selector }}).value = {{ value }};', + selector=input_selector, value=input_text) def InputForm(action_runner, input_text, input_id, form_id=None): """Sets the text value of an input field in a form on the page.
diff --git a/tools/perf/page_sets/polymer.py b/tools/perf/page_sets/polymer.py index 01e003a..47665aa 100644 --- a/tools/perf/page_sets/polymer.py +++ b/tools/perf/page_sets/polymer.py
@@ -4,6 +4,7 @@ from telemetry.page import page as page_module from telemetry.page import shared_page_state from telemetry import story +from telemetry.util import js_template class PolymerPage(page_module.Page): @@ -111,9 +112,8 @@ def AnimateShadow(self, action_runner, eid): for i in range(1, 6): - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript( - 'document.getElementById("{0}").z = {1}'.format(eid, i)) + 'document.getElementById({{ eid }}).z = {{ i }}', eid=eid, i=i) action_runner.Wait(1) @@ -138,15 +138,13 @@ def RunNavigateSteps(self, action_runner): super(PolymerSampler, self).RunNavigateSteps(action_runner) - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - waitForLoadJS = """ - window.Polymer.whenPolymerReady(function() { - %s.contentWindow.Polymer.whenPolymerReady(function() { - window.__polymer_ready = true; - }) - }); - """ % self.iframe_js - action_runner.ExecuteJavaScript(waitForLoadJS) + action_runner.ExecuteJavaScript(""" + window.Polymer.whenPolymerReady(function() { + {{ @iframe }}.contentWindow.Polymer.whenPolymerReady(function() { + window.__polymer_ready = true; + }) + }); + """, iframe=self.iframe_js) action_runner.WaitForJavaScriptCondition( 'window.__polymer_ready') @@ -192,14 +190,15 @@ def DoActionOnWidgetType(self, action_runner, widget_type, action_function): # Find all widgets of this type, but skip any that are disabled or are # currently active as they typically don't produce animation frames. - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - element_list_query = (self.iframe_js + - ('.querySelectorAll("body %s:not([disabled]):' - 'not([active])")' % widget_type)) + element_list_query = js_template.Render( + '{{ @iframe }}.querySelectorAll({{ selector }})', + iframe=self.iframe_js, + selector='body %s:not([disabled]):not([active])' % widget_type) + roles_count_query = element_list_query + '.length' for i in range(action_runner.EvaluateJavaScript(roles_count_query)): - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - element_query = element_list_query + ("[%d]" % i) + element_query = js_template.Render( + '{{ @query }}[{{ i }}]', query=element_list_query, i=i) if action_runner.EvaluateJavaScript( element_query + '.offsetParent != null'): # Only try to tap on visible elements (offsetParent != null)
diff --git a/tools/perf/page_sets/repaint_helpers.py b/tools/perf/page_sets/repaint_helpers.py index 08bd48f0..a08025c 100644 --- a/tools/perf/page_sets/repaint_helpers.py +++ b/tools/perf/page_sets/repaint_helpers.py
@@ -26,9 +26,10 @@ chrome.gpuBenchmarking.runMicroBenchmark( "invalidation_benchmark", function(value) {}, - """ + str(args) + """ + {{ args }} ); - """) + """, + args=args) micro_benchmark_id = action_runner.EvaluateJavaScript( 'window.benchmark_results.id') @@ -39,14 +40,14 @@ with action_runner.CreateInteraction('Repaint'): action_runner.RepaintContinuously(seconds=5) - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.ExecuteJavaScript(""" window.benchmark_results.message_handled = chrome.gpuBenchmarking.sendMessageToMicroBenchmark( - """ + str(micro_benchmark_id) + """, { - "notify_done": true - }); - """) + {{ micro_benchmark_id }}, { + "notify_done": true + }); + """, + micro_benchmark_id=micro_benchmark_id) def WaitThenRepaint(action_runner):
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py index fcc725a..3470aba 100644 --- a/tools/perf/page_sets/system_health/browsing_stories.py +++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -222,9 +222,9 @@ # window does not have a "Close" button, instead it has only a "Send link # to phone" button. So on tablets we run with the popup window open. The # popup is transparent, so this is mostly an aesthetical issue. - # TODO(catapult:#3028): Fix interpolation of JavaScript values. has_button = action_runner.EvaluateJavaScript( - '!!document.querySelector("%s")' % self._CLOSE_BUTTON_SELECTOR) + '!!document.querySelector({{ selector }})', + selector=self._CLOSE_BUTTON_SELECTOR) if has_button: action_runner.ClickElement(selector=self._CLOSE_BUTTON_SELECTOR) super(WashingtonPostMobileStory, self)._DidLoadDocument(action_runner)
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py index 2b0af06..022d74f3 100644 --- a/tools/perf/page_sets/system_health/loading_stories.py +++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -187,9 +187,9 @@ # window does not have a "Close" button, instead it has only a "Send link # to phone" button. So on tablets we run with the popup window open. The # popup is transparent, so this is mostly an aesthetical issue. - # TODO(catapult:#3028): Fix interpolation of JavaScript values. has_button = action_runner.EvaluateJavaScript( - '!!document.querySelector("%s")' % self._CLOSE_BUTTON_SELECTOR) + '!!document.querySelector({{ selector }})', + selector=self._CLOSE_BUTTON_SELECTOR) if has_button: action_runner.ClickElement(selector=self._CLOSE_BUTTON_SELECTOR)
diff --git a/tools/perf/page_sets/system_health/media_stories.py b/tools/perf/page_sets/system_health/media_stories.py index 6a8501f..ad079e8d 100644 --- a/tools/perf/page_sets/system_health/media_stories.py +++ b/tools/perf/page_sets/system_health/media_stories.py
@@ -35,9 +35,8 @@ raise NotImplementedError def _WaitForAndClickElementBySelector(self, action_runner, selector): - element_function = 'document.querySelector("%s")' % selector - action_runner.WaitForElement(element_function=element_function) - action_runner.ClickElement(element_function=element_function) + action_runner.WaitForElement(selector=selector) + action_runner.ClickElement(selector=selector) def _WaitForPlayTime(self, action_runner): action_runner.Wait(self.PLAY_DURATION) @@ -46,10 +45,9 @@ self.PLAY_DURATION - self._GetTimeInSeconds(action_runner)) def _GetTimeInSeconds(self, action_runner): - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - time_func = ( - 'document.querySelector("%s").textContent' % self.TIME_SELECTOR) - minutes, seconds = action_runner.EvaluateJavaScript(time_func).split(':') + minutes, seconds = action_runner.EvaluateJavaScript( + 'document.querySelector({{ selector }}).textContent', + selector=self.TIME_SELECTOR).split(':') return int(minutes * 60 + seconds)
diff --git a/tools/perf/page_sets/todomvc.py b/tools/perf/page_sets/todomvc.py index 35daccb..43ce61e 100644 --- a/tools/perf/page_sets/todomvc.py +++ b/tools/perf/page_sets/todomvc.py
@@ -5,6 +5,7 @@ from telemetry.page import page as page_module from telemetry.page import shared_page_state from telemetry import story +from telemetry.util import js_template URL_LIST = [ @@ -31,8 +32,8 @@ # TODO(jochen): This interaction does not include the # WindowProxy::initialize portion before the commit. To fix this, we'll # have to migrate to TBMv2. - self.script_to_evaluate_on_commit = ( - 'console.time("%s");' % INTERACTION_NAME) + self.script_to_evaluate_on_commit = js_template.Render( + 'console.time({{ label }});', label=INTERACTION_NAME) def RunPageInteractions(self, action_runner): action_runner.ExecuteJavaScript( @@ -48,8 +49,8 @@ """ ) action_runner.WaitForJavaScriptCondition('this.becameIdle === true') - # TODO(catapult:#3028): Fix interpolation of JavaScript values. - action_runner.ExecuteJavaScript('console.timeEnd("%s");' % INTERACTION_NAME) + action_runner.ExecuteJavaScript( + 'console.timeEnd({{ label }});', label=INTERACTION_NAME) class TodoMVCPageSet(story.StorySet):
diff --git a/tools/perf/page_sets/top_7_stress.py b/tools/perf/page_sets/top_7_stress.py index ee228d9..c46eb79 100644 --- a/tools/perf/page_sets/top_7_stress.py +++ b/tools/perf/page_sets/top_7_stress.py
@@ -11,9 +11,8 @@ def _WaitForLocationChange(action_runner, old_href): - # TODO(catapult:#3028): Fix interpolation of JavaScript values. action_runner.WaitForJavaScriptCondition( - 'document.location.href != "%s"' % old_href) + 'document.location.href != {{ old_href }}', old_href=old_href) class Top7StressPage(page_module.Page):