diff --git a/DEPS b/DEPS index 4ef66bc..72c8215d 100644 --- a/DEPS +++ b/DEPS
@@ -137,7 +137,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': 'fb86b888ef1c1265719208fd6c27a53ceb4920f7', + 'boringssl_revision': '13fd627449cefbae7576d4b145cb24fac303fc7d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -165,7 +165,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': '7453eba4feb2d90136a9415a6670ad41b866c93f', + 'catapult_revision': 'd525ef309fcaf7f1e5361c08592dbec3ae8ffa4c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -213,7 +213,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '6ff2f64702dcf298bcbbb33182ce82aa206e2b0a', + 'spv_tools_revision': '32381e30ef56f5a15207679a55c73a206483c1c4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -333,7 +333,7 @@ }, 'src/ios/third_party/material_sprited_animation_view_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-sprited-animation-view-ios.git' + '@' + 'c6e16d06bdafd95540c62b3402d9414692fbca81', + 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-sprited-animation-view-ios.git' + '@' + '8af9adaa182044cf2920dfb620b863669e1aeb7c', 'condition': 'checkout_ios', }, @@ -586,7 +586,7 @@ Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'), 'src/third_party/cct_dynamic_module/src': { - 'url': Var('chromium_git') + '/dynamicmodule' + '@' + 'dd6520c2ecc1b41c435a2ccf822b302489de0016', + 'url': Var('chromium_git') + '/dynamicmodule' + '@' + 'b89f5147c1fdf1d02850932ecd1ff16b8c0be545', 'condition': 'checkout_android', }, @@ -595,7 +595,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8241a7599974ed98de3e87c521b3a85047f614d3', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '82b404766db2865f290fb939577b2a0a931508eb', 'condition': 'checkout_linux', }, @@ -954,7 +954,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '40a2e1ea24495c6df976f194890e0843d52ada68', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '5cfa93810a407da48fe72b9e11df6e2bb7f17d9b', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1106,7 +1106,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6d2f3f4cb8bac1f7c4a945c73d07a33df74f22f9', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'cbcbc225687faf8226995c2823380adf06bd1afb', + Var('webrtc_git') + '/src.git' + '@' + '1ee9160a2e0bc6381caca2b8c42f7ce5507619bc', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1137,7 +1137,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@bea5a39cb8956b75ebf37087530c71e3e6fdd6e3', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@928526013073be9b73b8ca5140d37030a66bc0a2', 'condition': 'checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index b14dd954..8a85cbf 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -10,24 +10,24 @@ _EXCLUDED_PATHS = ( - r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py", - r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py", - r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk", - r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*", - r"^skia[\\\/].*", - r"^third_party[\\\/](WebKit|blink)[\\\/].*", - r"^third_party[\\\/]breakpad[\\\/].*", - r"^v8[\\\/].*", + r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_rules.py", + r"^native_client_sdk[\\/]src[\\/]build_tools[\\/]make_simple.py", + r"^native_client_sdk[\\/]src[\\/]tools[\\/].*.mk", + r"^net[\\/]tools[\\/]spdyshark[\\/].*", + r"^skia[\\/].*", + r"^third_party[\\/](WebKit|blink)[\\/].*", + r"^third_party[\\/]breakpad[\\/].*", + r"^v8[\\/].*", r".*MakeFile$", r".+_autogen\.h$", - r".+[\\\/]pnacl_shim\.c$", - r"^gpu[\\\/]config[\\\/].*_list_json\.cc$", - r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js", - r"tools[\\\/]md_browser[\\\/].*\.css$", + r".+[\\/]pnacl_shim\.c$", + r"^gpu[\\/]config[\\/].*_list_json\.cc$", + r"^chrome[\\/]browser[\\/]resources[\\/]pdf[\\/]index.js", + r"tools[\\/]md_browser[\\/].*\.css$", # Test pages for Maps telemetry tests. - r"tools[\\\/]perf[\\\/]page_sets[\\\/]maps_perf_test.*", + r"tools[\\/]perf[\\/]page_sets[\\/]maps_perf_test.*", # Test pages for WebRTC telemetry tests. - r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*", + r"tools[\\/]perf[\\/]page_sets[\\/]webrtc_cases.*", ) @@ -44,18 +44,18 @@ # Regular expression that matches code only used for test binaries # (best effort). _TEST_CODE_EXCLUDED_PATHS = ( - r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS, + r'.*[\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS, r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS, r'.+_(api|browser|eg|int|perf|pixel|unit|ui)?test(_[a-z]+)?%s' % _IMPLEMENTATION_EXTENSIONS, r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS, - r'.*[\\\/](test|tool(s)?)[\\\/].*', + r'.*[\\/](test|tool(s)?)[\\/].*', # content_shell is used for running layout tests. - r'content[\\\/]shell[\\\/].*', + r'content[\\/]shell[\\/].*', # Non-production example code. - r'mojo[\\\/]examples[\\\/].*', + r'mojo[\\/]examples[\\/].*', # Launcher for running iOS tests on the simulator. - r'testing[\\\/]iossim[\\\/]iossim\.mm$', + r'testing[\\/]iossim[\\/]iossim\.mm$', ) @@ -238,9 +238,9 @@ ), True, ( - r"^ui[\\\/]gl[\\\/].*\.cc$", - r"^media[\\\/]gpu[\\\/].*\.cc$", - r"^gpu[\\\/].*\.cc$", + r"^ui[\\/]gl[\\/].*\.cc$", + r"^media[\\/]gpu[\\/].*\.cc$", + r"^gpu[\\/].*\.cc$", ), ), ( @@ -250,9 +250,9 @@ ), True, ( - r"^gpu[\\\/]ipc[\\\/]service[\\\/]gpu_watchdog_thread\.cc$", - r"^remoting[\\\/]host[\\\/]linux[\\\/]x_server_clipboard\.cc$", - r"^ui[\\\/]gfx[\\\/]x[\\\/]x11_atom_cache\.cc$", + r"^gpu[\\/]ipc[\\/]service[\\/]gpu_watchdog_thread\.cc$", + r"^remoting[\\/]host[\\/]linux[\\/]x_server_clipboard\.cc$", + r"^ui[\\/]gfx[\\/]x[\\/]x11_atom_cache\.cc$", ), ), ( @@ -321,8 +321,8 @@ True, ( # Files that #define IGNORE_EINTR. - r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$', - r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$', + r'^base[\\/]posix[\\/]eintr_wrapper\.h$', + r'^ppapi[\\/]tests[\\/]test_broker\.cc$', ), ), ( @@ -333,7 +333,7 @@ ), True, ( - r'extensions[\\\/]renderer[\\\/]safe_builtins\.*', + r'extensions[\\/]renderer[\\/]safe_builtins\.*', ), ), ( @@ -343,7 +343,7 @@ ), True, ( - r'^third_party[\\\/]abseil-cpp[\\\/].*', + r'^third_party[\\/]abseil-cpp[\\/].*', ), ), ( @@ -386,9 +386,9 @@ ), False, ( - r'^content[\\\/]browser[\\\/]webui[\\\/]web_ui_impl\.(cc|h)$', - r'^content[\\\/]public[\\\/]browser[\\\/]web_ui\.h$', - r'^content[\\\/]public[\\\/]test[\\\/]test_web_ui\.(cc|h)$', + r'^content[\\/]browser[\\/]webui[\\/]web_ui_impl\.(cc|h)$', + r'^content[\\/]public[\\/]browser[\\/]web_ui\.h$', + r'^content[\\/]public[\\/]test[\\/]test_web_ui\.(cc|h)$', ), ), ( @@ -557,11 +557,11 @@ ), False, ( - r'^ios[\\\/].*\.(cc|h)$', - r'.*[\\\/]ios[\\\/].*\.(cc|h)$', + r'^ios[\\/].*\.(cc|h)$', + r'.*[\\/]ios[\\/].*\.(cc|h)$', r'.*_ios\.(cc|h)$', - r'^net[\\\/].*\.(cc|h)$', - r'.*[\\\/]tools[\\\/].*\.(cc|h)$', + r'^net[\\/].*\.(cc|h)$', + r'.*[\\/]tools[\\/].*\.(cc|h)$', ), ), ( @@ -597,18 +597,18 @@ ) _JAVA_MULTIPLE_DEFINITION_EXCLUDED_PATHS = [ - r".*[\\\/]BuildHooksAndroidImpl\.java", - r".*[\\\/]LicenseContentProvider\.java", - r".*[\\\/]PlatformServiceBridgeImpl.java", + r".*[\\/]BuildHooksAndroidImpl\.java", + r".*[\\/]LicenseContentProvider\.java", + r".*[\\/]PlatformServiceBridgeImpl.java", ] # These paths contain test data and other known invalid JSON files. _KNOWN_INVALID_JSON_FILE_PATTERNS = [ - r'test[\\\/]data[\\\/]', - r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$', - r'^third_party[\\\/]protobuf[\\\/]', - r'^third_party[\\\/]WebKit[\\\/]LayoutTests[\\\/]external[\\\/]wpt[\\\/]', - r'^third_party[\\\/]blink[\\\/]renderer[\\\/]devtools[\\\/]protocol\.json$', + r'test[\\/]data[\\/]', + r'^components[\\/]policy[\\/]resources[\\/]policy_templates\.json$', + r'^third_party[\\/]protobuf[\\/]', + r'^third_party[\\/]WebKit[\\/]LayoutTests[\\/]external[\\/]wpt[\\/]', + r'^third_party[\\/]blink[\\/]renderer[\\/]devtools[\\/]protocol\.json$', ] @@ -1412,7 +1412,7 @@ """ return input_api.FilterSourceFile( affected_file, - white_list=[r'^(android_webview|base|content|net)[\\\/].*'], + white_list=[r'^(android_webview|base|content|net)[\\/].*'], black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)) @@ -1445,7 +1445,7 @@ """ errors = [] white_list = [r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$'] - black_list = [r'^native_client_sdk[\\\/]'] + black_list = [r'^native_client_sdk[\\/]'] file_filter = lambda f: input_api.FilterSourceFile( f, white_list=white_list, black_list=black_list) for f in input_api.AffectedFiles(include_deletes=False, @@ -1540,7 +1540,7 @@ virtual_depended_on_files = set() file_filter = lambda f: not input_api.re.match( - r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath()) + r"^third_party[\\/](WebKit|blink)[\\/].*", f.LocalPath()) for f in input_api.AffectedFiles(include_deletes=False, file_filter=file_filter): filename = input_api.os_path.basename(f.LocalPath()) @@ -1615,44 +1615,44 @@ black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST + - (r"^base[\\\/]logging\.h$", - r"^base[\\\/]logging\.cc$", - r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$", - r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$", - r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]" + (r"^base[\\/]logging\.h$", + r"^base[\\/]logging\.cc$", + r"^chrome[\\/]app[\\/]chrome_main_delegate\.cc$", + r"^chrome[\\/]browser[\\/]chrome_browser_main\.cc$", + r"^chrome[\\/]browser[\\/]ui[\\/]startup[\\/]" r"startup_browser_creator\.cc$", - r"^chrome[\\\/]installer[\\\/]setup[\\\/].*", - r"^chrome[\\\/]chrome_cleaner[\\\/].*", - r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" + + r"^chrome[\\/]installer[\\/]setup[\\/].*", + r"^chrome[\\/]chrome_cleaner[\\/].*", + r"chrome[\\/]browser[\\/]diagnostics[\\/]" + r"diagnostics_writer\.cc$", - r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$", - r"^chromecast[\\\/]", - r"^cloud_print[\\\/]", - r"^components[\\\/]browser_watcher[\\\/]" + r"^chrome_elf[\\/]dll_hash[\\/]dll_hash_main\.cc$", + r"^chromecast[\\/]", + r"^cloud_print[\\/]", + r"^components[\\/]browser_watcher[\\/]" r"dump_stability_report_main_win.cc$", - r"^components[\\\/]html_viewer[\\\/]" + r"^components[\\/]html_viewer[\\/]" r"web_test_delegate_impl\.cc$", - r"^components[\\\/]zucchini[\\\/].*", + r"^components[\\/]zucchini[\\/].*", # TODO(peter): Remove this exception. https://crbug.com/534537 - r"^content[\\\/]browser[\\\/]notifications[\\\/]" + r"^content[\\/]browser[\\/]notifications[\\/]" r"notification_event_dispatcher_impl\.cc$", - r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]" + r"^content[\\/]common[\\/]gpu[\\/]client[\\/]" r"gl_helper_benchmark\.cc$", - r"^courgette[\\\/]courgette_minimal_tool\.cc$", - r"^courgette[\\\/]courgette_tool\.cc$", - r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$", - r"^ipc[\\\/]ipc_logging\.cc$", - r"^native_client_sdk[\\\/]", - r"^remoting[\\\/]base[\\\/]logging\.h$", - r"^remoting[\\\/]host[\\\/].*", - r"^sandbox[\\\/]linux[\\\/].*", - r"^tools[\\\/]", - r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$", - r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$", - r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]", - r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" + + r"^courgette[\\/]courgette_minimal_tool\.cc$", + r"^courgette[\\/]courgette_tool\.cc$", + r"^extensions[\\/]renderer[\\/]logging_native_handler\.cc$", + r"^ipc[\\/]ipc_logging\.cc$", + r"^native_client_sdk[\\/]", + r"^remoting[\\/]base[\\/]logging\.h$", + r"^remoting[\\/]host[\\/].*", + r"^sandbox[\\/]linux[\\/].*", + r"^tools[\\/]", + r"^ui[\\/]base[\\/]resource[\\/]data_pack.cc$", + r"^ui[\\/]aura[\\/]bench[\\/]bench_main\.cc$", + r"^ui[\\/]ozone[\\/]platform[\\/]cast[\\/]", + r"^storage[\\/]browser[\\/]fileapi[\\/]" + r"dump_file_system.cc$", - r"^headless[\\\/]app[\\\/]headless_shell\.cc$")) + r"^headless[\\/]app[\\/]headless_shell\.cc$")) source_file_filter = lambda x: input_api.FilterSourceFile( x, white_list=file_inclusion_pattern, black_list=black_list) @@ -1916,12 +1916,12 @@ } # Most JSON files are preprocessed and support comments, but these do not. json_no_comments_patterns = [ - r'^testing[\\\/]', + r'^testing[\\/]', ] # Only run IDL checker on files in these directories. idl_included_patterns = [ - r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]', - r'^extensions[\\\/]common[\\\/]api[\\\/]', + r'^chrome[\\/]common[\\/]extensions[\\/]api[\\/]', + r'^extensions[\\/]common[\\/]api[\\/]', ] def get_action(affected_file): @@ -2217,8 +2217,8 @@ black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST + - (r'^chromecast[\\\/].*', - r'^remoting[\\\/].*')), + (r'^chromecast[\\/].*', + r'^remoting[\\/].*')), white_list=[r'.*\.java$']) for f in input_api.AffectedSourceFiles(sources): @@ -2248,10 +2248,13 @@ # Do not check format of logs in the given files cr_log_check_excluded_paths = [ # //chrome/android/webapk cannot depend on //base - r"^chrome[\\\/]android[\\\/]webapk[\\\/].*", + r"^chrome[\\/]android[\\/]webapk[\\/].*", # WebView license viewer code cannot depend on //base; used in stub APK. - r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]" - r"webview[\\\/]chromium[\\\/]License.*", + r"^android_webview[\\/]glue[\\/]java[\\/]src[\\/]com[\\/]android[\\/]" + r"webview[\\/]chromium[\\/]License.*", + # The customtabs_benchmark is a small app that does not depend on Chromium + # java pieces. + r"tools[\\/]android[\\/]customtabs_benchmark[\\/].*", ] cr_log_import_pattern = input_api.re.compile( @@ -2456,7 +2459,7 @@ black_list=(_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST + - (r'^android_webview[\\\/]glue[\\\/].*',)), + (r'^android_webview[\\/]glue[\\/].*',)), white_list=[r'.*\.java$']) for f in input_api.AffectedSourceFiles(sources): @@ -2597,8 +2600,8 @@ # It's ok for base/memory/singleton.h to have |Singleton<|. black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST + - (r"^base[\\\/]memory[\\\/]singleton\.h$", - r"^net[\\\/]quic[\\\/]platform[\\\/]impl[\\\/]" + (r"^base[\\/]memory[\\/]singleton\.h$", + r"^net[\\/]quic[\\/]platform[\\/]impl[\\/]" r"quic_singleton_impl\.h$")) return input_api.FilterSourceFile(affected_file, black_list=black_list)
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 48b0bc0..03e6faea 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -9,6 +9,7 @@ import("//build/config/android/config.gni") import("//build/config/android/rules.gni") import("//build/config/locales.gni") +import("//chrome/android/trichrome.gni") import("//components/spellcheck/spellcheck_build_features.gni") import("//tools/grit/repack.gni") import("//tools/resources/generate_resource_whitelist.gni") @@ -109,6 +110,15 @@ variables = [ "manifest_package=$system_webview_package_name" ] } +jinja_template("trichrome_webview_manifest") { + input = "apk/java/AndroidManifest.xml" + output = trichrome_webview_android_manifest + variables = trichrome_jinja_variables + [ + "manifest_package=$system_webview_package_name", + "library=libmonochrome.so", + ] +} + webview_repack_locales("repack_locales") { input_locales = locales output_locales = locales @@ -1085,4 +1095,13 @@ deps = upstream_only_webview_deps apk_name = "SystemWebView" } + + system_webview_apk_tmpl("trichrome_webview_apk") { + version_name = chrome_version_name + android_manifest = trichrome_webview_android_manifest + android_manifest_dep = ":trichrome_webview_manifest" + deps = upstream_only_webview_deps + apk_name = "TrichromeWebView" + use_trichrome_library = true + } }
diff --git a/android_webview/apk/java/AndroidManifest.xml b/android_webview/apk/java/AndroidManifest.xml index ff64d48c..39f5d97 100644 --- a/android_webview/apk/java/AndroidManifest.xml +++ b/android_webview/apk/java/AndroidManifest.xml
@@ -80,5 +80,11 @@ {% endfor %} <meta-data android:name="org.chromium.content.browser.NUM_PRIVILEGED_SERVICES" android:value="0" /> + {% if trichrome_library is defined %} + <uses-static-library + android:name="{{ trichrome_library }}" + android:version="{{ trichrome_version }}" + android:certDigest="{{ trichrome_certdigest }}" /> + {% endif %} </application> </manifest>
diff --git a/android_webview/apk/java/proguard.flags b/android_webview/apk/java/proguard.flags index 40de75d..95fe04a 100644 --- a/android_webview/apk/java/proguard.flags +++ b/android_webview/apk/java/proguard.flags
@@ -71,3 +71,7 @@ # We strip some unused resources when preprocessing the GMS client libs. -dontwarn com.google.android.gms.R** + +# Trichrome builds don't include a native library list in the main APK; it's +# picked up from the library APK at runtime. +-dontwarn org.chromium.base.library_loader.NativeLibraries
diff --git a/android_webview/common/aw_hit_test_data.h b/android_webview/common/aw_hit_test_data.h index 8e5919b7..eefce49 100644 --- a/android_webview/common/aw_hit_test_data.h +++ b/android_webview/common/aw_hit_test_data.h
@@ -22,7 +22,7 @@ // except the special case described below. // For special case of invalid or javascript scheme url that would // otherwise be type an LINK type, |href| will contain the javascript - // string in the href attribute, and |anchor_text|i and |img_src| contain + // string in the href attribute, and |anchor_text| and |img_src| contain // their normal values for the respective type. UNKNOWN_TYPE = 0,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 4ed0eac..cfe0af2d 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -2244,7 +2244,6 @@ // In order to maintain compatibility with the old WebView's implementation, // the absolute (full) url is passed in the |url| field, not only the href attribute. - // Note: HitTestData could be cleaned up at this point. See http://crbug.com/290992. data.putString("url", mPossiblyStaleHitTestData.href); data.putString("title", mPossiblyStaleHitTestData.anchorText); data.putString("src", mPossiblyStaleHitTestData.imgSrc);
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index 759173f..819907a3a 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -25,14 +25,35 @@ } shared_resources = true - shared_libraries = [ "//android_webview:libwebviewchromium" ] - native_lib_version_rule = "//build/util:chrome_version_json" - _native_lib_file = - rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) - native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" - if (build_apk_secondary_abi && android_64bit_target_cpu) { - secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ] + + if (!defined(use_trichrome_library) || !use_trichrome_library) { + shared_libraries = [ "//android_webview:libwebviewchromium" ] + if (build_apk_secondary_abi && android_64bit_target_cpu) { + secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ] + } + } else { + # Include placeholder libraries to ensure we are treated as the desired + # architecture. + if (android_64bit_target_cpu) { + shared_libraries = [ "//android_webview:monochrome" ] + if (build_apk_secondary_abi) { + secondary_native_lib_placeholders = [ "libdummy.so" ] + } + } else { + native_lib_placeholders = [ "libdummy.so" ] + } } + + if (!defined(use_trichrome_library) || !use_trichrome_library || + android_64bit_target_cpu) { + # 32-bit TrichromeWebView doesn't have a native library, so only do this + # for other configs. + native_lib_version_rule = "//build/util:chrome_version_json" + _native_lib_file = + rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) + native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" + } + aapt_locale_whitelist = locales resource_blacklist_regex = "[/-]xxxhdpi[/-]"
diff --git a/android_webview/variables.gni b/android_webview/variables.gni index 94b8559..4e0b03b 100644 --- a/android_webview/variables.gni +++ b/android_webview/variables.gni
@@ -4,6 +4,8 @@ system_webview_android_manifest = "$root_gen_dir/android_webview/system_webview_apk/AndroidManifest.xml" +trichrome_webview_android_manifest = + "$root_gen_dir/android_webview/trichrome_webview_apk/AndroidManifest.xml" upstream_only_webview_deps = [ "//android_webview:platform_service_bridge_upstream_implementation_java",
diff --git a/ash/public/cpp/network_icon_image_source.cc b/ash/public/cpp/network_icon_image_source.cc index 5cfb152..b48b064 100644 --- a/ash/public/cpp/network_icon_image_source.cc +++ b/ash/public/cpp/network_icon_image_source.cc
@@ -5,6 +5,7 @@ #include "ash/public/cpp/network_icon_image_source.h" #include "ash/public/cpp/ash_constants.h" +#include "ash/public/cpp/ash_features.h" #include "third_party/skia/include/core/SkPath.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" @@ -75,7 +76,8 @@ // The other badges are flush against the edges of the canvas, except at the // top, where the badge is only 1dp higher than the base image. - const int top_badge_y = icon_y - 1; + const int top_badge_y = + features::IsSystemTrayUnifiedEnabled() ? icon_y : icon_y - 1; if (badges_.top_left.icon) paint_badge(badges_.top_left, 0, top_badge_y); if (badges_.bottom_left.icon) {
diff --git a/ash/resources/vector_icons/system_tray_managed.icon b/ash/resources/vector_icons/system_tray_managed.icon index 631374d3..848cfea 100644 --- a/ash/resources/vector_icons/system_tray_managed.icon +++ b/ash/resources/vector_icons/system_tray_managed.icon
@@ -3,57 +3,40 @@ // found in the LICENSE file. CANVAS_DIMENSIONS, 20, -MOVE_TO, 2, 3, -R_H_LINE_TO, 10, -R_V_LINE_TO, 4, -R_H_LINE_TO, 6, -R_V_LINE_TO, 10, -H_LINE_TO, 2, -V_LINE_TO, 3, +MOVE_TO, 9, 16, +LINE_TO, 9, 14, +LINE_TO, 7, 14, +LINE_TO, 7, 16, +LINE_TO, 4, 16, +LINE_TO, 4, 4, +LINE_TO, 12, 4, +LINE_TO, 12, 6, +LINE_TO, 16, 6, +LINE_TO, 16, 16, +LINE_TO, 11.83f, 16, +LINE_TO, 9, 16, CLOSE, -R_MOVE_TO, 10, 10, -R_V_LINE_TO, 2, -R_H_LINE_TO, 4, -V_LINE_TO, 9, -R_H_LINE_TO, -4, -R_V_LINE_TO, 2, -R_H_LINE_TO, 2, -R_V_LINE_TO, 2, -R_H_LINE_TO, -2, +MOVE_TO, 6, 10, +LINE_TO, 6, 12, +LINE_TO, 10, 12, +LINE_TO, 10, 10, +LINE_TO, 6, 10, CLOSE, -R_MOVE_TO, -4, 0, -R_V_LINE_TO, 2, -R_H_LINE_TO, 2, -R_V_LINE_TO, -2, -H_LINE_TO, 8, +MOVE_TO, 6, 6, +LINE_TO, 6, 8, +LINE_TO, 10, 8, +LINE_TO, 10, 6, +LINE_TO, 6, 6, CLOSE, -R_MOVE_TO, -4, 0, -R_V_LINE_TO, 2, -R_H_LINE_TO, 2, -R_V_LINE_TO, -2, -H_LINE_TO, 4, +MOVE_TO, 12, 8, +LINE_TO, 12, 10, +LINE_TO, 14, 10, +LINE_TO, 14, 8, +LINE_TO, 12, 8, CLOSE, -R_MOVE_TO, 4, -4, -R_V_LINE_TO, 2, -R_H_LINE_TO, 2, -V_LINE_TO, 9, -H_LINE_TO, 8, -CLOSE, -MOVE_TO, 4, 9, -R_V_LINE_TO, 2, -R_H_LINE_TO, 2, -V_LINE_TO, 9, -H_LINE_TO, 4, -CLOSE, -R_MOVE_TO, 4, -4, -R_V_LINE_TO, 2, -R_H_LINE_TO, 2, -V_LINE_TO, 5, -H_LINE_TO, 8, -CLOSE, -MOVE_TO, 4, 5, -R_V_LINE_TO, 2, -R_H_LINE_TO, 2, -V_LINE_TO, 5, -H_LINE_TO, 4, +MOVE_TO, 12, 12, +LINE_TO, 12, 14, +LINE_TO, 14, 14, +LINE_TO, 14, 12, +LINE_TO, 12, 12, CLOSE
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc index 7698b79..4b287b7e 100644 --- a/ash/system/network/network_icon.cc +++ b/ash/system/network/network_icon.cc
@@ -194,6 +194,8 @@ } gfx::Size GetSizeForBaseIconSize(const gfx::Size& base_icon_size) { + if (features::IsSystemTrayUnifiedEnabled()) + return base_icon_size; gfx::Size size = base_icon_size; const int badge_offset = base_icon_size.width() == kTrayIconSize ? kTrayIconBadgeOffset
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java index 5336906b..cb4589b 100644 --- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java +++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -21,6 +21,7 @@ import android.graphics.ColorFilter; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.VectorDrawable; import android.net.Uri; import android.os.Build; @@ -711,4 +712,52 @@ view.setAccessibilityTraversalBefore(viewFocusedAfter); } } + + /** + * Creates regular LayerDrawable on Android L+. On older versions creates a helper class that + * fixes issues around {@link LayerDrawable#mutate()}. See https://crbug.com/890317 for details. + * @param layers A list of drawables to use as layers in this new drawable. + */ + public static LayerDrawable createLayerDrawable(@NonNull Drawable[] layers) { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + return new LayerDrawableCompat(layers); + } + return new LayerDrawable(layers); + } + + private static class LayerDrawableCompat extends LayerDrawable { + private boolean mMutated; + + LayerDrawableCompat(@NonNull Drawable[] layers) { + super(layers); + } + + @Override + public Drawable mutate() { + // LayerDrawable in Android K loses bounds of layers, so this method works around that. + if (mMutated) { + // This object has already been mutated and shouldn't have any shared state. + return this; + } + + // Save bounds before mutation. + Rect[] oldBounds = new Rect[getNumberOfLayers()]; + for (int i = 0; i < getNumberOfLayers(); i++) { + oldBounds[i] = getDrawable(i).getBounds(); + } + + Drawable superResult = super.mutate(); + if (superResult != this) { + // Unexpected, LayerDrawable.mutate() always returns this. + return superResult; + } + + // Restore the saved bounds. + for (int i = 0; i < getNumberOfLayers(); i++) { + getDrawable(i).setBounds(oldBounds[i]); + } + mMutated = true; + return this; + } + } }
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc index 810200d..d1627e1a 100644 --- a/base/task/sequence_manager/sequence_manager_impl.cc +++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -115,7 +115,10 @@ graceful_shutdown_helper_->OnSequenceManagerDeleted(); main_thread_only().selector.SetTaskQueueSelectorObserver(nullptr); - controller_->RemoveNestingObserver(this); + + // In some tests a NestingObserver may not have been registered. + if (main_thread_only().nesting_observer_registered_) + controller_->RemoveNestingObserver(this); } SequenceManagerImpl::AnyThread::AnyThread() = default; @@ -150,7 +153,6 @@ void SequenceManagerImpl::BindToMessageLoop(MessageLoop* message_loop) { controller_->SetMessageLoop(message_loop); - BindToCurrentThread(); CompleteInitializationOnBoundThread(); } @@ -160,6 +162,7 @@ void SequenceManagerImpl::CompleteInitializationOnBoundThread() { controller_->AddNestingObserver(this); + main_thread_only().nesting_observer_registered_ = true; } void SequenceManagerImpl::RegisterTimeDomain(TimeDomain* time_domain) {
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h index 7b3a68f4..1572ac4 100644 --- a/base/task/sequence_manager/sequence_manager_impl.h +++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -90,7 +90,8 @@ // MessageLoop. The SequenceManager can be initialized on the current thread // and then needs to be bound and initialized on the target thread by calling // BindToCurrentThread() and CompleteInitializationOnBoundThread() during the - // thread's startup. + // thread's startup. If |message_loop| is null then BindToMessageLoop() must + // be called instead of CompleteInitializationOnBoundThread. // // This function should be called only once per MessageLoop. static std::unique_ptr<SequenceManagerImpl> CreateUnbound( @@ -251,6 +252,7 @@ std::vector<internal::TaskQueueImpl*> queues_to_reload; bool task_was_run_on_quiescence_monitored_queue = false; + bool nesting_observer_registered_ = false; // Due to nested runloops more than one task can be executing concurrently. std::list<ExecutingTask> task_execution_stack;
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc index 7b721d8..7a6bb5a7 100644 --- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc +++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -3381,6 +3381,7 @@ SequenceManagerCreatedBeforeMessageLoop) { std::unique_ptr<SequenceManager> manager = CreateUnboundSequenceManager(nullptr); + manager->BindToCurrentThread(); scoped_refptr<TaskQueue> default_task_queue = manager->CreateTaskQueue<TestTaskQueue>(TaskQueue::Spec("default")); EXPECT_THAT(default_task_queue.get(), testing::NotNull()); @@ -3405,6 +3406,12 @@ manager.reset(); } +TEST_P(SequenceManagerTestWithCustomInitialization, + CreateUnboundSequenceManagerWhichIsNeverBound) { + // This should not crash. + CreateUnboundSequenceManager(nullptr); +} + } // namespace sequence_manager_impl_unittest } // namespace internal } // namespace sequence_manager
diff --git a/build/chromeos/create_vm_test_script.py b/build/chromeos/create_vm_test_script.py index 80a7dbb4..5760cc7f 100755 --- a/build/chromeos/create_vm_test_script.py +++ b/build/chromeos/create_vm_test_script.py
@@ -51,6 +51,8 @@ parser.add_argument('--cros-cache') parser.add_argument('--board') parser.add_argument('--deploy-chrome', action='store_true') + parser.add_argument('--suite-name') + parser.add_argument('--tast-tests', action='append') args = parser.parse_args(args) def RelativizePathToScript(path): @@ -70,6 +72,14 @@ '--test-exe', args.test_exe, ]) + elif args.tast_tests: + vm_test_args.extend([ + 'tast', + '--suite-name', + args.suite_name, + ]) + for t in args.tast_tests: + vm_test_args.extend(['-t', t]) else: vm_test_args.append('host-cmd') if args.deploy_chrome:
diff --git a/build/chromeos/run_vm_test.py b/build/chromeos/run_vm_test.py index 964c0f3d..d40bb7c 100755 --- a/build/chromeos/run_vm_test.py +++ b/build/chromeos/run_vm_test.py
@@ -60,6 +60,8 @@ '--start', '--board', args.board, '--cache-dir', args.cros_cache, + # Don't persist any filesystem changes after the VM shutsdown. + '--copy-on-write', ] if args.vm_logs_dir: self._vm_test_cmd += [ @@ -80,6 +82,7 @@ self._test_env['USE'] = 'highdpi' self._test_env['PATH'] = ( self._test_env['PATH'] + ':' + os.path.join(CHROMITE_PATH, 'bin')) + @property def suite_name(self): raise NotImplementedError('Child classes need to define suite name.') @@ -407,6 +410,8 @@ '--start', '--board', args.board, '--cache-dir', args.cros_cache, + # Don't persist any filesystem changes after the VM shutsdown. + '--copy-on-write', ] if args.verbose: cros_run_vm_test_cmd.append('--debug')
diff --git a/build/config/chromeos/rules.gni b/build/config/chromeos/rules.gni index c87f0a8..047cab3 100644 --- a/build/config/chromeos/rules.gni +++ b/build/config/chromeos/rules.gni
@@ -19,6 +19,10 @@ # Args: # test_exe: Name of test binary located in the out dir. This will get copied # to the VM and executed there. +# tast_tests: List of Tast tests to run on the VM. Note that when this is +# specified, the target name used to invoke this template will be +# designated as the "name" of this test and will primarly used for test +# results tracking and displaying (eg: flakiness dashboard). # generated_script: Path to place the generated script. # deploy_chrome: If true, deploys a locally built chrome located in the root # build dir to the VM after launching it. @@ -35,6 +39,7 @@ "deploy_chrome", "generated_script", "runtime_deps_file", + "tast_tests", "testonly", "test_exe", ]) @@ -45,6 +50,9 @@ assert(defined(generated_script), "Must specify where to place generated test launcher script via " + "'generated_script'") + assert(!(defined(tast_tests) && defined(test_exe)), + "Tast tests are invoked from binaries shipped with the VM image. " + + "There should be no locally built binary needed.") action(target_name) { if (defined(runtime_deps_file)) { @@ -126,6 +134,36 @@ rebase_path(runtime_deps_file, root_build_dir), ] } + } else if (defined(tast_tests)) { + # When --tast-tests is specified, run_vm_test will call local_test_runner + # on the VM to run the set of tests. + args += [ + "--suite-name", + target_name, + ] + foreach(test, tast_tests) { + args += [ + "--tast-tests", + test, + ] + } } } } + +# TODO(crbug.com/876587): Support Tast conditionals as well. +template("tast_test") { + assert(defined(invoker.tast_tests), "A list of tast_tests must be specified.") + + generate_vm_runner_script(target_name) { + testonly = true + tast_tests = invoker.tast_tests + generated_script = "$root_build_dir/bin/run_${target_name}" + runtime_deps_file = "$root_out_dir/${target_name}/.runtime_deps" + deploy_chrome = true + data_deps = [ + "//:chromiumos_preflight", # Builds the browser. + "//chromeos:cros_chrome_deploy", # Adds additional browser run-time deps. + ] + } +}
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 88f7a115..1ddc90353 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1503,6 +1503,12 @@ "-Wno-ignored-pragma-optimize", ] } + if (llvm_force_head_revision) { + cflags += [ + # TODO(hans): https://crbug.com/890307 + "-Wno-defaulted-function-deleted", + ] + } } } }
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 38a1a97..3a41fb56 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -136,7 +136,7 @@ ldflags += [ "/TIMESTAMP:" + build_timestamp ] } - if (!is_debug && !is_component_build && !use_libfuzzer) { + if (!is_debug && !is_component_build) { # Enable standard linker optimizations like GC (/OPT:REF) and ICF in static # release builds. These are implied by /PROFILE below, but /PROFILE is # incompatible with /debug:fastlink and LLD ignores it as of this writing.
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 0a7ea94c..01c693ac 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -54,6 +54,7 @@ use_parent_backface_visibility(false), background_color(0), scrollable(false), + is_scrollbar(false), user_scrollable_horizontal(true), user_scrollable_vertical(true), main_thread_scrolling_reasons( @@ -909,6 +910,14 @@ SetNeedsCommit(); } +void Layer::SetIsScrollbar(bool is_scrollbar) { + if (inputs_.is_scrollbar == is_scrollbar) + return; + + inputs_.is_scrollbar = is_scrollbar; + SetNeedsCommit(); +} + void Layer::SetUserScrollable(bool horizontal, bool vertical) { DCHECK(IsPropertyChangeAllowed()); if (inputs_.user_scrollable_horizontal == horizontal && @@ -1284,6 +1293,8 @@ if (scrollable()) layer->SetScrollable(inputs_.scroll_container_bounds); + layer->set_is_scrollbar(inputs_.is_scrollbar); + // The property trees must be safe to access because they will be used below // to call |SetScrollOffsetClobberActiveValue|. DCHECK(layer->layer_tree_impl()->lifecycle().AllowsPropertyTreeAccess());
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index d525463..6522e552 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -395,6 +395,9 @@ return inputs_.scroll_container_bounds; } + void SetIsScrollbar(bool is_scrollbar); + bool is_scrollbar() const { return inputs_.is_scrollbar; } + // Set or get if this layer is able to be scrolled along each axis. These are // independant of the scrollable state, or size of the scrollable area // specified in SetScrollable(), as these may be enabled or disabled @@ -905,6 +908,9 @@ // |scroll_container_bounds|). bool scrollable : 1; + // Indicates that this layer is a scrollbar. + bool is_scrollbar : 1; + bool user_scrollable_horizontal : 1; bool user_scrollable_vertical : 1;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 4cd1b50..3a4bf453 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -78,6 +78,7 @@ debug_info_(nullptr), has_will_change_transform_hint_(false), needs_push_properties_(false), + is_scrollbar_(false), scrollbars_hidden_(false), needs_show_scrollbars_(false), raster_even_if_not_drawn_(false), @@ -347,6 +348,8 @@ if (scrollable_) layer->SetScrollable(scroll_container_bounds_); + layer->set_is_scrollbar(is_scrollbar_); + // If the main thread commits multiple times before the impl thread actually // draws, then damage tracking will become incorrect if we simply clobber the // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 1065f4e..bdfd63a 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -421,9 +421,9 @@ return contributes_to_drawn_render_surface_; } - bool IsDrawnScrollbar() { - return ToScrollbarLayer() && contributes_to_drawn_render_surface_; - } + bool is_scrollbar() const { return is_scrollbar_; } + + void set_is_scrollbar(bool is_scrollbar) { is_scrollbar_ = is_scrollbar; } void set_may_contain_video(bool yes) { may_contain_video_ = yes; } bool may_contain_video() const { return may_contain_video_; } @@ -597,6 +597,7 @@ bool has_will_change_transform_hint_ : 1; bool needs_push_properties_ : 1; + bool is_scrollbar_ : 1; bool scrollbars_hidden_ : 1; // The needs_show_scrollbars_ bit tracks a pending request from Blink to show
diff --git a/cc/layers/painted_overlay_scrollbar_layer.cc b/cc/layers/painted_overlay_scrollbar_layer.cc index 8bea0f87..ca94e661 100644 --- a/cc/layers/painted_overlay_scrollbar_layer.cc +++ b/cc/layers/painted_overlay_scrollbar_layer.cc
@@ -45,6 +45,7 @@ thumb_thickness_(scrollbar_->ThumbThickness()), thumb_length_(scrollbar_->ThumbLength()) { DCHECK(scrollbar_->UsesNinePatchThumbResource()); + SetIsScrollbar(true); } PaintedOverlayScrollbarLayer::~PaintedOverlayScrollbarLayer() = default;
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc index cf65df0..541c024e 100644 --- a/cc/layers/painted_scrollbar_layer.cc +++ b/cc/layers/painted_scrollbar_layer.cc
@@ -54,9 +54,11 @@ is_overlay_(scrollbar_->IsOverlay()), has_thumb_(scrollbar_->HasThumb()), thumb_opacity_(scrollbar_->ThumbOpacity()) { - if (!scrollbar_->IsOverlay()) + if (!scrollbar_->IsOverlay()) { AddMainThreadScrollingReasons( MainThreadScrollingReason::kScrollbarScrolling); + } + SetIsScrollbar(true); } PaintedScrollbarLayer::~PaintedScrollbarLayer() = default;
diff --git a/cc/layers/scrollbar_layer_impl_base.cc b/cc/layers/scrollbar_layer_impl_base.cc index 6a0f9eb6..24a855e2f 100644 --- a/cc/layers/scrollbar_layer_impl_base.cc +++ b/cc/layers/scrollbar_layer_impl_base.cc
@@ -26,7 +26,9 @@ scroll_layer_length_(0.f), orientation_(orientation), is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar), - vertical_adjust_(0.f) {} + vertical_adjust_(0.f) { + set_is_scrollbar(true); +} ScrollbarLayerImplBase::~ScrollbarLayerImplBase() { layer_tree_impl()->UnregisterScrollbar(this);
diff --git a/cc/layers/solid_color_scrollbar_layer.cc b/cc/layers/solid_color_scrollbar_layer.cc index f514b6d..c73f241a 100644 --- a/cc/layers/solid_color_scrollbar_layer.cc +++ b/cc/layers/solid_color_scrollbar_layer.cc
@@ -60,6 +60,7 @@ is_left_side_vertical_scrollbar, scroll_element_id) { Layer::SetOpacity(0.f); + SetIsScrollbar(true); } SolidColorScrollbarLayer::~SolidColorScrollbarLayer() = default;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index e53875b..285ed7b67 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -3638,6 +3638,24 @@ ClearCurrentlyScrollingNode(); + gfx::Point viewport_point(scroll_state->position_x(), + scroll_state->position_y()); + + gfx::PointF device_viewport_point = gfx::ScalePoint( + gfx::PointF(viewport_point), active_tree_->device_scale_factor()); + LayerImpl* first_scrolling_layer_or_scrollbar = + active_tree_->FindFirstScrollingLayerOrScrollbarThatIsHitByPoint( + device_viewport_point); + + if (IsTouchDraggingScrollbar(first_scrolling_layer_or_scrollbar, type)) { + TRACE_EVENT_INSTANT0("cc", "Scrollbar Scrolling", TRACE_EVENT_SCOPE_THREAD); + ScrollStatus scroll_status; + scroll_status.thread = SCROLL_ON_MAIN_THREAD; + scroll_status.main_thread_scrolling_reasons = + MainThreadScrollingReason::kScrollbarScrolling; + return scroll_status; + } + return ScrollBeginImpl(scroll_state, OuterViewportScrollNode(), type); } @@ -3667,7 +3685,21 @@ active_tree_->FindLayerThatIsHitByPoint(device_viewport_point); if (layer_impl) { - if (!IsInitialScrollHitTestReliable(layer_impl, device_viewport_point)) { + LayerImpl* first_scrolling_layer_or_scrollbar = + active_tree_->FindFirstScrollingLayerOrScrollbarThatIsHitByPoint( + device_viewport_point); + + // Touch dragging the scrollbar requires falling back to main-thread + // scrolling. + if (IsTouchDraggingScrollbar(first_scrolling_layer_or_scrollbar, type)) { + TRACE_EVENT_INSTANT0("cc", "Scrollbar Scrolling", + TRACE_EVENT_SCOPE_THREAD); + scroll_status.thread = SCROLL_ON_MAIN_THREAD; + scroll_status.main_thread_scrolling_reasons = + MainThreadScrollingReason::kScrollbarScrolling; + return scroll_status; + } else if (!IsInitialScrollHitTestReliable( + layer_impl, first_scrolling_layer_or_scrollbar)) { TRACE_EVENT_INSTANT0("cc", "Failed Hit Test", TRACE_EVENT_SCOPE_THREAD); scroll_status.thread = SCROLL_UNKNOWN; scroll_status.main_thread_scrolling_reasons = @@ -3693,17 +3725,23 @@ return ScrollBeginImpl(scroll_state, scrolling_node, type); } -// Some initial scroll tests are known to be unreliable and require falling -// back to main thread scrolling. +// Requires falling back to main thread scrolling when it hit tests in scrollbar +// from touch. +bool LayerTreeHostImpl::IsTouchDraggingScrollbar( + LayerImpl* first_scrolling_layer_or_scrollbar, + InputHandler::ScrollInputType type) { + return first_scrolling_layer_or_scrollbar && + first_scrolling_layer_or_scrollbar->is_scrollbar() && + type == InputHandler::TOUCHSCREEN; +} + +// Initial scroll hit testing can be unreliable in the presence of squashed +// layers. In this case, we fall back to main thread scrolling. bool LayerTreeHostImpl::IsInitialScrollHitTestReliable( LayerImpl* layer_impl, - const gfx::PointF& device_viewport_point) { - LayerImpl* first_scrolling_layer_or_drawn_scrollbar = - active_tree_->FindFirstScrollingLayerOrDrawnScrollbarThatIsHitByPoint( - device_viewport_point); - if (!first_scrolling_layer_or_drawn_scrollbar) + LayerImpl* first_scrolling_layer_or_scrollbar) { + if (!first_scrolling_layer_or_scrollbar) return true; - ScrollNode* closest_scroll_node = nullptr; auto& scroll_tree = active_tree_->property_trees()->scroll_tree; ScrollNode* scroll_node = scroll_tree.Node(layer_impl->scroll_tree_index()); @@ -3717,19 +3755,19 @@ if (!closest_scroll_node) return false; - // If |first_scrolling_layer_or_drawn_scrollbar| is scrollable, it will + // If |first_scrolling_layer_or_scrollbar| is scrollable, it will // create a scroll node. If this scroll node corresponds to first scrollable // ancestor along the scroll tree for |layer_impl|, the hit test has not // escaped to other areas of the scroll tree and is reliable. - if (first_scrolling_layer_or_drawn_scrollbar->scrollable()) { + if (first_scrolling_layer_or_scrollbar->scrollable()) { return closest_scroll_node->id == - first_scrolling_layer_or_drawn_scrollbar->scroll_tree_index(); + first_scrolling_layer_or_scrollbar->scroll_tree_index(); } - // If |first_scrolling_layer_or_drawn_scrollbar| is not scrollable, it must - // be a drawn scrollbar. These hit tests require falling back to main-thread - // scrolling. - DCHECK(first_scrolling_layer_or_drawn_scrollbar->IsDrawnScrollbar()); + // If |first_scrolling_layer_or_scrollbar| is not scrollable, it must + // be a drawn scrollbar. It may hit the squashing layer at the same time. + // These hit tests require falling back to main-thread scrolling. + DCHECK(first_scrolling_layer_or_scrollbar->is_scrollbar()); return false; }
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 34f94397..b9d0f9b 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -784,7 +784,12 @@ ScrollState* scroll_state, ScrollNode* scrolling_node, InputHandler::ScrollInputType type); - bool IsInitialScrollHitTestReliable(LayerImpl* layer, const gfx::PointF&); + bool IsTouchDraggingScrollbar( + LayerImpl* first_scrolling_layer_or_drawn_scrollbar, + InputHandler::ScrollInputType type); + bool IsInitialScrollHitTestReliable( + LayerImpl* layer, + LayerImpl* first_scrolling_layer_or_drawn_scrollbar); void DistributeScrollDelta(ScrollState* scroll_state); bool AnimatePageScale(base::TimeTicks monotonic_time);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 2955a50..f22b1f7 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -3954,9 +3954,10 @@ EXPECT_EQ(scrollbar_2_->Opacity(), 0.f); // Scroll on root should flash all scrollbars. - host_impl_->RootScrollBegin(BeginState(gfx::Point(10, 10)).get(), + host_impl_->RootScrollBegin(BeginState(gfx::Point(20, 20)).get(), InputHandler::WHEEL); - host_impl_->ScrollBy(UpdateState(gfx::Point(), gfx::Vector2d(0, 10)).get()); + host_impl_->ScrollBy( + UpdateState(gfx::Point(20, 20), gfx::Vector2d(0, 10)).get()); host_impl_->ScrollEnd(EndState().get()); EXPECT_TRUE(scrollbar_1_->Opacity()); @@ -3966,8 +3967,8 @@ ResetScrollbars(); // Scroll on child should flash all scrollbars. - host_impl_->ScrollAnimatedBegin(BeginState(gfx::Point(51, 51)).get()); - host_impl_->ScrollAnimated(gfx::Point(51, 51), gfx::Vector2d(0, 100)); + host_impl_->ScrollAnimatedBegin(BeginState(gfx::Point(70, 70)).get()); + host_impl_->ScrollAnimated(gfx::Point(70, 70), gfx::Vector2d(0, 100)); host_impl_->ScrollEnd(EndState().get()); EXPECT_TRUE(scrollbar_1_->Opacity()); @@ -4002,6 +4003,49 @@ EXPECT_FALSE(animation_task_.Equals(base::Closure())); } +TEST_F(LayerTreeHostImplTestMultiScrollable, ScrollHitTestOnScrollbar) { + LayerTreeSettings settings = DefaultSettings(); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(500); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); + settings.scrollbar_animator = LayerTreeSettings::NO_ANIMATOR; + + SetUpLayers(settings); + + // Wheel scroll on root scrollbar should process on impl thread. + { + InputHandler::ScrollStatus status = host_impl_->RootScrollBegin( + BeginState(gfx::Point(1, 1)).get(), InputHandler::WHEEL); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + } + + // Touch scroll on root scrollbar should process on main thread. + { + InputHandler::ScrollStatus status = host_impl_->RootScrollBegin( + BeginState(gfx::Point(1, 1)).get(), InputHandler::TOUCHSCREEN); + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling, + status.main_thread_scrolling_reasons); + } + + // Wheel scroll on scrollbar should fallback to main thread. + { + InputHandler::ScrollStatus status = host_impl_->ScrollBegin( + BeginState(gfx::Point(51, 51)).get(), InputHandler::WHEEL); + EXPECT_EQ(InputHandler::SCROLL_UNKNOWN, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kFailedHitTest, + status.main_thread_scrolling_reasons); + } + + // Touch scroll on scrollbar should process on main thread. + { + InputHandler::ScrollStatus status = host_impl_->RootScrollBegin( + BeginState(gfx::Point(51, 51)).get(), InputHandler::TOUCHSCREEN); + EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling, + status.main_thread_scrolling_reasons); + } +} + TEST_F(LayerTreeHostImplTest, ScrollbarVisibilityChangeCausesRedrawAndCommit) { LayerTreeSettings settings = DefaultSettings(); settings.scrollbar_animator = LayerTreeSettings::AURA_OVERLAY;
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 4bd0719..018455c 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -2109,19 +2109,18 @@ } } -struct FindScrollingLayerOrDrawnScrollbarFunctor { +struct FindScrollingLayerOrScrollbarFunctor { bool operator()(LayerImpl* layer) const { - return layer->scrollable() || layer->IsDrawnScrollbar(); + return layer->scrollable() || layer->is_scrollbar(); } }; -LayerImpl* -LayerTreeImpl::FindFirstScrollingLayerOrDrawnScrollbarThatIsHitByPoint( +LayerImpl* LayerTreeImpl::FindFirstScrollingLayerOrScrollbarThatIsHitByPoint( const gfx::PointF& screen_space_point) { FindClosestMatchingLayerState state; LayerImpl* root_layer = layer_list_.empty() ? nullptr : layer_list_[0]; FindClosestMatchingLayer(screen_space_point, root_layer, - FindScrollingLayerOrDrawnScrollbarFunctor(), &state); + FindScrollingLayerOrScrollbarFunctor(), &state); return state.closest_match; }
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 299c9a832..f5dd26f 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -502,7 +502,7 @@ void UnregisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer); ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const; - LayerImpl* FindFirstScrollingLayerOrDrawnScrollbarThatIsHitByPoint( + LayerImpl* FindFirstScrollingLayerOrScrollbarThatIsHitByPoint( const gfx::PointF& screen_space_point); LayerImpl* FindLayerThatIsHitByPoint(const gfx::PointF& screen_space_point);
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index e4aa553..cc5f72b 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -22,6 +22,8 @@ import("channel.gni") import("java_sources.gni") import("static_initializers.gni") +import("trichrome.gni") + if (modularize_ar) { import("//chrome/android/modules/ar/ar_module_tmpl.gni") } @@ -41,6 +43,10 @@ "$target_gen_dir/chrome_sync_shell_apk/AndroidManifest.xml" monochrome_public_android_manifest = "$target_gen_dir/monochrome_public_apk/AndroidManifest.xml" +trichrome_library_android_manifest = + "$target_gen_dir/trichrome_library_apk/AndroidManifest.xml" +trichrome_chrome_android_manifest = + "$target_gen_dir/trichrome_chrome_apk/AndroidManifest.xml" chrome_sync_shell_jinja_variables = default_chrome_public_jinja_variables + @@ -89,6 +95,20 @@ [ "target_sdk_version=$android_sdk_version" ] } +jinja_template("trichrome_library_android_manifest") { + input = "java/AndroidManifest_trichrome_library.xml" + output = trichrome_library_android_manifest + variables = trichrome_jinja_variables + + [ "manifest_package=$trichrome_library_package" ] +} + +jinja_template("trichrome_chrome_android_manifest") { + input = "java/AndroidManifest_trichrome_chrome.xml" + includes = [ "java/AndroidManifest.xml" ] + output = trichrome_chrome_android_manifest + variables = chrome_public_jinja_variables + trichrome_jinja_variables +} + jinja_template("chrome_sync_shell_android_manifest") { input = "java/AndroidManifest.xml" output = chrome_sync_shell_android_manifest @@ -1441,15 +1461,20 @@ monochrome_public_common_apk_or_module_tmpl(target_name) { forward_variables_from(invoker, [ + "android_manifest", + "android_manifest_dep", "apk_name", "is_base_module", "module_name", "proguard_jar_path", "target_type", + "use_trichrome_library", ]) - android_manifest = monochrome_public_android_manifest - android_manifest_dep = ":monochrome_public_android_manifest" + if (!defined(android_manifest) && !defined(android_manifest_dep)) { + android_manifest = monochrome_public_android_manifest + android_manifest_dep = ":monochrome_public_android_manifest" + } if (public_android_sdk) { # Resource whitelist used when generating R.java files and causes @@ -1465,8 +1490,10 @@ "//chrome/android:chrome_java", ] - add_unwind_tables_in_apk = _add_unwind_tables_in_chrome_public_apk - if (_add_unwind_tables_in_chrome_public_apk && can_unwind_with_cfi_table) { + add_unwind_tables_in_apk = + _add_unwind_tables_in_chrome_public_apk && + (!defined(use_trichrome_library) || !use_trichrome_library) + if (add_unwind_tables_in_apk && can_unwind_with_cfi_table) { shared_library_for_unwind_asset = "monochrome" } @@ -1486,6 +1513,52 @@ is_base_module = true } +android_apk("trichrome_library_apk") { + apk_name = "TrichromeLibrary" + android_manifest = trichrome_library_android_manifest + android_manifest_dep = ":trichrome_library_android_manifest" + + # TODO(torne): this contains the list of locales amongst other things. + # Skip building it because the version in the library won't be used anyway; + # the one in the main APK will take precedence. + generate_buildconfig_java = false + + # TODO(torne): since there's no real java code in the library right now, + # leave out the build hooks and let them get compiled into each APK. Later + # this should probably be in the library. + no_build_hooks = true + + alternative_android_sdk_dep = webview_framework_dep + app_as_shared_lib = true + use_chromium_linker = false + uncompress_shared_libraries = true + + _native_lib_file = + rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) + native_lib_version_arg = "@FileArg($_native_lib_file:full-quoted)" + native_lib_version_rule = "//build/util:chrome_version_json" + + if (android_64bit_target_cpu) { + # Include a 64-bit placeholder library to ensure that the library is treated + # as multiarch and gets its Java code precompiled for both architectures. + native_lib_placeholders = [ "libdummy.so" ] + if (build_apk_secondary_abi) { + # Include the actual 32-bit libmonochrome library. + secondary_abi_shared_libraries = [ ":monochrome_secondary_abi_lib" ] + } + } else { + shared_libraries = [ ":monochrome" ] + } +} + +monochrome_public_apk_or_module_tmpl("trichrome_chrome_apk") { + apk_name = "TrichromeChrome" + target_type = "android_apk" + android_manifest = trichrome_chrome_android_manifest + android_manifest_dep = ":trichrome_chrome_android_manifest" + use_trichrome_library = true +} + chrome_public_common_apk_or_module_tmpl("chrome_sync_shell_apk") { testonly = true target_type = "android_apk"
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index a95fdead..883b7ab 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -195,16 +195,28 @@ _enable_multidex = is_java_debug || multidex_in_release } chrome_public_common_apk_or_module_tmpl(target_name) { - # Always build 64-bit //android_webview:monochrome because Chrome runs - # in 32-bit mode. - if (android_64bit_target_cpu) { - shared_libraries = [ "//android_webview:monochrome" ] + if (!defined(invoker.use_trichrome_library) || + !invoker.use_trichrome_library) { + # Always build 64-bit //android_webview:monochrome because Chrome runs + # in 32-bit mode. + if (android_64bit_target_cpu) { + shared_libraries = [ "//android_webview:monochrome" ] + } else { + shared_libraries = [ "//chrome/android:monochrome" ] + } + if (android_64bit_target_cpu && build_apk_secondary_abi) { + secondary_abi_shared_libraries = + [ "//chrome/android:monochrome_secondary_abi_lib" ] + } } else { - shared_libraries = [ "//chrome/android:monochrome" ] - } - if (android_64bit_target_cpu && build_apk_secondary_abi) { - secondary_abi_shared_libraries = - [ "//chrome/android:monochrome_secondary_abi_lib" ] + # Include a 32-bit placeholder library to ensure that Chrome runs in + # 32-bit mode. + if (android_64bit_target_cpu) { + # We don't want to be 64-bit, only include a placeholder for secondary. + secondary_native_lib_placeholders = [ "libdummy.so" ] + } else { + native_lib_placeholders = [ "libdummy.so" ] + } } alternative_android_sdk_dep = webview_framework_dep
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedBasicLogging.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedBasicLogging.java index d1f8d84..c0f4410 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedBasicLogging.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedBasicLogging.java
@@ -11,7 +11,15 @@ * Implementation of {@link BasicLoggingApi} that log actions performed on the Feed. */ public class FeedBasicLogging implements BasicLoggingApi { - // TODO(gangwu): implement BasicLoggingApi functionality. + private FeedLoggingBridge mFeedLoggingBridge; + + /** + * Creates a {@link FeedBasicLogging} for accessing native logging logic. + */ + public FeedBasicLogging() { + mFeedLoggingBridge = new FeedLoggingBridge(); + } + @Override public void onContentViewed(ContentLoggingData data) {} @Override @@ -26,8 +34,12 @@ public void onMoreButtonViewed(int position) {} @Override public void onMoreButtonClicked(int position) {} + @Override - public void onOpenedWithContent(int timeToPopulateMs, int contentCount) {} + public void onOpenedWithContent(int timeToPopulateMs, int contentCount) { + mFeedLoggingBridge.onOpenedWithContent(contentCount); + } + @Override public void onOpenedWithNoImmediateContent() {} @Override
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java index 2a18f7b0..a53336d 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java
@@ -45,11 +45,6 @@ @VisibleForTesting public FeedContentBridge() {} - /** - * Initializes the native side of this bridge. - */ - public void init() {} - /** Cleans up native half of this bridge. */ public void destroy() { assert mNativeFeedContentBridge != 0;
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java new file mode 100644 index 0000000..fcf034a6 --- /dev/null +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
@@ -0,0 +1,39 @@ +// Copyright 2018 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. + +package org.chromium.chrome.browser.feed; + +import org.chromium.base.annotations.JNINamespace; + +/** + * Provides access to native implementation of feed logging. + */ +@JNINamespace("feed") +public class FeedLoggingBridge { + private long mNativeFeedLoggingBridge; + + /** + * Creates a {@link FeedLoggingBridge} for accessing native feed logging + * implementation for the current user, and initial native side bridge. + */ + public FeedLoggingBridge() { + mNativeFeedLoggingBridge = nativeInit(); + } + + /** Cleans up native half of this bridge. */ + public void destroy() { + assert mNativeFeedLoggingBridge != 0; + nativeDestroy(mNativeFeedLoggingBridge); + mNativeFeedLoggingBridge = 0; + } + + public void onOpenedWithContent(int contentCount) { + assert mNativeFeedLoggingBridge != 0; + nativeOnOpenedWithContent(mNativeFeedLoggingBridge, contentCount); + } + + private native long nativeInit(); + private native void nativeDestroy(long nativeFeedLoggingBridge); + private native void nativeOnOpenedWithContent(long nativeFeedLoggingBridge, int contentCount); +}
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni index 40d9865..2b4debf 100644 --- a/chrome/android/feed/feed_java_sources.gni +++ b/chrome/android/feed/feed_java_sources.gni
@@ -17,6 +17,7 @@ "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalBridge.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalStorage.java", + "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPageMediator.java",
diff --git a/chrome/android/java/AndroidManifest_trichrome_chrome.xml b/chrome/android/java/AndroidManifest_trichrome_chrome.xml new file mode 100644 index 0000000..5118d38 --- /dev/null +++ b/chrome/android/java/AndroidManifest_trichrome_chrome.xml
@@ -0,0 +1,27 @@ +{% extends "chrome/android/java/AndroidManifest.xml" %} + +## Copyright 2018 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. + +## Note: This is a jinja2 template, processed at build time into the final manifest. + +## TODO(torne): we need a Trichrome application subclass to use the library preloader +##{% block application_name %}org.chromium.chrome.browser.MonochromeApplication{% endblock %} + +{% block extra_application_attributes %} +{{ super() }} +android:extractNativeLibs="false" +{% endblock %} + +{% block extra_keyset_definitions %} + <!-- No keyset definitions should exist for any trichrome apks --> +{% endblock %} + +{% block extra_application_definitions %} +{{ super() }} +<uses-static-library + android:name="{{ trichrome_library }}" + android:version="{{ trichrome_version }}" + android:certDigest="{{ trichrome_certdigest }}" /> +{% endblock %}
diff --git a/chrome/android/java/AndroidManifest_trichrome_library.xml b/chrome/android/java/AndroidManifest_trichrome_library.xml new file mode 100644 index 0000000..7c01616 --- /dev/null +++ b/chrome/android/java/AndroidManifest_trichrome_library.xml
@@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 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. --> + +<!-- +Note: This is a jinja2 template, processed at build time into the final manifest. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="{{ manifest_package }}" + tools:ignore="MissingVersion"> + + <uses-sdk android:minSdkVersion="{{min_sdk_version}}" android:targetSdkVersion="{{target_sdk_version}}" /> + <uses-feature android:glEsVersion="0x00020000" /> + <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> + + <!-- TODO(torne): we should specify an icon, roundIcon, and label from resources. --> + <application + android:label="Trichrome Library" + android:multiArch="true" + android:extractNativeLibs="false"> + + <static-library android:name="{{ trichrome_library }}" android:version="{{ trichrome_version }}" /> + </application> +</manifest>
diff --git a/chrome/android/java/proguard.flags b/chrome/android/java/proguard.flags index 9e169d00..e673817 100644 --- a/chrome/android/java/proguard.flags +++ b/chrome/android/java/proguard.flags
@@ -26,3 +26,7 @@ -keepclassmembers class android.support.design.internal.BottomNavigationMenuView { boolean mShiftingMode; } + +# Trichrome builds don't include a native library list in the main APK; it's +# picked up from the library APK at runtime. +-dontwarn org.chromium.base.library_loader.NativeLibraries
diff --git a/chrome/android/java/res/layout/custom_tabs_control_container.xml b/chrome/android/java/res/layout/custom_tabs_control_container.xml index 05a03b2..cc22798c 100644 --- a/chrome/android/java/res/layout/custom_tabs_control_container.xml +++ b/chrome/android/java/res/layout/custom_tabs_control_container.xml
@@ -42,5 +42,12 @@ android:layout_marginEnd="@dimen/find_in_page_popup_margin_end" android:layout_gravity="end|top" android:layout="@layout/find_toolbar" /> + <ViewStub + android:id="@+id/topbar_stub" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="start|top" + android:inflatedId="@+id/topbar" + android:layout="@layout/custom_tabs_topbar" /> </view> </org.chromium.chrome.browser.toolbar.ToolbarControlContainer>
diff --git a/chrome/android/java/res/layout/custom_tabs_topbar.xml b/chrome/android/java/res/layout/custom_tabs_topbar.xml new file mode 100644 index 0000000..371209e --- /dev/null +++ b/chrome/android/java/res/layout/custom_tabs_topbar.xml
@@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2018 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. --> + +<org.chromium.ui.widget.OptimizedFrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + />
diff --git a/chrome/android/java/res/layout/update_menu_item.xml b/chrome/android/java/res/layout/update_menu_item.xml index 7f9e9bf8..f2f8a1b 100644 --- a/chrome/android/java/res/layout/update_menu_item.xml +++ b/chrome/android/java/res/layout/update_menu_item.xml
@@ -24,15 +24,13 @@ android:id="@+id/menu_item_text" android:layout_width="wrap_content" android:layout_height="match_parent" - android:textAppearance="?android:attr/textAppearanceLargePopupMenu" - android:textColor="#dc5554" /> + android:textAppearance="@style/TextAppearance.UpdateMenuItem" /> <TextView android:id="@+id/menu_item_summary" android:layout_width="wrap_content" android:layout_height="match_parent" - android:textSize="12sp" - android:textColor="#646464" /> + android:textAppearance="@style/BlackCaption" /> </LinearLayout>
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index 5e651cd..3d946cde 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -587,6 +587,10 @@ <item name="android:paddingEnd">16dp</item> <item name="android:background">?attr/listChoiceBackgroundIndicator</item> </style> + <style name="TextAppearance.UpdateMenuItem"> + <item name="android:textColor">@color/update_menu_item_text_color</item> + <item name="android:textSize">@dimen/text_size_large</item> + </style> <style name="SadTabBodyText"> <item name="android:textAppearance">@style/BlackBody</item> <item name="android:layout_gravity">start</item>
diff --git a/chrome/android/java/res/values-v23/styles.xml b/chrome/android/java/res/values-v26/styles.xml similarity index 100% rename from chrome/android/java/res/values-v23/styles.xml rename to chrome/android/java/res/values-v26/styles.xml
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index 131293c..bd9fe551 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -61,6 +61,9 @@ <!-- App banner colors --> <color name="app_banner_install_button_bg">#0F9D58</color> + <!-- App menu colors --> + <color name="update_menu_item_text_color">#DC5554</color> + <!-- Connection Info Popup colors --> <color name="connection_info_popup_reset_cert_decisions_button">#000000</color> <color name="connection_info_popup_text">@color/modern_grey_900</color>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index 10f8228..7a21711c 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -267,6 +267,7 @@ <dimen name="tablet_toolbar_start_padding">4dp</dimen> <dimen name="tablet_toolbar_end_padding">6dp</dimen> <dimen name="location_bar_status_separator_width">1dp</dimen> + <dimen name="toolbar_optional_button_animation_translation">10dp</dimen> <!-- Modern toolbar dimensions --> <dimen name="modern_toolbar_background_size">40dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java index 2e032204..d6c633f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java
@@ -13,6 +13,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.layouts.content.TitleBitmapFactory; import org.chromium.chrome.browser.favicon.FaviconHelper; import org.chromium.chrome.browser.favicon.FaviconHelper.DefaultFaviconHelper; @@ -120,7 +121,8 @@ private String getUpdatedTitleInternal(Tab tab, String titleString, boolean fetchFaviconFromHistory) { final int tabId = tab.getId(); - boolean isDarkTheme = tab.isIncognito(); + boolean isDarkTheme = tab.isIncognito() + && !ChromeFeatureList.isEnabled(ChromeFeatureList.HORIZONTAL_TAB_SWITCHER_ANDROID); Bitmap originalFavicon = tab.getFavicon(); if (originalFavicon == null) { originalFavicon = mDefaultFaviconHelper.getDefaultFaviconBitmap(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java index 4dabb1e..13b8a399 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
@@ -65,6 +65,9 @@ viewport.top, viewport.width(), viewport.height(), layerTitleCache, tabContentManager, resourceManager); + boolean isHTSEnabled = + ChromeFeatureList.isEnabled(ChromeFeatureList.HORIZONTAL_TAB_SWITCHER_ANDROID); + for (int i = 0; i < tabsCount; i++) { LayoutTab t = tabs[i]; assert t.isVisible() : "LayoutTab in that list should be visible"; @@ -72,14 +75,14 @@ float shadowAlpha = decoration / 2; int urlBarBackgroundId = R.drawable.modern_location_bar; + boolean useLightIcon = t.isIncognito() && !isHTSEnabled; - int defaultThemeColor = ColorUtils.getDefaultThemeColor(res, t.isIncognito()); + int defaultThemeColor = ColorUtils.getDefaultThemeColor(res, useLightIcon); // In the modern design, the text box is always drawn opaque in the compositor. float textBoxAlpha = 1.f; - int closeButtonColor = - ColorUtils.getThemedAssetColor(defaultThemeColor, t.isIncognito()); + int closeButtonColor = ColorUtils.getThemedAssetColor(defaultThemeColor, useLightIcon); int borderColorResource = t.isIncognito() ? R.color.tab_back_incognito : R.color.tab_back;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java index d64570a..84d7b75 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
@@ -25,6 +25,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.toolbar.ToolbarManager; +import org.chromium.chrome.browser.toolbar.ToolbarPhone; import org.chromium.chrome.browser.util.AccessibilityUtil; import org.chromium.chrome.browser.util.MathUtils; import org.chromium.chrome.browser.widget.ListMenuButton; @@ -289,7 +290,8 @@ reportEvent(ContextualSuggestionsEvent.UI_BUTTON_SHOWN); TrackerFactory.getTrackerForProfile(mProfile).notifyEvent( EventConstants.CONTEXTUAL_SUGGESTIONS_BUTTON_SHOWN); - maybeShowHelpBubble(); + mHandler.postDelayed(() -> maybeShowHelpBubble(), + ToolbarPhone.LOC_BAR_WIDTH_CHANGE_ANIMATION_DURATION_MS); } @Override @@ -433,13 +435,19 @@ } private void maybeShowHelpBubble() { + View anchorView = + mIphParentView.getRootView().findViewById(R.id.experimental_toolbar_button); + if (mToolbarManager.isUrlBarFocused() || anchorView == null + || anchorView.getVisibility() != View.VISIBLE) { + return; + } + Tracker tracker = TrackerFactory.getTrackerForProfile(mProfile); if (!tracker.shouldTriggerHelpUI(FeatureConstants.CONTEXTUAL_SUGGESTIONS_FEATURE)) { return; } - ViewRectProvider rectProvider = new ViewRectProvider( - mIphParentView.getRootView().findViewById(R.id.experimental_toolbar_button)); + ViewRectProvider rectProvider = new ViewRectProvider(anchorView); rectProvider.setInsetPx(0, 0, 0, mIphParentView.getResources().getDimensionPixelOffset( R.dimen.text_bubble_menu_anchor_y_inset));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index dd66286..f3bee68 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -155,6 +155,7 @@ private BrowserSessionContentHandler mBrowserSessionContentHandler; private Tab mMainTab; private CustomTabBottomBarDelegate mBottomBarDelegate; + private CustomTabTopBarDelegate mTopBarDelegate; private CustomTabTabPersistencePolicy mTabPersistencePolicy; // This is to give the right package name while using the client's resources during an @@ -437,6 +438,11 @@ loadUrlInTab(mMainTab, new LoadUrlParams(uri.toString()), SystemClock.elapsedRealtime()); } + public void setTopBarContentView(View view) { + mTopBarDelegate.setTopBarContentView(view); + mTopBarDelegate.showTopBarIfNecessary(); + } + @Override public boolean shouldAllocateChildConnection() { return !mHasCreatedTabEarly && !mHasSpeculated @@ -475,6 +481,7 @@ mBottomBarDelegate = new CustomTabBottomBarDelegate(this, mIntentDataProvider, getFullscreenManager()); mBottomBarDelegate.showBottomBarIfNecessary(); + mTopBarDelegate = new CustomTabTopBarDelegate(this); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java new file mode 100644 index 0000000..2802de7 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java
@@ -0,0 +1,54 @@ +// Copyright 2018 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. + +package org.chromium.chrome.browser.customtabs; + +import android.support.annotation.Nullable; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewStub; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeActivity; + +/** + * Delegate that manages top bar area inside of {@link CustomTabActivity}. + */ +class CustomTabTopBarDelegate { + private ChromeActivity mActivity; + private ViewGroup mTopBarView; + @Nullable + private View mTopBarContentView; + + public CustomTabTopBarDelegate(ChromeActivity activity) { + mActivity = activity; + } + + /** + * Makes the top bar area to show, if any. + */ + public void showTopBarIfNecessary() { + if (mTopBarContentView != null && mTopBarContentView.getParent() == null) { + getTopBarView().addView(mTopBarContentView); + } + } + + /** + * Sets the content of the top bar. + */ + public void setTopBarContentView(View view) { + mTopBarContentView = view; + } + + /** + * Gets the {@link ViewGroup} of the top bar. If it has not been inflated, inflate it first. + */ + private ViewGroup getTopBarView() { + if (mTopBarView == null) { + ViewStub topBarStub = ((ViewStub) mActivity.findViewById(R.id.topbar_stub)); + mTopBarView = (ViewGroup) topBarStub.inflate(); + } + return mTopBarView; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java index 8a4a617..2e1cc5c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java
@@ -43,4 +43,9 @@ public void loadUri(Uri uri) { mActivity.loadUri(uri); } + + @Override + public void setTopBarView(IObjectWrapper topBarView) { + mActivity.setTopBarContentView(ObjectWrapper.unwrap(topBarView, View.class)); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ThumbnailGradient.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ThumbnailGradient.java index 9154f09f..60e42ae 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ThumbnailGradient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ThumbnailGradient.java
@@ -9,7 +9,6 @@ import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; import android.os.SystemClock; import android.support.annotation.IntDef; @@ -84,7 +83,7 @@ ? R.drawable.thumbnail_gradient_top_left : R.drawable.thumbnail_gradient_top_right); - return new LayerDrawable( + return ApiCompatibilityUtils.createLayerDrawable( new Drawable[] {new BitmapDrawable(resources, bitmap), gradient}); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java index 9734c6ae..125178c0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -63,7 +63,7 @@ /** * The ImageButton view that represents the menu button. */ - private TintedImageButton mMenuButton; + protected TintedImageButton mMenuButton; private ImageView mMenuBadge; private View mMenuButtonWrapper; private AppMenuButtonHelper mAppMenuButtonHelper;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 1de9970..26792e8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -668,6 +668,13 @@ } /** + * @return Whether the UrlBar currently has focus. + */ + public boolean isUrlBarFocused() { + return getToolbarLayout().getLocationBar().isUrlBarFocused(); + } + + /** * @param reason A {@link OmniboxFocusReason} that the omnibox was focused. */ public static void recordOmniboxFocusReason(@OmniboxFocusReason int reason) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java index 17524e97..789ce1d7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -105,6 +105,7 @@ public static final int URL_FOCUS_CHANGE_ANIMATION_DURATION_MS = 225; private static final int URL_FOCUS_TOOLBAR_BUTTONS_TRANSLATION_X_DP = 10; private static final int URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS = 100; + private static final int URL_CLEAR_FOCUS_EXPERIMENTAL_BUTTON_DELAY_MS = 150; private static final int URL_CLEAR_FOCUS_TABSTACK_DELAY_MS = 200; private static final int URL_CLEAR_FOCUS_MENU_DELAY_MS = 250; @@ -113,6 +114,11 @@ private static final int TAB_SWITCHER_MODE_EXIT_FADE_ANIMATION_DURATION_MS = 100; private static final int TAB_SWITCHER_MODE_POST_EXIT_ANIMATION_DURATION_MS = 100; + // Values used during animation to show/hide optional toolbar button. + public static final int LOC_BAR_WIDTH_CHANGE_ANIMATION_DURATION_MS = 225; + private static final int EXPERIMENTAL_ICON_ANIMATION_DURATION_MS = 100; + private static final int EXPERIMENTAL_ICON_ANIMATION_DELAY_MS = 125; + private static final float UNINITIALIZED_PERCENT = -1f; /** States that the toolbar can be in regarding the tab switcher. */ @@ -210,6 +216,7 @@ protected boolean mDisableLocationBarRelayout; protected boolean mLayoutLocationBarInFocusedMode; + private boolean mLayoutLocationBarWithoutExtraButton; protected int mUnfocusedLocationBarLayoutWidth; protected int mUnfocusedLocationBarLayoutLeft; protected int mUnfocusedLocationBarLayoutRight; @@ -300,6 +307,17 @@ private float mPreTextureCaptureAlpha = 1f; private boolean mIsOverlayTabStackDrawableLight; + private AnimatorSet mExperimentalButtonAnimator; + private boolean mExperimentalButtonAnimationRunning; + private int mExperimentalButtonTranslation; + /** + * The percent completion for the location bar width change animation that is run when the + * experimental button is shown/hidden. Animates from 1.f to 0.f when showing the button and + * 0.f to 1.f when hiding the button, where 0.f indicates the location bar width is not offset + * at all for the animation. + */ + private float mLocBarWidthChangePercent; + /** * A global layout listener used to capture a new texture when the experimental toolbar button * is added or removed. @@ -336,6 +354,20 @@ } }; + private final Property<ToolbarPhone, Float> mLocBarWidthChangePercentProperty = + new Property<ToolbarPhone, Float>(Float.class, "") { + @Override + public Float get(ToolbarPhone object) { + return object.mLocBarWidthChangePercent; + } + + @Override + public void set(ToolbarPhone object, Float value) { + mLocBarWidthChangePercent = value; + updateLocationBarLayoutForExpansionAnimation(); + } + }; + /** * Constructs a ToolbarPhone object. * @param context The Context in which this View object is created. @@ -684,6 +716,12 @@ leftMargin = mUnfocusedLocationBarLayoutLeft; } + if (mLayoutLocationBarWithoutExtraButton) { + float offset = getLocationBarWidthOffsetForExperimentalButton(); + if (ApiCompatibilityUtils.isLayoutRtl(this)) leftMargin -= (int) offset; + width += (int) offset; + } + boolean changed = false; changed |= (width != locationBarLayoutParams.width); locationBarLayoutParams.width = width; @@ -915,6 +953,11 @@ int leftViewPosition = (int) MathUtils.interpolate(getViewBoundsLeftOfLocationBar(visualState), getFocusedLeftPositionOfLocationBarBackground(), expansion); + + if (mExperimentalButtonAnimationRunning && ApiCompatibilityUtils.isLayoutRtl(this)) { + leftViewPosition -= getLocationBarBackgroundOffsetForExperimentalButton(); + } + return leftViewPosition; } @@ -936,10 +979,39 @@ (int) MathUtils.interpolate(getViewBoundsRightOfLocationBar(visualState), getFocusedRightPositionOfLocationBarBackground(), expansion); + if (mExperimentalButtonAnimationRunning && !ApiCompatibilityUtils.isLayoutRtl(this)) { + rightViewPosition += getLocationBarBackgroundOffsetForExperimentalButton(); + } + return rightViewPosition; } /** + * @return The location bar background position offset, for use when the experimental button + * show/hide animation is running. + */ + private int getLocationBarBackgroundOffsetForExperimentalButton() { + return (int) (getLocationBarWidthOffsetForExperimentalButton() * mLocBarWidthChangePercent); + } + + /** + * @return The difference in the location bar width when the experimental button is hidden + * rather than showing. This is effectively the width of the experimental button with + * some adjustment to account for possible padding differences when the button + * visibility changes. + */ + private float getLocationBarWidthOffsetForExperimentalButton() { + float widthChange = mExperimentalButton.getWidth(); + + // When the experimental button is the only visible button after the location bar and the + // button is hidden mToolbarSidePadding is used for the padding after the location bar. + if (!isMenuButtonPresent()) { + widthChange -= mToolbarSidePadding; + } + return widthChange; + } + + /** * @return The right drawing position for the location bar background when the location bar * has focus. */ @@ -1003,12 +1075,32 @@ int currentWidth = locationBarLayoutParams.width; float locationBarBaseTranslationX = mUnfocusedLocationBarLayoutLeft - currentLeftMargin; + if (mExperimentalButtonAnimationRunning) { + // When showing the button, we disable location bar relayout + // (mDisableLocationBarRelayout), so the location bar's left margin and + // mUnfocusedLocationBarLayoutLeft have not been updated to take into account the + // appearance of the experimental icon. The views to left of the location bar will + // be wider than mUnfocusedlocationBarLayoutLeft in RTL, so adjust the translation by + // that amount. + // When hiding the button, we force a relayout without the experimental toolbar button + // (mLayoutLocationBarWithoutExtraButton). mUnfocusedLocationBarLayoutLeft reflects + // the view bounds left of the location bar, which still includes the experimental + // button. The location bar left margin, however, has been adjusted to reflect its + // end value when the experimental button is fully hidden. The + // locationBarBaseTranslationX above accounts for the difference between + // mUnfocusedLocationBarLayoutLeft and the location bar's current left margin. + locationBarBaseTranslationX += + getViewBoundsLeftOfLocationBar(mVisualState) - mUnfocusedLocationBarLayoutLeft; + } + boolean isLocationBarRtl = ApiCompatibilityUtils.isLayoutRtl(mLocationBar); if (isLocationBarRtl) { locationBarBaseTranslationX += mUnfocusedLocationBarLayoutWidth - currentWidth; } - locationBarBaseTranslationX *= 1f - mUrlExpansionPercent; + locationBarBaseTranslationX *= 1f + - (mExperimentalButtonAnimationRunning ? mLocBarWidthChangePercent + : mUrlExpansionPercent); mLocationBarBackgroundNtpOffset.setEmpty(); mLocationBarNtpOffsetLeft = 0; @@ -1038,23 +1130,25 @@ } mLocationBar.setTranslationX(locationBarTranslationX); - mUrlActionContainer.setTranslationX(getUrlActionsTranslationXForExpansionAnimation( - isLocationBarRtl, locationBarBaseTranslationX)); - mLocationBar.setUrlFocusChangePercent(mUrlExpansionPercent); + if (!mExperimentalButtonAnimationRunning) { + mUrlActionContainer.setTranslationX(getUrlActionsTranslationXForExpansionAnimation( + isLocationBarRtl, locationBarBaseTranslationX)); + mLocationBar.setUrlFocusChangePercent(mUrlExpansionPercent); - // Only transition theme colors if in static tab mode that is not the NTP. In practice this - // only runs when you focus the omnibox on a web page. - if (!isLocationBarShownInNTP() && mTabSwitcherState == STATIC_TAB) { - int defaultColor = ColorUtils.getDefaultThemeColor(getResources(), isIncognito()); - int defaultLocationBarColor = getLocationBarColorForToolbarColor(defaultColor); - int primaryColor = getToolbarDataProvider().getPrimaryColor(); - int themedLocationBarColor = getLocationBarColorForToolbarColor(primaryColor); + // Only transition theme colors if in static tab mode that is not the NTP. In practice + // this only runs when you focus the omnibox on a web page. + if (!isLocationBarShownInNTP() && mTabSwitcherState == STATIC_TAB) { + int defaultColor = ColorUtils.getDefaultThemeColor(getResources(), isIncognito()); + int defaultLocationBarColor = getLocationBarColorForToolbarColor(defaultColor); + int primaryColor = getToolbarDataProvider().getPrimaryColor(); + int themedLocationBarColor = getLocationBarColorForToolbarColor(primaryColor); - updateToolbarBackground(ColorUtils.getColorWithOverlay( - primaryColor, defaultColor, mUrlFocusChangePercent)); + updateToolbarBackground(ColorUtils.getColorWithOverlay( + primaryColor, defaultColor, mUrlFocusChangePercent)); - updateModernLocationBarColor(ColorUtils.getColorWithOverlay( - themedLocationBarColor, defaultLocationBarColor, mUrlFocusChangePercent)); + updateModernLocationBarColor(ColorUtils.getColorWithOverlay( + themedLocationBarColor, defaultLocationBarColor, mUrlFocusChangePercent)); + } } // Force an invalidation of the location bar to properly handle the clipping of the URL @@ -1441,7 +1535,7 @@ // viewport used to draw the background. During expansion transitions, compensation // is applied to increase the clip regions such that when the location bar converts // to the narrower collapsed layout the visible content is the same. - if (mUrlExpansionPercent != 1f) { + if (mUrlExpansionPercent != 1f && !mExperimentalButtonAnimationRunning) { int leftDelta = mUnfocusedLocationBarLayoutLeft - getViewBoundsLeftOfLocationBar(mVisualState); int rightDelta = getViewBoundsRightOfLocationBar(mVisualState) @@ -1461,6 +1555,13 @@ locationBarClipRight -= ViewCompat.getPaddingEnd(mLocationBar) * inversePercent; } } + if (mExperimentalButtonAnimationRunning) { + if (ApiCompatibilityUtils.isLayoutRtl(mLocationBar)) { + locationBarClipLeft += ViewCompat.getPaddingStart(mLocationBar); + } else { + locationBarClipRight -= ViewCompat.getPaddingEnd(mLocationBar); + } + } // Clip the location bar child to the URL viewport calculated in onDraw. canvas.clipRect( @@ -1969,6 +2070,19 @@ animators.add(animator); } + if (mExperimentalButton != null && mExperimentalButton.getVisibility() != View.GONE) { + animator = ObjectAnimator.ofFloat( + mExperimentalButton, TRANSLATION_X, toolbarButtonTranslationX); + animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); + animator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); + animators.add(animator); + + animator = ObjectAnimator.ofFloat(mExperimentalButton, ALPHA, 0); + animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); + animator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); + animators.add(animator); + } + animator = ObjectAnimator.ofFloat(mToolbarShadow, ALPHA, 0); animator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS); animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); @@ -2010,6 +2124,23 @@ animators.add(animator); } + if (mExperimentalButton != null && mExperimentalButton.getVisibility() != View.GONE) { + // TODO(twellington): it's possible that the experimental button was shown while + // the url bar was focused, in which case the translation x and alpha animators + // are a no-op. Account for this case. + animator = ObjectAnimator.ofFloat(mExperimentalButton, TRANSLATION_X, 0); + animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); + animator.setStartDelay(URL_CLEAR_FOCUS_EXPERIMENTAL_BUTTON_DELAY_MS); + animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); + animators.add(animator); + + animator = ObjectAnimator.ofFloat(mExperimentalButton, ALPHA, 1); + animator.setDuration(URL_FOCUS_TOOLBAR_BUTTONS_DURATION_MS); + animator.setStartDelay(URL_CLEAR_FOCUS_EXPERIMENTAL_BUTTON_DELAY_MS); + animator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); + animators.add(animator); + } + for (int i = 0; i < mLocationBar.getChildCount(); i++) { View childView = mLocationBar.getChildAt(i); if (childView == mLocationBar.getFirstViewVisibleWhenFocused()) break; @@ -2042,6 +2173,7 @@ mUrlFocusLayoutAnimator.cancel(); mUrlFocusLayoutAnimator = null; } + if (mExperimentalButtonAnimationRunning) mExperimentalButtonAnimator.end(); List<Animator> animators = new ArrayList<>(); if (hasFocus) { @@ -2559,10 +2691,14 @@ ViewStub viewStub = findViewById(R.id.experimental_button_stub); mExperimentalButton = (TintedImageButton) viewStub.inflate(); - if (FeatureUtilities.isBottomToolbarEnabled()) { - mExperimentalButton.setPadding(0, 0, 0, 0); - } + if (!isMenuButtonPresent()) mExperimentalButton.setPadding(0, 0, 0, 0); + mExperimentalButtonTranslation = getResources().getDimensionPixelSize( + R.dimen.toolbar_optional_button_animation_translation); + if (ApiCompatibilityUtils.isLayoutRtl(this)) mExperimentalButtonTranslation *= -1; } else { + if (mExperimentalButtonAnimationRunning) { + mExperimentalButtonAnimator.end(); + } assert mExperimentalButton.getVisibility() == View.GONE : "#disableExperimentalButton() should be called first."; } @@ -2573,8 +2709,13 @@ mExperimentalButton.setContentDescription( getContext().getResources().getString(contentDescriptionResId)); mExperimentalButton.setTint(mUseLightToolbarDrawables ? mLightModeTint : mDarkModeTint); + if (mTabSwitcherState == STATIC_TAB) { - mExperimentalButton.setVisibility(View.VISIBLE); + if (!mUrlFocusChangeInProgress && !urlHasFocus()) { + runShowExperimentalButtonAnimation(); + } else { + mExperimentalButton.setVisibility(View.VISIBLE); + } } else { mExperimentalButton.setVisibility(View.INVISIBLE); } @@ -2585,24 +2726,158 @@ @Override public void disableExperimentalButton() { - if (mExperimentalButton == null) return; + if (mExperimentalButton == null || mExperimentalButton.getVisibility() == View.GONE) { + return; + } - mExperimentalButton.setVisibility(View.GONE); + if (mTabSwitcherState == STATIC_TAB && !mUrlFocusChangeInProgress && !urlHasFocus()) { + runHideExperimentalButtonsAnimators(); + } else { + mExperimentalButton.setVisibility(View.GONE); + } + mBrowsingModeViews.remove(mExperimentalButton); getViewTreeObserver().addOnGlobalLayoutListener(mExperimentalButtonLayoutListener); } + /** + * Whether the menu button is visible. Used as a proxy for whether there are end toolbar + * buttons besides the experimental button. + */ + private boolean isMenuButtonPresent() { + return mMenuButton != null; + } + private void requestLayoutHostUpdateForExperimentalButton() { if (mLayoutUpdateHost != null) mLayoutUpdateHost.requestUpdate(); getViewTreeObserver().removeOnGlobalLayoutListener(mExperimentalButtonLayoutListener); } + /** + * Runs an animation that fades in the experimental button while shortening the location bar + * background. + */ + private void runShowExperimentalButtonAnimation() { + if (mExperimentalButtonAnimationRunning) mExperimentalButtonAnimator.end(); + + List<Animator> animators = new ArrayList<>(); + + mLocBarWidthChangePercent = 1.f; + Animator widthChangeAnimator = + ObjectAnimator.ofFloat(this, mLocBarWidthChangePercentProperty, 0.f); + widthChangeAnimator.setDuration(LOC_BAR_WIDTH_CHANGE_ANIMATION_DURATION_MS); + widthChangeAnimator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); + animators.add(widthChangeAnimator); + + mExperimentalButton.setAlpha(0.f); + ObjectAnimator buttonAnimator = + ObjectAnimator.ofFloat(mExperimentalButton, View.ALPHA, 1.f); + buttonAnimator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); + buttonAnimator.setStartDelay(EXPERIMENTAL_ICON_ANIMATION_DELAY_MS); + buttonAnimator.setDuration(EXPERIMENTAL_ICON_ANIMATION_DURATION_MS); + animators.add(buttonAnimator); + + mExperimentalButton.setTranslationX(mExperimentalButtonTranslation); + ObjectAnimator buttonTranslationAnimator = + ObjectAnimator.ofFloat(mExperimentalButton, View.TRANSLATION_X, 0); + buttonTranslationAnimator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); + buttonTranslationAnimator.setStartDelay(EXPERIMENTAL_ICON_ANIMATION_DELAY_MS); + buttonTranslationAnimator.setDuration(EXPERIMENTAL_ICON_ANIMATION_DURATION_MS); + animators.add(buttonTranslationAnimator); + + mExperimentalButtonAnimator = new AnimatorSet(); + mExperimentalButtonAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + mDisableLocationBarRelayout = true; + mExperimentalButtonAnimationRunning = true; + mExperimentalButton.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + onExperimentalButtonAnimationEnd(); + mDisableLocationBarRelayout = false; + mExperimentalButtonAnimationRunning = false; + requestLayout(); + } + }); + mExperimentalButtonAnimator.playTogether(animators); + mExperimentalButtonAnimator.start(); + } + + /** + * Runs an animation that fades out the experimental button while lengthening the location bar + * background. + */ + private void runHideExperimentalButtonsAnimators() { + if (mExperimentalButtonAnimationRunning) mExperimentalButtonAnimator.end(); + + List<Animator> animators = new ArrayList<>(); + + mLocBarWidthChangePercent = 0.f; + Animator widthChangeAnimator = + ObjectAnimator.ofFloat(this, mLocBarWidthChangePercentProperty, 1.f); + widthChangeAnimator.setDuration(LOC_BAR_WIDTH_CHANGE_ANIMATION_DURATION_MS); + widthChangeAnimator.setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE); + animators.add(widthChangeAnimator); + + mExperimentalButton.setAlpha(1.f); + ObjectAnimator buttonAnimator = + ObjectAnimator.ofFloat(mExperimentalButton, View.ALPHA, 0.f); + buttonAnimator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); + buttonAnimator.setDuration(EXPERIMENTAL_ICON_ANIMATION_DURATION_MS); + animators.add(buttonAnimator); + + mExperimentalButton.setTranslationX(0); + ObjectAnimator buttonTranslationAnimator = ObjectAnimator.ofFloat( + mExperimentalButton, View.TRANSLATION_X, mExperimentalButtonTranslation); + buttonTranslationAnimator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); + buttonTranslationAnimator.setDuration(EXPERIMENTAL_ICON_ANIMATION_DURATION_MS); + animators.add(buttonTranslationAnimator); + + mExperimentalButtonAnimator = new AnimatorSet(); + mExperimentalButtonAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + mLayoutLocationBarWithoutExtraButton = true; + mExperimentalButtonAnimationRunning = true; + requestLayout(); + } + + @Override + public void onAnimationEnd(Animator animation) { + onExperimentalButtonAnimationEnd(); + mExperimentalButton.setVisibility(View.GONE); + mLayoutLocationBarWithoutExtraButton = false; + mExperimentalButtonAnimationRunning = false; + } + }); + mExperimentalButtonAnimator.playTogether(animators); + mExperimentalButtonAnimator.start(); + } + + /** + * Resets the alpha and translation X for all views affected by the animations for showing or + * hiding buttons. + */ + private void onExperimentalButtonAnimationEnd() { + mExperimentalButtonAnimator = null; + mExperimentalButton.setAlpha(1.f); + mExperimentalButton.setTranslationX(0); + } + @VisibleForTesting public View getExperimentalButtonForTesting() { return mExperimentalButton; } + @VisibleForTesting + public void endExperimentalButtonAnimationForTesting() { + if (mExperimentalButtonAnimator != null) mExperimentalButtonAnimator.end(); + } + private void setTabSwitcherAnimationMenuDrawable() { mTabSwitcherAnimationMenuDrawable = ApiCompatibilityUtils.getDrawable( getResources(), R.drawable.ic_more_vert_black_24dp);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialog.java index 585f29d..d2c4413 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PromoDialog.java
@@ -84,10 +84,10 @@ * Force the promo dialog to have a fully opaque background hiding any underlying content. */ protected void forceOpaqueBackground() { - LayerDrawable background = new LayerDrawable(new Drawable[] { - new ColorDrawable(Color.WHITE), - new ColorDrawable(ApiCompatibilityUtils.getColor( - getContext().getResources(), R.color.modal_dialog_scrim_color))}); + LayerDrawable background = ApiCompatibilityUtils.createLayerDrawable( + new Drawable[] {new ColorDrawable(Color.WHITE), + new ColorDrawable(ApiCompatibilityUtils.getColor( + getContext().getResources(), R.color.modal_dialog_scrim_color))}); mScrimView.setBackground(background); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java index fd10f30d..eb2ded88 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ViewHighlighter.java
@@ -9,6 +9,7 @@ import android.graphics.drawable.LayerDrawable; import android.view.View; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; import org.chromium.chrome.R; @@ -49,9 +50,9 @@ background = background.getConstantState().newDrawable(resources); } - LayerDrawable drawable = - new LayerDrawable(background == null ? new Drawable[] {pulseDrawable} - : new Drawable[] {background, pulseDrawable}); + LayerDrawable drawable = ApiCompatibilityUtils.createLayerDrawable(background == null + ? new Drawable[] {pulseDrawable} + : new Drawable[] {background, pulseDrawable}); view.setBackground(drawable); view.setTag(R.id.highlight_state, true);
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 14b2c4c..3f1434fc 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -379,6 +379,7 @@ "java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java", + "java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionService.java", "java/src/org/chromium/chrome/browser/customtabs/FirstMeaningfulPaintObserver.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java index 8eb642c..dab21fd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java
@@ -528,7 +528,10 @@ "Toolbar button should be visible", View.VISIBLE, toolbarButton.getVisibility()); // Simulate suggestions being cleared. - ThreadUtils.runOnUiThreadBlocking(() -> mMediator.clearState()); + ThreadUtils.runOnUiThreadBlocking(() -> { + mMediator.clearState(); + getToolbarPhone().endExperimentalButtonAnimationForTesting(); + }); assertEquals("Toolbar button should be gone", View.GONE, toolbarButton.getVisibility()); assertEquals("Suggestions should be cleared", 0, mModel.getClusterList().getItemCount()); @@ -598,10 +601,8 @@ } private View getToolbarButton(ChromeActivity activity) throws ExecutionException { - return ThreadUtils.runOnUiThreadBlocking(() -> { - return ((ToolbarPhone) activity.getToolbarManager().getToolbarLayout()) - .getExperimentalButtonForTesting(); - }); + return ThreadUtils.runOnUiThreadBlocking( + () -> { return getToolbarPhone(activity).getExperimentalButtonForTesting(); }); } private void clickToolbarButton() throws ExecutionException { @@ -641,6 +642,9 @@ CriteriaHelper.pollUiThread(() -> { return mActivityTestRule.getActivity().getActivityTab().getUrl().equals(expectedUrl); }); + + ThreadUtils.runOnUiThreadBlocking( + () -> getToolbarPhone().endExperimentalButtonAnimationForTesting()); } private void dismissHelpBubble() { @@ -650,4 +654,12 @@ } }); } + + private ToolbarPhone getToolbarPhone() { + return getToolbarPhone(mActivityTestRule.getActivity()); + } + + private ToolbarPhone getToolbarPhone(ChromeActivity activity) { + return (ToolbarPhone) activity.getToolbarManager().getToolbarLayout(); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 19b4c32..e099558 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -1112,6 +1112,39 @@ @Test @SmallTest + @RetryOnFailure + public void testSetTopBarContentView() throws Exception { + Intent intent = createMinimalCustomTabIntent(); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + + ThreadUtils.runOnUiThread(() -> { + CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity(); + View anyView = new View(cctActivity); + cctActivity.setTopBarContentView(anyView); + ViewGroup topBar = cctActivity.findViewById(R.id.topbar); + Assert.assertNotNull(topBar); + Assert.assertThat(anyView.getParent(), equalTo(topBar)); + }); + } + + @Test + @SmallTest + @RetryOnFailure + public void testSetTopBarContentView_secondCallIsNoOp() throws Exception { + Intent intent = createMinimalCustomTabIntent(); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + + ThreadUtils.runOnUiThread(() -> { + CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity(); + View anyView = new View(cctActivity); + cctActivity.setTopBarContentView(anyView); + // Second call will not crash. + cctActivity.setTopBarContentView(anyView); + }); + } + + @Test + @SmallTest @Feature({"UiCatalogue"}) public void testRemoteViews() throws Exception { Intent intent = createMinimalCustomTabIntent();
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni new file mode 100644 index 0000000..7bd0c30 --- /dev/null +++ b/chrome/android/trichrome.gni
@@ -0,0 +1,17 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/config.gni") + +trichrome_library_package = "org.chromium.trichromelibrary" +trichrome_certdigest = + "1975b2f17177bc89a5dff31f9e64a6cae281a53dc1d1d59b1d147fe1c82afa00" + +trichrome_jinja_variables = [ + "min_sdk_version=26", + "target_sdk_version=$android_sdk_version", + "trichrome_library=$trichrome_library_package", + "trichrome_version=$android_default_version_code", + "trichrome_certdigest=$trichrome_certdigest", +]
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 54d47fc..742c10d 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2662,6 +2662,12 @@ <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION_DESCRIPTION" desc="Sub label for notification-enable toggle."> Enables the Assistant to show you notifications. </message> + <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN" desc="Title for a toggle that determines whether to open the microphone when launching the Assistant."> + Launch Assistant with microphone open + </message> + <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN_DESCRIPTION" desc="Sub label for launch-with-microphone-open toggle."> + Always launch the Assistant with microphone open. + </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_SETTINGS" desc="Title for a button that opens the Google Assistant app settings."> Google Assistant settings </message>
diff --git a/chrome/app_shim/chrome_main_app_mode_mac.mm b/chrome/app_shim/chrome_main_app_mode_mac.mm index 6f345237..ae415b25 100644 --- a/chrome/app_shim/chrome_main_app_mode_mac.mm +++ b/chrome/app_shim/chrome_main_app_mode_mac.mm
@@ -47,7 +47,7 @@ #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/views/cocoa/bridge_factory_impl.h" +#include "ui/views_bridge_mac/bridge_factory_impl.h" #include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h" namespace {
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f54ffe17..632368c 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4506,6 +4506,8 @@ "android/feed/feed_image_loader_bridge.h", "android/feed/feed_journal_bridge.cc", "android/feed/feed_journal_bridge.h", + "android/feed/feed_logging_bridge.cc", + "android/feed/feed_logging_bridge.h", "android/feed/feed_network_bridge.cc", "android/feed/feed_network_bridge.h", "android/feed/feed_offline_bridge.cc", @@ -4786,6 +4788,7 @@ "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalBridge.java", + "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedOfflineBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java",
diff --git a/chrome/browser/android/feed/feed_logging_bridge.cc b/chrome/browser/android/feed/feed_logging_bridge.cc new file mode 100644 index 0000000..f9ffc9e1 --- /dev/null +++ b/chrome/browser/android/feed/feed_logging_bridge.cc
@@ -0,0 +1,34 @@ +// Copyright 2018 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/android/feed/feed_logging_bridge.h" + +#include <jni.h> + +#include "jni/FeedLoggingBridge_jni.h" + +namespace feed { + +using base::android::JavaRef; +using base::android::JavaParamRef; + +static jlong JNI_FeedLoggingBridge_Init(JNIEnv* env, + const JavaParamRef<jobject>& j_this) { + FeedLoggingBridge* native_logging_bridge = new FeedLoggingBridge(); + return reinterpret_cast<intptr_t>(native_logging_bridge); +} + +FeedLoggingBridge::FeedLoggingBridge() = default; + +FeedLoggingBridge::~FeedLoggingBridge() = default; + +void FeedLoggingBridge::Destroy(JNIEnv* env, const JavaRef<jobject>& j_this) { + delete this; +} + +void FeedLoggingBridge::OnOpenedWithContent(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const jint j_content_count) {} + +} // namespace feed
diff --git a/chrome/browser/android/feed/feed_logging_bridge.h b/chrome/browser/android/feed/feed_logging_bridge.h new file mode 100644 index 0000000..d264367a --- /dev/null +++ b/chrome/browser/android/feed/feed_logging_bridge.h
@@ -0,0 +1,32 @@ +// Copyright 2018 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 CHROME_BROWSER_ANDROID_FEED_FEED_LOGGING_BRIDGE_H_ +#define CHROME_BROWSER_ANDROID_FEED_FEED_LOGGING_BRIDGE_H_ + +#include "base/android/scoped_java_ref.h" + +namespace feed { + +// Native counterpart of FeedLoggingBridge.java. Holds non-owning pointers +// to native implementation, to which operations are delegated. This bridge is +// instantiated, owned, and destroyed from Java. +class FeedLoggingBridge { + public: + FeedLoggingBridge(); + ~FeedLoggingBridge(); + + void Destroy(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this); + + void OnOpenedWithContent(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const jint j_content_count); + + private: + DISALLOW_COPY_AND_ASSIGN(FeedLoggingBridge); +}; + +} // namespace feed + +#endif // CHROME_BROWSER_ANDROID_FEED_FEED_LOGGING_BRIDGE_H_
diff --git a/chrome/browser/apps/platform_apps/api/BUILD.gn b/chrome/browser/apps/platform_apps/api/BUILD.gn index 6cb17da..589307c 100644 --- a/chrome/browser/apps/platform_apps/api/BUILD.gn +++ b/chrome/browser/apps/platform_apps/api/BUILD.gn
@@ -30,6 +30,10 @@ ] deps = [ + # TODO(https://crbug.com/883570): It'd be nice to have more APIs here + # extracted into their own BUILD files (so they are easy to audit, add, or + # remove), but any that depend on //chrome/browser:browser can't. + "//chrome/browser/apps/platform_apps/api/music_manager_private", "//chrome/browser/extensions", "//chrome/common/apps/platform_apps/api", "//extensions/browser",
diff --git a/chrome/browser/apps/platform_apps/api/music_manager_private/BUILD.gn b/chrome/browser/apps/platform_apps/api/music_manager_private/BUILD.gn new file mode 100644 index 0000000..c543fd81 --- /dev/null +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/BUILD.gn
@@ -0,0 +1,41 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/features.gni") +import("//extensions/buildflags/buildflags.gni") +import("//rlz/buildflags/buildflags.gni") + +assert(enable_extensions) + +source_set("music_manager_private") { + sources = [ + "device_id.cc", + "device_id.h", + "device_id_chromeos.cc", + "device_id_linux.cc", + "device_id_mac.cc", + "device_id_win.cc", + "music_manager_private_api.cc", + "music_manager_private_api.h", + ] + + deps = [ + "//base", + "//chrome/common/apps/platform_apps/api", + "//content/public/browser", + "//extensions/browser", + "//rlz/buildflags", + "//crypto", + ] + + if (is_chromeos) { + sources -= [ "device_id_linux.cc" ] + + deps += [ "//chromeos" ] + } + + if (enable_rlz_support) { + deps += [ "//rlz:rlz_lib" ] + } +}
diff --git a/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.cc new file mode 100644 index 0000000..5352a0c --- /dev/null +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.cc
@@ -0,0 +1,195 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h" + +#include <stdint.h> +#include <vector> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "content/public/browser/browser_thread.h" +#include "crypto/hmac.h" + +namespace chrome_apps { +namespace api { + +namespace { + +// Compute HMAC-SHA256(|key|, |text|) as a string. +bool ComputeHmacSha256(const std::string& key, + const std::string& text, + std::string* signature_return) { + crypto::HMAC hmac(crypto::HMAC::SHA256); + const size_t digest_length = hmac.DigestLength(); + std::vector<uint8_t> digest(digest_length); + bool result = hmac.Init(key) && hmac.Sign(text, &digest[0], digest.size()); + if (result) { + *signature_return = + base::ToLowerASCII(base::HexEncode(digest.data(), digest.size())); + } + return result; +} + +void GetRawDeviceIdCallback(const std::string& extension_id, + const DeviceId::IdCallback& callback, + const std::string& raw_device_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (raw_device_id.empty()) { + callback.Run(""); + return; + } + + std::string device_id; + if (!ComputeHmacSha256(raw_device_id, extension_id, &device_id)) { + DLOG(ERROR) << "Error while computing HMAC-SHA256 of device id."; + callback.Run(""); + return; + } + callback.Run(device_id); +} + +bool IsValidMacAddressImpl(const void* bytes, size_t size) { + const size_t MAC_LENGTH = 6; + const size_t OUI_LENGTH = 3; + struct InvalidMacEntry { + size_t size; + unsigned char address[MAC_LENGTH]; + }; + + // VPN, virtualization, tethering, bluetooth, etc. + static InvalidMacEntry invalidAddresses[] = { + // Empty address + {MAC_LENGTH, {0, 0, 0, 0, 0, 0}}, + // VMware + {OUI_LENGTH, {0x00, 0x50, 0x56}}, + {OUI_LENGTH, {0x00, 0x05, 0x69}}, + {OUI_LENGTH, {0x00, 0x0c, 0x29}}, + {OUI_LENGTH, {0x00, 0x1c, 0x14}}, + // VirtualBox + {OUI_LENGTH, {0x08, 0x00, 0x27}}, + // PdaNet + {MAC_LENGTH, {0x00, 0x26, 0x37, 0xbd, 0x39, 0x42}}, + // Cisco AnyConnect VPN + {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}}, + // Marvell sometimes uses this as a dummy address + {MAC_LENGTH, {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, + // Apple uses this across machines for Bluetooth ethernet adapters. + {MAC_LENGTH - 1, {0x65, 0x90, 0x07, 0x42, 0xf1}}, + // Juniper uses this for their Virtual Adapter, the other 4 bytes are + // reassigned at every boot. 00-ff-xx is not assigned to anyone. + {2, {0x00, 0xff}}, + // T-Mobile Wireless Ethernet + {MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}}, + // Generic Bluetooth device + {MAC_LENGTH, {0x00, 0x15, 0x83, 0x3d, 0x0a, 0x57}}, + // RAS Async Adapter + {MAC_LENGTH, {0x20, 0x41, 0x53, 0x59, 0x4e, 0xff}}, + // Qualcomm USB ethernet adapter + {MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}}, + // Windows VPN + {MAC_LENGTH, {0x00, 0x53, 0x45, 0x00, 0x00, 0x00}}, + // Bluetooth + {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x08, 0x30}}, + {MAC_LENGTH, {0x00, 0x1b, 0x10, 0x00, 0x2a, 0xec}}, + {MAC_LENGTH, {0x00, 0x15, 0x83, 0x15, 0xa3, 0x10}}, + {MAC_LENGTH, {0x00, 0x15, 0x83, 0x07, 0xC6, 0x5A}}, + {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0x00}}, + {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0xdd}}, + // Ceton TV tuner + {MAC_LENGTH, {0x00, 0x22, 0x2c, 0xff, 0xff, 0xff}}, + // Check Point VPN + {MAC_LENGTH, {0x54, 0x55, 0x43, 0x44, 0x52, 0x09}}, + {MAC_LENGTH, {0x54, 0xEF, 0x14, 0x71, 0xE4, 0x0E}}, + {MAC_LENGTH, {0x54, 0xBA, 0xC6, 0xFF, 0x74, 0x10}}, + // Cisco VPN + {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}}, + // Cisco VPN + {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x78, 0x00}}, + // Intel USB cell modem + {MAC_LENGTH, {0x00, 0x1e, 0x10, 0x1f, 0x00, 0x01}}, + // Microsoft tethering + {MAC_LENGTH, {0x80, 0x00, 0x60, 0x0f, 0xe8, 0x00}}, + // Nortel VPN + {MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x42, 0x00}}, + // AEP VPN + {MAC_LENGTH, {0x00, 0x30, 0x70, 0x00, 0x00, 0x01}}, + // Positive VPN + {MAC_LENGTH, {0x00, 0x02, 0x03, 0x04, 0x05, 0x06}}, + // Bluetooth + {MAC_LENGTH, {0x00, 0x15, 0x83, 0x0B, 0x13, 0xC0}}, + // Kerio Virtual Network Adapter + {MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x4f, 0x53}}, + // Sierra Wireless cell modems. + {OUI_LENGTH, {0x00, 0xA0, 0xD5}}, + // FRITZ!web DSL + {MAC_LENGTH, {0x00, 0x04, 0x0E, 0xFF, 0xFF, 0xFF}}, + // VirtualPC + {MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, + // Bluetooth + {MAC_LENGTH, {0x00, 0x1F, 0x81, 0x00, 0x01, 0x00}}, + {MAC_LENGTH, {0x00, 0x30, 0x91, 0x10, 0x00, 0x26}}, + {MAC_LENGTH, {0x00, 0x25, 0x00, 0x5A, 0xC3, 0xD0}}, + {MAC_LENGTH, {0x00, 0x15, 0x83, 0x0C, 0xBF, 0xEB}}, + // Huawei cell modem + {MAC_LENGTH, {0x58, 0x2C, 0x80, 0x13, 0x92, 0x63}}, + // Fortinet VPN + {OUI_LENGTH, {0x00, 0x09, 0x0F}}, + // Realtek + {MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x30}}, + // Other rare dupes. + {MAC_LENGTH, {0x00, 0x11, 0xf5, 0x0d, 0x8a, 0xe8}}, // Atheros + {MAC_LENGTH, {0x00, 0x20, 0x07, 0x01, 0x16, 0x06}}, // Atheros + {MAC_LENGTH, {0x0d, 0x0b, 0x00, 0x00, 0xe0, 0x00}}, // Atheros + {MAC_LENGTH, {0x90, 0x4c, 0xe5, 0x0b, 0xc8, 0x8e}}, // Atheros + {MAC_LENGTH, {0x00, 0x1c, 0x23, 0x38, 0x49, 0xa4}}, // Broadcom + {MAC_LENGTH, {0x00, 0x12, 0x3f, 0x82, 0x7c, 0x32}}, // Broadcom + {MAC_LENGTH, {0x00, 0x11, 0x11, 0x32, 0xc3, 0x77}}, // Broadcom + {MAC_LENGTH, {0x00, 0x24, 0xd6, 0xae, 0x3e, 0x39}}, // Microsoft + {MAC_LENGTH, {0x00, 0x0f, 0xb0, 0x3a, 0xb4, 0x80}}, // Realtek + {MAC_LENGTH, {0x08, 0x10, 0x74, 0xa1, 0xda, 0x1b}}, // Realtek + {MAC_LENGTH, {0x00, 0x21, 0x9b, 0x2a, 0x0a, 0x9c}}, // Realtek + }; + + if (size != MAC_LENGTH) { + return false; + } + + if (static_cast<const unsigned char*>(bytes)[0] & 0x02) { + // Locally administered. + return false; + } + + for (size_t i = 0; i < arraysize(invalidAddresses); ++i) { + size_t count = invalidAddresses[i].size; + if (memcmp(invalidAddresses[i].address, bytes, count) == 0) { + return false; + } + } + return true; +} + +} // namespace + +// static +void DeviceId::GetDeviceId(const std::string& extension_id, + const IdCallback& callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + CHECK(!extension_id.empty()); + + // Forward call to platform specific implementation, then compute the HMAC + // in the callback. + GetRawDeviceId(base::Bind(&GetRawDeviceIdCallback, extension_id, callback)); +} + +// static +bool DeviceId::IsValidMacAddress(const void* bytes, size_t size) { + return IsValidMacAddressImpl(bytes, size); +} + +} // namespace api +} // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id.h b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h similarity index 87% rename from chrome/browser/extensions/api/music_manager_private/device_id.h rename to chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h index 623a00b..8d82caa 100644 --- a/chrome/browser/extensions/api/music_manager_private/device_id.h +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_EXTENSIONS_API_MUSIC_MANAGER_PRIVATE_DEVICE_ID_H_ -#define CHROME_BROWSER_EXTENSIONS_API_MUSIC_MANAGER_PRIVATE_DEVICE_ID_H_ +#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MUSIC_MANAGER_PRIVATE_DEVICE_ID_H_ +#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MUSIC_MANAGER_PRIVATE_DEVICE_ID_H_ #include <stddef.h> @@ -12,7 +12,7 @@ #include "base/bind.h" #include "base/task/task_traits.h" -namespace extensions { +namespace chrome_apps { namespace api { class DeviceId { @@ -55,6 +55,6 @@ }; } // namespace api -} // namespace extensions +} // namespace chrome_apps -#endif // CHROME_BROWSER_EXTENSIONS_API_MUSIC_MANAGER_PRIVATE_DEVICE_ID_H_ +#endif // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MUSIC_MANAGER_PRIVATE_DEVICE_ID_H_
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_chromeos.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_chromeos.cc similarity index 74% rename from chrome/browser/extensions/api/music_manager_private/device_id_chromeos.cc rename to chrome/browser/apps/platform_apps/api/music_manager_private/device_id_chromeos.cc index f49e513..418e2a25 100644 --- a/chrome/browser/extensions/api/music_manager_private/device_id_chromeos.cc +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_chromeos.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/api/music_manager_private/device_id.h" +#include "chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h" #include "chromeos/cryptohome/system_salt_getter.h" -namespace extensions { +namespace chrome_apps { namespace api { // static @@ -15,4 +15,4 @@ } } // namespace api -} // namespace extensions +} // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_linux.cc similarity index 88% rename from chrome/browser/extensions/api/music_manager_private/device_id_linux.cc rename to chrome/browser/apps/platform_apps/api/music_manager_private/device_id_linux.cc index 9bcb8d3..6a0bc7e5 100644 --- a/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_linux.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/api/music_manager_private/device_id.h" +#include "chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h" #include <ifaddrs.h> #include <net/if.h> @@ -25,24 +25,24 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -namespace { +namespace chrome_apps { +namespace api { -using extensions::api::DeviceId; +namespace { typedef base::Callback<bool(const void* bytes, size_t size)> IsValidMacAddressCallback; const char kDiskByUuidDirectoryName[] = "/dev/disk/by-uuid"; const char* const kDeviceNames[] = { - "sda1", "hda1", "dm-0", "xvda1", "sda2", "hda2", "dm-1", "xvda2", + "sda1", "hda1", "dm-0", "xvda1", "sda2", "hda2", "dm-1", "xvda2", }; // Fedora 15 uses biosdevname feature where Embedded ethernet uses the // "em" prefix and PCI cards use the p[0-9]c[0-9] format based on PCI // slot and card information. const char* const kNetDeviceNamePrefixes[] = { - "eth", "em", "en", "wl", "ww", "p0", "p1", "p2", "p3", "p4", "p5", "p6", - "p7", "p8", "p9", "wlan" -}; + "eth", "em", "en", "wl", "ww", "p0", "p1", "p2", + "p3", "p4", "p5", "p6", "p7", "p8", "p9", "wlan"}; // Map from device name to disk uuid typedef std::map<base::FilePath, base::FilePath> DiskEntries; @@ -71,8 +71,7 @@ // Look for first device name matching an entry of |kDeviceNames|. std::string result; for (size_t i = 0; i < arraysize(kDeviceNames); i++) { - DiskEntries::iterator it = - disk_uuids.find(base::FilePath(kDeviceNames[i])); + DiskEntries::iterator it = disk_uuids.find(base::FilePath(kDeviceNames[i])); if (it != disk_uuids.end()) { DVLOG(1) << "Returning uuid: \"" << it->second.value() << "\" for device \"" << it->first.value() << "\""; @@ -86,10 +85,10 @@ if (result.empty() && !error_logged) { error_logged = true; LOG(ERROR) << "Could not find appropriate disk uuid."; - for (DiskEntries::iterator it = disk_uuids.begin(); - it != disk_uuids.end(); ++it) { - LOG(ERROR) << " DeviceID=" << it->first.value() << ", uuid=" - << it->second.value(); + for (DiskEntries::iterator it = disk_uuids.begin(); it != disk_uuids.end(); + ++it) { + LOG(ERROR) << " DeviceID=" << it->first.value() + << ", uuid=" << it->second.value(); } } @@ -100,10 +99,9 @@ public: explicit MacAddressProcessor( const IsValidMacAddressCallback& is_valid_mac_address) - : is_valid_mac_address_(is_valid_mac_address) { - } + : is_valid_mac_address_(is_valid_mac_address) {} - bool ProcessInterface(struct ifaddrs *ifaddr, + bool ProcessInterface(struct ifaddrs* ifaddr, const char* const prefixes[], size_t prefixes_count) { const int MAC_LENGTH = 6; @@ -190,9 +188,6 @@ } // namespace -namespace extensions { -namespace api { - // static void DeviceId::GetRawDeviceId(const IdCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -204,4 +199,4 @@ } } // namespace api -} // namespace extensions +} // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_mac.cc similarity index 84% rename from chrome/browser/extensions/api/music_manager_private/device_id_mac.cc rename to chrome/browser/apps/platform_apps/api/music_manager_private/device_id_mac.cc index 39d4cd23..2f9aebc 100644 --- a/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_mac.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/api/music_manager_private/device_id.h" +#include "chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h" #include <CoreFoundation/CoreFoundation.h> #include <DiskArbitration/DADisk.h> @@ -26,9 +26,10 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -namespace { +namespace chrome_apps { +namespace api { -using extensions::api::DeviceId; +namespace { const char kRootDirectory[] = "/"; @@ -83,8 +84,7 @@ } CFUUIDRef volume_uuid = base::mac::GetValueFromDictionary<CFUUIDRef>( - disk_description, - kDADiskDescriptionVolumeUUIDKey); + disk_description, kDADiskDescriptionVolumeUUIDKey); if (volume_uuid == NULL) { VLOG(1) << "Error getting volume UUID of disk."; return std::string(); @@ -116,18 +116,14 @@ class MacAddressProcessor { public: MacAddressProcessor(const IsValidMacAddressCallback& is_valid_mac_address) - : is_valid_mac_address_(is_valid_mac_address) { - } + : is_valid_mac_address_(is_valid_mac_address) {} bool ProcessNetworkController(io_object_t network_controller) { // Use the MAC address of the first network interface. bool keep_going = true; base::ScopedCFTypeRef<CFDataRef> mac_address_data( - static_cast<CFDataRef>( - IORegistryEntryCreateCFProperty(network_controller, - CFSTR(kIOMACAddress), - kCFAllocatorDefault, - 0))); + static_cast<CFDataRef>(IORegistryEntryCreateCFProperty( + network_controller, CFSTR(kIOMACAddress), kCFAllocatorDefault, 0))); if (!mac_address_data) return keep_going; @@ -136,18 +132,16 @@ if (!is_valid_mac_address_.Run(mac_address, mac_address_size)) return keep_going; - std::string mac_address_string = base::ToLowerASCII(base::HexEncode( - mac_address, mac_address_size)); + std::string mac_address_string = + base::ToLowerASCII(base::HexEncode(mac_address, mac_address_size)); base::ScopedCFTypeRef<CFStringRef> provider_class( - static_cast<CFStringRef>( - IORegistryEntryCreateCFProperty(network_controller, - CFSTR(kIOProviderClassKey), - kCFAllocatorDefault, - 0))); + static_cast<CFStringRef>(IORegistryEntryCreateCFProperty( + network_controller, CFSTR(kIOProviderClassKey), kCFAllocatorDefault, + 0))); if (provider_class) { if (CFStringCompare(provider_class, CFSTR("IOPCIDevice"), 0) == - kCFCompareEqualTo) { + kCFCompareEqualTo) { // MAC address from built-in network card is always best choice. found_mac_address_ = mac_address_string; keep_going = false; @@ -186,9 +180,7 @@ } io_iterator_t iterator_ref; - kr = IOServiceGetMatchingServices(master_port, - match_classes, - &iterator_ref); + kr = IOServiceGetMatchingServices(master_port, match_classes, &iterator_ref); if (kr != KERN_SUCCESS) { LOG(ERROR) << "IOServiceGetMatchingServices failed: " << kr; return ""; @@ -203,8 +195,7 @@ break; io_object_t controller_service_ref; - kr = IORegistryEntryGetParentEntry(interface_service, - kIOServicePlane, + kr = IORegistryEntryGetParentEntry(interface_service, kIOServicePlane, &controller_service_ref); if (kr != KERN_SUCCESS) { LOG(ERROR) << "IORegistryEntryGetParentEntry failed: " << kr; @@ -236,9 +227,6 @@ } // namespace -namespace extensions { -namespace api { - // static void DeviceId::GetRawDeviceId(const IdCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -250,4 +238,4 @@ } } // namespace api -} // namespace extensions +} // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_win.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_win.cc similarity index 86% rename from chrome/browser/extensions/api/music_manager_private/device_id_win.cc rename to chrome/browser/apps/platform_apps/api/music_manager_private/device_id_win.cc index 7f1497bb..2ce3693 100644 --- a/chrome/browser/extensions/api/music_manager_private/device_id_win.cc +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/device_id_win.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/api/music_manager_private/device_id.h" +#include "chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h" // Note: The order of header includes is important, as we want both pre-Vista // and post-Vista data structures to be defined, specifically @@ -33,9 +33,10 @@ #include "rlz/lib/machine_id.h" #endif -namespace { +namespace chrome_apps { +namespace api { -using extensions::api::DeviceId; +namespace { typedef base::Callback<bool(const void* bytes, size_t size)> IsValidMacAddressCallback; @@ -43,9 +44,7 @@ class MacAddressProcessor { public: MacAddressProcessor(const IsValidMacAddressCallback& is_valid_mac_address) - : is_valid_mac_address_(is_valid_mac_address), - found_index_(ULONG_MAX) { - } + : is_valid_mac_address_(is_valid_mac_address), found_index_(ULONG_MAX) {} // Iterate through the interfaces, looking for the valid MAC address with the // lowest IfIndex. @@ -53,8 +52,7 @@ if (address->IfType == IF_TYPE_TUNNEL) return; - ProcessPhysicalAddress(address->IfIndex, - address->PhysicalAddress, + ProcessPhysicalAddress(address->IfIndex, address->PhysicalAddress, address->PhysicalAddressLength); } @@ -64,8 +62,7 @@ return; } - ProcessPhysicalAddress(row->InterfaceIndex, - row->PhysicalAddress, + ProcessPhysicalAddress(row->InterfaceIndex, row->PhysicalAddress, row->PhysicalAddressLength); } @@ -104,14 +101,13 @@ PIP_ADAPTER_ADDRESSES adapterAddresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front()); - DWORD result = GetAdaptersAddresses(AF_UNSPEC, flags, 0, - adapterAddresses, &bufferSize); + DWORD result = + GetAdaptersAddresses(AF_UNSPEC, flags, 0, adapterAddresses, &bufferSize); if (result == ERROR_BUFFER_OVERFLOW) { buffer.resize(bufferSize); - adapterAddresses = - reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front()); - result = GetAdaptersAddresses(AF_UNSPEC, flags, 0, - adapterAddresses, &bufferSize); + adapterAddresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front()); + result = GetAdaptersAddresses(AF_UNSPEC, flags, 0, adapterAddresses, + &bufferSize); } if (result != NO_ERROR) { @@ -133,8 +129,8 @@ // This is available on Vista+ only. base::ScopedNativeLibrary library(base::FilePath(L"Iphlpapi.dll")); - typedef DWORD (NETIOAPI_API_ *GetIfTablePtr)(PMIB_IF_TABLE2*); - typedef void (NETIOAPI_API_ *FreeMibTablePtr)(PMIB_IF_TABLE2); + typedef DWORD(NETIOAPI_API_ * GetIfTablePtr)(PMIB_IF_TABLE2*); + typedef void(NETIOAPI_API_ * FreeMibTablePtr)(PMIB_IF_TABLE2); GetIfTablePtr getIfTable = reinterpret_cast<GetIfTablePtr>( library.GetFunctionPointer("GetIfTable2")); @@ -145,7 +141,7 @@ return ""; } - PMIB_IF_TABLE2 ifTable = NULL; + PMIB_IF_TABLE2 ifTable = NULL; DWORD result = getIfTable(&ifTable); if (result != NO_ERROR || ifTable == NULL) { VLOG(ERROR) << "GetIfTable failed with error " << result; @@ -208,9 +204,6 @@ } // namespace -namespace extensions { -namespace api { - // static void DeviceId::GetRawDeviceId(const IdCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -222,4 +215,4 @@ } } // namespace api -} // namespace extensions +} // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.cc similarity index 65% rename from chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc rename to chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.cc index 08d2bca..9e050c2 100644 --- a/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.cc
@@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/api/music_manager_private/music_manager_private_api.h" +#include "chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h" #include <memory> -#include "chrome/browser/extensions/api/music_manager_private/device_id.h" +#include "base/bind.h" +#include "base/values.h" +#include "chrome/browser/apps/platform_apps/api/music_manager_private/device_id.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; @@ -15,28 +17,24 @@ const char kDeviceIdNotSupported[] = "Device ID API is not supported on this platform."; - } -namespace extensions { +namespace chrome_apps { namespace api { MusicManagerPrivateGetDeviceIdFunction:: - MusicManagerPrivateGetDeviceIdFunction() { -} + MusicManagerPrivateGetDeviceIdFunction() {} MusicManagerPrivateGetDeviceIdFunction:: - ~MusicManagerPrivateGetDeviceIdFunction() { -} + ~MusicManagerPrivateGetDeviceIdFunction() {} ExtensionFunction::ResponseAction MusicManagerPrivateGetDeviceIdFunction::Run() { DCHECK_CURRENTLY_ON(BrowserThread::UI); DeviceId::GetDeviceId( - this->extension_id(), - base::Bind( - &MusicManagerPrivateGetDeviceIdFunction::DeviceIdCallback, - this)); + extension_id(), + base::Bind(&MusicManagerPrivateGetDeviceIdFunction::DeviceIdCallback, + this)); // GetDeviceId will respond asynchronously. return RespondLater(); } @@ -51,5 +49,5 @@ } } -} // namespace api -} // namespace extensions +} // namespace api +} // namespace chrome_apps
diff --git a/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.h b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h similarity index 65% rename from chrome/browser/extensions/api/music_manager_private/music_manager_private_api.h rename to chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h index 0e61f0d2..a726b00 100644 --- a/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.h +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_api.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_EXTENSIONS_API_MUSIC_MANAGER_PRIVATE_MUSIC_MANAGER_PRIVATE_API_H_ -#define CHROME_BROWSER_EXTENSIONS_API_MUSIC_MANAGER_PRIVATE_MUSIC_MANAGER_PRIVATE_API_H_ +#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MUSIC_MANAGER_PRIVATE_MUSIC_MANAGER_PRIVATE_API_H_ +#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MUSIC_MANAGER_PRIVATE_MUSIC_MANAGER_PRIVATE_API_H_ #include "extensions/browser/extension_function.h" -namespace extensions { +namespace chrome_apps { namespace api { class MusicManagerPrivateGetDeviceIdFunction @@ -27,7 +27,7 @@ void DeviceIdCallback(const std::string& device_id); }; -} // namespace api -} // namespace extensions +} // namespace api +} // namespace chrome_apps -#endif // CHROME_BROWSER_EXTENSIONS_API_MUSIC_MANAGER_PRIVATE_MUSIC_MANAGER_PRIVATE_API_H_ +#endif // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MUSIC_MANAGER_PRIVATE_MUSIC_MANAGER_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_browsertest.cc similarity index 86% rename from chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc rename to chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_browsertest.cc index bd3cf0f..9382c7c1 100644 --- a/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc +++ b/chrome/browser/apps/platform_apps/api/music_manager_private/music_manager_private_browsertest.cc
@@ -10,13 +10,12 @@ // Supported on all platforms, but on Windows only if RLZ is enabled. #if !defined(OS_WIN) || BUILDFLAG(ENABLE_RLZ) -class MusicManagerPrivateTest : public extensions::PlatformAppBrowserTest { -}; +using MusicManagerPrivateTest = extensions::PlatformAppBrowserTest; IN_PROC_BROWSER_TEST_F(MusicManagerPrivateTest, DeviceIdValueReturned) { ASSERT_TRUE(RunPlatformAppTest( "platform_apps/music_manager_private/device_id_value_returned")) - << message_; + << message_; } #endif
diff --git a/chrome/browser/background_fetch/background_fetch_browsertest.cc b/chrome/browser/background_fetch/background_fetch_browsertest.cc index 270b052..8f7bc11a 100644 --- a/chrome/browser/background_fetch/background_fetch_browsertest.cc +++ b/chrome/browser/background_fetch/background_fetch_browsertest.cc
@@ -144,6 +144,12 @@ finished_processing_item_callback_ = std::move(callback); } + void set_delegate(BackgroundFetchDelegateImpl* delegate) { + delegate_ = delegate; + } + + void PauseOnNextUpdate() { pause_ = true; } + // OfflineContentProvider::Observer implementation: void OnItemsAdded( const OfflineContentProvider::OfflineItemList& items) override { @@ -155,16 +161,34 @@ void OnItemUpdated(const OfflineItem& item) override { if (item.state != offline_items_collection::OfflineItemState::IN_PROGRESS && item.state != offline_items_collection::OfflineItemState::PENDING && - finished_processing_item_callback_) + item.state != offline_items_collection::OfflineItemState::PAUSED && + finished_processing_item_callback_) { std::move(finished_processing_item_callback_).Run(item); + } + + if (pause_) { + if (item.state == offline_items_collection::OfflineItemState::PAUSED) { + Resume(item.id); + pause_ = false; + } else { + delegate_->PauseDownload(item.id); + } + } + latest_item_ = item; } const OfflineItem& latest_item() const { return latest_item_; } private: + void Resume(const ContentId& id) { + delegate_->ResumeDownload(id, false /* has_user_gesture */); + } + ItemsAddedCallback items_added_callback_; FinishedProcessingItemCallback finished_processing_item_callback_; + BackgroundFetchDelegateImpl* delegate_ = nullptr; + bool pause_ = false; OfflineItem latest_item_; @@ -206,6 +230,13 @@ ->AddObserver(offline_content_provider_observer_.get()); SetUpBrowser(browser()); + + BackgroundFetchDelegateImpl* delegate = + static_cast<BackgroundFetchDelegateImpl*>( + active_browser_->profile()->GetBackgroundFetchDelegate()); + DCHECK(delegate); + + offline_content_provider_observer_->set_delegate(delegate); } void SetUpBrowser(Browser* browser) { @@ -642,6 +673,12 @@ "New Failed Title!", base::CompareCase::SENSITIVE)); } +IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest, FetchCanBePausedAndResumed) { + offline_content_provider_observer_->PauseOnNextUpdate(); + ASSERT_NO_FATAL_FAILURE(RunScriptAndCheckResultingMessage( + "RunFetchTillCompletion()", "backgroundfetchsuccess")); +} + IN_PROC_BROWSER_TEST_F(BackgroundFetchBrowserTest, FetchRejectedWithoutPermission) { RevokeDownloadPermission();
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc index c782ea68..efa22ba2 100644 --- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc +++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -73,8 +73,7 @@ std::unique_ptr<content::BackgroundFetchDescription> fetch_description, const std::string& provider_namespace, bool is_off_the_record) - : cancelled(false), - offline_item(offline_items_collection::ContentId( + : offline_item(offline_items_collection::ContentId( provider_namespace, fetch_description->job_unique_id)), fetch_description(std::move(fetch_description)) { @@ -125,6 +124,8 @@ // response was an HTTP error, e.g. 404. offline_item.state = OfflineItemState::COMPLETE; offline_item.is_openable = true; + } else if (paused) { + offline_item.state = OfflineItemState::PAUSED; } else { offline_item.state = OfflineItemState::IN_PROGRESS; } @@ -253,9 +254,6 @@ DCHECK(job_details_map_.count(job_unique_id)); DCHECK(!download_job_unique_id_map_.count(download_guid)); - JobDetails& job_details = job_details_map_.find(job_unique_id)->second; - job_details.current_download_guids.insert(download_guid); - download_job_unique_id_map_.emplace(download_guid, job_unique_id); download::DownloadParams params; @@ -269,6 +267,22 @@ params.traffic_annotation = net::MutableNetworkTrafficAnnotationTag(traffic_annotation); + JobDetails& job_details = job_details_map_.find(job_unique_id)->second; + if (job_details.paused) { + job_details.on_resume = + base::BindOnce(&BackgroundFetchDelegateImpl::StartDownload, + GetWeakPtr(), job_unique_id, params); + } else { + StartDownload(job_unique_id, params); + } +} + +void BackgroundFetchDelegateImpl::StartDownload( + const std::string& job_unique_id, + const download::DownloadParams& params) { + DCHECK(job_details_map_.count(job_unique_id)); + JobDetails& job_details = job_details_map_.find(job_unique_id)->second; + job_details.current_download_guids.insert(params.guid); GetDownloadService()->StartDownload(params); } @@ -520,12 +534,9 @@ return; JobDetails& job_details = job_details_iter->second; + job_details.paused = true; for (auto& download_guid : job_details.current_download_guids) GetDownloadService()->PauseDownload(download_guid); - - // TODO(delphick): Mark overall download job as paused so that future - // downloads are not started until resume. (Initially not a worry because only - // one download will be scheduled at a time). } void BackgroundFetchDelegateImpl::ResumeDownload( @@ -536,10 +547,12 @@ return; JobDetails& job_details = job_details_iter->second; + job_details.paused = false; for (auto& download_guid : job_details.current_download_guids) GetDownloadService()->ResumeDownload(download_guid); - // TODO(delphick): Start new downloads that weren't started because of pause. + if (job_details.on_resume) + std::move(job_details.on_resume).Run(); } void BackgroundFetchDelegateImpl::GetItemById(
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h index 9d167e6..776b723 100644 --- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h +++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
@@ -128,8 +128,8 @@ void UpdateOfflineItem(); - bool cancelled; - bool failed; + bool cancelled = false; + bool paused = false; // Set of DownloadService GUIDs that are currently downloading. They are // added by DownloadUrl and are removed when the download completes, fails @@ -139,6 +139,8 @@ offline_items_collection::OfflineItem offline_item; std::unique_ptr<content::BackgroundFetchDescription> fetch_description; + base::OnceClosure on_resume; + private: // Whether we should report progress of the job in terms of size of // downloads or in terms of the number of files being downloaded. @@ -147,6 +149,10 @@ DISALLOW_COPY_AND_ASSIGN(JobDetails); }; + // Starts a download according to |params| belonging to |job_unique_id|. + void StartDownload(const std::string& job_unique_id, + const download::DownloadParams& params); + // Updates the OfflineItem that controls the contents of download // notifications and notifies any OfflineContentProvider::Observer that was // registered with this instance.
diff --git a/chrome/browser/background_fetch/background_fetch_download_client.cc b/chrome/browser/background_fetch/background_fetch_download_client.cc index 3d095d38..40f1d9c 100644 --- a/chrome/browser/background_fetch/background_fetch_download_client.cc +++ b/chrome/browser/background_fetch/background_fetch_download_client.cc
@@ -31,7 +31,7 @@ case download::Client::FailureReason::TIMEDOUT: return BackgroundFetchFailureReason::TIMEDOUT; case download::Client::FailureReason::UNKNOWN: - return BackgroundFetchFailureReason::UNKNOWN; + return BackgroundFetchFailureReason::FETCH_ERROR; case download::Client::FailureReason::ABORTED: case download::Client::FailureReason::CANCELLED: return BackgroundFetchFailureReason::CANCELLED;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 0451655..92039b7 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2564,18 +2564,18 @@ "blocklist_additions"); } -net::URLRequestContext* -ChromeContentBrowserClient::OverrideRequestContextForURL( - const GURL& url, content::ResourceContext* context) { +net::CookieStore* ChromeContentBrowserClient::OverrideCookieStoreForURL( + const GURL& url, + content::ResourceContext* context) { DCHECK_CURRENTLY_ON(BrowserThread::IO); #if BUILDFLAG(ENABLE_EXTENSIONS) if (url.SchemeIs(extensions::kExtensionScheme)) { ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); - return io_data->extensions_request_context(); + return io_data->GetExtensionsCookieStore(); } #endif - return NULL; + return nullptr; } scoped_refptr<network::SharedURLLoaderFactory> @@ -4531,7 +4531,7 @@ content::BrowserContext* browser_context, content::RenderFrameHost* frame, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request, bool* bypass_redirect_checks) { DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); @@ -4555,7 +4555,7 @@ #endif use_proxy |= signin::ProxyingURLLoaderFactory::MaybeProxyRequest( - frame, is_navigation, url, factory_request); + frame, is_navigation, request_initiator, factory_request); return use_proxy; }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index b3d1b5f..66d96ca 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -246,7 +246,7 @@ const url::Origin& requesting_origin, const url::Origin& embedding_origin) override; std::string GetWebBluetoothBlocklist() override; - net::URLRequestContext* OverrideRequestContextForURL( + net::CookieStore* OverrideCookieStoreForURL( const GURL& url, content::ResourceContext* context) override; scoped_refptr<network::SharedURLLoaderFactory> @@ -438,7 +438,7 @@ content::BrowserContext* browser_context, content::RenderFrameHost* frame, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request, bool* bypass_redirect_checks) override; std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
diff --git a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc index 759cc56..e60ee34 100644 --- a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc +++ b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc
@@ -32,11 +32,6 @@ // Should be a no-op on ARC. This is managed on the Android side. } -void ArcPictureInPictureWindowControllerImpl::ClickCustomControl( - const std::string& control_id) { - // Should be a no-op on ARC. This is managed on the Android side. -} - void ArcPictureInPictureWindowControllerImpl::SetPictureInPictureCustomControls( const std::vector<blink::PictureInPictureControlInfo>& info) { // Should be a no-op on ARC. This is managed on the Android side. @@ -80,6 +75,11 @@ return false; } +void ArcPictureInPictureWindowControllerImpl::CustomControlPressed( + const std::string& control_id) { + // Should be a no-op on ARC. This is managed on the Android side. +} + void ArcPictureInPictureWindowControllerImpl::SetAlwaysHidePlayPauseButton( bool is_visible) { // Should be a no-op on ARC. This is managed on the Android side.
diff --git a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h index c6316356..40fefe03 100644 --- a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h +++ b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h
@@ -36,7 +36,6 @@ gfx::Size Show() override; void Close(bool should_pause_video) override; void OnWindowDestroyed() override; - void ClickCustomControl(const std::string& control_id) override; void SetPictureInPictureCustomControls( const std::vector<blink::PictureInPictureControlInfo>& info) override; void EmbedSurface(const viz::SurfaceId& surface_id, @@ -46,6 +45,7 @@ bool IsPlayerActive() override; content::WebContents* GetInitiatorWebContents() override; bool TogglePlayPause() override; + void CustomControlPressed(const std::string& control_id) override; void UpdatePlaybackState(bool is_playing, bool reached_end_of_stream) override; void SetAlwaysHidePlayPauseButton(bool is_visible) override;
diff --git a/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.cc b/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.cc index 920e2d4..e9e3531 100644 --- a/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.cc +++ b/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.cc
@@ -94,6 +94,12 @@ status_uploader_->ScheduleNextStatusUploadImmediately(); } +base::TimeDelta ConsumerStatusReportingService::GetChildScreenTime() const { + return const_cast<policy::DeviceStatusCollector*>( + status_uploader_->device_status_collector()) + ->GetActiveChildScreenTime(); +} + void ConsumerStatusReportingService::OnTimeLimitsPolicyChanged() { CreateStatusUploaderIfNeeded(user_cloud_policy_manager_->core()->client()); }
diff --git a/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h b/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h index 431c5cd3..0fed1d12 100644 --- a/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h +++ b/chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h
@@ -36,6 +36,9 @@ ~ConsumerStatusReportingService() override; void RequestImmediateStatusReport(); + // Get the child's usage time so far today. + base::TimeDelta GetChildScreenTime() const; + private: // Creates new status uploader if parameters changed. void CreateStatusUploaderIfNeeded(policy::CloudPolicyClient* client);
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc index 3c35b09..6732f6b 100644 --- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc +++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
@@ -32,8 +32,6 @@ base::TimeDelta::FromMinutes(5); constexpr base::TimeDelta kExitNotificationTimeout = base::TimeDelta::FromMinutes(1); -constexpr base::TimeDelta kScreenTimeUsageUpdateFrequency = - base::TimeDelta::FromMinutes(1); // The notification id. All the time limit notifications share the same id so // that a subsequent notification can replace the previous one. @@ -57,9 +55,6 @@ // static void ScreenTimeController::RegisterProfilePrefs(PrefRegistrySimple* registry) { - registry->RegisterTimePref(prefs::kCurrentScreenStartTime, base::Time()); - registry->RegisterTimePref(prefs::kFirstScreenStartTime, base::Time()); - registry->RegisterIntegerPref(prefs::kScreenTimeMinutesUsed, 0); registry->RegisterDictionaryPref(prefs::kUsageTimeLimit); registry->RegisterDictionaryPref(prefs::kScreenTimeLastState); } @@ -79,18 +74,11 @@ ScreenTimeController::~ScreenTimeController() { session_manager::SessionManager::Get()->RemoveObserver(this); system::TimezoneSettings::GetInstance()->RemoveObserver(this); - SaveScreenTimeProgressBeforeExit(); } -base::TimeDelta ScreenTimeController::GetScreenTimeDuration() const { - base::TimeDelta previous_duration = base::TimeDelta::FromMinutes( - pref_service_->GetInteger(prefs::kScreenTimeMinutesUsed)); - if (current_screen_start_time_.is_null()) - return previous_duration; - - base::TimeDelta current_screen_duration = - base::Time::Now() - current_screen_start_time_; - return current_screen_duration + previous_duration; +base::TimeDelta ScreenTimeController::GetScreenTimeDuration() { + return ConsumerStatusReportingServiceFactory::GetForBrowserContext(context_) + ->GetChildScreenTime(); } void ScreenTimeController::CheckTimeLimit(const std::string& source) { @@ -107,27 +95,8 @@ const base::DictionaryValue* time_limit = pref_service_->GetDictionary(prefs::kUsageTimeLimit); - // Refresh the screen time usage when needed. - // |first_screen_start_time_| is retrieved from prefs::kFirstScreenStartTime - // which stores the timestamp of last screen time reset. - base::TimeDelta used_time = GetScreenTimeDuration(); - base::Time reset_time = usage_time_limit::GetExpectedResetTime( - time_limit->CreateDeepCopy(), now, &time_zone); - if (reset_time - first_screen_start_time_ >= base::TimeDelta::FromDays(1)) { - VLOG(1) << "Reset screen time now."; - RefreshScreenLimit(); - used_time = base::TimeDelta::FromMinutes(0); - } else { - VLOG(1) << "Scheduling screen reset timer in " << reset_time - now; - reset_screen_time_timer_.Start( - FROM_HERE, reset_time - now, - base::BindRepeating(&ScreenTimeController::CheckTimeLimit, - base::Unretained(this), - "reset_screen_time_timer_")); - } - usage_time_limit::State state = usage_time_limit::GetState( - time_limit->CreateDeepCopy(), used_time, first_screen_start_time_, now, + time_limit->CreateDeepCopy(), GetScreenTimeDuration(), now, now, &time_zone, last_state); SaveCurrentStateToPref(state); @@ -180,11 +149,15 @@ } } - if (!state.next_state_change_time.is_null()) { + base::Time next_get_state_time = + std::min(state.next_state_change_time, + usage_time_limit::GetExpectedResetTime( + time_limit->CreateDeepCopy(), now, &time_zone)); + if (!next_get_state_time.is_null()) { VLOG(1) << "Scheduling state change timer in " << state.next_state_change_time - now; next_state_timer_.Start( - FROM_HERE, state.next_state_change_time - now, + FROM_HERE, next_get_state_time - now, base::BindRepeating(&ScreenTimeController::CheckTimeLimit, base::Unretained(this), "next_state_timer_")); } @@ -243,17 +216,6 @@ ->Display(NotificationHandler::Type::TRANSIENT, *notification); } -void ScreenTimeController::RefreshScreenLimit() { - base::Time now = base::Time::Now(); - pref_service_->SetTime(prefs::kFirstScreenStartTime, now); - pref_service_->SetTime(prefs::kCurrentScreenStartTime, now); - pref_service_->SetInteger(prefs::kScreenTimeMinutesUsed, 0); - pref_service_->CommitPendingWrite(); - - first_screen_start_time_ = now; - current_screen_start_time_ = now; -} - void ScreenTimeController::OnPolicyChanged() { CheckTimeLimit("OnPolicyChanged"); } @@ -261,33 +223,12 @@ void ScreenTimeController::ResetStateTimers() { VLOG(1) << "Stopping state timers"; next_state_timer_.Stop(); - reset_screen_time_timer_.Stop(); } void ScreenTimeController::ResetInSessionTimers() { VLOG(1) << "Stopping in-session timers"; warning_notification_timer_.Stop(); exit_notification_timer_.Stop(); - save_screen_time_timer_.Stop(); -} - -void ScreenTimeController::SaveScreenTimeProgressBeforeExit() { - VLOG(1) << "Saving screen time progress before exiting"; - pref_service_->SetInteger(prefs::kScreenTimeMinutesUsed, - GetScreenTimeDuration().InMinutes()); - pref_service_->ClearPref(prefs::kCurrentScreenStartTime); - pref_service_->CommitPendingWrite(); - current_screen_start_time_ = base::Time(); - ResetInSessionTimers(); -} - -void ScreenTimeController::SaveScreenTimeProgressPeriodically() { - pref_service_->SetInteger(prefs::kScreenTimeMinutesUsed, - GetScreenTimeDuration().InMinutes()); - current_screen_start_time_ = base::Time::Now(); - pref_service_->SetTime(prefs::kCurrentScreenStartTime, - current_screen_start_time_); - pref_service_->CommitPendingWrite(); } void ScreenTimeController::SaveCurrentStateToPref( @@ -416,40 +357,9 @@ UpdateTimeLimitsMessage(true /*visible*/, next_unlock_time_.value()); next_unlock_time_.reset(); } - SaveScreenTimeProgressBeforeExit(); + ResetInSessionTimers(); } else if (session_state == session_manager::SessionState::ACTIVE) { - base::Time now = base::Time::Now(); - const base::Time first_screen_start_time = - pref_service_->GetTime(prefs::kFirstScreenStartTime); - if (first_screen_start_time.is_null()) { - pref_service_->SetTime(prefs::kFirstScreenStartTime, now); - first_screen_start_time_ = now; - } else { - first_screen_start_time_ = first_screen_start_time; - } - - const base::Time current_screen_start_time = - pref_service_->GetTime(prefs::kCurrentScreenStartTime); - if (!current_screen_start_time.is_null() && - current_screen_start_time < now && - (now - current_screen_start_time) < - 2 * kScreenTimeUsageUpdateFrequency) { - current_screen_start_time_ = current_screen_start_time; - } else { - // If kCurrentScreenStartTime is not set or it's been too long since the - // last update, set the time to now. - current_screen_start_time_ = now; - } - pref_service_->SetTime(prefs::kCurrentScreenStartTime, - current_screen_start_time_); - pref_service_->CommitPendingWrite(); CheckTimeLimit("OnSessionStateChanged"); - - save_screen_time_timer_.Start( - FROM_HERE, kScreenTimeUsageUpdateFrequency, - base::BindRepeating( - &ScreenTimeController::SaveScreenTimeProgressPeriodically, - base::Unretained(this))); } }
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.h b/chrome/browser/chromeos/child_accounts/screen_time_controller.h index 40285a1e..cea35890 100644 --- a/chrome/browser/chromeos/child_accounts/screen_time_controller.h +++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.h
@@ -35,9 +35,9 @@ explicit ScreenTimeController(content::BrowserContext* context); ~ScreenTimeController() override; - // Returns the screen time duration. This includes time in - // kScreenTimeMinutesUsed plus time passed since |current_screen_start_time_|. - base::TimeDelta GetScreenTimeDuration() const; + // Returns the child's screen time duration. This is how long the child has + // used the device today (since the last reset). + base::TimeDelta GetScreenTimeDuration(); private: // The types of time limit notifications. |SCREEN_TIME| is used when the @@ -66,9 +66,6 @@ void ShowNotification(ScreenTimeController::TimeLimitNotificationType type, const base::TimeDelta& time_remaining); - // Reset time tracking relevant prefs and local timestamps. - void RefreshScreenLimit(); - // Called when the policy of time limits changes. void OnPolicyChanged(); @@ -76,14 +73,6 @@ void ResetStateTimers(); void ResetInSessionTimers(); - // Save the screen time progress when screen is locked, or user sign out or - // power down the device. - void SaveScreenTimeProgressBeforeExit(); - - // Save the screen time progress periodically in case of a crash or power - // outage. - void SaveScreenTimeProgressPeriodically(); - // Save the |state| to |prefs::kScreenTimeLastState|. void SaveCurrentStateToPref(const usage_time_limit::State& state); @@ -104,26 +93,11 @@ base::OneShotTimer warning_notification_timer_; base::OneShotTimer exit_notification_timer_; - // Called to record the current amount of time spent in-session. - base::RepeatingTimer save_screen_time_timer_; - // Timers that are called when lock screen state change event happens, ie, // bedtime is over or the usage limit ends. base::OneShotTimer next_state_timer_; base::OneShotTimer reset_screen_time_timer_; - // Timestamp to keep track of the screen start time for the current active - // screen. This timestamp is periodically updated by - // SaveScreenTimeProgressPeriodically(), and is cleared when user exits the - // active screen(lock, sign out, shutdown). - base::Time current_screen_start_time_; - - // Timestamp to keep track of the screen start time when user starts using - // the device for the first time of the day. - // Used to calculate the screen time limit and this will be refreshed by - // RefreshScreenLimit(); - base::Time first_screen_start_time_; - PrefChangeRegistrar pref_change_registrar_; // Used to update the time limits message, if any, when screen is locked.
diff --git a/chrome/browser/chromeos/extensions/autotest_private/DEPS b/chrome/browser/chromeos/extensions/autotest_private/DEPS index 53fd62a1..1043b3e 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/DEPS +++ b/chrome/browser/chromeos/extensions/autotest_private/DEPS
@@ -1,3 +1,10 @@ include_rules = [ "+chrome/browser/ui/views/crostini", ] + +specific_include_rules = { + "autotest_private_api\.cc": [ + # TODO(mash): Remove the line below, http://crbug.com/557397 + "+ash/shell.h", + ] +}
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index 189fb40..7211d982 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -34,6 +34,8 @@ #if defined(OS_CHROMEOS) #include "ash/public/interfaces/ash_message_center_controller.mojom.h" #include "ash/public/interfaces/constants.mojom.h" +#include "ash/shell.h" +#include "base/base64.h" #include "base/feature_list.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" @@ -842,6 +844,47 @@ } #endif +AutotestPrivateTakeScreenshotFunction:: + ~AutotestPrivateTakeScreenshotFunction() = default; + +ExtensionFunction::ResponseAction AutotestPrivateTakeScreenshotFunction::Run() { + DVLOG(1) << "AutotestPrivateTakeScreenshotFunction"; +#if defined(OS_CHROMEOS) + auto grabber = std::make_unique<ui::ScreenshotGrabber>(); + // TODO(mash): Fix for mash, http://crbug.com/557397 + aura::Window* primary_root = ash::Shell::GetPrimaryRootWindow(); + // Pass the ScreenshotGrabber to the callback so that it stays alive for the + // duration of the operation, it'll then get deallocated when the callback + // completes. + grabber->TakeScreenshot( + primary_root, primary_root->bounds(), + base::BindOnce(&AutotestPrivateTakeScreenshotFunction::ScreenshotTaken, + this, base::Passed(&grabber))); + return RespondLater(); +#else + return RespondNow(Error(kOnlyAvailableOnChromeOSError)); +#endif +} + +#if defined(OS_CHROMEOS) +void AutotestPrivateTakeScreenshotFunction::ScreenshotTaken( + std::unique_ptr<ui::ScreenshotGrabber> grabber, + ui::ScreenshotResult screenshot_result, + scoped_refptr<base::RefCountedMemory> png_data) { + if (screenshot_result == ui::ScreenshotResult::SUCCESS) { + // Base64 encode the result so we can return it as a string. + std::string base64Png(png_data->front(), + png_data->front() + png_data->size()); + base::Base64Encode(base64Png, &base64Png); + Respond(OneArgument(std::make_unique<base::Value>(base64Png))); + } else { + Respond(Error(base::StrCat( + {"Error taking screenshot ", + base::NumberToString(static_cast<int>(screenshot_result))}))); + } +} +#endif + AutotestPrivateBootstrapMachineLearningServiceFunction:: ~AutotestPrivateBootstrapMachineLearningServiceFunction() = default;
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h index 11f38f5..f2acf42d 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -16,6 +16,7 @@ #include "ash/public/interfaces/ash_message_center_controller.mojom.h" #include "chrome/browser/chromeos/printing/cups_printers_manager.h" #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h" +#include "ui/snapshot/screenshot_grabber.h" #endif namespace message_center { @@ -310,6 +311,23 @@ DISALLOW_COPY_AND_ASSIGN(AutotestPrivateRunCrostiniUninstallerFunction); }; +class AutotestPrivateTakeScreenshotFunction : public UIThreadExtensionFunction { + public: + AutotestPrivateTakeScreenshotFunction() = default; + DECLARE_EXTENSION_FUNCTION("autotestPrivate.takeScreenshot", + AUTOTESTPRIVATE_TAKESCREENSHOT) + + private: + ~AutotestPrivateTakeScreenshotFunction() override; + ResponseAction Run() override; +#if defined(OS_CHROMEOS) + void ScreenshotTaken(std::unique_ptr<ui::ScreenshotGrabber> grabber, + ui::ScreenshotResult screenshot_result, + scoped_refptr<base::RefCountedMemory> png_data); +#endif + DISALLOW_COPY_AND_ASSIGN(AutotestPrivateTakeScreenshotFunction); +}; + class AutotestPrivateGetPrinterListFunction : public UIThreadExtensionFunction { public: AutotestPrivateGetPrinterListFunction() = default;
diff --git a/chrome/browser/chromeos/policy/app_install_event_log_uploader.h b/chrome/browser/chromeos/policy/app_install_event_log_uploader.h index 813ac541e..b84edf2 100644 --- a/chrome/browser/chromeos/policy/app_install_event_log_uploader.h +++ b/chrome/browser/chromeos/policy/app_install_event_log_uploader.h
@@ -80,7 +80,6 @@ // request when the client registers, by asking the delegate to serialize logs // and with the exponential backoff reset to its minimum. void OnRegistrationStateChanged(CloudPolicyClient* client) override; - void OnRobotAuthCodesFetched(CloudPolicyClient* client) override {} void OnClientError(CloudPolicyClient* client) override {} private:
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc index 4eb20f05..80fc32d3 100644 --- a/chrome/browser/chromeos/policy/device_status_collector.cc +++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -459,7 +459,8 @@ // represents the distance from midnight. ActivityStorage(PrefService* pref_service, const std::string& pref_name, - TimeDelta activity_day_start); + TimeDelta activity_day_start, + bool is_enterprise_reporting); ~ActivityStorage(); // Adds an activity period. Accepts empty |active_user_email| if it should not @@ -501,6 +502,7 @@ void ProcessActivityPeriods(const base::DictionaryValue& activity_times, const std::vector<std::string>& reporting_users, base::DictionaryValue* const filtered_times); + void StoreChildScreenTime(Time activity_day_start, TimeDelta activity); // Determine the day key (milliseconds since epoch for corresponding // |day_start_| in UTC) for a given |timestamp|. @@ -513,16 +515,21 @@ // from midnight. const TimeDelta day_start_; + // Whether reporting is for enterprise or consumer. + bool is_enterprise_reporting_ = false; + DISALLOW_COPY_AND_ASSIGN(ActivityStorage); }; DeviceStatusCollector::ActivityStorage::ActivityStorage( PrefService* pref_service, const std::string& pref_name, - TimeDelta activity_day_start) + TimeDelta activity_day_start, + bool is_enterprise_reporting) : pref_service_(pref_service), pref_name_(pref_name), - day_start_(activity_day_start) { + day_start_(activity_day_start), + is_enterprise_reporting_(is_enterprise_reporting) { DCHECK(pref_service_); const PrefService::PrefInitializationStatus pref_service_status = pref_service_->GetInitializationStatus(); @@ -554,6 +561,15 @@ int previous_activity = 0; activity_times->GetInteger(key, &previous_activity); activity_times->SetInteger(key, previous_activity + activity); + + // If the user is a child, the child screen time pref may need to be + // updated. + if (user_manager::UserManager::Get()->IsLoggedInAsChildUser() && + !is_enterprise_reporting_) { + StoreChildScreenTime(day_start - TimeDelta::FromDays(1), + TimeDelta::FromMilliseconds(activity)); + } + start = day_start; } } @@ -705,6 +721,35 @@ return out_time.ToJavaTime(); } +void DeviceStatusCollector::ActivityStorage::StoreChildScreenTime( + Time activity_day_start, + TimeDelta activity) { + DCHECK(user_manager::UserManager::Get()->IsLoggedInAsChildUser() && + !is_enterprise_reporting_); + + // Today's start time. + Time today_start = Time::Now().LocalMidnight() + day_start_; + + TimeDelta previous_activity = TimeDelta::FromMilliseconds( + pref_service_->GetInteger(prefs::kChildScreenTimeMilliseconds)); + + // Reset screen time if it has not been reset today. + if (today_start > pref_service_->GetTime(prefs::kLastChildScreenTimeReset)) { + pref_service_->SetTime(prefs::kLastChildScreenTimeReset, Time::Now()); + pref_service_->SetInteger(prefs::kChildScreenTimeMilliseconds, 0); + previous_activity = TimeDelta::FromSeconds(0); + } + + // If this activity window belongs to the current day, the screen time pref + // should be updated. + if (activity_day_start >= today_start) { + pref_service_->SetInteger(prefs::kChildScreenTimeMilliseconds, + (previous_activity + activity).InMilliseconds()); + pref_service_->SetTime(prefs::kLastChildScreenTimeSaved, Time::Now()); + } + pref_service_->CommitPendingWrite(); +} + DeviceStatusCollector::DeviceStatusCollector( PrefService* pref_service, chromeos::system::StatisticsProvider* provider, @@ -822,7 +867,7 @@ pref_service_, (is_enterprise_reporting_ ? prefs::kDeviceActivityTimes : prefs::kUserActivityTimes), - activity_day_start); + activity_day_start, is_enterprise_reporting_); } DeviceStatusCollector::~DeviceStatusCollector() { @@ -841,6 +886,18 @@ registry->RegisterBooleanPref(prefs::kReportArcStatusEnabled, false); registry->RegisterDictionaryPref(prefs::kUserActivityTimes, std::make_unique<base::DictionaryValue>()); + registry->RegisterTimePref(prefs::kLastChildScreenTimeReset, Time()); + registry->RegisterTimePref(prefs::kLastChildScreenTimeSaved, Time()); + registry->RegisterIntegerPref(prefs::kChildScreenTimeMilliseconds, 0); +} + +TimeDelta DeviceStatusCollector::GetActiveChildScreenTime() { + if (!user_manager::UserManager::Get()->IsLoggedInAsChildUser()) + return TimeDelta::FromSeconds(0); + + UpdateChildUsageTime(); + return TimeDelta::FromMilliseconds( + pref_service_->GetInteger(prefs::kChildScreenTimeMilliseconds)); } void DeviceStatusCollector::CheckIdleState() { @@ -929,7 +986,7 @@ void DeviceStatusCollector::IdleStateCallback(ui::IdleState state) { // Do nothing if device activity reporting is disabled or if it's a child // account. Usage time for child accounts are calculated differently. - if (!report_activity_times_ || + if (!report_activity_times_ || !is_enterprise_reporting_ || user_manager::UserManager::Get()->IsLoggedInAsChildUser()) { return; } @@ -1147,8 +1204,9 @@ bool DeviceStatusCollector::GetActivityTimes( em::DeviceStatusReportRequest* status) { - if (user_manager::UserManager::Get()->IsLoggedInAsChildUser()) + if (user_manager::UserManager::Get()->IsLoggedInAsChildUser()) { UpdateChildUsageTime(); + } // If user reporting is off, data should be aggregated per day. // Signed-in user is reported in non-enterprise reporting.
diff --git a/chrome/browser/chromeos/policy/device_status_collector.h b/chrome/browser/chromeos/policy/device_status_collector.h index ff72d58..8f1ae47 100644 --- a/chrome/browser/chromeos/policy/device_status_collector.h +++ b/chrome/browser/chromeos/policy/device_status_collector.h
@@ -139,6 +139,10 @@ // The total number of hardware resource usage samples cached internally. static const unsigned int kMaxResourceUsageSamples = 10; + // Returns the amount of time the child has used so far today. If the user is + // not a child or if there is no user logged in, it returns 0. + base::TimeDelta GetActiveChildScreenTime(); + protected: // Check whether the user has been idle for a certain period of time. virtual void CheckIdleState();
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc index 5d1290e..772d2e6 100644 --- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -64,6 +64,7 @@ #include "chromeos/system/fake_statistics_provider.h" #include "components/account_id/account_id.h" #include "components/policy/proto/device_management_backend.pb.h" +#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/prefs/testing_pref_service.h" #include "components/user_manager/scoped_user_manager.h" @@ -2436,6 +2437,9 @@ ASSERT_EQ(1, device_status_.active_period_size()); EXPECT_EQ(5 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); + EXPECT_EQ( + 5 * ActivePeriodMilliseconds(), + profile_pref_service_.GetInteger(prefs::kChildScreenTimeMilliseconds)); EXPECT_EQ(user_account_id_.GetUserEmail(), device_status_.active_period(0).user_email()); } @@ -2458,6 +2462,9 @@ ASSERT_EQ(1, device_status_.active_period_size()); EXPECT_EQ(4 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); + EXPECT_EQ( + 4 * ActivePeriodMilliseconds(), + profile_pref_service_.GetInteger(prefs::kChildScreenTimeMilliseconds)); EXPECT_EQ(user_account_id_.GetUserEmail(), device_status_.active_period(0).user_email()); } @@ -2482,6 +2489,9 @@ ASSERT_EQ(1, device_status_.active_period_size()); EXPECT_EQ(5 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); + EXPECT_EQ( + 5 * ActivePeriodMilliseconds(), + profile_pref_service_.GetInteger(prefs::kChildScreenTimeMilliseconds)); EXPECT_EQ(user_account_id_.GetUserEmail(), device_status_.active_period(0).user_email()); } @@ -2519,6 +2529,9 @@ GetStatus(); EXPECT_EQ(12 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); + EXPECT_EQ( + 12 * ActivePeriodMilliseconds(), + profile_pref_service_.GetInteger(prefs::kChildScreenTimeMilliseconds)); } TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, @@ -2543,10 +2556,49 @@ EXPECT_EQ(1, device_status_.active_period_size()); EXPECT_EQ(5 * ActivePeriodMilliseconds(), GetActiveMilliseconds(device_status_)); + EXPECT_EQ( + 5 * ActivePeriodMilliseconds(), + profile_pref_service_.GetInteger(prefs::kChildScreenTimeMilliseconds)); // Nothing should be written to local state, because it is only used for // enterprise reporting. EXPECT_TRUE(local_state_.GetDictionary(prefs::kDeviceActivityTimes)->empty()); } +TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, + ActivityCrossingMidnight) { + DeviceStateTransitions test_states[] = { + DeviceStateTransitions::kEnterSessionActive, + DeviceStateTransitions::kLeaveSessionActive}; + + // Set the baseline time to 15 seconds before midnight, so the activity is + // split between two days. + status_collector_->SetBaselineTime(Time::Now().LocalMidnight() - + TimeDelta::FromSeconds(15)); + + SimulateStateChanges(test_states, + sizeof(test_states) / sizeof(DeviceStateTransitions)); + GetStatus(); + ASSERT_EQ(2, device_status_.active_period_size()); + + em::ActiveTimePeriod period0 = device_status_.active_period(0); + em::ActiveTimePeriod period1 = device_status_.active_period(1); + EXPECT_EQ(ActivePeriodMilliseconds() - 15000, period0.active_duration()); + EXPECT_EQ(15000, period1.active_duration()); + + em::TimePeriod time_period0 = period0.time_period(); + em::TimePeriod time_period1 = period1.time_period(); + + EXPECT_EQ(time_period0.end_timestamp(), time_period1.start_timestamp()); + + // Ensure that the start and end times for the period are a day apart. + EXPECT_EQ(time_period0.end_timestamp() - time_period0.start_timestamp(), + kMillisecondsPerDay); + EXPECT_EQ(time_period1.end_timestamp() - time_period1.start_timestamp(), + kMillisecondsPerDay); + EXPECT_EQ( + 0.5 * ActivePeriodMilliseconds(), + profile_pref_service_.GetInteger(prefs::kChildScreenTimeMilliseconds)); +} + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc index 07710da03..6407191 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -551,7 +551,10 @@ } else { domain_ = gaia::ExtractDomainName(gaia::CanonicalizeEmail(username)); SetStep(STEP_ROBOT_AUTH_FETCH); - client_->FetchRobotAuthCodes(dm_auth_->Clone()); + client_->FetchRobotAuthCodes( + dm_auth_->Clone(), + base::BindOnce(&EnrollmentHandlerChromeOS::OnRobotAuthCodesFetched, + weak_ptr_factory_.GetWeakPtr())); } } else { ReportResult(EnrollmentStatus::ForValidationError(validator->status())); @@ -559,11 +562,14 @@ } void EnrollmentHandlerChromeOS::OnRobotAuthCodesFetched( - CloudPolicyClient* client) { - DCHECK_EQ(client_.get(), client); + DeviceManagementStatus status, + const std::string& auth_code) { CHECK_EQ(STEP_ROBOT_AUTH_FETCH, enrollment_step_); - - if (client->robot_api_auth_code().empty()) { + if (status != DM_STATUS_SUCCESS) { + OnClientError(client_.get()); + return; + } + if (auth_code.empty()) { // If the server doesn't provide an auth code, skip the robot auth setup. // This allows clients running against the test server to transparently skip // robot auth. @@ -583,8 +589,8 @@ // Use the system request context to avoid sending user cookies. gaia_oauth_client_.reset(new gaia::GaiaOAuthClient( g_browser_process->shared_url_loader_factory())); - gaia_oauth_client_->GetTokensFromAuthCode( - client_info, client->robot_api_auth_code(), 0 /* max_retries */, this); + gaia_oauth_client_->GetTokensFromAuthCode(client_info, auth_code, + 0 /* max_retries */, this); } // GaiaOAuthClient::Delegate callback for OAuth2 refresh token fetched.
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h index a118ba93..ca92b25f 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
@@ -100,7 +100,6 @@ // CloudPolicyClient::Observer: void OnPolicyFetched(CloudPolicyClient* client) override; void OnRegistrationStateChanged(CloudPolicyClient* client) override; - void OnRobotAuthCodesFetched(CloudPolicyClient* client) override; void OnClientError(CloudPolicyClient* client) override; // CloudPolicyStore::Observer: @@ -211,6 +210,10 @@ // Handles the policy validation result for the offline demo mode. void OnOfflinePolicyValidated(DeviceCloudPolicyValidator* validator); + // Handles the fetching auth codes for robot accounts during enrollment. + void OnRobotAuthCodesFetched(DeviceManagementStatus status, + const std::string& auth_code); + std::unique_ptr<DeviceCloudPolicyValidator> CreateValidator( std::unique_ptr<enterprise_management::PolicyFetchResponse> policy, const std::string& domain);
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc index 89d3159..e96a469 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -1011,11 +1011,14 @@ break; case DeviceSettingsService::STORE_VALIDATION_ERROR: case DeviceSettingsService::STORE_INVALID_POLICY: - case DeviceSettingsService::STORE_OPERATION_FAILED: - LOG(ERROR) << "Failed to retrieve cros policies. Reason: " - << device_settings_service_->status(); + case DeviceSettingsService::STORE_OPERATION_FAILED: { + DeviceSettingsService::Status status = device_settings_service_->status(); + LOG(ERROR) << "Failed to retrieve cros policies. Reason: " << status + << " (" << DeviceSettingsService::StatusToString(status) + << ")"; trusted_status_ = PERMANENTLY_UNTRUSTED; break; + } } // Notify the observers we are done.
diff --git a/chrome/browser/chromeos/settings/device_settings_service.cc b/chrome/browser/chromeos/settings/device_settings_service.cc index 278656b..a6f9795 100644 --- a/chrome/browser/chromeos/settings/device_settings_service.cc +++ b/chrome/browser/chromeos/settings/device_settings_service.cc
@@ -66,6 +66,25 @@ return g_device_settings_service; } +// static +const char* DeviceSettingsService::StatusToString(Status status) { + switch (status) { + case STORE_SUCCESS: + return "SUCCESS"; + case STORE_KEY_UNAVAILABLE: + return "KEY_UNAVAILABLE"; + case STORE_OPERATION_FAILED: + return "OPERATION_FAILED"; + case STORE_NO_POLICY: + return "NO_POLICY"; + case STORE_INVALID_POLICY: + return "INVALID_POLICY"; + case STORE_VALIDATION_ERROR: + return "VALIDATION_ERROR"; + } + return "UNKNOWN"; +} + DeviceSettingsService::DeviceSettingsService() { device_off_hours_controller_ = std::make_unique<policy::off_hours::DeviceOffHoursController>(); @@ -311,7 +330,8 @@ device_settings_.swap(off_device_settings); } } else if (status != STORE_KEY_UNAVAILABLE) { - LOG(ERROR) << "Session manager operation failed: " << status; + LOG(ERROR) << "Session manager operation failed: " << status << " (" + << StatusToString(status) << ")"; } public_key_ = scoped_refptr<PublicKey>(operation->public_key());
diff --git a/chrome/browser/chromeos/settings/device_settings_service.h b/chrome/browser/chromeos/settings/device_settings_service.h index 9ee38b14..74d14559 100644 --- a/chrome/browser/chromeos/settings/device_settings_service.h +++ b/chrome/browser/chromeos/settings/device_settings_service.h
@@ -97,6 +97,9 @@ static void Shutdown(); static DeviceSettingsService* Get(); + // Returns a human-readable string describing |status|. + static const char* StatusToString(Status status); + // Creates a device settings service instance. This is meant for unit tests, // production code uses the singleton returned by Get() above. DeviceSettingsService();
diff --git a/chrome/browser/chromeos/settings/session_manager_operation.cc b/chrome/browser/chromeos/settings/session_manager_operation.cc index 831e5673..5532af2 100644 --- a/chrome/browser/chromeos/settings/session_manager_operation.cc +++ b/chrome/browser/chromeos/settings/session_manager_operation.cc
@@ -213,7 +213,10 @@ device_settings_ = std::move(validator->payload()); ReportResult(DeviceSettingsService::STORE_SUCCESS); } else { - LOG(ERROR) << "Policy validation failed: " << validator->status(); + LOG(ERROR) << "Policy validation failed: " << validator->status() << " (" + << policy::DeviceCloudPolicyValidator::StatusToString( + validator->status()) + << ")"; ReportResult(DeviceSettingsService::STORE_VALIDATION_ERROR); } }
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 32b520fb..8e96597 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -260,14 +260,6 @@ "api/metrics_private/chrome_metrics_private_delegate.h", "api/module/module.cc", "api/module/module.h", - "api/music_manager_private/device_id.cc", - "api/music_manager_private/device_id.h", - "api/music_manager_private/device_id_chromeos.cc", - "api/music_manager_private/device_id_linux.cc", - "api/music_manager_private/device_id_mac.cc", - "api/music_manager_private/device_id_win.cc", - "api/music_manager_private/music_manager_private_api.cc", - "api/music_manager_private/music_manager_private_api.h", "api/networking_private/networking_private_credentials_getter_chromeos.cc", "api/networking_private/networking_private_ui_delegate_chromeos.cc", "api/networking_private/networking_private_ui_delegate_chromeos.h", @@ -986,7 +978,6 @@ "updater/local_extension_cache.h", ] - sources -= [ "api/music_manager_private/device_id_linux.cc" ] if (use_dbus) { configs += [ "//build/config/linux/dbus" ] }
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id.cc b/chrome/browser/extensions/api/music_manager_private/device_id.cc deleted file mode 100644 index 08de538..0000000 --- a/chrome/browser/extensions/api/music_manager_private/device_id.cc +++ /dev/null
@@ -1,197 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/extensions/api/music_manager_private/device_id.h" - -#include <stdint.h> - -#include "base/bind.h" -#include "base/macros.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "content/public/browser/browser_thread.h" -#include "crypto/hmac.h" - -namespace { - -using extensions::api::DeviceId; - -// Compute HMAC-SHA256(|key|, |text|) as a string. -bool ComputeHmacSha256(const std::string& key, - const std::string& text, - std::string* signature_return) { - crypto::HMAC hmac(crypto::HMAC::SHA256); - const size_t digest_length = hmac.DigestLength(); - std::vector<uint8_t> digest(digest_length); - bool result = hmac.Init(key) && - hmac.Sign(text, &digest[0], digest.size()); - if (result) { - *signature_return = base::ToLowerASCII( - base::HexEncode(digest.data(), digest.size())); - } - return result; -} - -void GetRawDeviceIdCallback(const std::string& extension_id, - const DeviceId::IdCallback& callback, - const std::string& raw_device_id) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (raw_device_id.empty()) { - callback.Run(""); - return; - } - - std::string device_id; - if (!ComputeHmacSha256(raw_device_id, extension_id, &device_id)) { - DLOG(ERROR) << "Error while computing HMAC-SHA256 of device id."; - callback.Run(""); - return; - } - callback.Run(device_id); -} - -bool IsValidMacAddressImpl(const void* bytes, size_t size) { - const size_t MAC_LENGTH = 6; - const size_t OUI_LENGTH = 3; - struct InvalidMacEntry { - size_t size; - unsigned char address[MAC_LENGTH]; - }; - - // VPN, virtualization, tethering, bluetooth, etc. - static InvalidMacEntry invalidAddresses[] = { - // Empty address - {MAC_LENGTH, {0, 0, 0, 0, 0, 0}}, - // VMware - {OUI_LENGTH, {0x00, 0x50, 0x56}}, - {OUI_LENGTH, {0x00, 0x05, 0x69}}, - {OUI_LENGTH, {0x00, 0x0c, 0x29}}, - {OUI_LENGTH, {0x00, 0x1c, 0x14}}, - // VirtualBox - {OUI_LENGTH, {0x08, 0x00, 0x27}}, - // PdaNet - {MAC_LENGTH, {0x00, 0x26, 0x37, 0xbd, 0x39, 0x42}}, - // Cisco AnyConnect VPN - {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}}, - // Marvell sometimes uses this as a dummy address - {MAC_LENGTH, {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, - // Apple uses this across machines for Bluetooth ethernet adapters. - {MAC_LENGTH-1, {0x65, 0x90, 0x07, 0x42, 0xf1}}, - // Juniper uses this for their Virtual Adapter, the other 4 bytes are - // reassigned at every boot. 00-ff-xx is not assigned to anyone. - {2, {0x00, 0xff}}, - // T-Mobile Wireless Ethernet - {MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}}, - // Generic Bluetooth device - {MAC_LENGTH, {0x00, 0x15, 0x83, 0x3d, 0x0a, 0x57}}, - // RAS Async Adapter - {MAC_LENGTH, {0x20, 0x41, 0x53, 0x59, 0x4e, 0xff}}, - // Qualcomm USB ethernet adapter - {MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}}, - // Windows VPN - {MAC_LENGTH, {0x00, 0x53, 0x45, 0x00, 0x00, 0x00}}, - // Bluetooth - {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x08, 0x30}}, - {MAC_LENGTH, {0x00, 0x1b, 0x10, 0x00, 0x2a, 0xec}}, - {MAC_LENGTH, {0x00, 0x15, 0x83, 0x15, 0xa3, 0x10}}, - {MAC_LENGTH, {0x00, 0x15, 0x83, 0x07, 0xC6, 0x5A}}, - {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0x00}}, - {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0xdd}}, - // Ceton TV tuner - {MAC_LENGTH, {0x00, 0x22, 0x2c, 0xff, 0xff, 0xff}}, - // Check Point VPN - {MAC_LENGTH, {0x54, 0x55, 0x43, 0x44, 0x52, 0x09}}, - {MAC_LENGTH, {0x54, 0xEF, 0x14, 0x71, 0xE4, 0x0E}}, - {MAC_LENGTH, {0x54, 0xBA, 0xC6, 0xFF, 0x74, 0x10}}, - // Cisco VPN - {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}}, - // Cisco VPN - {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x78, 0x00}}, - // Intel USB cell modem - {MAC_LENGTH, {0x00, 0x1e, 0x10, 0x1f, 0x00, 0x01}}, - // Microsoft tethering - {MAC_LENGTH, {0x80, 0x00, 0x60, 0x0f, 0xe8, 0x00}}, - // Nortel VPN - {MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x42, 0x00}}, - // AEP VPN - {MAC_LENGTH, {0x00, 0x30, 0x70, 0x00, 0x00, 0x01}}, - // Positive VPN - {MAC_LENGTH, {0x00, 0x02, 0x03, 0x04, 0x05, 0x06}}, - // Bluetooth - {MAC_LENGTH, {0x00, 0x15, 0x83, 0x0B, 0x13, 0xC0}}, - // Kerio Virtual Network Adapter - {MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x4f, 0x53}}, - // Sierra Wireless cell modems. - {OUI_LENGTH, {0x00, 0xA0, 0xD5}}, - // FRITZ!web DSL - {MAC_LENGTH, {0x00, 0x04, 0x0E, 0xFF, 0xFF, 0xFF}}, - // VirtualPC - {MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, - // Bluetooth - {MAC_LENGTH, {0x00, 0x1F, 0x81, 0x00, 0x01, 0x00}}, - {MAC_LENGTH, {0x00, 0x30, 0x91, 0x10, 0x00, 0x26}}, - {MAC_LENGTH, {0x00, 0x25, 0x00, 0x5A, 0xC3, 0xD0}}, - {MAC_LENGTH, {0x00, 0x15, 0x83, 0x0C, 0xBF, 0xEB}}, - // Huawei cell modem - {MAC_LENGTH, {0x58, 0x2C, 0x80, 0x13, 0x92, 0x63}}, - // Fortinet VPN - {OUI_LENGTH, {0x00, 0x09, 0x0F}}, - // Realtek - {MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x30}}, - // Other rare dupes. - {MAC_LENGTH, {0x00, 0x11, 0xf5, 0x0d, 0x8a, 0xe8}}, // Atheros - {MAC_LENGTH, {0x00, 0x20, 0x07, 0x01, 0x16, 0x06}}, // Atheros - {MAC_LENGTH, {0x0d, 0x0b, 0x00, 0x00, 0xe0, 0x00}}, // Atheros - {MAC_LENGTH, {0x90, 0x4c, 0xe5, 0x0b, 0xc8, 0x8e}}, // Atheros - {MAC_LENGTH, {0x00, 0x1c, 0x23, 0x38, 0x49, 0xa4}}, // Broadcom - {MAC_LENGTH, {0x00, 0x12, 0x3f, 0x82, 0x7c, 0x32}}, // Broadcom - {MAC_LENGTH, {0x00, 0x11, 0x11, 0x32, 0xc3, 0x77}}, // Broadcom - {MAC_LENGTH, {0x00, 0x24, 0xd6, 0xae, 0x3e, 0x39}}, // Microsoft - {MAC_LENGTH, {0x00, 0x0f, 0xb0, 0x3a, 0xb4, 0x80}}, // Realtek - {MAC_LENGTH, {0x08, 0x10, 0x74, 0xa1, 0xda, 0x1b}}, // Realtek - {MAC_LENGTH, {0x00, 0x21, 0x9b, 0x2a, 0x0a, 0x9c}}, // Realtek - }; - - if (size != MAC_LENGTH) { - return false; - } - - if (static_cast<const unsigned char *>(bytes)[0] & 0x02) { - // Locally administered. - return false; - } - - for (size_t i = 0; i < arraysize(invalidAddresses); ++i) { - size_t count = invalidAddresses[i].size; - if (memcmp(invalidAddresses[i].address, bytes, count) == 0) { - return false; - } - } - return true; -} - -} // namespace - -namespace extensions { -namespace api { - -// static -void DeviceId::GetDeviceId(const std::string& extension_id, - const IdCallback& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - CHECK(!extension_id.empty()); - - // Forward call to platform specific implementation, then compute the HMAC - // in the callback. - GetRawDeviceId(base::Bind(&GetRawDeviceIdCallback, extension_id, callback)); -} - -// static -bool DeviceId::IsValidMacAddress(const void* bytes, size_t size) { - return IsValidMacAddressImpl(bytes, size); -} - -} // namespace api -} // namespace extensions
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc index 8b975a1f..892ea52 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
@@ -224,7 +224,7 @@ entry.index = base::checked_cast<int>(i); entry.num_characters_in_password = form->password_value.length(); - if (!form->federation_origin.unique()) { + if (!form->federation_origin.opaque()) { entry.federation_text.reset(new std::string(l10n_util::GetStringFUTF8( IDS_PASSWORDS_VIA_FEDERATION, base::UTF8ToUTF16(form->federation_origin.host()))));
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index cda1e33..43ced6b4 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -371,6 +371,8 @@ settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[arc::prefs::kVoiceInteractionNotificationEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[arc::prefs::kVoiceInteractionLaunchWithMicOpen] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; // Misc. (*s_whitelist)[::prefs::kUse24HourClock] =
diff --git a/chrome/browser/extensions/data_deleter.cc b/chrome/browser/extensions/data_deleter.cc index cbecc61..06aa322 100644 --- a/chrome/browser/extensions/data_deleter.cc +++ b/chrome/browser/extensions/data_deleter.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_special_storage_policy.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_io_data.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -37,10 +38,9 @@ namespace { -void ClearCookiesOnIOThread(scoped_refptr<net::URLRequestContextGetter> context, +void ClearCookiesOnIOThread(base::OnceCallback<net::CookieStore*()> getter, const GURL& origin) { - net::CookieStore* cookie_store = - context->GetURLRequestContext()->cookie_store(); + net::CookieStore* cookie_store = std::move(getter).Run(); net::CookieDeletionInfo delete_info; delete_info.host = origin.host(); cookie_store->DeleteAllMatchingInfoAsync(std::move(delete_info), @@ -76,10 +76,8 @@ // TODO(rdsmith): Mojoify this call and get rid of the thread hopping. base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, - base::BindOnce( - &ClearCookiesOnIOThread, - base::WrapRefCounted(profile->GetRequestContextForExtensions()), - origin)); + base::BindOnce(&ClearCookiesOnIOThread, + profile->GetExtensionsCookieStoreGetter(), origin)); } else { // We don't need to worry about the media request context because that // shares the same cookie store as the main request context.
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 08225a9..73308a7 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -4848,9 +4848,8 @@ std::string origin_id = storage::GetIdentifierFromOrigin(ext_url); // Set a cookie for the extension. - net::CookieStore* cookie_store = profile()->GetRequestContextForExtensions() - ->GetURLRequestContext() - ->cookie_store(); + net::CookieStore* cookie_store = + profile()->GetExtensionsCookieStoreGetter().Run(); ASSERT_TRUE(cookie_store); net::CookieOptions options; cookie_store->SetCookieWithOptionsAsync(
diff --git a/chrome/browser/media/android/cdm/media_drm_storage_factory.cc b/chrome/browser/media/android/cdm/media_drm_storage_factory.cc index fa0e074..37cfd33 100644 --- a/chrome/browser/media/android/cdm/media_drm_storage_factory.cc +++ b/chrome/browser/media/android/cdm/media_drm_storage_factory.cc
@@ -35,7 +35,7 @@ PrefService* pref_service = profile->GetPrefs(); DCHECK(pref_service) << "PrefService not available."; - if (render_frame_host->GetLastCommittedOrigin().unique()) { + if (render_frame_host->GetLastCommittedOrigin().opaque()) { DVLOG(1) << __func__ << ": Unique origin."; return; }
diff --git a/chrome/browser/media/cdm_storage_id.cc b/chrome/browser/media/cdm_storage_id.cc index 9aaf614..ebfee13 100644 --- a/chrome/browser/media/cdm_storage_id.cc +++ b/chrome/browser/media/cdm_storage_id.cc
@@ -55,7 +55,7 @@ return {}; } - if (origin.unique()) { + if (origin.opaque()) { DLOG(ERROR) << "Unexpected origin: " << origin; return {}; }
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc index 2c53c9a5..af1f0ea2 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc
@@ -68,7 +68,7 @@ const content::PresentationRequest& request2) { return request1.render_frame_host_id == request2.render_frame_host_id && request1.presentation_urls == request2.presentation_urls && - ((request1.frame_origin.unique() && request2.frame_origin.unique()) || + ((request1.frame_origin.opaque() && request2.frame_origin.opaque()) || (request1.frame_origin == request2.frame_origin)); }
diff --git a/chrome/browser/net/chrome_url_request_context_getter.cc b/chrome/browser/net/chrome_url_request_context_getter.cc index 8d44a53..eca8e53 100644 --- a/chrome/browser/net/chrome_url_request_context_getter.cc +++ b/chrome/browser/net/chrome_url_request_context_getter.cc
@@ -63,20 +63,6 @@ content::URLRequestInterceptorScopedVector request_interceptors_; }; -// Factory that creates the URLRequestContext for extensions. -class FactoryForExtensions : public ChromeURLRequestContextFactory { - public: - explicit FactoryForExtensions(const ProfileIOData* profile_io_data) - : profile_io_data_(profile_io_data) {} - - net::URLRequestContext* Create() override { - return profile_io_data_->GetExtensionsRequestContext(); - } - - private: - const ProfileIOData* const profile_io_data_; -}; - // Factory that creates the URLRequestContext for a given isolated app. class FactoryForIsolatedApp : public ChromeURLRequestContextFactory { public: @@ -254,15 +240,6 @@ // static scoped_refptr<ChromeURLRequestContextGetter> -ChromeURLRequestContextGetter::CreateForExtensions( - Profile* profile, - const ProfileIOData* profile_io_data) { - return ChromeURLRequestContextGetter::CreateAndInit( - std::make_unique<FactoryForExtensions>(profile_io_data)); -} - -// static -scoped_refptr<ChromeURLRequestContextGetter> ChromeURLRequestContextGetter::CreateForIsolatedApp( Profile* profile, const ProfileIOData* profile_io_data,
diff --git a/chrome/browser/net/chrome_url_request_context_getter.h b/chrome/browser/net/chrome_url_request_context_getter.h index a870e0dd..b17941e 100644 --- a/chrome/browser/net/chrome_url_request_context_getter.h +++ b/chrome/browser/net/chrome_url_request_context_getter.h
@@ -53,12 +53,6 @@ Profile* profile, const ProfileIOData* profile_io_data); - // Create an instance for an original profile for extensions. This is expected - // to get called on UI thread. - static scoped_refptr<ChromeURLRequestContextGetter> CreateForExtensions( - Profile* profile, - const ProfileIOData* profile_io_data); - // Create an instance for an original profile for an app with isolated // storage. This is expected to get called on UI thread. static scoped_refptr<ChromeURLRequestContextGetter> CreateForIsolatedApp(
diff --git a/chrome/browser/notifications/notification_channels_provider_android.cc b/chrome/browser/notifications/notification_channels_provider_android.cc index 76fa6c7..56710d2e 100644 --- a/chrome/browser/notifications/notification_channels_provider_android.cc +++ b/chrome/browser/notifications/notification_channels_provider_android.cc
@@ -326,7 +326,7 @@ InitCachedChannels(); url::Origin origin = url::Origin::Create(GURL(primary_pattern.ToString())); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); const std::string origin_string = origin.Serialize(); ContentSetting setting = content_settings::ValueToContentSetting(value); @@ -386,7 +386,7 @@ return base::Time(); } url::Origin origin = url::Origin::Create(GURL(primary_pattern.ToString())); - if (origin.unique()) + if (origin.opaque()) return base::Time(); const std::string origin_string = origin.Serialize(); @@ -425,7 +425,7 @@ const content_settings::Rule& rule) { url::Origin origin = url::Origin::Create(GURL(rule.primary_pattern.ToString())); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); const std::string origin_string = origin.Serialize(); ContentSetting content_setting = content_settings::ValueToContentSetting(rule.value.get());
diff --git a/chrome/browser/password_manager/credential_android.cc b/chrome/browser/password_manager/credential_android.cc index 31d730f..c5a68d0 100644 --- a/chrome/browser/password_manager/credential_android.cc +++ b/chrome/browser/password_manager/credential_android.cc
@@ -22,7 +22,7 @@ ? password_form.origin.GetOrigin().spec() : std::string(); std::string federation = - password_form.federation_origin.unique() + password_form.federation_origin.opaque() ? std::string() : l10n_util::GetStringFUTF8( IDS_PASSWORDS_VIA_FEDERATION,
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc index 1fcc156..e52bc04 100644 --- a/chrome/browser/password_manager/native_backend_gnome_x.cc +++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -321,7 +321,7 @@ "avatar_url", form.icon_url.spec().c_str(), // We serialize unique origins as "", in order to make other systems that // read from the login database happy. https://crbug.com/591310 - "federation_url", form.federation_origin.unique() + "federation_url", form.federation_origin.opaque() ? "" : form.federation_origin.Serialize().c_str(), "should_skip_zero_click", form.skip_zero_click,
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc index 22ae222..42181269 100644 --- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc +++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -476,7 +476,7 @@ // We serialize unique origins as "", in order to make other systems that // read from the login database happy. https://crbug.com/591310 CheckStringAttribute(item, "federation_url", - form.federation_origin.unique() + form.federation_origin.opaque() ? "" : form.federation_origin.Serialize()); CheckUint32Attribute(item, "should_skip_zero_click", form.skip_zero_click);
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.cc b/chrome/browser/password_manager/native_backend_kwallet_x.cc index 75ec1c8..a323b10 100644 --- a/chrome/browser/password_manager/native_backend_kwallet_x.cc +++ b/chrome/browser/password_manager/native_backend_kwallet_x.cc
@@ -274,7 +274,7 @@ pickle->WriteString(form->icon_url.spec()); // We serialize unique origins as "", in order to make other systems that // read from the login database happy. https://crbug.com/591310 - pickle->WriteString(form->federation_origin.unique() + pickle->WriteString(form->federation_origin.opaque() ? std::string() : form->federation_origin.Serialize()); pickle->WriteBool(form->skip_zero_click);
diff --git a/chrome/browser/password_manager/native_backend_libsecret.cc b/chrome/browser/password_manager/native_backend_libsecret.cc index a73e77a..3426c52e 100644 --- a/chrome/browser/password_manager/native_backend_libsecret.cc +++ b/chrome/browser/password_manager/native_backend_libsecret.cc
@@ -352,7 +352,7 @@ "avatar_url", form.icon_url.spec().c_str(), // We serialize unique origins as "", in order to make other systems that // read from the login database happy. https://crbug.com/591310 - "federation_url", form.federation_origin.unique() + "federation_url", form.federation_origin.opaque() ? "" : form.federation_origin.Serialize().c_str(), "should_skip_zero_click", form.skip_zero_click,
diff --git a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc index e8b2e05..bbd34bb5 100644 --- a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc +++ b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
@@ -420,7 +420,7 @@ // We serialize unique origins as "", in order to make other systems that // read from the login database happy. https://crbug.com/591310 CheckStringAttribute(item, "federation_url", - form.federation_origin.unique() + form.federation_origin.opaque() ? "" : form.federation_origin.Serialize()); CheckUint32Attribute(item, "should_skip_zero_click", form.skip_zero_click);
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc index 6918854..16ffbc9 100644 --- a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc +++ b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
@@ -57,7 +57,7 @@ base::string16 message; gfx::Range message_link_range = gfx::Range(); PasswordTitleType type = - form_to_save_->GetPendingCredentials().federation_origin.unique() + form_to_save_->GetPendingCredentials().federation_origin.opaque() ? PasswordTitleType::SAVE_PASSWORD : PasswordTitleType::SAVE_ACCOUNT; GetSavePasswordDialogTitleTextAndLinkRange(
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc index b770088..bc5b09a 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -56,7 +56,6 @@ MOCK_METHOD0(Show, gfx::Size()); MOCK_METHOD1(Close, void(bool)); MOCK_METHOD0(OnWindowDestroyed, void()); - MOCK_METHOD1(ClickCustomControl, void(const std::string&)); MOCK_METHOD1(SetPictureInPictureCustomControls, void(const std::vector<blink::PictureInPictureControlInfo>&)); MOCK_METHOD2(EmbedSurface, void(const viz::SurfaceId&, const gfx::Size&)); @@ -66,6 +65,7 @@ MOCK_METHOD0(GetInitiatorWebContents, content::WebContents*()); MOCK_METHOD2(UpdatePlaybackState, void(bool, bool)); MOCK_METHOD0(TogglePlayPause, bool()); + MOCK_METHOD1(CustomControlPressed, void(const std::string&)); MOCK_METHOD1(SetAlwaysHidePlayPauseButton, void(bool)); private: @@ -427,8 +427,7 @@ std::string control_id = "Test custom control ID"; base::string16 expected_title = base::ASCIIToUTF16(control_id); - static_cast<OverlayWindowViews*>(overlay_window) - ->ClickCustomControl(control_id); + window_controller()->CustomControlPressed(control_id); EXPECT_EQ(expected_title, content::TitleWatcher(active_web_contents, expected_title) @@ -466,8 +465,7 @@ base::string16 expected_title = base::ASCIIToUTF16(kControlId); - static_cast<OverlayWindowViews*>(overlay_window) - ->ClickCustomControl(kControlId); + window_controller()->CustomControlPressed(kControlId); EXPECT_EQ(expected_title, content::TitleWatcher(active_web_contents, expected_title) .WaitAndGetTitle()); @@ -507,8 +505,7 @@ base::string16 left_expected_title = base::ASCIIToUTF16(kLeftControlId); - static_cast<OverlayWindowViews*>(overlay_window) - ->ClickCustomControl(kLeftControlId); + window_controller()->CustomControlPressed(kLeftControlId); EXPECT_EQ(left_expected_title, content::TitleWatcher(active_web_contents, left_expected_title) .WaitAndGetTitle()); @@ -548,8 +545,7 @@ base::string16 right_expected_title = base::ASCIIToUTF16(kRightControlId); - static_cast<OverlayWindowViews*>(overlay_window) - ->ClickCustomControl(kRightControlId); + window_controller()->CustomControlPressed(kRightControlId); EXPECT_EQ(right_expected_title, content::TitleWatcher(active_web_contents, right_expected_title) .WaitAndGetTitle());
diff --git a/chrome/browser/plugins/plugin_info_host_impl.cc b/chrome/browser/plugins/plugin_info_host_impl.cc index a19f5d4f..989d5d0 100644 --- a/chrome/browser/plugins/plugin_info_host_impl.cc +++ b/chrome/browser/plugins/plugin_info_host_impl.cc
@@ -479,7 +479,7 @@ g_browser_process->rappor_service(); if (!rappor_service) return; - if (main_frame_origin.unique()) + if (main_frame_origin.opaque()) return; if (mime_type != content::kFlashPluginSwfMimeType &&
diff --git a/chrome/browser/policy/test/policy_testserver.py b/chrome/browser/policy/test/policy_testserver.py index 4e53926..c78440b 100644 --- a/chrome/browser/policy/test/policy_testserver.py +++ b/chrome/browser/policy/test/policy_testserver.py
@@ -53,8 +53,11 @@ "available_licenses" : { "annual": 10, "perpetual": 20 - } - + }, + "token_enrollment": { + "token": "abcd-ef01-123123123", + "username": "admin@example.com" + }, } """ @@ -391,6 +394,18 @@ return None + def CheckEnrollmentToken(self): + """Extracts the enrollment token from the request and returns it. The token + is GoogleEnrollmentToken token from an Authorization header. Returns None + if no token is present. + """ + match = re.match('GoogleEnrollmentToken auth=(\\w+)', + self.headers.getheader('Authorization', '')) + if match: + return match.group(1) + + return None + def ProcessRegister(self, msg): """Handles a register request. @@ -403,15 +418,26 @@ Returns: A tuple of HTTP status code and response data to send to the client. """ - # Check the auth token and device ID. - auth = self.CheckGoogleLogin() - if not auth: - return (403, 'No authorization') - + enrollment_token = self.CheckEnrollmentToken() policy = self.server.GetPolicies() - if ('managed_users' not in policy): - return (500, 'Error in config - no managed users') - username = self.server.ResolveUser(auth) + if enrollment_token: + if ((not policy['token_enrollment']) or + (not policy['token_enrollment']['token']) or + (not policy['token_enrollment']['username'])): + return (500, 'Error in config - no token-based enrollment') + if policy['token_enrollment']['token'] != enrollment_token: + return (403, 'Invalid enrollment token') + username = policy['token_enrollment']['username'] + else: + # Check the auth token and device ID. + auth = self.CheckGoogleLogin() + if not auth: + return (403, 'No authorization') + + if ('managed_users' not in policy): + return (500, 'Error in config - no managed users') + username = self.server.ResolveUser(auth) + if ('*' not in policy['managed_users'] and username not in policy['managed_users']): return (403, 'Unmanaged')
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc index 323c79a0..062c4fc 100644 --- a/chrome/browser/prefs/chrome_pref_service_factory.cc +++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -308,7 +308,7 @@ std::string legacy_device_id; #if defined(OS_WIN) && BUILDFLAG(ENABLE_RLZ) // This is used by - // chrome/browser/extensions/api/music_manager_private/device_id_win.cc + // chrome/browser/apps/platform_apps/api/music_manager_private/device_id_win.cc // but that API is private (http://crbug.com/276485) and other platforms are // not available synchronously. // As part of improving pref metrics on other platforms we may want to find
diff --git a/chrome/browser/printing/print_preview_message_handler.cc b/chrome/browser/printing/print_preview_message_handler.cc index bc90f2b..37b7d6d 100644 --- a/chrome/browser/printing/print_preview_message_handler.cc +++ b/chrome/browser/printing/print_preview_message_handler.cc
@@ -8,6 +8,7 @@ #include <memory> #include <utility> +#include <vector> #include "base/bind.h" #include "base/memory/read_only_shared_memory_region.h" @@ -31,6 +32,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "printing/nup_parameters.h" +#include "printing/page_setup.h" #include "printing/print_job_constants.h" #include "printing/print_settings.h" @@ -63,25 +65,6 @@ return page_number >= 0 && page_number < page_count; } -// Checks whether |printable_area| can be used to form a valid symmetrical -// printable area, so that margin_left equals margin_right, and margin_top -// equals margin_bottom. For example if -// printable_area.x() * 2 >= page_size.width(), then the -// content_width = page_size.width() - 2 * printable_area.x() would be zero or -// negative, which is invalid. -// |page_size| is the physical page size that includes margins. -bool IsValidPrintableArea(const gfx::Size& page_size, - const gfx::Rect& printable_area) { - return !printable_area.IsEmpty() && printable_area.x() >= 0 && - printable_area.y() >= 0 && - printable_area.right() <= page_size.width() && - printable_area.bottom() <= page_size.height() && - printable_area.x() * 2 < page_size.width() && - printable_area.y() * 2 < page_size.height() && - printable_area.right() * 2 > page_size.width() && - printable_area.bottom() * 2 > page_size.height(); -} - } // namespace PrintPreviewMessageHandler::PrintPreviewMessageHandler( @@ -360,7 +343,7 @@ std::vector<base::ReadOnlySharedMemoryRegion> pdf_page_regions = print_preview_ui->TakePagesForNupConvert(); - gfx::Rect printable_area = GetSymmetricalPrintableArea( + gfx::Rect printable_area = PageSetup::GetSymmetricalPrintableArea( print_preview_ui->page_size(), print_preview_ui->printable_area()); if (printable_area.IsEmpty()) return; @@ -421,7 +404,7 @@ auto* client = PdfNupConverterClient::FromWebContents(web_contents()); DCHECK(client); - gfx::Rect printable_area = GetSymmetricalPrintableArea( + gfx::Rect printable_area = PageSetup::GetSymmetricalPrintableArea( print_preview_ui->page_size(), print_preview_ui->printable_area()); if (printable_area.IsEmpty()) return; @@ -490,24 +473,4 @@ return handled; } -// static -gfx::Rect PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - const gfx::Size& page_size, - const gfx::Rect& printable_area) { - if (!IsValidPrintableArea(page_size, printable_area)) - return gfx::Rect(); - - int left_right_margin = - std::max(printable_area.x(), page_size.width() - printable_area.right()); - int top_bottom_margin = std::max( - printable_area.y(), page_size.height() - printable_area.bottom()); - int width = page_size.width() - 2 * left_right_margin; - int height = page_size.height() - 2 * top_bottom_margin; - - gfx::Rect symmetrical_printable_area = gfx::Rect(page_size); - symmetrical_printable_area.ClampToCenteredSize(gfx::Size(width, height)); - - return symmetrical_printable_area; -} - } // namespace printing
diff --git a/chrome/browser/printing/print_preview_message_handler.h b/chrome/browser/printing/print_preview_message_handler.h index cf88ffc..8e3dd31c 100644 --- a/chrome/browser/printing/print_preview_message_handler.h +++ b/chrome/browser/printing/print_preview_message_handler.h
@@ -32,7 +32,6 @@ namespace gfx { class Rect; -class Size; } namespace printing { @@ -50,11 +49,6 @@ bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) override; - // Gets a symmetrical printable area. It is defined as a static function to - // make writing unit tests easier. - static gfx::Rect GetSymmetricalPrintableArea(const gfx::Size& page_size, - const gfx::Rect& printable_area); - private: friend class content::WebContentsUserData<PrintPreviewMessageHandler>;
diff --git a/chrome/browser/printing/print_preview_message_handler_unittest.cc b/chrome/browser/printing/print_preview_message_handler_unittest.cc deleted file mode 100644 index c8401fc2..0000000 --- a/chrome/browser/printing/print_preview_message_handler_unittest.cc +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2018 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/printing/print_preview_message_handler.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace printing { - -using PrintPreviewMessageHandlerTest = testing::Test; - -TEST_F(PrintPreviewMessageHandlerTest, GetSymmetricalPrintableArea) { - gfx::Rect printable_area = - PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(0, 0, 560, 750)); - EXPECT_EQ(gfx::Rect(52, 42, 508, 708), printable_area); - - printable_area = PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(50, 60, 550, 700)); - EXPECT_EQ(gfx::Rect(50, 60, 512, 672), printable_area); - - printable_area = PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(-1, 60, 520, 700)); - EXPECT_EQ(gfx::Rect(), printable_area); - printable_area = PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(50, -1, 520, 700)); - EXPECT_EQ(gfx::Rect(), printable_area); - printable_area = PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(100, 60, 520, 700)); - EXPECT_EQ(gfx::Rect(), printable_area); - printable_area = PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(50, 100, 520, 700)); - EXPECT_EQ(gfx::Rect(), printable_area); - printable_area = PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(400, 60, 212, 700)); - EXPECT_EQ(gfx::Rect(), printable_area); - printable_area = PrintPreviewMessageHandler::GetSymmetricalPrintableArea( - gfx::Size(612, 792), gfx::Rect(40, 600, 212, 192)); - EXPECT_EQ(gfx::Rect(), printable_area); -} - -} // namespace printing
diff --git a/chrome/browser/profiles/gaia_info_update_service.cc b/chrome/browser/profiles/gaia_info_update_service.cc index cb9fb5cd..368e124 100644 --- a/chrome/browser/profiles/gaia_info_update_service.cc +++ b/chrome/browser/profiles/gaia_info_update_service.cc
@@ -43,6 +43,12 @@ IdentityManagerFactory::GetForProfile(profile_); identity_manager->AddObserver(this); + if (!identity_manager->HasPrimaryAccount()) { + // Handle the case when the primary account was cleared while loading the + // profile, before the |GAIAInfoUpdateService| is created. + OnUsernameChanged(std::string()); + } + PrefService* prefs = profile_->GetPrefs(); last_updated_ = base::Time::FromInternalValue( prefs->GetInt64(prefs::kProfileGAIAInfoUpdateTime));
diff --git a/chrome/browser/profiles/gaia_info_update_service_unittest.cc b/chrome/browser/profiles/gaia_info_update_service_unittest.cc index 667a504..da425fe 100644 --- a/chrome/browser/profiles/gaia_info_update_service_unittest.cc +++ b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
@@ -70,9 +70,28 @@ }; // TODO(anthonyvd) : remove ProfileInfoCacheTest from the test fixture. -class GAIAInfoUpdateServiceTest : public ProfileInfoCacheTest { +class GAIAInfoUpdateServiceTestBase : public ProfileInfoCacheTest { protected: - GAIAInfoUpdateServiceTest() : profile_(NULL) { + explicit GAIAInfoUpdateServiceTestBase(bool create_gaia_info_service_on_setup) + : create_gaia_info_service_on_setup_(create_gaia_info_service_on_setup) {} + ~GAIAInfoUpdateServiceTestBase() override = default; + + void SetUp() override { + ProfileInfoCacheTest::SetUp(); + if (create_gaia_info_service_on_setup_) { + service_.reset(new NiceMock<GAIAInfoUpdateServiceMock>(profile())); + downloader_.reset(new NiceMock<ProfileDownloaderMock>(service())); + } + }; + + void TearDown() override { + if (downloader_) + downloader_.reset(); + if (service_) { + service_->Shutdown(); + service_.reset(); + } + ProfileInfoCacheTest::TearDown(); } Profile* profile() { @@ -157,27 +176,36 @@ EXPECT_EQ(given_name, entry->GetGAIAGivenName()); } - private: - void SetUp() override; - void TearDown() override; - - Profile* profile_; + const bool create_gaia_info_service_on_setup_; + Profile* profile_ = nullptr; std::unique_ptr<NiceMock<GAIAInfoUpdateServiceMock>> service_; std::unique_ptr<NiceMock<ProfileDownloaderMock>> downloader_; + + private: + DISALLOW_COPY_AND_ASSIGN(GAIAInfoUpdateServiceTestBase); }; -void GAIAInfoUpdateServiceTest::SetUp() { - ProfileInfoCacheTest::SetUp(); - service_.reset(new NiceMock<GAIAInfoUpdateServiceMock>(profile())); - downloader_.reset(new NiceMock<ProfileDownloaderMock>(service())); -} +class GAIAInfoUpdateServiceTest : public GAIAInfoUpdateServiceTestBase { + public: + GAIAInfoUpdateServiceTest() + : GAIAInfoUpdateServiceTestBase( + /*create_gaia_info_service_on_setup_=*/true) {} + ~GAIAInfoUpdateServiceTest() override = default; -void GAIAInfoUpdateServiceTest::TearDown() { - downloader_.reset(); - service_->Shutdown(); - service_.reset(); - ProfileInfoCacheTest::TearDown(); -} + private: + DISALLOW_COPY_AND_ASSIGN(GAIAInfoUpdateServiceTest); +}; + +class GAIAInfoUpdateServiceMiscTest : public GAIAInfoUpdateServiceTestBase { + public: + GAIAInfoUpdateServiceMiscTest() + : GAIAInfoUpdateServiceTestBase( + /*create_gaia_info_service_on_setup_=*/false) {} + ~GAIAInfoUpdateServiceMiscTest() override = default; + + private: + DISALLOW_COPY_AND_ASSIGN(GAIAInfoUpdateServiceMiscTest); +}; } // namespace @@ -363,4 +391,23 @@ EXPECT_EQ(kLocalAvatarIndex, entry->GetAvatarIconIndex()); } +TEST_F(GAIAInfoUpdateServiceMiscTest, ClearGaiaInfoOnStartup) { + // Simulate a state where the profile entry has GAIA related information + // when there is not primary account set. + EXPECT_FALSE( + IdentityManagerFactory::GetForProfile(profile())->HasPrimaryAccount()); + ASSERT_EQ(1u, storage()->GetNumberOfProfiles()); + ProfileAttributesEntry* entry = storage()->GetAllProfilesAttributes().front(); + entry->SetGAIAName(base::UTF8ToUTF16("foo")); + entry->SetGAIAGivenName(base::UTF8ToUTF16("Pat Foo")); + gfx::Image gaia_picture = gfx::test::CreateImage(256, 256); + entry->SetGAIAPicture(&gaia_picture); + + // Verify that creating the GAIAInfoUpdateService resets the GAIA related + // profile attributes if the profile no longer has a primary account. + service_.reset(new NiceMock<GAIAInfoUpdateServiceMock>(profile())); + EXPECT_TRUE(entry->GetGAIAName().empty()); + EXPECT_TRUE(entry->GetGAIAGivenName().empty()); + EXPECT_FALSE(entry->GetGAIAPicture()); +} #endif
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index 193b8cf0..901dcbe 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -393,9 +393,14 @@ return GetDefaultStoragePartition(this)->GetURLRequestContext(); } -net::URLRequestContextGetter* - OffTheRecordProfileImpl::GetRequestContextForExtensions() { - return io_data_->GetExtensionsRequestContextGetter().get(); +base::OnceCallback<net::CookieStore*()> +OffTheRecordProfileImpl::GetExtensionsCookieStoreGetter() { + return base::BindOnce( + [](content::ResourceContext* context) { + auto* io_data = ProfileIOData::FromResourceContext(context); + return io_data->GetExtensionsCookieStore(); + }, + GetResourceContext()); } scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h index 77f24ffa..c8faf0c 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.h +++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -56,7 +56,8 @@ const PrefService* GetPrefs() const override; PrefService* GetOffTheRecordPrefs() override; net::URLRequestContextGetter* GetRequestContext() override; - net::URLRequestContextGetter* GetRequestContextForExtensions() override; + base::OnceCallback<net::CookieStore*()> GetExtensionsCookieStoreGetter() + override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; net::URLRequestContextGetter* CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers,
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc index fe5fee3..de26825 100644 --- a/chrome/browser/profiles/off_the_record_profile_io_data.cc +++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc
@@ -105,17 +105,6 @@ } scoped_refptr<ChromeURLRequestContextGetter> -OffTheRecordProfileIOData::Handle::GetExtensionsRequestContextGetter() const { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - LazyInitialize(); - if (!extensions_request_context_getter_.get()) { - extensions_request_context_getter_ = - ChromeURLRequestContextGetter::CreateForExtensions(profile_, io_data_); - } - return extensions_request_context_getter_; -} - -scoped_refptr<ChromeURLRequestContextGetter> OffTheRecordProfileIOData::Handle::GetIsolatedAppRequestContextGetter( const base::FilePath& partition_path, bool in_memory) const { @@ -205,9 +194,6 @@ for (; iter != app_request_context_getter_map_.end(); ++iter) context_getters->push_back(iter->second); - if (extensions_request_context_getter_.get()) - context_getters->push_back(extensions_request_context_getter_); - if (main_request_context_getter_.get()) context_getters->push_back(main_request_context_getter_); @@ -241,22 +227,17 @@ void OffTheRecordProfileIOData::OnMainRequestContextCreated( ProfileParams* profile_params) const { #if BUILDFLAG(ENABLE_EXTENSIONS) - InitializeExtensionsRequestContext(profile_params); + InitializeExtensionsCookieStore(profile_params); #endif } -void OffTheRecordProfileIOData:: - InitializeExtensionsRequestContext(ProfileParams* profile_params) const { - // All we care about for extensions is the cookie store. For incognito, we - // use a non-persistent cookie store. - net::URLRequestContext* extensions_context = extensions_request_context(); - +void OffTheRecordProfileIOData::InitializeExtensionsCookieStore( + ProfileParams* profile_params) const { content::CookieStoreConfig cookie_config; // Enable cookies for chrome-extension URLs. cookie_config.cookieable_schemes.push_back(extensions::kExtensionScheme); extensions_cookie_store_ = content::CreateCookieStore( cookie_config, profile_params->io_thread->net_log()); - extensions_context->set_cookie_store(extensions_cookie_store_.get()); } net::URLRequestContext* @@ -281,3 +262,7 @@ NOTREACHED(); return NULL; } + +net::CookieStore* OffTheRecordProfileIOData::GetExtensionsCookieStore() const { + return extensions_cookie_store_.get(); +}
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.h b/chrome/browser/profiles/off_the_record_profile_io_data.h index 8b915d0..6c86ef5 100644 --- a/chrome/browser/profiles/off_the_record_profile_io_data.h +++ b/chrome/browser/profiles/off_the_record_profile_io_data.h
@@ -53,8 +53,6 @@ content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) const; scoped_refptr<ChromeURLRequestContextGetter> - GetExtensionsRequestContextGetter() const; - scoped_refptr<ChromeURLRequestContextGetter> GetIsolatedAppRequestContextGetter( const base::FilePath& partition_path, bool in_memory) const; @@ -88,8 +86,6 @@ // ProfileIOData instance is deleted. mutable scoped_refptr<ChromeURLRequestContextGetter> main_request_context_getter_; - mutable scoped_refptr<ChromeURLRequestContextGetter> - extensions_request_context_getter_; mutable ChromeURLRequestContextGetterMap app_request_context_getter_map_; OffTheRecordProfileIOData* const io_data_; @@ -112,7 +108,7 @@ request_interceptors) const override; void OnMainRequestContextCreated( ProfileParams* profile_params) const override; - void InitializeExtensionsRequestContext( + void InitializeExtensionsCookieStore( ProfileParams* profile_params) const override; net::URLRequestContext* InitializeMediaRequestContext( net::URLRequestContext* original_context, @@ -122,6 +118,7 @@ net::URLRequestContext* AcquireIsolatedMediaRequestContext( net::URLRequestContext* app_context, const StoragePartitionDescriptor& partition_descriptor) const override; + net::CookieStore* GetExtensionsCookieStore() const override; mutable std::unique_ptr<net::CookieStore> extensions_cookie_store_;
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index 6309ea2..e52b848 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h
@@ -197,9 +197,10 @@ // Returns the main request context. virtual net::URLRequestContextGetter* GetRequestContext() = 0; - // Returns the request context used for extension-related requests. This - // is only used for a separate cookie store currently. - virtual net::URLRequestContextGetter* GetRequestContextForExtensions() = 0; + // Returns a callback (which must be executed on the IO thread) that returns + // the cookie store for the chrome-extensions:// scheme. + virtual base::OnceCallback<net::CookieStore*()> + GetExtensionsCookieStoreGetter() = 0; // Returns the main URLLoaderFactory. virtual scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 0dd40e7..5012debc 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -1068,8 +1068,14 @@ return GetDefaultStoragePartition(this)->GetURLRequestContext(); } -net::URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() { - return io_data_.GetExtensionsRequestContextGetter().get(); +base::OnceCallback<net::CookieStore*()> +ProfileImpl::GetExtensionsCookieStoreGetter() { + return base::BindOnce( + [](content::ResourceContext* context) { + auto* io_data = ProfileIOData::FromResourceContext(context); + return io_data->GetExtensionsCookieStore(); + }, + GetResourceContext()); } scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index a016448..b7cbdf1 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h
@@ -133,7 +133,8 @@ PrefService* GetOffTheRecordPrefs() override; PrefService* GetReadOnlyOffTheRecordPrefs() override; net::URLRequestContextGetter* GetRequestContext() override; - net::URLRequestContextGetter* GetRequestContextForExtensions() override; + base::OnceCallback<net::CookieStore*()> GetExtensionsCookieStoreGetter() + override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; bool IsSameProfile(Profile* profile) override; base::Time GetStartTime() const override;
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 8bad0ec..3bd55049 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -269,17 +269,6 @@ } scoped_refptr<ChromeURLRequestContextGetter> -ProfileImplIOData::Handle::GetExtensionsRequestContextGetter() const { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - LazyInitialize(); - if (!extensions_request_context_getter_.get()) { - extensions_request_context_getter_ = - ChromeURLRequestContextGetter::CreateForExtensions(profile_, io_data_); - } - return extensions_request_context_getter_; -} - -scoped_refptr<ChromeURLRequestContextGetter> ProfileImplIOData::Handle::CreateIsolatedAppRequestContextGetter( const base::FilePath& partition_path, bool in_memory, @@ -396,9 +385,6 @@ for (; iter != app_request_context_getter_map_.end(); ++iter) context_getters->push_back(iter->second); - if (extensions_request_context_getter_.get()) - context_getters->push_back(extensions_request_context_getter_); - if (media_request_context_getter_.get()) context_getters->push_back(media_request_context_getter_); @@ -481,7 +467,7 @@ DCHECK(lazy_params_); #if BUILDFLAG(ENABLE_EXTENSIONS) - InitializeExtensionsRequestContext(profile_params); + InitializeExtensionsCookieStore(profile_params); #endif MaybeDeleteMediaCache(lazy_params_->media_cache_path); @@ -494,12 +480,8 @@ lazy_params_.reset(); } -void ProfileImplIOData:: - InitializeExtensionsRequestContext(ProfileParams* profile_params) const { - // The extensions context only serves to hold onto the extensions cookie - // store. - net::URLRequestContext* extensions_context = extensions_request_context(); - +void ProfileImplIOData::InitializeExtensionsCookieStore( + ProfileParams* profile_params) const { content::CookieStoreConfig cookie_config( lazy_params_->extensions_cookie_path, lazy_params_->restore_old_session_cookies, @@ -507,10 +489,8 @@ cookie_config.crypto_delegate = cookie_config::GetCookieCryptoDelegate(); // Enable cookies for chrome-extension URLs. cookie_config.cookieable_schemes.push_back(extensions::kExtensionScheme); - cookie_config.channel_id_service = extensions_context->channel_id_service(); extensions_cookie_store_ = content::CreateCookieStore( cookie_config, profile_params->io_thread->net_log()); - extensions_context->set_cookie_store(extensions_cookie_store_.get()); } net::URLRequestContext* ProfileImplIOData::InitializeMediaRequestContext( @@ -579,3 +559,7 @@ DCHECK(media_request_context); return media_request_context; } + +net::CookieStore* ProfileImplIOData::GetExtensionsCookieStore() const { + return extensions_cookie_store_.get(); +}
diff --git a/chrome/browser/profiles/profile_impl_io_data.h b/chrome/browser/profiles/profile_impl_io_data.h index 0f6ab9b..fb9fdfbb 100644 --- a/chrome/browser/profiles/profile_impl_io_data.h +++ b/chrome/browser/profiles/profile_impl_io_data.h
@@ -73,8 +73,6 @@ scoped_refptr<ChromeURLRequestContextGetter> GetMediaRequestContextGetter() const; scoped_refptr<ChromeURLRequestContextGetter> - GetExtensionsRequestContextGetter() const; - scoped_refptr<ChromeURLRequestContextGetter> GetIsolatedMediaRequestContextGetter( const base::FilePath& partition_path, bool in_memory) const; @@ -103,8 +101,6 @@ main_request_context_getter_; mutable scoped_refptr<ChromeURLRequestContextGetter> media_request_context_getter_; - mutable scoped_refptr<ChromeURLRequestContextGetter> - extensions_request_context_getter_; mutable ChromeURLRequestContextGetterMap app_request_context_getter_map_; mutable ChromeURLRequestContextGetterMap isolated_media_request_context_getter_map_; @@ -149,7 +145,7 @@ request_interceptors) const override; void OnMainRequestContextCreated( ProfileParams* profile_params) const override; - void InitializeExtensionsRequestContext( + void InitializeExtensionsCookieStore( ProfileParams* profile_params) const override; net::URLRequestContext* InitializeMediaRequestContext( net::URLRequestContext* original_context, @@ -159,6 +155,7 @@ net::URLRequestContext* AcquireIsolatedMediaRequestContext( net::URLRequestContext* app_context, const StoragePartitionDescriptor& partition_descriptor) const override; + net::CookieStore* GetExtensionsCookieStore() const override; // Returns a net::ReportingService, if reporting should be enabled. Otherwise, // returns nullptr.
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 11fe1a0..e9104165 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -632,11 +632,6 @@ if (domain_reliability_monitor_unowned_) domain_reliability_monitor_unowned_->Shutdown(); - // TODO(ajwong): These AssertNoURLRequests() calls are unnecessary since they - // are already done in the URLRequestContext destructor. - if (extensions_request_context_) - extensions_request_context_->AssertNoURLRequests(); - current_context = 0; for (URLRequestContextMap::iterator it = isolated_media_request_context_map_.begin(); @@ -749,11 +744,6 @@ return context; } -net::URLRequestContext* ProfileIOData::GetExtensionsRequestContext() const { - DCHECK(initialized_); - return extensions_request_context_.get(); -} - net::URLRequestContext* ProfileIOData::GetIsolatedAppRequestContext( IOThread* io_thread, net::URLRequestContext* main_context, @@ -967,10 +957,6 @@ account_consistency_ = profile_params_->account_consistency; - // Create extension request context. Only used for cookies. - extensions_request_context_.reset(new net::URLRequestContext()); - extensions_request_context_->set_name("extensions"); - // Take ownership over these parameters. cookie_settings_ = profile_params_->cookie_settings; host_content_settings_map_ = profile_params_->host_content_settings_map;
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 8a7b8a2..2a89b541 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -137,7 +137,7 @@ net::URLRequestContext* GetMainRequestContext() const; net::URLRequestContext* GetMediaRequestContext() const; - net::URLRequestContext* GetExtensionsRequestContext() const; + virtual net::CookieStore* GetExtensionsCookieStore() const = 0; net::URLRequestContext* GetIsolatedAppRequestContext( IOThread* io_thread, net::URLRequestContext* main_context, @@ -167,10 +167,6 @@ bool IsSyncEnabled() const; bool SyncHasAuthError() const; - net::URLRequestContext* extensions_request_context() const { - return extensions_request_context_.get(); - } - BooleanPrefMember* safe_browsing_enabled() const { return &safe_browsing_enabled_; } @@ -501,8 +497,8 @@ virtual void OnMainRequestContextCreated( ProfileParams* profile_params) const = 0; - // Initializes the RequestContext for extensions. - virtual void InitializeExtensionsRequestContext( + // Initializes the cookie store for extensions. + virtual void InitializeExtensionsCookieStore( ProfileParams* profile_params) const = 0; // Does an on-demand initialization of a media RequestContext for the given @@ -599,7 +595,6 @@ mutable network::URLRequestContextOwner main_request_context_owner_; mutable net::URLRequestContext* main_request_context_; - mutable std::unique_ptr<net::URLRequestContext> extensions_request_context_; // One URLRequestContext per isolated app for main and media requests. mutable URLRequestContextMap app_request_context_map_; mutable URLRequestContextMap isolated_media_request_context_map_;
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc index 31daf61..8122aca 100644 --- a/chrome/browser/profiles/profiles_state.cc +++ b/chrome/browser/profiles/profiles_state.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" @@ -157,11 +158,13 @@ base::UTF16ToUTF8(new_profile_name)); } -std::vector<std::string> GetSecondaryAccountsForProfile( - Profile* profile, - const std::string& primary_account) { +std::vector<std::string> GetSecondaryAccountsForSignedInProfile( + Profile* profile) { std::vector<std::string> accounts = ProfileOAuth2TokenServiceFactory::GetForProfile(profile)->GetAccounts(); + std::string primary_account = + SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedAccountId(); + DCHECK(!primary_account.empty()); // The vector returned by ProfileOAuth2TokenService::GetAccounts() contains // the primary account too, so we need to remove it from the list.
diff --git a/chrome/browser/profiles/profiles_state.h b/chrome/browser/profiles/profiles_state.h index b0be81cb..bc66518 100644 --- a/chrome/browser/profiles/profiles_state.h +++ b/chrome/browser/profiles/profiles_state.h
@@ -69,12 +69,10 @@ void UpdateProfileName(Profile* profile, const base::string16& new_profile_name); -// Returns the list of secondary accounts for a specific |profile|, which is -// all the email addresses associated with the profile that are not equal to -// the |primary_account|. -std::vector<std::string> GetSecondaryAccountsForProfile( - Profile* profile, - const std::string& primary_account); +// Returns the list of secondary accounts for a specific +// |profile|. Note that the profile must be signed in. +std::vector<std::string> GetSecondaryAccountsForSignedInProfile( + Profile* profile); #endif // !defined(OS_CHROMEOS) // Returns whether the |browser|'s profile is a non-incognito or guest profile.
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js index c291d64..92543b7b 100644 --- a/chrome/browser/resources/print_preview/data/destination.js +++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -163,9 +163,24 @@ }; /** + * Enumeration of duplex modes used by Chromium. + * This has to coincide with |printing::DuplexModeRestriction| as defined in + * printing/backend/printing_restrictions.h + * @enum {number} + */ +print_preview.DuplexModeRestriction = { + NONE: 0x0, + SIMPLEX: 0x1, + LONG_EDGE: 0x2, + SHORT_EDGE: 0x4, + DUPLEX: 0x6 +}; + +/** * Policies affecting a destination. * @typedef {{ - * allowedColorModes: ?number, + * allowedColorModes: ?print_preview.ColorMode, + * allowedDuplexModes: ?print_preview.DuplexModeRestriction, * }} */ print_preview.Policies; @@ -780,8 +795,7 @@ } /** - * @return {?number} Color mode set by policy. Valid values are |null|, - |print_preview.ColorMode.COLOR| and |print_preview.ColorMode.GRAY|. + * @return {?print_preview.ColorMode} Color mode set by policy. * @private */ colorPolicy_() { @@ -791,6 +805,17 @@ } /** + * @return {print_preview.DuplexModeRestriction} Duplex modes allowed by + * policy. + * @private + */ + duplexPolicy_() { + return this.policies && this.policies.allowedDuplexModes ? + this.policies.allowedDuplexModes : + print_preview.DuplexModeRestriction.NONE; + } + + /** * @return {boolean} Whether the printer supports both black and white and * color printing. */ @@ -809,22 +834,35 @@ return hasColor && hasMonochrome; } - /** - * @return {boolean} Whether the printer color mode is set by policy. - */ + /** @return {boolean} Whether the printer color mode is set by policy. */ get isColorManaged() { return !!this.colorPolicy_(); } - /** - * @return {?boolean} Value for color setting set by policy. - */ + /** @return {?boolean} Value of color setting given by policy. */ get colorPolicyValue() { return this.colorPolicy_() ? this.colorPolicy_() == print_preview.ColorMode.COLOR : null; } + /** @return {boolean} Whether the printer duplex mode is set by policy. */ + get isDuplexManaged() { + return !!this.duplexPolicy_(); + } + + /** @return {?boolean} Value for duplex setting given by policy. */ + get duplexPolicyValue() { + switch (this.duplexPolicy_()) { + case print_preview.DuplexModeRestriction.NONE: + return null; + case print_preview.DuplexModeRestriction.SIMPLEX: + return false; + default: + return true; + } + } + /** * @param {boolean} isColor Whether to use a color printing mode. * @return {Object} Selected color option.
diff --git a/chrome/browser/resources/print_preview/new/model.js b/chrome/browser/resources/print_preview/new/model.js index c4a473f0..064d31b2c 100644 --- a/chrome/browser/resources/print_preview/new/model.js +++ b/chrome/browser/resources/print_preview/new/model.js
@@ -364,14 +364,18 @@ this.set('settings.collate.available', !!caps && !!(caps.collate)); this.set('settings.layout.available', this.isLayoutAvailable_(caps)); this.set('settings.color.available', this.destination.hasColorCapability); + if (this.destination.isColorManaged) { // |this.setSetting| does nothing if policy is present. // We want to set the value nevertheless so we call |this.set| directly. this.set('settings.color.value', this.destination.colorPolicyValue); } - this.set('settings.color.setByPolicy', this.destination.isColorManaged); + if (this.destination.isDuplexManaged) + this.set('settings.duplex.value', this.destination.duplexPolicyValue); + this.set('settings.duplex.setByPolicy', this.destination.isDuplexManaged); + this.set( 'settings.dpi.available', !!caps && !!caps.dpi && !!caps.dpi.option &&
diff --git a/chrome/browser/resources/print_preview/new/settings_section.html b/chrome/browser/resources/print_preview/new/settings_section.html index bd2ad8bc..90b09f8c 100644 --- a/chrome/browser/resources/print_preview/new/settings_section.html +++ b/chrome/browser/resources/print_preview/new/settings_section.html
@@ -56,7 +56,7 @@ } iron-icon { - fill: var(--google-grey-600); + fill: var(--google-grey-refresh-700); flex: 0; min-width: var(--policy-icon-size); }
diff --git a/chrome/browser/resources/settings/downloads_page/smb_shares_page.html b/chrome/browser/resources/settings/downloads_page/smb_shares_page.html index aff446c..584488a 100644 --- a/chrome/browser/resources/settings/downloads_page/smb_shares_page.html +++ b/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
@@ -18,7 +18,7 @@ <div class="settings-box first"> <div class="start"> <span>$i18n{smbSharesLearnMoreLabel}</span> - <a href="http://support.google.com" target="_blank"> + <a href="$i18n{smbSharesLearnMoreURL}" target="_blank"> $i18n{learnMore} </a> <div class="secondary" hidden="false">
diff --git a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html index e87f2d0f..6892117 100644 --- a/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html +++ b/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
@@ -36,14 +36,18 @@ label="$i18n{googleAssistantEnableHotword}" sub-label="$i18n{googleAssistantEnableHotwordDescription}"> </settings-toggle-button> - </template> - <template is="dom-if" if="[[assistantFeatureEnabled_]]"> <settings-toggle-button id="googleAssistantNotificationEnable" class="continuation indented" pref="{{prefs.settings.voice_interaction.notification.enabled}}" label="$i18n{googleAssistantEnableNotification}" sub-label="$i18n{googleAssistantEnableNotificationDescription}"> </settings-toggle-button> + <settings-toggle-button id="googleAssistantLaunchWithMicOpen" + class="continuation indented" + pref="{{prefs.settings.voice_interaction.launch_with_mic_open}}" + label="$i18n{googleAssistantLaunchWithMicOpen}" + sub-label="$i18n{googleAssistantLaunchWithMicOpenDescription}"> + </settings-toggle-button> </template> <div id="googleAssistantSettings" class="settings-box" on-click="onGoogleAssistantSettingsTapped_" actionable>
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc index 34b0f02..d16fd33 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
@@ -239,13 +239,14 @@ // static bool AdvancedProtectionStatusManager::IsUnderAdvancedProtection( Profile* profile) { - // Advanced protection is off for incognito mode. - if (profile->IsOffTheRecord()) - return false; + Profile* original_profile = + profile->IsOffTheRecord() ? profile->GetOriginalProfile() : profile; - return AdvancedProtectionStatusManagerFactory::GetInstance() - ->GetForBrowserContext(static_cast<content::BrowserContext*>(profile)) - ->is_under_advanced_protection(); + return original_profile && + AdvancedProtectionStatusManagerFactory::GetInstance() + ->GetForBrowserContext( + static_cast<content::BrowserContext*>(original_profile)) + ->is_under_advanced_protection(); } bool AdvancedProtectionStatusManager::IsPrimaryAccount(
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.h b/chrome/browser/safe_browsing/advanced_protection_status_manager.h index a5c943f5..1892245 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager.h +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
@@ -17,8 +17,10 @@ // Responsible for keeping track of advanced protection status of the sign-in // profile. -// Note that for profile that is not signed-in or is in incognito mode, we -// consider it NOT under advanced protection. +// Note that for profile that is not signed-in, we consider it NOT under +// advanced protection. +// For incognito profile Chrome returns users' advanced protection status +// of its original profile. class AdvancedProtectionStatusManager : public KeyedService, public AccountTrackerService::Observer, public SigninManagerBase::Observer {
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.cc index 10f146f..9b649fba 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.cc +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.cc
@@ -51,9 +51,4 @@ return true; } -bool AdvancedProtectionStatusManagerFactory::ServiceIsNULLWhileTesting() const { - // TODO(jialiul): Change this to 'false' when this class is wired into Chrome. - return true; -} - } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h b/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h index fe7fd2c5..3ed3aa1 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h
@@ -36,7 +36,6 @@ KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override; bool ServiceIsCreatedWithBrowserContext() const override; - bool ServiceIsNULLWhileTesting() const override; DISALLOW_COPY_AND_ASSIGN(AdvancedProtectionStatusManagerFactory); };
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc index 98d3929..ca0b7df 100644 --- a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc +++ b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
@@ -225,8 +225,8 @@ prefs::kAdvancedProtectionLastRefreshInUs, base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds()); - // Simulates the situation where user signed in long time ago, thus - // has no advanced protection status. + // Simulates the situation where the user has already signed in and is + // under advanced protection. std::string account_id = SignIn("gaia_id", "email", /* is_under_advanced_protection = */ true); AdvancedProtectionStatusManager aps_manager( @@ -241,6 +241,44 @@ aps_manager.UnsubscribeFromSigninEvents(); } +TEST_F(AdvancedProtectionStatusManagerTest, + AlreadySignedInAndUnderAPIncognito) { + testing_profile_->GetPrefs()->SetInt64( + prefs::kAdvancedProtectionLastRefreshInUs, + base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds()); + + // Simulates the situation where the user has already signed in and is + // under advanced protection. + std::string account_id = + SignIn("gaia_id", "email", /* is_under_advanced_protection = */ true); + + // Incognito profile should share the advanced protection status with the + // original profile. + EXPECT_TRUE(AdvancedProtectionStatusManager::IsUnderAdvancedProtection( + testing_profile_->GetOffTheRecordProfile())); + EXPECT_TRUE(AdvancedProtectionStatusManager::IsUnderAdvancedProtection( + testing_profile_.get())); +} + +TEST_F(AdvancedProtectionStatusManagerTest, + AlreadySignedInAndNotUnderAPIncognito) { + testing_profile_->GetPrefs()->SetInt64( + prefs::kAdvancedProtectionLastRefreshInUs, + base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds()); + + // Simulates the situation where the user has already signed in and is + // NOT under advanced protection. + std::string account_id = + SignIn("gaia_id", "email", /* is_under_advanced_protection = */ false); + + // Incognito profile should share the advanced protection status with the + // original profile. + EXPECT_FALSE(AdvancedProtectionStatusManager::IsUnderAdvancedProtection( + testing_profile_->GetOffTheRecordProfile())); + EXPECT_FALSE(AdvancedProtectionStatusManager::IsUnderAdvancedProtection( + testing_profile_.get())); +} + TEST_F(AdvancedProtectionStatusManagerTest, StayInAdvancedProtection) { base::Time last_update = base::Time::Now(); testing_profile_->GetPrefs()->SetInt64(
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service.cc index e9fdc24f1..d535dec4 100644 --- a/chrome/browser/safe_browsing/download_protection/download_protection_service.cc +++ b/chrome/browser/safe_browsing/download_protection/download_protection_service.cc
@@ -18,12 +18,11 @@ #include "chrome/browser/safe_browsing/download_protection/download_url_sb_client.h" #include "chrome/browser/safe_browsing/download_protection/ppapi_download_request.h" #include "chrome/browser/sessions/session_tab_helper.h" -#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" #include "chrome/common/url_constants.h" #include "components/google/core/common/google_util.h" #include "components/safe_browsing/common/safebrowsing_switches.h" -#include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -31,6 +30,7 @@ #include "content/public/browser/web_contents.h" #include "net/base/url_util.h" #include "net/cert/x509_util.h" +#include "services/identity/public/cpp/identity_manager.h" #include "services/network/public/cpp/shared_url_loader_factory.h" using content::BrowserThread; @@ -493,11 +493,11 @@ void DownloadProtectionService::OnDangerousDownloadOpened( const download::DownloadItem* item, Profile* profile) { - const SigninManagerBase* signin_manager = - SigninManagerFactory::GetForProfileIfExists(profile); - std::string username = - signin_manager ? signin_manager->GetAuthenticatedAccountInfo().email - : std::string(); + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfileIfExists(profile); + std::string username = identity_manager + ? identity_manager->GetPrimaryAccountInfo().email + : std::string(); std::string raw_digest_sha256 = item->GetHash(); extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc index a985d93..d6215cc 100644 --- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc +++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
@@ -442,7 +442,7 @@ bool ProxyingURLLoaderFactory::MaybeProxyRequest( content::RenderFrameHost* render_frame_host, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -452,7 +452,8 @@ // This proxy should only be installed for subresource requests from a frame // that is rendering the GAIA signon realm. - if (!render_frame_host || !gaia::IsGaiaSignonRealm(url.GetOrigin())) { + if (!render_frame_host || + !gaia::IsGaiaSignonRealm(request_initiator.GetURL())) { return false; }
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h index 9dd6228..6d0028f 100644 --- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h +++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h
@@ -50,7 +50,7 @@ static bool MaybeProxyRequest( content::RenderFrameHost* render_frame_host, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request); // network::mojom::URLLoaderFactory:
diff --git a/chrome/browser/site_details.cc b/chrome/browser/site_details.cc index e4dafde..69bb8bd 100644 --- a/chrome/browser/site_details.cc +++ b/chrome/browser/site_details.cc
@@ -151,7 +151,7 @@ url::Origin origin = frame->GetLastCommittedOrigin(); GURL site = SiteInstance::GetSiteForURL( context, - origin.unique() ? frame->GetLastCommittedURL() : origin.GetURL()); + origin.opaque() ? frame->GetLastCommittedURL() : origin.GetURL()); bool should_isolate = ShouldIsolate(context, scenario, site);
diff --git a/chrome/browser/subresource_filter/subresource_filter_special_subframe_navigations_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_special_subframe_navigations_browsertest.cc index 677ac1b..d33a061 100644 --- a/chrome/browser/subresource_filter/subresource_filter_special_subframe_navigations_browsertest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_special_subframe_navigations_browsertest.cc
@@ -83,7 +83,7 @@ return rfh->GetLastCommittedURL().scheme_piece() == url::kDataScheme; })); ASSERT_NE(target, nullptr); - EXPECT_TRUE(target->GetLastCommittedOrigin().unique()); + EXPECT_TRUE(target->GetLastCommittedOrigin().opaque()); EXPECT_FALSE(WasParsedScriptElementLoaded(target)); }
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc index 8eec3f3..7d8cdab3 100644 --- a/chrome/browser/task_manager/task_manager_browsertest.cc +++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -677,7 +677,13 @@ ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchTab("title1.html"))); } -IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, SentDataObserved) { +#if defined(MEMORY_SANITIZER) +// This tests times out when MSan is enabled. See https://crbug.com/890313. +#define MAYBE_SentDataObserved DISABLED_SentDataObserved +#else +#define MAYBE_SentDataObserved SentDataObserved +#endif +IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, MAYBE_SentDataObserved) { ShowTaskManager(); GURL test_gurl = embedded_test_server()->GetURL("/title1.html"); @@ -709,7 +715,13 @@ model()->GetColumnValue(ColumnSpecifier::TOTAL_NETWORK_USE, 0)); } -IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, TotalSentDataObserved) { +#if defined(MEMORY_SANITIZER) +// This tests times out when MSan is enabled. See https://crbug.com/890313. +#define MAYBE_TotalSentDataObserved DISABLED_TotalSentDataObserved +#else +#define MAYBE_TotalSentDataObserved TotalSentDataObserved +#endif +IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, MAYBE_TotalSentDataObserved) { ShowTaskManager(); GURL test_gurl = embedded_test_server()->GetURL("/title1.html");
diff --git a/chrome/browser/ui/android/bluetooth_chooser_android.cc b/chrome/browser/ui/android/bluetooth_chooser_android.cc index 0c567a81..0bf18ee 100644 --- a/chrome/browser/ui/android/bluetooth_chooser_android.cc +++ b/chrome/browser/ui/android/bluetooth_chooser_android.cc
@@ -29,7 +29,7 @@ : web_contents_(content::WebContents::FromRenderFrameHost(frame)), event_handler_(event_handler) { const url::Origin origin = frame->GetLastCommittedOrigin(); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); base::android::ScopedJavaLocalRef<jobject> window_android = web_contents_->GetNativeView()->GetWindowAndroid()->GetJavaObject();
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc b/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc index 5e8c231..0411c72 100644 --- a/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc +++ b/chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ui/app_list/crostini/crostini_app_icon_loader.h" -#include "ash/public/cpp/app_list/app_list_config.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -36,9 +35,8 @@ if (icon_map_.find(app_id) != icon_map_.end()) return; - std::unique_ptr<CrostiniAppIcon> icon = std::make_unique<CrostiniAppIcon>( - profile(), app_id, - app_list::AppListConfig::instance().grid_icon_dimension(), this); + std::unique_ptr<CrostiniAppIcon> icon = + std::make_unique<CrostiniAppIcon>(profile(), app_id, icon_size(), this); icon->image_skia().EnsureRepsForSupportedScales(); icon_map_[app_id] = std::move(icon); UpdateImage(app_id);
diff --git a/chrome/browser/ui/app_list/test/fake_profile.cc b/chrome/browser/ui/app_list/test/fake_profile.cc index 97ef0aa..d662941 100644 --- a/chrome/browser/ui/app_list/test/fake_profile.cc +++ b/chrome/browser/ui/app_list/test/fake_profile.cc
@@ -160,8 +160,9 @@ return nullptr; } -net::URLRequestContextGetter* FakeProfile::GetRequestContextForExtensions() { - return nullptr; +base::OnceCallback<net::CookieStore*()> +FakeProfile::GetExtensionsCookieStoreGetter() { + return base::BindOnce([]() -> net::CookieStore* { return nullptr; }); } bool FakeProfile::IsSameProfile(Profile* profile) {
diff --git a/chrome/browser/ui/app_list/test/fake_profile.h b/chrome/browser/ui/app_list/test/fake_profile.h index 97e5e65..40f5bb60 100644 --- a/chrome/browser/ui/app_list/test/fake_profile.h +++ b/chrome/browser/ui/app_list/test/fake_profile.h
@@ -76,7 +76,8 @@ const PrefService* GetPrefs() const override; PrefService* GetOffTheRecordPrefs() override; net::URLRequestContextGetter* GetRequestContext() override; - net::URLRequestContextGetter* GetRequestContextForExtensions() override; + base::OnceCallback<net::CookieStore*()> GetExtensionsCookieStoreGetter() + override; bool IsSameProfile(Profile* profile) override; base::Time GetStartTime() const override; base::FilePath last_selected_directory() override;
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc index d4937b7639..2f02ced1 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
@@ -547,6 +547,10 @@ case BubbleType::INACTIVE: NOTREACHED(); } + + if (observer_for_testing_) { + observer_for_testing_->OnBubbleShown(); + } } void SaveCardBubbleControllerImpl::UpdateIcon() {
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h index 8eb14300..cd77a61d 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h
@@ -30,6 +30,13 @@ public content::WebContentsObserver, public content::WebContentsUserData<SaveCardBubbleControllerImpl> { public: + // An observer class used by browsertests that gets notified whenever + // particular actions occur. + class ObserverForTest { + public: + virtual void OnBubbleShown() = 0; + }; + ~SaveCardBubbleControllerImpl() override; // Sets up the controller for local save and shows the bubble. @@ -121,6 +128,7 @@ private: friend class content::WebContentsUserData<SaveCardBubbleControllerImpl>; + friend class SaveCardBubbleViewsBrowserTestBase; void FetchAccountInfo(); @@ -131,6 +139,11 @@ void OpenUrl(const GURL& url); + // For testing. + void SetEventObserverForTesting(ObserverForTest* observer) { + observer_for_testing_ = observer; + } + // The web_contents associated with this controller. content::WebContents* web_contents_; @@ -184,6 +197,9 @@ // The security level for the current context. security_state::SecurityLevel security_level_; + // Observer for when a bubble is created. Initialized only during tests. + ObserverForTest* observer_for_testing_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleControllerImpl); };
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index d4901768..602715e 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -173,7 +173,7 @@ std::string link_destination(chrome::kChromeUIContentSettingsURL); // TODO(https://crbug.com/444047): Site Details should work with file:// urls // when this bug is fixed, so add it to the whitelist when that happens. - if (!site_origin.unique() && (url.SchemeIsHTTPOrHTTPS() || + if (!site_origin.opaque() && (url.SchemeIsHTTPOrHTTPS() || url.SchemeIs(extensions::kExtensionScheme))) { std::string origin_string = site_origin.Serialize(); url::RawCanonOutputT<char> percent_encoded_origin;
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa_views_mac.mm b/chrome/browser/ui/cocoa/browser_window_cocoa_views_mac.mm index ecfa2bbe..286231c 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa_views_mac.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa_views_mac.mm
@@ -4,13 +4,8 @@ #import "chrome/browser/ui/cocoa/browser_window_views_mac.h" -#import "chrome/browser/ui/cocoa/browser_window_controller.h" #import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h" -BrowserWindowController* BrowserWindowControllerForWindow(NSWindow* window) { - return [BrowserWindowController browserWindowControllerForWindow:window]; -} - TabWindowController* TabWindowControllerForWindow(NSWindow* window) { return [TabWindowController tabWindowControllerForWindow:window]; }
diff --git a/chrome/browser/ui/cocoa/browser_window_views_mac.h b/chrome/browser/ui/cocoa/browser_window_views_mac.h index 24c0170d..c85d389 100644 --- a/chrome/browser/ui/cocoa/browser_window_views_mac.h +++ b/chrome/browser/ui/cocoa/browser_window_views_mac.h
@@ -12,14 +12,9 @@ // visible here (or in any files that import this header). Declare a protocol // instead that describes the dependencies needed outside of Cocoa-specific // code. -@class BrowserWindowController; @class NSWindow; @class TabWindowController; -// Returns the BrowserWindowController backing a Cocoa browser window. Always -// returns nil if |window| is a views browser window. -BrowserWindowController* BrowserWindowControllerForWindow(NSWindow* window); - // Returns the TabWindowController backing a Cocoa browser window. Always // returns nil if |window| is a views browser window. TabWindowController* TabWindowControllerForWindow(NSWindow* window);
diff --git a/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm b/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm index ccb704dc..c08891c 100644 --- a/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm +++ b/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm
@@ -31,18 +31,6 @@ if (!window) return NO; - // Logic for handling Cocoa windows. - BrowserWindowController* controller = - BrowserWindowControllerForWindow(window); - if (controller) { - if ([controller respondsToSelector:@selector - (handledByExtensionCommand:priority:)]) { - if ([controller handledByExtensionCommand:event priority:priority]) - return YES; - } - return NO; - } - // Logic for handling Views windows. // // There are 3 ways for extensions to register accelerators in Views:
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm index 0a449de..33bc698 100644 --- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm +++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm
@@ -5,7 +5,7 @@ #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "ui/views/cocoa/bridged_native_widget.h" +#include "ui/views_bridge_mac/bridged_native_widget_impl.h" @implementation FullscreenToolbarControllerViews
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm index 63a214e3..7066deb 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm
@@ -21,7 +21,7 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "testing/gtest_mac.h" -#include "ui/views/cocoa/window_touch_bar_delegate.h" +#include "ui/views_bridge_mac/window_touch_bar_delegate.h" // TODO(spqchan): Write tests that will check for page load and bookmark // updates.
diff --git a/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.cc b/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.cc index cab95dc1..2a630a3c 100644 --- a/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.cc +++ b/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.cc
@@ -7,8 +7,6 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/desktop_ios_promotion/sms_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "components/signin/core/browser/profile_oauth2_token_service.h" -#include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc index 5474840..9561463 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -469,7 +469,7 @@ state_ == password_manager::ui::PENDING_PASSWORD_STATE) && IsSyncUser(GetProfile()) && // TODO(crbug.com/862269): Remove when "Smart Lock" is gone. - pending_password_.federation_origin.unique(); + pending_password_.federation_origin.opaque(); } const base::string16& ManagePasswordsBubbleModel::GetCurrentUsername() const { @@ -532,7 +532,7 @@ PasswordTitleType type = state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE ? PasswordTitleType::UPDATE_PASSWORD - : (pending_password_.federation_origin.unique() + : (pending_password_.federation_origin.opaque() ? PasswordTitleType::SAVE_PASSWORD : PasswordTitleType::SAVE_ACCOUNT); GetSavePasswordDialogTitleTextAndLinkRange(
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc index c1f86f4..338d09e7 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
@@ -56,7 +56,7 @@ std::pair<base::string16, base::string16> GetCredentialLabelsForAccountChooser( const autofill::PasswordForm& form) { base::string16 federation; - if (!form.federation_origin.unique()) { + if (!form.federation_origin.opaque()) { federation = l10n_util::GetStringFUTF16( IDS_PASSWORDS_VIA_FEDERATION, base::UTF8ToUTF16(form.federation_origin.host()));
diff --git a/chrome/browser/ui/views/autofill/dialog_view_ids.h b/chrome/browser/ui/views/autofill/dialog_view_ids.h index d76f6d3..4f298d5 100644 --- a/chrome/browser/ui/views/autofill/dialog_view_ids.h +++ b/chrome/browser/ui/views/autofill/dialog_view_ids.h
@@ -22,6 +22,9 @@ SIGN_IN_PROMO_VIEW, // Contains the sign-in promo view MANAGE_CARDS_VIEW, // The manage cards view + // The sub-view that contains the sign-in button in the promo. + SIGN_IN_VIEW, + // The following are views::LabelButton objects (clickable). OK_BUTTON, // Can say [Save], [Next], [Confirm], // or [Done] depending on context
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc index 13b5bbc..54005152 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -205,9 +205,10 @@ return view; } -void SaveCardBubbleViews::SetFootnoteViewForTesting( - views::View* footnote_view) { +void SaveCardBubbleViews::InitFootnoteView(views::View* footnote_view) { + DCHECK(!footnote_view_); footnote_view_ = footnote_view; + footnote_view_->set_id(DialogViewId::FOOTNOTE_VIEW); } void SaveCardBubbleViews::AssignIdsToDialogClientView() {
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_bubble_views.h index 008c1c0f..692015bb 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.h +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.h
@@ -83,8 +83,8 @@ // footnote. virtual std::unique_ptr<views::View> CreateMainContentView(); - // Set the footnote view so that its accessible for testing. - void SetFootnoteViewForTesting(views::View* footnote_view); + // Called by sub-classes to initialize |footnote_view_|. + virtual void InitFootnoteView(views::View* footnote_view); SaveCardBubbleController* controller() { return controller_; @@ -101,11 +101,7 @@ ~SaveCardBubbleViews() override; private: - FRIEND_TEST_ALL_PREFIXES(SaveCardBubbleViewsFullFormBrowserTest, - Upload_ClickingCloseClosesBubble); - FRIEND_TEST_ALL_PREFIXES( - SaveCardBubbleViewsFullFormBrowserTest, - Upload_DecliningUploadDoesNotLogUserAcceptedCardOriginUMA); + friend class SaveCardBubbleViewsBrowserTestBase; views::View* footnote_view_ = nullptr;
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc index 053d17c..21d9b8c 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
@@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> #include <string> #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/metrics/user_action_tester.h" #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -13,6 +15,7 @@ #include "chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h" #include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/signin/core/browser/signin_buildflags.h" #include "content/public/test/browser_test_utils.h" #include "net/url_request/test_url_fetcher_factory.h" #include "ui/views/bubble/bubble_frame_view.h" @@ -21,6 +24,14 @@ #include "ui/views/controls/textfield/textfield.h" #include "ui/views/window/dialog_client_view.h" +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +#include "chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h" +#endif + +#if defined(OS_CHROMEOS) +#include "chrome/browser/ui/settings_window_manager_chromeos.h" +#endif + using base::Bucket; using testing::ElementsAre; @@ -94,17 +105,24 @@ // Clicking [Save] should accept and close it. base::HistogramTester histogram_tester; + base::UserActionTester user_action_tester; ClickOnDialogViewWithIdAndWait(DialogViewId::OK_BUTTON); // UMA should have recorded bubble acceptance. histogram_tester.ExpectUniqueSample( "Autofill.SaveCreditCardPrompt.Local.FirstShow", AutofillMetrics::SAVE_CARD_PROMPT_END_ACCEPTED, 1); - // The sign-in promo should not be shown because the experiment is disabled. - // TODO(crbug/855186): Add test that checks that sign-in promo is not showing. + + // No bubble should be showing and no sign-in impression should have been + // recorded. + EXPECT_EQ(nullptr, GetSaveCardBubbleViews()); + EXPECT_FALSE(GetSaveCardIconView()->visible()); + EXPECT_EQ(0, user_action_tester.GetActionCount( + "Signin_Impression_FromSaveCardBubble")); } // Tests the sign in promo bubble. Ensures that clicking the [Save] button // on the local save bubble successfully causes the sign in promo to show. +#if !defined(OS_CHROMEOS) IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, Local_ClickingSaveShowsSigninPromo) { // Enable the sign-in promo. @@ -126,11 +144,24 @@ EXPECT_TRUE( FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible()); + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + // Click [Save] should close the offer-to-save bubble // and pop up the sign-in promo. - // TODO(crbug/855186): Add test that checks that sign-in promo shows after - // clicking save. + base::UserActionTester user_action_tester; + ClickOnDialogViewWithId(DialogViewId::OK_BUTTON); + WaitForObservedEvent(); + + // Sign-in promo should be showing and user actions should have recorded + // impression. + EXPECT_TRUE( + FindViewInBubbleById(DialogViewId::SIGN_IN_PROMO_VIEW)->visible()); } +#endif // Tests the sign in promo bubble. Ensures that the sign-in promo // is not shown when the user is signed-in and syncing, even if @@ -161,11 +192,381 @@ // Click [Save] should close the offer-to-save bubble // but no sign-in promo should show because user is signed in. + base::UserActionTester user_action_tester; ClickOnDialogViewWithIdAndWait(DialogViewId::OK_BUTTON); - // TODO(crbug/855186): Add test that checks that sign-in promo - // is not showing. + + // No bubble should be showing and no sign-in impression should have been + // recorded. + EXPECT_EQ(nullptr, GetSaveCardBubbleViews()); + EXPECT_EQ(0, user_action_tester.GetActionCount( + "Signin_Impression_FromSaveCardBubble")); } +// Tests the sign in promo bubble. Ensures that signin impression is recorded +// when promo is shown. +#if !defined(OS_CHROMEOS) +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Local_Metrics_SigninImpressionSigninPromo) { + // Enable the sign-in promo. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillSaveCardSignInAfterLocalSave); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + FillAndSubmitForm(); + WaitForObservedEvent(); + + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + + // Click [Save] should close the offer-to-save bubble + // and pop up the sign-in promo. + base::UserActionTester user_action_tester; + ClickOnDialogViewWithId(DialogViewId::OK_BUTTON); + WaitForObservedEvent(); + + // User actions should have recorded impression. + EXPECT_EQ(1, user_action_tester.GetActionCount( + "Signin_Impression_FromSaveCardBubble")); +} +#endif + +// Tests the sign in promo bubble. Ensures that signin action is recorded when +// user accepts promo. +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Local_Metrics_AcceptingSigninPromo) { + // Enable the sign-in promo. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillSaveCardSignInAfterLocalSave); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + FillAndSubmitForm(); + WaitForObservedEvent(); + + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + + // Click [Save] should close the offer-to-save bubble + // and pop up the sign-in promo. + base::UserActionTester user_action_tester; + ClickOnDialogViewWithId(DialogViewId::OK_BUTTON); + WaitForObservedEvent(); + + // Click on [Sign in] button. + ClickOnDialogView(static_cast<DiceBubbleSyncPromoView*>( + FindViewInBubbleById(DialogViewId::SIGN_IN_VIEW)) + ->GetSigninButtonForTesting()); + + // User actions should have recorded impression and click. + EXPECT_EQ(1, user_action_tester.GetActionCount( + "Signin_Impression_FromSaveCardBubble")); + EXPECT_EQ( + 1, user_action_tester.GetActionCount("Signin_Signin_FromSaveCardBubble")); +} +#endif + +// Tests the manage cards bubble. Ensures that it shows up by clicking the +// credit card icon. +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Local_ClickingIconShowsManageCards) { + // Enable the sign-in promo. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillSaveCardSignInAfterLocalSave); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + FillAndSubmitForm(); + WaitForObservedEvent(); + + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + +#if !defined(OS_CHROMEOS) + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); +#endif + + // Click [Save] should close the offer-to-save bubble and show "Card saved" + // animation -- followed by the sign-in promo (if not on Chrome OS). + ClickOnDialogViewWithIdAndWait(DialogViewId::OK_BUTTON); + +#if !defined(OS_CHROMEOS) + // Wait for and then close the promo. + WaitForObservedEvent(); + ClickOnCloseButton(); +#endif + + // Open up Manage Cards prompt. + base::HistogramTester histogram_tester; + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + ClickOnView(GetSaveCardIconView()); + WaitForObservedEvent(); + + // Bubble should be showing. + EXPECT_TRUE(FindViewInBubbleById(DialogViewId::MANAGE_CARDS_VIEW)->visible()); + histogram_tester.ExpectUniqueSample("Autofill.ManageCardsPrompt.Local", + AutofillMetrics::MANAGE_CARDS_SHOWN, 1); +} + +// Tests the manage cards bubble. Ensures that clicking the [Manage cards] +// button redirects properly. +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Local_ManageCardsButtonRedirects) { + // Enable the sign-in promo. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillSaveCardSignInAfterLocalSave); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + FillAndSubmitForm(); + WaitForObservedEvent(); + + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + +#if !defined(OS_CHROMEOS) + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); +#endif + + // Click [Save] should close the offer-to-save bubble and show "Card saved" + // animation -- followed by the sign-in promo (if not on Chrome OS). + ClickOnDialogViewWithIdAndWait(DialogViewId::OK_BUTTON); + +#if !defined(OS_CHROMEOS) + // Wait for and then close the promo. + WaitForObservedEvent(); + ClickOnCloseButton(); +#endif + + // Open up Manage Cards prompt. + base::HistogramTester histogram_tester; + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + ClickOnView(GetSaveCardIconView()); + WaitForObservedEvent(); + + // Click on the redirect button. + ClickOnDialogViewWithId(DialogViewId::MANAGE_CARDS_BUTTON); + +#if defined(OS_CHROMEOS) + // ChromeOS should have opened up the settings window. + EXPECT_TRUE( + chrome::SettingsWindowManager::GetInstance()->FindBrowserForProfile( + browser()->profile())); +#else + // Otherwise, another tab should have opened. + EXPECT_EQ(2, browser()->tab_strip_model()->count()); +#endif + + // Metrics should have been recorded correctly. + EXPECT_THAT( + histogram_tester.GetAllSamples("Autofill.ManageCardsPrompt.Local"), + ElementsAre(Bucket(AutofillMetrics::MANAGE_CARDS_SHOWN, 1), + Bucket(AutofillMetrics::MANAGE_CARDS_MANAGE_CARDS, 1))); +} + +// Tests the manage cards bubble. Ensures that clicking the [Done] +// button closes the bubble. +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Local_ManageCardsDoneButtonClosesBubble) { + // Enable the sign-in promo. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillSaveCardSignInAfterLocalSave); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + FillAndSubmitForm(); + WaitForObservedEvent(); + + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + +#if !defined(OS_CHROMEOS) + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); +#endif + + // Click [Save] should close the offer-to-save bubble and show "Card saved" + // animation -- followed by the sign-in promo (if not on Chrome OS). + ClickOnDialogViewWithIdAndWait(DialogViewId::OK_BUTTON); + +#if !defined(OS_CHROMEOS) + // Wait for and then close the promo. + WaitForObservedEvent(); + ClickOnCloseButton(); +#endif + + // Open up Manage Cards prompt. + base::HistogramTester histogram_tester; + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + ClickOnView(GetSaveCardIconView()); + WaitForObservedEvent(); + + // Click on the [Done] button. + ClickOnDialogViewWithIdAndWait(DialogViewId::OK_BUTTON); + + // No bubble should be showing now and metrics should be recorded correctly. + EXPECT_EQ(nullptr, GetSaveCardBubbleViews()); + EXPECT_THAT( + histogram_tester.GetAllSamples("Autofill.ManageCardsPrompt.Local"), + ElementsAre(Bucket(AutofillMetrics::MANAGE_CARDS_SHOWN, 1), + Bucket(AutofillMetrics::MANAGE_CARDS_DONE, 1))); +} + +// Tests the manage cards bubble. Ensures that sign-in impression is recorded +// correctly. +#if !defined(OS_CHROMEOS) +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Local_Metrics_SigninImpressionManageCards) { + // Enable the sign-in promo. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillSaveCardSignInAfterLocalSave); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + FillAndSubmitForm(); + WaitForObservedEvent(); + + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + + // Click [Save] should close the offer-to-save bubble + // and pop up the sign-in promo. + base::UserActionTester user_action_tester; + ClickOnDialogViewWithId(DialogViewId::OK_BUTTON); + WaitForObservedEvent(); + + // Close promo. + ClickOnCloseButton(); + + // Open up Manage Cards prompt. + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + ClickOnView(GetSaveCardIconView()); + WaitForObservedEvent(); + + // User actions should have recorded impression. + EXPECT_EQ(1, user_action_tester.GetActionCount( + "Signin_Impression_FromManageCardsBubble")); +} +#endif + +// Tests the Manage Cards bubble. Ensures that signin action is recorded when +// user accepts footnote promo. +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, + Local_Metrics_AcceptingFootnotePromoManageCards) { + // Enable the sign-in promo. + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillSaveCardSignInAfterLocalSave); + + // Set up the Payments RPC. + SetUploadDetailsRpcPaymentsDeclines(); + + // Submitting the form and having Payments decline offering to save should + // show the local save bubble. + // (Must wait for response from Payments before accessing the controller.) + ResetEventWaiterForSequence( + {DialogEvent::REQUESTED_UPLOAD_SAVE, + DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, + DialogEvent::OFFERED_LOCAL_SAVE}); + FillAndSubmitForm(); + WaitForObservedEvent(); + + // Adding an event observer to the controller so we can wait for the bubble to + // show. + AddEventObserverToController(); + ReduceAnimationTime(); + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + + // Click [Save] should close the offer-to-save bubble + // and pop up the sign-in promo. + base::UserActionTester user_action_tester; + ClickOnDialogViewWithId(DialogViewId::OK_BUTTON); + WaitForObservedEvent(); + + // Close promo. + ClickOnCloseButton(); + + // Open up Manage Cards prompt. + ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN}); + ClickOnView(GetSaveCardIconView()); + WaitForObservedEvent(); + + // Click on [Sign in] button in footnote. + ClickOnDialogView(static_cast<DiceBubbleSyncPromoView*>( + FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)) + ->GetSigninButtonForTesting()); + + // User actions should have recorded impression and click. + EXPECT_EQ(1, user_action_tester.GetActionCount( + "Signin_Impression_FromManageCardsBubble")); + EXPECT_EQ(1, user_action_tester.GetActionCount( + "Signin_Signin_FromManageCardsBubble")); +} +#endif + // Tests the local save bubble. Ensures that the Harmony version of the bubble // does not have a [No thanks] button (it has an [X] Close button instead.) IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest, @@ -300,8 +701,7 @@ // Clicking the [X] close button should dismiss the bubble. base::HistogramTester histogram_tester; - ClickOnDialogViewAndWait( - GetSaveCardBubbleViews()->GetBubbleFrameView()->GetCloseButtonForTest()); + ClickOnCloseButton(); } // Tests the upload save bubble. Ensures that the bubble does not surface the @@ -814,8 +1214,7 @@ EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible()); // Clicking the [X] close button should dismiss the bubble. - ClickOnDialogViewAndWait( - GetSaveCardBubbleViews()->GetBubbleFrameView()->GetCloseButtonForTest()); + ClickOnCloseButton(); // Ensure that UMA was logged correctly. histogram_tester.ExpectUniqueSample(
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc index 841ee5e8..86cfa810 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc
@@ -7,6 +7,7 @@ #include <list> #include <memory> #include <string> +#include <utility> #include "chrome/browser/signin/account_fetcher_service_factory.h" #include "chrome/browser/signin/account_tracker_service_factory.h" @@ -16,9 +17,13 @@ #include "chrome/browser/ui/autofill/chrome_autofill_client.h" #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/views/autofill/dialog_view_ids.h" #include "chrome/browser/ui/views/autofill/save_card_bubble_views.h" +#include "chrome/browser/ui/views/autofill/save_card_icon_view.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "chrome/test/base/ui_test_utils.h" #include "components/autofill/content/browser/content_autofill_driver.h" #include "components/autofill/core/browser/credit_card_save_manager.h" @@ -134,6 +139,11 @@ event_waiter_->OnEvent(DialogEvent::SENT_UPLOAD_CARD_REQUEST); } +void SaveCardBubbleViewsBrowserTestBase::OnBubbleShown() { + if (event_waiter_) + event_waiter_->OnEvent(DialogEvent::BUBBLE_SHOWN); +} + void SaveCardBubbleViewsBrowserTestBase::SetUpInProcessBrowserTestFixture() { will_create_browser_context_services_subscription_ = BrowserContextDependencyManager::GetInstance() @@ -336,6 +346,18 @@ net::HTTP_INTERNAL_SERVER_ERROR); } +void SaveCardBubbleViewsBrowserTestBase::ClickOnView(views::View* view) { + DCHECK(view); + ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + view->OnMousePressed(pressed); + ui::MouseEvent released_event = ui::MouseEvent( + ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); + view->OnMouseReleased(released_event); +} + void SaveCardBubbleViewsBrowserTestBase::ClickOnDialogView(views::View* view) { GetSaveCardBubbleViews() ->GetDialogClientView() @@ -346,16 +368,7 @@ ->non_client_view() ->frame_view()); bubble_frame_view->ResetViewShownTimeStampForTesting(); - - DCHECK(view); - ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON); - view->OnMousePressed(pressed); - ui::MouseEvent released_event = ui::MouseEvent( - ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(), - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); - view->OnMouseReleased(released_event); + ClickOnView(view); } void SaveCardBubbleViewsBrowserTestBase::ClickOnDialogViewAndWait( @@ -407,6 +420,13 @@ return specified_view; } +void SaveCardBubbleViewsBrowserTestBase::ClickOnCloseButton() { + SaveCardBubbleViews* save_card_bubble_views = GetSaveCardBubbleViews(); + DCHECK(save_card_bubble_views); + ClickOnDialogViewAndWait( + save_card_bubble_views->GetBubbleFrameView()->GetCloseButtonForTest()); +} + SaveCardBubbleViews* SaveCardBubbleViewsBrowserTestBase::GetSaveCardBubbleViews() { SaveCardBubbleControllerImpl* save_card_bubble_controller_impl = @@ -420,11 +440,31 @@ return static_cast<SaveCardBubbleViews*>(save_card_bubble_view); } +SaveCardIconView* SaveCardBubbleViewsBrowserTestBase::GetSaveCardIconView() { + if (!browser()) + return nullptr; + LocationBarView* location_bar_view = + static_cast<LocationBarView*>(browser()->window()->GetLocationBar()); + DCHECK(location_bar_view->save_credit_card_icon_view()); + return location_bar_view->save_credit_card_icon_view(); +} + content::WebContents* SaveCardBubbleViewsBrowserTestBase::GetActiveWebContents() { return browser()->tab_strip_model()->GetActiveWebContents(); } +void SaveCardBubbleViewsBrowserTestBase::AddEventObserverToController() { + SaveCardBubbleControllerImpl* save_card_bubble_controller_impl = + SaveCardBubbleControllerImpl::FromWebContents(GetActiveWebContents()); + DCHECK(save_card_bubble_controller_impl); + save_card_bubble_controller_impl->SetEventObserverForTesting(this); +} + +void SaveCardBubbleViewsBrowserTestBase::ReduceAnimationTime() { + GetSaveCardIconView()->ReduceAnimationTimeForTesting(); +} + void SaveCardBubbleViewsBrowserTestBase::ResetEventWaiterForSequence( std::list<DialogEvent> event_sequence) { event_waiter_ =
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h index 4c8e110..481d931 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h
@@ -13,8 +13,10 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/views/autofill/dialog_view_ids.h" #include "chrome/browser/ui/views/autofill/save_card_bubble_views.h" +#include "chrome/browser/ui/views/autofill/save_card_icon_view.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/autofill/core/browser/credit_card_save_manager.h" #include "components/autofill/core/browser/test_event_waiter.h" @@ -36,7 +38,8 @@ // need to show and interact with the offer-to-save bubble. class SaveCardBubbleViewsBrowserTestBase : public InProcessBrowserTest, - public CreditCardSaveManager::ObserverForTest { + public CreditCardSaveManager::ObserverForTest, + public SaveCardBubbleControllerImpl::ObserverForTest { public: // Various events that can be waited on by the DialogEventWaiter. enum DialogEvent : int { @@ -44,6 +47,7 @@ REQUESTED_UPLOAD_SAVE, RECEIVED_GET_UPLOAD_DETAILS_RESPONSE, SENT_UPLOAD_CARD_REQUEST, + BUBBLE_SHOWN }; protected: @@ -63,6 +67,9 @@ void OnReceivedGetUploadDetailsResponse() override; void OnSentUploadCardRequest() override; + // SaveCardBubbleControllerImpl::ObserverForTest: + void OnBubbleShown() override; + // BrowserTestBase: void SetUpInProcessBrowserTestFixture() override; @@ -90,9 +97,12 @@ void SetUploadDetailsRpcServerError(); // Clicks on the given views::View*. + void ClickOnView(views::View* view); + + // Clicks on the given dialog views::View*. void ClickOnDialogView(views::View* view); - // Clicks on the given views::View* and waits for the dialog to close. + // Clicks on the given dialog views::View* and waits for the dialog to close. void ClickOnDialogViewAndWait(views::View* view); // Clicks on a view from within the dialog. @@ -104,11 +114,26 @@ // Returns the views::View* that was previously assigned the id |view_id|. views::View* FindViewInBubbleById(DialogViewId view_id); + // Assert that there is a SaveCardBubbleViews bubble open, then click on the + // [X] button. + void ClickOnCloseButton(); + // Gets the views::View* instance of the save credit card bubble. SaveCardBubbleViews* GetSaveCardBubbleViews(); + // Gets the views::View* instance of the credit card icon. + SaveCardIconView* GetSaveCardIconView(); + content::WebContents* GetActiveWebContents(); + // Adding an observer to the controller so we know when the sign-in promo + // shows after the animation. + void AddEventObserverToController(); + + // Reduces the animation time to one millisecond so that the test does not + // take long. + void ReduceAnimationTime(); + // Resets the event waiter for a given |event_sequence|. void ResetEventWaiterForSequence(std::list<DialogEvent> event_sequence); // Wait for the event(s) passed to ResetEventWaiter*() to occur.
diff --git a/chrome/browser/ui/views/autofill/save_card_icon_view.h b/chrome/browser/ui/views/autofill/save_card_icon_view.h index 409d85ed..9fd90f1 100644 --- a/chrome/browser/ui/views/autofill/save_card_icon_view.h +++ b/chrome/browser/ui/views/autofill/save_card_icon_view.h
@@ -38,6 +38,8 @@ const gfx::VectorIcon& GetVectorIcon() const override; private: + friend class SaveCardBubbleViewsBrowserTestBase; + SaveCardBubbleControllerImpl* GetController() const; // gfx::AnimationDelegate:
diff --git a/chrome/browser/ui/views/autofill/save_card_manage_cards_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_manage_cards_bubble_views.cc index 6891ab9e..80a01bf 100644 --- a/chrome/browser/ui/views/autofill/save_card_manage_cards_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_manage_cards_bubble_views.cc
@@ -35,7 +35,7 @@ if (!controller()->ShouldShowSignInPromo()) return nullptr; - views::View* footnote_view_ = nullptr; + views::View* promo_view = nullptr; Profile* profile = controller()->GetProfile(); sync_promo_delegate_ = @@ -44,7 +44,7 @@ signin_metrics::AccessPoint::ACCESS_POINT_MANAGE_CARDS_BUBBLE); if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile)) { #if BUILDFLAG(ENABLE_DICE_SUPPORT) - footnote_view_ = new DiceBubbleSyncPromoView( + promo_view = new DiceBubbleSyncPromoView( profile, sync_promo_delegate_.get(), signin_metrics::AccessPoint::ACCESS_POINT_MANAGE_CARDS_BUBBLE, IDS_AUTOFILL_SIGNIN_PROMO_MESSAGE, IDS_AUTOFILL_SYNC_PROMO_MESSAGE, @@ -53,15 +53,15 @@ NOTREACHED(); #endif } else { - footnote_view_ = new BubbleSyncPromoView( + promo_view = new BubbleSyncPromoView( sync_promo_delegate_.get(), signin_metrics::AccessPoint::ACCESS_POINT_MANAGE_CARDS_BUBBLE, IDS_AUTOFILL_SIGNIN_PROMO_LINK_DICE_DISABLED, IDS_AUTOFILL_SIGNIN_PROMO_MESSAGE_DICE_DISABLED); } - SetFootnoteViewForTesting(footnote_view_); - return footnote_view_; + InitFootnoteView(promo_view); + return promo_view; } views::View* SaveCardManageCardsBubbleViews::CreateExtraView() {
diff --git a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc index 78c721ba..d7a89ab 100644 --- a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h" +#include <memory> + #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" @@ -56,12 +58,11 @@ if (controller()->GetLegalMessageLines().empty()) return nullptr; - footnote_view_ = + legal_message_view_ = new LegalMessageView(controller()->GetLegalMessageLines(), this); - footnote_view_->set_id(DialogViewId::FOOTNOTE_VIEW); - SetFootnoteViewForTesting(footnote_view_); - return footnote_view_; + InitFootnoteView(legal_message_view_); + return legal_message_view_; } bool SaveCardOfferBubbleViews::Accept() { @@ -101,7 +102,7 @@ if (!controller()) return; - footnote_view_->OnLinkClicked(label, range, web_contents_); + legal_message_view_->OnLinkClicked(label, range, web_contents_); } void SaveCardOfferBubbleViews::ContentsChanged(
diff --git a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h index b68ee32..fe71f2ec 100644 --- a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h +++ b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h
@@ -55,7 +55,7 @@ views::Textfield* cardholder_name_textfield_ = nullptr; - LegalMessageView* footnote_view_ = nullptr; + LegalMessageView* legal_message_view_ = nullptr; DISALLOW_COPY_AND_ASSIGN(SaveCardOfferBubbleViews); };
diff --git a/chrome/browser/ui/views/autofill/save_card_sign_in_promo_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_sign_in_promo_bubble_views.cc index 8efd4143..2ddd989 100644 --- a/chrome/browser/ui/views/autofill/save_card_sign_in_promo_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_sign_in_promo_bubble_views.cc
@@ -48,6 +48,7 @@ provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL))); view->set_id(DialogViewId::SIGN_IN_PROMO_VIEW); + std::unique_ptr<views::View> signin_view; Profile* profile = controller()->GetProfile(); sync_promo_delegate_ = std::make_unique<SaveCardSignInPromoBubbleViews::SyncPromoDelegate>( @@ -55,19 +56,21 @@ signin_metrics::AccessPoint::ACCESS_POINT_SAVE_CARD_BUBBLE); if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile)) { #if BUILDFLAG(ENABLE_DICE_SUPPORT) - view->AddChildView(new DiceBubbleSyncPromoView( + signin_view = std::make_unique<DiceBubbleSyncPromoView>( profile, sync_promo_delegate_.get(), - signin_metrics::AccessPoint::ACCESS_POINT_SAVE_CARD_BUBBLE)); + signin_metrics::AccessPoint::ACCESS_POINT_SAVE_CARD_BUBBLE); #else NOTREACHED(); #endif } else { - view->AddChildView(new BubbleSyncPromoView( + signin_view = std::make_unique<BubbleSyncPromoView>( sync_promo_delegate_.get(), signin_metrics::AccessPoint::ACCESS_POINT_SAVE_CARD_BUBBLE, IDS_AUTOFILL_SIGNIN_PROMO_LINK_DICE_DISABLED, - IDS_AUTOFILL_SIGNIN_PROMO_MESSAGE_DICE_DISABLED)); + IDS_AUTOFILL_SIGNIN_PROMO_MESSAGE_DICE_DISABLED); } + signin_view->set_id(DialogViewId::SIGN_IN_VIEW); + view->AddChildView(signin_view.release()); return view; }
diff --git a/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h b/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h index 2a6fd6b..60f986c 100644 --- a/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h +++ b/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h
@@ -64,6 +64,9 @@ void OnMouseEntered(const ui::MouseEvent& event) override; void OnMouseExited(const ui::MouseEvent& event) override; gfx::Rect GetBubbleBounds() override; + void UpdateHighlightedButton(bool highlighted) override { + // Do nothing: the anchor for promo bubbles should not highlight. + } // Starts a timer to close the promo bubble. void StartAutoCloseTimer(base::TimeDelta auto_close_duration);
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.mm b/chrome/browser/ui/views/frame/browser_frame_mac.mm index bca3621..30e91604 100644 --- a/chrome/browser/ui/views/frame/browser_frame_mac.mm +++ b/chrome/browser/ui/views/frame/browser_frame_mac.mm
@@ -18,7 +18,7 @@ #include "components/web_modal/web_contents_modal_dialog_host.h" #include "content/public/browser/native_web_keyboard_event.h" #import "ui/base/cocoa/window_size_constants.h" -#import "ui/views/cocoa/window_touch_bar_delegate.h" +#import "ui/views_bridge_mac/window_touch_bar_delegate.h" namespace {
diff --git a/chrome/browser/ui/views/frame/browser_native_widget_window_mac.h b/chrome/browser/ui/views/frame/browser_native_widget_window_mac.h index ee8dd6bb..5d98387 100644 --- a/chrome/browser/ui/views/frame/browser_native_widget_window_mac.h +++ b/chrome/browser/ui/views/frame/browser_native_widget_window_mac.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_ #define CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_ -#import "ui/views/cocoa/native_widget_mac_nswindow.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" @interface BrowserNativeWidgetWindow : NativeWidgetMacNSWindow @end
diff --git a/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.h b/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.h index 9b7ac0b..52b054b 100644 --- a/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.h +++ b/chrome/browser/ui/views/frame/native_widget_mac_frameless_nswindow.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_ #define CHROME_BROWSER_UI_VIEWS_FRAME_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_ -#import "ui/views/cocoa/native_widget_mac_nswindow.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" // Overrides contentRect <-> frameRect conversion methods to keep them equal to // each other, even for windows that do not use NSBorderlessWindowMask. This
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc index c49a812..48ec85b 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -538,6 +538,10 @@ slide_animation_.Reset(show_label); } +void IconLabelBubbleView::ReduceAnimationTimeForTesting() { + slide_animation_.SetSlideDuration(1); +} + void IconLabelBubbleView::PauseAnimation() { if (slide_animation_.is_animating()) { // If the user clicks while we're animating, the bubble arrow will be
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h index 7fb9872..c6e9984 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -185,6 +185,10 @@ // currently paused. bool is_animation_paused() const { return is_animation_paused_; } + // Reduces the slide duration to 1ms such that animation still follows + // through in the code but is short enough that it is essentially skipped. + void ReduceAnimationTimeForTesting(); + private: // Spacing between the image and the label. int GetInternalSpacing() const;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc index 189a2c7..ff12066 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.cc +++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -734,10 +734,10 @@ TogglePlayPause(); if (sender == first_custom_controls_view_.get()) - controller_->ClickCustomControl(first_custom_controls_view_->id()); + controller_->CustomControlPressed(first_custom_controls_view_->id()); if (sender == second_custom_controls_view_.get()) - controller_->ClickCustomControl(second_custom_controls_view_->id()); + controller_->CustomControlPressed(second_custom_controls_view_->id()); } gfx::Rect OverlayWindowViews::GetCloseControlsBounds() { @@ -780,10 +780,6 @@ play_pause_controls_view_->SetToggled(is_active); } -void OverlayWindowViews::ClickCustomControl(const std::string& control_id) { - controller_->ClickCustomControl(control_id); -} - views::ToggleImageButton* OverlayWindowViews::play_pause_controls_view_for_testing() const { return play_pause_controls_view_.get();
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h index 81f1830..e1c7f5a0 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.h +++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -66,9 +66,6 @@ gfx::Rect GetFirstCustomControlsBounds(); gfx::Rect GetSecondCustomControlsBounds(); - // Send the message that a custom control on |this| has been clicked. - void ClickCustomControl(const std::string& control_id); - views::ToggleImageButton* play_pause_controls_view_for_testing() const; views::View* controls_parent_view_for_testing() const;
diff --git a/chrome/browser/ui/views/passwords/password_items_view.cc b/chrome/browser/ui/views/passwords/password_items_view.cc index 68c13b6a..0a9e791 100644 --- a/chrome/browser/ui/views/passwords/password_items_view.cc +++ b/chrome/browser/ui/views/passwords/password_items_view.cc
@@ -126,7 +126,7 @@ int federation_message_id, bool are_passwords_revealed) { base::string16 text = - form.federation_origin.unique() + form.federation_origin.opaque() ? form.password_value : l10n_util::GetStringFUTF16( federation_message_id, @@ -134,9 +134,9 @@ auto label = std::make_unique<views::Label>(text, CONTEXT_BODY_TEXT_LARGE, STYLE_SECONDARY); label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - if (form.federation_origin.unique() && !are_passwords_revealed) + if (form.federation_origin.opaque() && !are_passwords_revealed) label->SetObscured(true); - if (!form.federation_origin.unique()) + if (!form.federation_origin.opaque()) label->SetElideBehavior(gfx::ELIDE_HEAD); return label;
diff --git a/chrome/browser/ui/views/passwords/password_pending_view.cc b/chrome/browser/ui/views/passwords/password_pending_view.cc index a69c46a..bcc79b01 100644 --- a/chrome/browser/ui/views/passwords/password_pending_view.cc +++ b/chrome/browser/ui/views/passwords/password_pending_view.cc
@@ -232,7 +232,7 @@ .release(); } - const bool is_password_credential = password_form.federation_origin.unique(); + const bool is_password_credential = password_form.federation_origin.opaque(); if (is_password_credential) { password_view_button_ = CreatePasswordViewButton(this, are_passwords_revealed_).release();
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index 6131232..c96cdef 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -1425,25 +1425,24 @@ profiles::kAvatarBubbleAccountsBackgroundColor)); views::GridLayout* layout = CreateSingleColumnLayout(view, menu_width_); - Profile* profile = browser_->profile(); - std::string primary_account = - SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedAccountId(); - DCHECK(!primary_account.empty()); - std::vector<std::string> accounts = - profiles::GetSecondaryAccountsForProfile(profile, primary_account); - // Get state of authentication error, if any. + Profile* profile = browser_->profile(); std::string error_account_id = GetAuthErrorAccountId(profile); // The primary account should always be listed first. // TODO(rogerta): we still need to further differentiate the primary account // from the others in the UI, so more work is likely required here: // crbug.com/311124. + std::string primary_account = + SigninManagerFactory::GetForProfile(profile)->GetAuthenticatedAccountId(); + DCHECK(!primary_account.empty()); CreateAccountButton(layout, primary_account, true, error_account_id == primary_account, menu_width_); - for (size_t i = 0; i < accounts.size(); ++i) - CreateAccountButton(layout, accounts[i], false, - error_account_id == accounts[i], menu_width_); + for (const std::string& account : + profiles::GetSecondaryAccountsForSignedInProfile(profile)) { + CreateAccountButton(layout, account, false, error_account_id == account, + menu_width_); + } ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); const int vertical_spacing =
diff --git a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc index 67ff5cc..9cbd5311 100644 --- a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc +++ b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.cc
@@ -110,6 +110,10 @@ NOTREACHED(); } +views::View* DiceBubbleSyncPromoView::GetSigninButtonForTesting() { + return signin_button_view_ ? signin_button_view_->signin_button() : nullptr; +} + void DiceBubbleSyncPromoView::EnableSync( bool is_default_promo_account, const base::Optional<AccountInfo>& account) {
diff --git a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h index 187f519..1d8ff96 100644 --- a/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h +++ b/chrome/browser/ui/views/sync/dice_bubble_sync_promo_view.h
@@ -52,6 +52,9 @@ // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; + // Returns the sign-in button. + views::View* GetSigninButtonForTesting(); + private: // Used to enable sync in the DiceAccountsMenu and when |signin_button_| is // pressed.
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc index 9f9cbaf..6be9bd9 100644 --- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc +++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc
@@ -38,8 +38,10 @@ const web_modal::WebContentsModalDialogManager* manager = web_modal::WebContentsModalDialogManager::FromWebContents(web_contents_); - if (manager && manager->IsDialogActive()) + if (manager && manager->IsDialogActive()) { manager->FocusTopmostDialog(); + return true; + } return false; }
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index cd2cb8ea..956a6b38 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -187,6 +187,9 @@ policies.SetInteger( printing::kAllowedColorModes, profile_->GetPrefs()->GetInteger(prefs::kPrintingAllowedColorModes)); + policies.SetInteger( + printing::kAllowedDuplexModes, + profile_->GetPrefs()->GetInteger(prefs::kPrintingAllowedDuplexModes)); // fetch settings on the blocking pool and invoke callback. FetchCapabilities(std::move(printer), std::move(policies), std::move(cb)); return;
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 6dbb63a..bc10d2f 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -852,6 +852,8 @@ #if defined(OS_CHROMEOS) html_source->AddBoolean("enableNativeSmbSetting", base::FeatureList::IsEnabled(features::kNativeSmb)); + html_source->AddString("smbSharesLearnMoreURL", + GetHelpUrlWithBoard(chrome::kSmbSharesLearnMoreURL)); #endif } @@ -2181,6 +2183,10 @@ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION}, {"googleAssistantEnableNotificationDescription", IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION_DESCRIPTION}, + {"googleAssistantLaunchWithMicOpen", + IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN}, + {"googleAssistantLaunchWithMicOpenDescription", + IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN_DESCRIPTION}, {"googleAssistantSettings", IDS_SETTINGS_GOOGLE_ASSISTANT_SETTINGS}, }; AddLocalizedStringsBulk(html_source, localized_strings,
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index 04422c78..554ec6a 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -123,7 +123,7 @@ bool PatternAppliesToSingleOrigin(const ContentSettingPatternSource& pattern) { const GURL url(pattern.primary_pattern.ToString()); // Default settings and other patterns apply to multiple origins. - if (url::Origin::Create(url).unique()) + if (url::Origin::Create(url).opaque()) return false; // Embedded content settings only when |url| is embedded in another origin, so // ignore non-wildcard secondary patterns that are different to the primary.
diff --git a/chrome/browser/ui/webui/site_settings_helper.cc b/chrome/browser/ui/webui/site_settings_helper.cc index f7cfefa..457f8350 100644 --- a/chrome/browser/ui/webui/site_settings_helper.cc +++ b/chrome/browser/ui/webui/site_settings_helper.cc
@@ -318,7 +318,7 @@ const GURL& url, const extensions::ExtensionRegistry* extension_registry) { const url::Origin origin = url::Origin::Create(url); - if (origin.unique()) + if (origin.opaque()) return url.spec(); std::string display_name =
diff --git a/chrome/browser/vr/webxr_vr_transition_browser_test.cc b/chrome/browser/vr/webxr_vr_transition_browser_test.cc index fda129fb..106544ba 100644 --- a/chrome/browser/vr/webxr_vr_transition_browser_test.cc +++ b/chrome/browser/vr/webxr_vr_transition_browser_test.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "chrome/browser/vr/test/webvr_browser_test.h" + +#include "build/build_config.h" #include "chrome/browser/vr/test/webxr_vr_browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -78,8 +80,14 @@ // Tests that WebVR does not return any devices if OpenVR support is disabled. // Since WebVR isn't actually used, we can remove the GPU requirement. +#if defined(OS_WIN) +#define MAYBE_TestWebVrNoDevicesWithoutOpenVr \ + DISABLED_TestWebVrNoDevicesWithoutOpenVr +#else +#define MAYBE_TestWebVrNoDevicesWithoutOpenVr TestWebVrNoDevicesWithoutOpenVr +#endif IN_PROC_BROWSER_TEST_F(WebVrBrowserTestOpenVrDisabled, - TestWebVrNoDevicesWithoutOpenVr) { + MAYBE_TestWebVrNoDevicesWithoutOpenVr) { LoadUrlAndAwaitInitialization(GetHtmlTestFile("generic_webvr_page")); EXPECT_FALSE(XrDeviceFound()) << "Found a VRDisplay even with OpenVR disabled";
diff --git a/chrome/chrome_cleaner/BUILD.gn b/chrome/chrome_cleaner/BUILD.gn index 840d269..389300fb9 100644 --- a/chrome/chrome_cleaner/BUILD.gn +++ b/chrome/chrome_cleaner/BUILD.gn
@@ -33,6 +33,7 @@ # Tests from sub-directories. "//chrome/chrome_cleaner/chrome_utils:unittest_sources", + "//chrome/chrome_cleaner/components:unittest_sources", "//chrome/chrome_cleaner/http:unittest_sources", "//chrome/chrome_cleaner/interfaces/typemaps:unittest_sources", "//chrome/chrome_cleaner/ipc:unittest_sources",
diff --git a/chrome/chrome_cleaner/components/BUILD.gn b/chrome/chrome_cleaner/components/BUILD.gn new file mode 100644 index 0000000..3a9bf1fb --- /dev/null +++ b/chrome/chrome_cleaner/components/BUILD.gn
@@ -0,0 +1,85 @@ +# Copyright 2018 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. + +source_set("crx_file") { + sources = [ + "crx_file.cc", + "crx_file.h", + ] + + deps = [ + "//base", + "//components/chrome_cleaner/public/constants:constants", + ] +} + +source_set("components") { + sources = [ + "component_api.h", + "component_manager.cc", + "component_manager.h", + "component_unpacker.cc", + "component_unpacker.h", + "recovery_component.cc", + "recovery_component.h", + "system_report_component.cc", + "system_report_component.h", + "system_restore_point_component.cc", + "system_restore_point_component.h", + ] + + deps = [ + ":crx_file", + "//base:base", + "//chrome/chrome_cleaner/chrome_utils:chrome_util_lib", + "//chrome/chrome_cleaner/chrome_utils:extensions_util_lib", + "//chrome/chrome_cleaner/constants:common_strings", + "//chrome/chrome_cleaner/constants:uws_id", + "//chrome/chrome_cleaner/http:http", + "//chrome/chrome_cleaner/http:http_status_codes", + "//chrome/chrome_cleaner/json_parser", + "//chrome/chrome_cleaner/logging:common", + "//chrome/chrome_cleaner/logging:scoped_timed_task_logger", + "//chrome/chrome_cleaner/logging/proto:shared_data_proto", + "//chrome/chrome_cleaner/os:cleaner_os", + "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/pup_data:pup_data_base", + "//components/chrome_cleaner/public/constants:constants", + "//crypto:crypto", + "//third_party/zlib/google:zip", + "//url:url", + ] +} + +source_set("unittest_sources") { + testonly = true + + sources = [ + "component_manager_unittest.cc", + "recovery_component_unittest.cc", + "system_report_component_unittest.cc", + "system_restore_point_component_unittest.cc", + ] + + deps = [ + ":components", + "//base", + "//base/test:test_support", + "//chrome/chrome_cleaner/chrome_utils:chrome_util_lib", + "//chrome/chrome_cleaner/constants:common_strings", + "//chrome/chrome_cleaner/constants:uws_id", + "//chrome/chrome_cleaner/http:mock_http_agent_factory", + "//chrome/chrome_cleaner/json_parser", + "//chrome/chrome_cleaner/logging:cleaner_logging", + "//chrome/chrome_cleaner/logging/proto:chrome_cleaner_report_proto", + "//chrome/chrome_cleaner/os:cleaner_os", + "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/test:test_branding_header", + "//chrome/chrome_cleaner/test:test_component", + "//chrome/chrome_cleaner/test:test_pup_data", + "//chrome/chrome_cleaner/test:test_util", + "//components/chrome_cleaner/public/constants", + "//testing/gtest", + ] +}
diff --git a/chrome/chrome_cleaner/components/DEPS b/chrome/chrome_cleaner/components/DEPS new file mode 100644 index 0000000..4394973 --- /dev/null +++ b/chrome/chrome_cleaner/components/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+third_party/zlib/google", +]
diff --git a/chrome/chrome_cleaner/components/component_api.h b/chrome/chrome_cleaner/components/component_api.h new file mode 100644 index 0000000..fd06746 --- /dev/null +++ b/chrome/chrome_cleaner/components/component_api.h
@@ -0,0 +1,54 @@ +// Copyright 2018 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 CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_API_H_ +#define CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_API_H_ + +#include <vector> + +#include "chrome/chrome_cleaner/constants/uws_id.h" +#include "components/chrome_cleaner/public/constants/result_codes.h" + +namespace chrome_cleaner { + +class RebooterAPI; + +// This class is used to register components that are to be executed by the main +// controller either before the scanner or after the cleaner. +class ComponentAPI { + public: + virtual ~ComponentAPI() {} + + // Called before the scanning starts. Components may need to consult the + // command line to identify if this is a post-reboot scan. + virtual void PreScan() = 0; + + // Called after scanning. |found_pups| contains the ids of the found pups. + virtual void PostScan(const std::vector<UwSId>& found_pups) = 0; + + // Called before cleanup starts. + virtual void PreCleanup() = 0; + + // Called after the final cleanup. |result_code| can be used to identify if + // a post-reboot removal will be needed, or other status that might be useful + // to the component. |rebooter| is specified in case the component needs to + // specify command line arguments for the post-reboot run so that the + // |PostValidation| call below can take some decisions based on it. |rebooter| + // can be null in tests. + virtual void PostCleanup(ResultCode result_code, RebooterAPI* rebooter) = 0; + + // Called after the post reboot run scanner is done validating the cleanup. + virtual void PostValidation(ResultCode result_code) = 0; + + // Called when the final dialog window is closed. As above, |result_code| can + // be used to tell the result of the run (i.e., whether a cleanup was needed + // or not). Since this happens after users had a chance to look at the logs to + // decide whether they want to opt-out or not, any logging done here won't be + // uploaded back to Google. + virtual void OnClose(ResultCode result_code) = 0; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_API_H_
diff --git a/chrome/chrome_cleaner/components/component_manager.cc b/chrome/chrome_cleaner/components/component_manager.cc new file mode 100644 index 0000000..87cf1fd --- /dev/null +++ b/chrome/chrome_cleaner/components/component_manager.cc
@@ -0,0 +1,186 @@ +// Copyright 2018 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/chrome_cleaner/components/component_manager.h" + +#include <memory> +#include <utility> + +#include "base/run_loop.h" +#include "base/task/post_task.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/chrome_cleaner/components/component_api.h" + +namespace chrome_cleaner { + +namespace { + +// A set of factory functions to create the calls to code to be executed in +// worker threads. Since the code to loop through the components is the same +// for all calls, it was extracted in the |PostComponentTasks| method. So the +// public API methods must specify which function to call on the components. +// Since the component pointer must be the first argument, and we can't pre-pend +// args to bound calls, the public API methods sends a bound version of these +// factory functions so that |PostComponentTasks| can call them to get the +// closure by passing the component pointer to them. The component pointer +// must be the last argument to these factory functions so that the other +// arguments are pre-bound by the public API methods when they call +// |PostComponentTasks| (e.g., |found_pups|). +base::OnceClosure BindPreScan(ComponentAPI* component) { + return base::BindOnce(&ComponentAPI::PreScan, base::Unretained(component)); +} + +base::OnceClosure BindPostScan(const std::vector<UwSId>& found_pups, + ComponentAPI* component) { + return base::BindOnce(&ComponentAPI::PostScan, base::Unretained(component), + found_pups); +} + +base::OnceClosure BindPreCleanup(ComponentAPI* component) { + return base::BindOnce(&ComponentAPI::PreCleanup, base::Unretained(component)); +} + +base::OnceClosure BindPostCleanup(ResultCode result_code, + RebooterAPI* rebooter, + ComponentAPI* component) { + return base::BindOnce(&ComponentAPI::PostCleanup, base::Unretained(component), + result_code, rebooter); +} + +} // namespace + +ComponentManager::ComponentManager(ComponentManagerDelegate* delegate) + : delegate_(delegate) { + DCHECK(delegate_); +} + +ComponentManager::~ComponentManager() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Make sure |CloseAllComponents| was called. IT can't be called from here + // because it needs the result code. The components will still be released by + // the scoped vector, but their OnClose won't be called if + // |CloseAllComponents| wasn't called. + DCHECK(!cancelable_task_tracker_.HasTrackedTasks()); + DCHECK(components_.empty()); + DCHECK(done_callback_.is_null()); +} + +void ComponentManager::AddComponent(std::unique_ptr<ComponentAPI> component) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Components can't be added while tasks are in flight. + DCHECK(!cancelable_task_tracker_.HasTrackedTasks()); + DCHECK(done_callback_.is_null()); + DCHECK_EQ(0UL, num_tasks_pending_); + + components_.push_back(std::move(component)); +} + +void ComponentManager::PreScan() { + // No task should be pending when any method from the ComponentsAPI are + // called. + DCHECK(done_callback_.is_null()); + done_callback_ = base::BindOnce(&ComponentManagerDelegate::PreScanDone, + base::Unretained(delegate_)); + PostComponentTasks(base::BindRepeating(&BindPreScan), "PreScan"); +} + +void ComponentManager::PostScan(const std::vector<UwSId>& found_pups) { + DCHECK(done_callback_.is_null()); + done_callback_ = base::BindOnce(&ComponentManagerDelegate::PostScanDone, + base::Unretained(delegate_)); + PostComponentTasks(base::BindRepeating(&BindPostScan, found_pups), + "PostScan"); +} + +void ComponentManager::PreCleanup() { + DCHECK(done_callback_.is_null()); + done_callback_ = base::BindOnce(&ComponentManagerDelegate::PreCleanupDone, + base::Unretained(delegate_)); + PostComponentTasks(base::BindRepeating(&BindPreCleanup), "PreCleanup"); +} + +void ComponentManager::PostCleanup(ResultCode result_code, + RebooterAPI* rebooter) { + DCHECK(done_callback_.is_null()); + done_callback_ = base::BindOnce(&ComponentManagerDelegate::PostCleanupDone, + base::Unretained(delegate_)); + PostComponentTasks( + base::BindRepeating(&BindPostCleanup, result_code, rebooter), + "PostCleanup"); +} + +void ComponentManager::PostValidation(ResultCode result_code) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!cancelable_task_tracker_.HasTrackedTasks()); + DCHECK_EQ(0UL, num_tasks_pending_); + + for (auto& component : components_) + component->PostValidation(result_code); +} + +void ComponentManager::CloseAllComponents(ResultCode result_code) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (num_tasks_pending_ > 0) { + cancelable_task_tracker_.TryCancelAll(); + while (cancelable_task_tracker_.HasTrackedTasks()) + base::RunLoop().RunUntilIdle(); + done_callback_.Reset(); + } else { + DCHECK(!cancelable_task_tracker_.HasTrackedTasks()); + } + + for (auto& component : components_) + component->OnClose(result_code); + components_.clear(); +} + +void ComponentManager::PostComponentTasks( + const base::RepeatingCallback<base::OnceClosure(ComponentAPI*)> + component_task, + const char* method_name) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!cancelable_task_tracker_.HasTrackedTasks()); + DCHECK_EQ(0UL, num_tasks_pending_); + + if (components_.empty()) { + DCHECK(!done_callback_.is_null()); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(done_callback_)); + return; + } + + // Allow blocking operations, such as file operations, in the component task. + // This is allowed since there is no UI for it to block. + auto task_runner = base::CreateTaskRunnerWithTraits(base::MayBlock()); + for (auto& component : components_) { + if (cancelable_task_tracker_.PostTaskAndReply( + task_runner.get(), FROM_HERE, + component_task.Run(component.get()), // This returns a Closure. + base::BindOnce(&ComponentManager::TaskCompleted, + base::Unretained(this))) == + base::CancelableTaskTracker::kBadTaskId) { + PLOG(ERROR) << "Failed to run component's method: " << method_name; + } else { + // The reply task is never called synchronously, so it's OK to increment + // the number of tasks pending after the task was posted. + ++num_tasks_pending_; + } + } +} + +void ComponentManager::TaskCompleted() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_GT(num_tasks_pending_, 0UL); + + if (--num_tasks_pending_ == 0) { + // The callback must be run asynchronously so that the task tracker is not + // on the call stack anymore in cases where the callback ends up calling + // CloseAllComponents. + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(done_callback_)); + } +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/component_manager.h b/chrome/chrome_cleaner/components/component_manager.h new file mode 100644 index 0000000..c707c601 --- /dev/null +++ b/chrome/chrome_cleaner/components/component_manager.h
@@ -0,0 +1,100 @@ +// Copyright 2018 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 CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_MANAGER_H_ +#define CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_MANAGER_H_ + +#include <vector> + +#include "base/sequence_checker.h" +#include "base/task/cancelable_task_tracker.h" +#include "chrome/chrome_cleaner/components/component_api.h" +#include "chrome/chrome_cleaner/constants/uws_id.h" +#include "chrome/chrome_cleaner/os/rebooter_api.h" +#include "components/chrome_cleaner/public/constants/result_codes.h" + +namespace chrome_cleaner { + +// A delegate API to be called back when all requested tasks are completed. +class ComponentManagerDelegate { + public: + virtual ~ComponentManagerDelegate() {} + virtual void PreScanDone() = 0; + virtual void PostScanDone() = 0; + virtual void PreCleanupDone() = 0; + virtual void PostCleanupDone() = 0; +}; + +// This class is used to register components that are to be executed by the main +// controller either before the scanner or after the cleaner. +class ComponentManager { + public: + // |delegate| must outlive the ComponentManager. + explicit ComponentManager(ComponentManagerDelegate* delegate); + + // |CloseAllComponents| must be called before deleting the component manager. + // Self cleanup is NOT supported! + ~ComponentManager(); + + // Add a new component. The ComponentManager takes ownership of the component. + // This method can't be called while there is an active call to the + // ComponentsAPI methods below that has not been completed by a call to + // |delegate_| yet. + void AddComponent(std::unique_ptr<ComponentAPI> component); + + // All ComponentsAPI methods are duplicated here. Each of these calls run + // asynchronously and call their respective counterpart on |delegate_|. There + // can only be one of these calls active at a time. Callers must wait for + // |delegate_| to be called back before attempting other calls on this API. + void PreScan(); + void PostScan(const std::vector<UwSId>& found_pups); + void PreCleanup(); + void PostCleanup(ResultCode result_code, RebooterAPI* rebooter); + // This call is synchronous so doesn't have an equivalent done call on the + // delegate. TODO(csharp): This is confusing, fix it! b/23372645. + void PostValidation(ResultCode result_code); + + // Call OnClose on all components and then destroy them. Any pending component + // tasks will be canceled and any pending threads will be joined. |delegate_| + // won't be called, even if there was a pending task. This must absolutely + // be called before the object is destroyed. + void CloseAllComponents(ResultCode result_code); + + // Return the number of pending tasks. Mainly used by tests. + size_t num_tasks_pending() const { return num_tasks_pending_; } + + private: + // Common code to post tasks to the worker threads. |component_task| is called + // to create the closure that will run in the worker threads for each + // component. |method_name| is used for logging. + void PostComponentTasks(const base::RepeatingCallback< + base::OnceClosure(ComponentAPI*)> component_task, + const char* method_name); + + // Called back on the main thread when a task is completed. When the last task + // completes, run |done_callback_| asynchronously to avoid re-entrance. + void TaskCompleted(); + + // The components that are to be called before / after the scan / cleanup. + std::vector<std::unique_ptr<ComponentAPI>> components_; + + // The task tracker that can be used to cancel pending tasks. + base::CancelableTaskTracker cancelable_task_tracker_; + + SEQUENCE_CHECKER(sequence_checker_); + + // The delegate to be called when tasks are completed. + ComponentManagerDelegate* delegate_; + + // The closure to callback once all tasks completed. This always contains a + // call to |delegate_|. + base::OnceClosure done_callback_; + + // The number of pending tasks that have not called |TaskCompleted| yet. + size_t num_tasks_pending_ = 0; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_MANAGER_H_
diff --git a/chrome/chrome_cleaner/components/component_manager_unittest.cc b/chrome/chrome_cleaner/components/component_manager_unittest.cc new file mode 100644 index 0000000..9efa7623 --- /dev/null +++ b/chrome/chrome_cleaner/components/component_manager_unittest.cc
@@ -0,0 +1,197 @@ +// Copyright 2018 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/chrome_cleaner/components/component_manager.h" + +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/chrome_cleaner/components/component_api.h" +#include "chrome/chrome_cleaner/test/test_component.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chrome_cleaner { + +namespace { + +const UwSId kFakePupId = 42; + +// This delegate validates that calls were made, and also interrupt the +// currently running message loop, waiting for the delegate methods to be +// called. +class TestComponentManagerDelegate : public ComponentManagerDelegate { + public: + struct Calls { + bool pre_scan = false; + bool post_scan = false; + bool pre_cleanup = false; + bool post_cleanup = false; + }; + explicit TestComponentManagerDelegate(Calls* calls) : calls_(calls) {} + + void set_quit_closure(base::OnceClosure quit_closure) { + quit_closure_ = std::move(quit_closure); + } + + // ComponentManagerDelegate + void PreScanDone() override { + calls_->pre_scan = true; + if (quit_closure_) + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(quit_closure_)); + } + void PostScanDone() override { + calls_->post_scan = true; + if (quit_closure_) + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(quit_closure_)); + } + void PreCleanupDone() override { + calls_->pre_cleanup = true; + if (quit_closure_) + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(quit_closure_)); + } + void PostCleanupDone() override { + calls_->post_cleanup = true; + if (quit_closure_) + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(quit_closure_)); + } + + private: + Calls* calls_; + base::OnceClosure quit_closure_; +}; + +} // namespace + +TEST(ComponentManagerTest, Empty) { + base::test::ScopedTaskEnvironment scoped_task_environment; + + TestComponentManagerDelegate::Calls calls; + TestComponentManagerDelegate delegate(&calls); + ComponentManager component_manager(&delegate); + + base::RunLoop run_loop1; + delegate.set_quit_closure(run_loop1.QuitWhenIdleClosure()); + component_manager.PreScan(); + run_loop1.Run(); + EXPECT_TRUE(calls.pre_scan); + calls.pre_scan = false; + EXPECT_FALSE(calls.post_scan); + EXPECT_FALSE(calls.pre_cleanup); + EXPECT_FALSE(calls.post_cleanup); + + base::RunLoop run_loop2; + delegate.set_quit_closure(run_loop2.QuitWhenIdleClosure()); + component_manager.PostScan(std::vector<UwSId>()); + run_loop2.Run(); + EXPECT_FALSE(calls.pre_scan); + EXPECT_TRUE(calls.post_scan); + calls.post_scan = false; + EXPECT_FALSE(calls.pre_cleanup); + EXPECT_FALSE(calls.post_cleanup); + + base::RunLoop run_loop3; + delegate.set_quit_closure(run_loop3.QuitWhenIdleClosure()); + component_manager.PreCleanup(); + run_loop3.Run(); + EXPECT_FALSE(calls.pre_scan); + EXPECT_FALSE(calls.post_scan); + EXPECT_TRUE(calls.pre_cleanup); + calls.pre_cleanup = false; + EXPECT_FALSE(calls.post_cleanup); + + base::RunLoop run_loop4; + delegate.set_quit_closure(run_loop4.QuitWhenIdleClosure()); + component_manager.PostCleanup(RESULT_CODE_SUCCESS, nullptr); + run_loop4.Run(); + EXPECT_FALSE(calls.pre_scan); + EXPECT_FALSE(calls.post_scan); + EXPECT_FALSE(calls.pre_cleanup); + EXPECT_TRUE(calls.post_cleanup); + + // Nothing to validate, just make sure it can be called. + component_manager.CloseAllComponents(RESULT_CODE_FAILED); +} + +TEST(ComponentManagerTest, All) { + base::test::ScopedTaskEnvironment scoped_task_environment; + + TestComponentManagerDelegate::Calls delegate_calls; + TestComponentManagerDelegate delegate(&delegate_calls); + ComponentManager component_manager(&delegate); + + TestComponent::Calls component_calls; + component_manager.AddComponent( + std::make_unique<TestComponent>(&component_calls)); + + base::RunLoop run_loop1; + delegate.set_quit_closure(run_loop1.QuitWhenIdleClosure()); + component_manager.PreScan(); + run_loop1.Run(); + EXPECT_TRUE(delegate_calls.pre_scan); + EXPECT_TRUE(component_calls.pre_scan); + + base::RunLoop run_loop2; + delegate.set_quit_closure(run_loop2.QuitWhenIdleClosure()); + std::vector<UwSId> pup_ids; + pup_ids.push_back(kFakePupId); + component_manager.PostScan(pup_ids); + run_loop2.Run(); + EXPECT_TRUE(delegate_calls.post_scan); + EXPECT_TRUE(component_calls.post_scan); + ASSERT_EQ(1UL, component_calls.post_scan_found_pups.size()); + EXPECT_EQ(kFakePupId, component_calls.post_scan_found_pups[0]); + + base::RunLoop run_loop3; + delegate.set_quit_closure(run_loop3.QuitWhenIdleClosure()); + component_manager.PreCleanup(); + run_loop3.Run(); + EXPECT_TRUE(delegate_calls.pre_cleanup); + EXPECT_TRUE(component_calls.pre_cleanup); + + base::RunLoop run_loop4; + delegate.set_quit_closure(run_loop4.QuitWhenIdleClosure()); + component_manager.PostCleanup(RESULT_CODE_SUCCESS, nullptr); + run_loop4.Run(); + EXPECT_TRUE(delegate_calls.post_cleanup); + EXPECT_TRUE(component_calls.post_cleanup); + EXPECT_EQ(RESULT_CODE_SUCCESS, component_calls.result_code); + component_calls.result_code = RESULT_CODE_INVALID; + + component_manager.PostValidation(RESULT_CODE_FAILED); + EXPECT_TRUE(component_calls.post_validation); + EXPECT_EQ(RESULT_CODE_FAILED, component_calls.result_code); + + component_manager.CloseAllComponents(RESULT_CODE_CANCELED); + EXPECT_TRUE(component_calls.on_close); + EXPECT_TRUE(component_calls.destroyed); + EXPECT_EQ(RESULT_CODE_CANCELED, component_calls.result_code); +} + +TEST(ComponentManagerTest, Interrupt) { + base::test::ScopedTaskEnvironment scoped_task_environment; + + TestComponentManagerDelegate::Calls delegate_calls; + TestComponentManagerDelegate delegate(&delegate_calls); + ComponentManager component_manager(&delegate); + + TestComponent::Calls component_calls; + for (size_t i = 0; i < 1000; ++i) { + component_manager.AddComponent( + std::make_unique<TestComponent>(&component_calls)); + } + + component_manager.PreScan(); + EXPECT_FALSE(delegate_calls.pre_scan); + component_manager.CloseAllComponents(RESULT_CODE_INVALID); + EXPECT_FALSE(delegate_calls.pre_scan); + // We rely on test harness leak detector to make sure TestComponents were + // properly destroyed. + EXPECT_GT(component_manager.num_tasks_pending(), 0UL); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/component_unpacker.cc b/chrome/chrome_cleaner/components/component_unpacker.cc new file mode 100644 index 0000000..7989b63 --- /dev/null +++ b/chrome/chrome_cleaner/components/component_unpacker.cc
@@ -0,0 +1,122 @@ +// Copyright 2018 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. +// Stolen from chrome/browser/component_updater/component_unpacker.cc + +#include "chrome/chrome_cleaner/components/component_unpacker.h" + +#include <memory> +#include <vector> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_file.h" +#include "base/logging.h" +#include "chrome/chrome_cleaner/components/crx_file.h" +#include "chrome/chrome_cleaner/os/file_path_sanitization.h" +#include "crypto/secure_hash.h" +#include "crypto/signature_verifier.h" +#include "third_party/zlib/google/zip.h" + +using crypto::SecureHash; + +namespace chrome_cleaner { + +namespace { + +// This class makes sure that the CRX digital signature is valid and well +// formed. +class CRXValidator { + public: + explicit CRXValidator(FILE* crx_file) : valid_(false) { + CrxFile::Header header; + size_t len = fread(&header, 1, sizeof(header), crx_file); + if (len < sizeof(header)) + return; + + CrxFile::Error error; + std::unique_ptr<CrxFile> crx(CrxFile::Parse(header, &error)); + if (!crx.get()) + return; + DCHECK(!CrxFile::HeaderIsDelta(header)); + + std::vector<uint8_t> key(header.key_size); + len = fread(&key[0], sizeof(uint8_t), header.key_size, crx_file); + if (len < header.key_size) + return; + + std::vector<uint8_t> signature(header.signature_size); + len = + fread(&signature[0], sizeof(uint8_t), header.signature_size, crx_file); + if (len < header.signature_size) + return; + + crypto::SignatureVerifier verifier; + if (!verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, + signature, key)) { + // Signature verification initialization failed. This is most likely + // caused by a public key in the wrong format (should encode algorithm). + return; + } + + const size_t kBufSize = 8 * 1024; + std::vector<uint8_t> buf(kBufSize); + while ((len = fread(buf.data(), 1, kBufSize, crx_file)) > 0) + verifier.VerifyUpdate(buf); + + if (!verifier.VerifyFinal()) + return; + + public_key_.swap(key); + valid_ = true; + } + + bool valid() const { return valid_; } + + const std::vector<uint8_t>& public_key() const { return public_key_; } + + private: + bool valid_; + std::vector<uint8_t> public_key_; +}; + +} // namespace + +ComponentUnpacker::ComponentUnpacker(const std::vector<uint8_t>& pk_hash, + const base::FilePath& path) + : pk_hash_(pk_hash), path_(path) {} + +bool ComponentUnpacker::Unpack(const base::FilePath& ouput_folder) { + return Verify() && zip::Unzip(path_, ouput_folder); +} + +bool ComponentUnpacker::Verify() { + if (pk_hash_.empty() || path_.empty()) + return false; + // First, validate the CRX header and signature. As of today this is SHA1 with + // RSA 1024. + base::ScopedFILE file(base::OpenFile(path_, "rb")); + if (!file.get()) + return false; + CRXValidator validator(file.get()); + file.reset(); + if (!validator.valid()) + return false; + + // File is valid and the digital signature matches. Now make sure the public + // key hash matches the expected hash. If they do we fully trust this CRX. + uint8_t hash[32] = {}; + std::unique_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256)); + sha256->Update(&(validator.public_key()[0]), validator.public_key().size()); + sha256->Finish(hash, base::size(hash)); + + if (!std::equal(pk_hash_.begin(), pk_hash_.end(), hash)) { + LOG(WARNING) << "Hash mismatch: " << SanitizePath(path_); + return false; + } + return true; +} + +ComponentUnpacker::~ComponentUnpacker() {} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/component_unpacker.h b/chrome/chrome_cleaner/components/component_unpacker.h new file mode 100644 index 0000000..34260a8 --- /dev/null +++ b/chrome/chrome_cleaner/components/component_unpacker.h
@@ -0,0 +1,52 @@ +// Copyright 2018 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. +// Stolen from chrome/browser/component_updater/component_unpacker.h + +#ifndef CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_UNPACKER_H_ +#define CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_UNPACKER_H_ + +#include <stdint.h> + +#include <string> +#include <vector> + +#include "base/files/file_path.h" + +namespace chrome_cleaner { + +// In charge of unpacking the component CRX package and verifying that it is +// well formed and the cryptographic signature is correct. +// +// This class is inspired by and overlaps with code in the extension's +// SandboxedUnpacker. +// The main differences are: +// - The public key hash is full SHA256. +// - Does not use a sandboxed unpacker. A valid component is fully trusted. +class ComponentUnpacker { + public: + // Constructs an unpacker for a specific component unpacking operation. + // |pk_hash| is the expected public key SHA256 hash. |path| is the current + // location of the CRX. + ComponentUnpacker(const std::vector<uint8_t>& pk_hash, + const base::FilePath& path); + virtual ~ComponentUnpacker(); + + // Unpack the file to the provided folder. Return true on success. + bool Unpack(const base::FilePath& ouput_folder); + + private: + // The first step of unpacking is to verify the file. Return false if an + // error is encountered, the file is malformed, or the file is incorrectly + // signed. + bool Verify(); + + std::vector<uint8_t> pk_hash_; + base::FilePath path_; + + DISALLOW_COPY_AND_ASSIGN(ComponentUnpacker); +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_COMPONENTS_COMPONENT_UNPACKER_H_
diff --git a/chrome/chrome_cleaner/components/crx_file.cc b/chrome/chrome_cleaner/components/crx_file.cc new file mode 100644 index 0000000..abad50a --- /dev/null +++ b/chrome/chrome_cleaner/components/crx_file.cc
@@ -0,0 +1,87 @@ +// Copyright 2018 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. +// +// Stolen from extensions/common/crx_file.cc +// TODO(crbug.com/889575): The above file no longer exists. It's been +// refactored and now lives in components/crx_file. Should pull in that +// component directly. + +#include "chrome/chrome_cleaner/components/crx_file.h" + +#include "base/memory/ptr_util.h" + +namespace chrome_cleaner { + +namespace { + +// The current version of the crx format. +static const uint32_t kCurrentVersion = 2; + +// The current version of the crx diff format. +static const uint32_t kCurrentDiffVersion = 0; + +// The maximum size the crx parser will tolerate for a public key. +static const uint32_t kMaxPublicKeySize = 1 << 16; + +// The maximum size the crx parser will tolerate for a signature. +static const uint32_t kMaxSignatureSize = 1 << 16; + +} // namespace + +// The magic string embedded in the header. +const char kCrxFileHeaderMagic[] = "Cr24"; +const char kCrxDiffFileHeaderMagic[] = "CrOD"; + +std::unique_ptr<CrxFile> CrxFile::Parse(const CrxFile::Header& header, + CrxFile::Error* error) { + if (HeaderIsValid(header, error)) + return base::WrapUnique<CrxFile>(new CrxFile(header)); + return nullptr; +} + +std::unique_ptr<CrxFile> CrxFile::Create(const uint32_t key_size, + const uint32_t signature_size, + CrxFile::Error* error) { + CrxFile::Header header; + memcpy(&header.magic, kCrxFileHeaderMagic, kCrxFileHeaderMagicSize); + header.version = kCurrentVersion; + header.key_size = key_size; + header.signature_size = signature_size; + if (HeaderIsValid(header, error)) + return base::WrapUnique<CrxFile>(new CrxFile(header)); + return nullptr; +} + +CrxFile::CrxFile(const Header& header) : header_(header) {} + +bool CrxFile::HeaderIsDelta(const CrxFile::Header& header) { + return !strncmp(kCrxDiffFileHeaderMagic, header.magic, sizeof(header.magic)); +} + +bool CrxFile::HeaderIsValid(const CrxFile::Header& header, + CrxFile::Error* error) { + bool valid = false; + bool diffCrx = false; + if (!strncmp(kCrxDiffFileHeaderMagic, header.magic, sizeof(header.magic))) + diffCrx = true; + if (strncmp(kCrxFileHeaderMagic, header.magic, sizeof(header.magic)) && + !diffCrx) + *error = kWrongMagic; + else if (header.version != kCurrentVersion && + !(diffCrx && header.version == kCurrentDiffVersion)) + *error = kInvalidVersion; + else if (header.key_size > kMaxPublicKeySize) + *error = kInvalidKeyTooLarge; + else if (header.key_size == 0) + *error = kInvalidKeyTooSmall; + else if (header.signature_size > kMaxSignatureSize) + *error = kInvalidSignatureTooLarge; + else if (header.signature_size == 0) + *error = kInvalidSignatureTooSmall; + else + valid = true; + return valid; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/crx_file.h b/chrome/chrome_cleaner/components/crx_file.h new file mode 100644 index 0000000..363586ac --- /dev/null +++ b/chrome/chrome_cleaner/components/crx_file.h
@@ -0,0 +1,81 @@ +// Copyright 2018 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. +// Stolen from extensions/common/crx_file.h + +#ifndef CHROME_CHROME_CLEANER_COMPONENTS_CRX_FILE_H_ +#define CHROME_CHROME_CLEANER_COMPONENTS_CRX_FILE_H_ + +#include <stdint.h> +#include <sys/types.h> + +#include <memory> + +namespace chrome_cleaner { + +// CRX files have a header that includes a magic key, version number, and +// some signature sizing information. Use CrxFile object to validate whether +// the header is valid or not. +class CrxFile { + public: + // The size of the magic character sequence at the beginning of each crx + // file, in bytes. This should be a multiple of 4. + static const size_t kCrxFileHeaderMagicSize = 4; + + // This header is the first data at the beginning of an extension. Its + // contents are purposely 32-bit aligned so that it can just be slurped into + // a struct without manual parsing. + struct Header { + char magic[kCrxFileHeaderMagicSize]; + uint32_t version; + uint32_t key_size; // The size of the public key, in bytes. + uint32_t signature_size; // The size of the signature, in bytes. + // An ASN.1-encoded PublicKeyInfo structure follows. + // The signature follows. + }; + + enum Error { + kWrongMagic, + kInvalidVersion, + kInvalidKeyTooLarge, + kInvalidKeyTooSmall, + kInvalidSignatureTooLarge, + kInvalidSignatureTooSmall, + }; + + // Construct a new CRX file header object with bytes of a header + // read from a CRX file. If a null std::unique_ptr is returned, |error| + // contains an error code with additional information. + static std::unique_ptr<CrxFile> Parse(const Header& header, Error* error); + + // Construct a new header for the given key and signature sizes. + // Returns a null std::unique_ptr if erroneous values of |key_size| and/or + // |signature_size| are provided. |error| contains an error code with + // additional information. + // Use this constructor and then .header() to obtain the Header + // for writing out to a CRX file. + static std::unique_ptr<CrxFile> Create(const uint32_t key_size, + const uint32_t signature_size, + Error* error); + + // Returns the header structure for writing out to a CRX file. + const Header& header() const { return header_; } + + // Checks a valid |header| to determine whether or not the CRX represents a + // differential CRX. + static bool HeaderIsDelta(const Header& header); + + private: + Header header_; + + // Constructor is private. Clients should use static factory methods above. + explicit CrxFile(const Header& header); + + // Checks the |header| for validity and returns true if the values are valid. + // If false is returned, more detailed error code is returned in |error|. + static bool HeaderIsValid(const Header& header, Error* error); +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_COMPONENTS_CRX_FILE_H_
diff --git a/chrome/chrome_cleaner/components/recovery_component.cc b/chrome/chrome_cleaner/components/recovery_component.cc new file mode 100644 index 0000000..cc75282 --- /dev/null +++ b/chrome/chrome_cleaner/components/recovery_component.cc
@@ -0,0 +1,289 @@ +// Copyright 2018 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/chrome_cleaner/components/recovery_component.h" + +#include <stdint.h> + +#include <memory> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback_helpers.h" +#include "base/command_line.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/message_loop/message_loop.h" +#include "base/numerics/safe_conversions.h" +#include "base/process/kill.h" +#include "base/process/launch.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "chrome/chrome_cleaner/components/component_unpacker.h" +#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" +#include "chrome/chrome_cleaner/http/http_agent.h" +#include "chrome/chrome_cleaner/http/http_agent_factory.h" +#include "chrome/chrome_cleaner/http/http_response.h" +#include "chrome/chrome_cleaner/http/http_status_codes.h" +#include "chrome/chrome_cleaner/pup_data/pup_data.h" + +namespace chrome_cleaner { + +namespace { + +const char kComponentDownloadUrl[] = + "https://clients2.google.com/service/update2/crx?response=redirect&os=win" + "&arch=x86&installsource=swreporter&x=id%3Dnpdjjkjlcidkjlamlmmdelcjbcpdjocm" + "%26v%3D0.0.0.0%26uc"; + +// CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm. +const uint8_t kSha2Hash[] = {0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c, + 0xbc, 0xc3, 0x4b, 0x29, 0x12, 0xf3, 0x9e, 0x2c, + 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c, + 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7}; + +// Name of the executable file as well as the command line arg to use for Foil. +const wchar_t kChromeRecoveryExe[] = L"ChromeRecovery.exe"; +const char kChromeRecoveryArg[] = "/installsource swreporter"; + +const int kDownloadCrxWaitTimeInMin = 2; +const int kExecutionCrxWaitTimeInMin = 1; + +const HttpAgentFactory* current_http_agent_factory{nullptr}; + +constexpr net::NetworkTrafficAnnotationTag kComponentDownloadTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("download_recovery_component", R"( + semantics { + sender: "Chrome Cleanup" + description: + "Chrome on Windows is able to detect and remove software that " + "violates Google's Unwanted Software Policy " + "(https://www.google.com/about/unwanted-software-policy.html). " + "When potentially unwanted software is detected and the user " + "accepts Chrome's offer to remove it, as part of the cleanup " + "Chrome sends a request to Google to download the Chrome " + "Recovery component, which can repair the Chrome update system " + "to ensure that unwanted software does not block Chrome from " + "getting security updates." + trigger: + "The user either accepted a prompt to remove unwanted software, " + "or went to \"Clean up computer\" in the settings page and chose " + "to \"Find and remove harmful software\"." + data: "None" + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: NO + setting: + "Chrome Cleanup is offered in \"Reset and clean up\" in settings " + "under Advanced and never happens without explicit user consent. " + chrome_policy { + ChromeCleanupEnabled { + ChromeCleanupEnabled: false + } + } + } + )"); + +bool SaveHttpResponseDataToFile(const base::FilePath& file_path, + chrome_cleaner::HttpResponse* response) { + base::File file(file_path, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + + uint32_t count = RecoveryComponent::kReadDataFromResponseBufferSize; + std::vector<char> buffer(count); + while (true) { + if (!response->ReadData(buffer.data(), &count)) { + LOG(ERROR) << "ReadData failed"; + return false; + } else if (!count) { + break; + } + + if (file.WriteAtCurrentPos(buffer.data(), base::checked_cast<int>(count)) == + -1) { + PLOG(ERROR) << "WriteAtCurrentPos"; + return false; + } + } + + return true; +} + +const HttpAgentFactory* GetHttpAgentFactory() { + // This is "leaked" on purpose to avoid static destruction order woes. + // Neither HttpAgentFactory nor its parent classes dtors do any work. + static HttpAgentFactory* http_agent_factory = new HttpAgentFactory(); + + if (!current_http_agent_factory) { + current_http_agent_factory = http_agent_factory; + } + + return current_http_agent_factory; +} + +} // namespace + +// static +bool RecoveryComponent::IsAvailable() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); +// Only add the recovery component in official builds, unless it's forced, and +// not if it's explicitly disabled. +#if defined(CHROME_CLEANER_OFFICIAL_BUILD) + return !command_line->HasSwitch(kNoRecoveryComponentSwitch); +#else + return command_line->HasSwitch(kForceRecoveryComponentSwitch); +#endif +} + +RecoveryComponent::RecoveryComponent() + : recovery_io_thread_("RecoveryComponentIO"), + done_expanding_crx_(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED) {} + +// static +void RecoveryComponent::SetHttpAgentFactoryForTesting( + const HttpAgentFactory* factory) { + current_http_agent_factory = factory; +} + +void RecoveryComponent::PreScan() { + bool success = recovery_io_thread_.StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + DCHECK(success) << "Can't start File Thread!"; + + recovery_io_thread_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&RecoveryComponent::FetchOnIOThread, + base::Unretained(this))); +} + +void RecoveryComponent::PostScan(const std::vector<UwSId>& found_pups) { + // If there won't be any cleanup, then run the recovery component now. + if (!PUPData::HasFlaggedPUP(found_pups, &PUPData::HasRemovalFlag)) { + Run(); + } +} + +void RecoveryComponent::PreCleanup() {} + +void RecoveryComponent::PostCleanup(ResultCode result_code, + RebooterAPI* rebooter) { + if (result_code == RESULT_CODE_PENDING_REBOOT) { + LOG(INFO) << "Not executing ChromeRecovery before reboot."; + return; + } + Run(); +} + +void RecoveryComponent::PostValidation(ResultCode result_code) { + PreScan(); + Run(); +} + +void RecoveryComponent::Run() { + DCHECK(!ran_); + ran_ = true; + // We must make sure that the crx expansion is complete. + if (!done_expanding_crx_.TimedWait( + base::TimeDelta::FromMinutes(kDownloadCrxWaitTimeInMin))) { + LOG(WARNING) << "Timed out waiting for crx expansion completion."; + return; + } + + if (!component_path_.IsValid()) { + LOG(WARNING) << "No access to the component path."; + return; + } + + base::FilePath chrome_recovery( + component_path_.GetPath().Append(kChromeRecoveryExe)); + DCHECK(base::PathExists(chrome_recovery)); + + base::CommandLine recovery_command_line(chrome_recovery); + recovery_command_line.AppendArg(kChromeRecoveryArg); + base::Process recovery_process = + base::LaunchProcess(recovery_command_line, base::LaunchOptions()); + if (!recovery_process.IsValid()) { + LOG(WARNING) << "Failed to launch " << kChromeRecoveryExe << " " + << kChromeRecoveryArg; + return; + } + + int exit_code = -1; + bool success = recovery_process.WaitForExitWithTimeout( + base::TimeDelta::FromMinutes(kExecutionCrxWaitTimeInMin), &exit_code); + LOG_IF(INFO, success) << "ChromeRecovery returned code: " << exit_code; + PLOG_IF(ERROR, !success) << "ChromeRecovery failed to start in time."; +} + +void RecoveryComponent::OnClose(ResultCode result_code) {} + +void RecoveryComponent::UnpackComponent(const base::FilePath& crx_file) { + std::vector<uint8_t> pk_hash; + pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); + + ComponentUnpacker unpacker(pk_hash, crx_file); + bool success = unpacker.Unpack(component_path_.GetPath()); + DCHECK(success) << "Failed to unpack component."; +} + +void RecoveryComponent::FetchOnIOThread() { + DCHECK_EQ(base::MessageLoop::current(), recovery_io_thread_.message_loop()); + std::unique_ptr<chrome_cleaner::HttpAgent> http_agent = + GetHttpAgentFactory()->CreateHttpAgent(); + + LOG(INFO) << "Sending request to download Recovery Component."; + const GURL download_url(kComponentDownloadUrl); + std::unique_ptr<chrome_cleaner::HttpResponse> http_response = http_agent->Get( + base::UTF8ToWide(download_url.host()), + base::checked_cast<uint16_t>(download_url.EffectiveIntPort()), + base::UTF8ToWide(download_url.PathForRequest()), + download_url.SchemeIsCryptographic(), + L"", // No extra headers. + kComponentDownloadTrafficAnnotation); + + // Make sure to signal the event when this method returns. + base::ScopedClosureRunner set_event( + base::BindOnce(base::IgnoreResult(&base::WaitableEvent::Signal), + base::Unretained(&done_expanding_crx_))); + + if (!http_response.get()) { + LOG(WARNING) << "Recovery Component failed to download (no response)"; + return; + } + + uint16_t status_code = 0; + if (!http_response->GetStatusCode(&status_code) || + status_code != static_cast<uint16_t>(HttpStatus::kOk)) { + LOG(WARNING) << "Recovery Component failed to download. Response: " + << status_code; + return; + } + + LOG(INFO) << "Recovery Component successfully downloaded."; + + base::FilePath crx_file; + if (!base::CreateTemporaryFile(&crx_file)) { + LOG(ERROR) << "Failed to create temporary file to save crx"; + return; + } + + base::ScopedClosureRunner delete_file( + base::BindOnce(base::IgnoreResult(&base::DeleteFile), crx_file, false)); + + if (!SaveHttpResponseDataToFile(crx_file, http_response.get())) { + LOG(WARNING) << "Failed to save downloaded recovery component"; + return; + } + + if (component_path_.CreateUniqueTempDir()) + UnpackComponent(crx_file); + else + NOTREACHED() << "Couldn't create a temp dir?"; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/recovery_component.h b/chrome/chrome_cleaner/components/recovery_component.h new file mode 100644 index 0000000..cb58dee5 --- /dev/null +++ b/chrome/chrome_cleaner/components/recovery_component.h
@@ -0,0 +1,80 @@ +// Copyright 2018 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 CHROME_CHROME_CLEANER_COMPONENTS_RECOVERY_COMPONENT_H_ +#define CHROME_CHROME_CLEANER_COMPONENTS_RECOVERY_COMPONENT_H_ + +#include <memory> +#include <vector> + +#include "base/files/scoped_temp_dir.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" +#include "chrome/chrome_cleaner/components/component_api.h" +#include "url/gurl.h" + +namespace chrome_cleaner { + +class HttpAgentFactory; + +// This class starts downloading the recovery component before the scanner +// starts, and it runs it after the cleaner completed, except if a reboot is +// pending. +class RecoveryComponent : public ComponentAPI { + public: + // Return true when the recovery component is available for the current build + // and command line flags combination. + static bool IsAvailable(); + + RecoveryComponent(); + ~RecoveryComponent() override = default; + + // Replace the HttpAgent factory with a new factory. Passing in an empty + // factory (nullptr) will reset to the default factory. Exposed so tests can + // create mock HttpAgent objects. This method is not thread-safe. + static void SetHttpAgentFactoryForTesting(const HttpAgentFactory* factory); + + // ComponentAPI methods. + void PreScan() override; + void PostScan(const std::vector<UwSId>& found_pups) override; + void PreCleanup() override; + void PostCleanup(ResultCode result_code, RebooterAPI* rebooter) override; + void PostValidation(ResultCode result_code) override; + void OnClose(ResultCode result_code) override; + + // Exposed for testing. The size of the buffer used when reading data from the + // response. + static const size_t kReadDataFromResponseBufferSize = 8192; + + protected: + // Try to run the recovery component if it's ready, or wait for it. Protected + // virtual to test the logic of the public methods. + virtual void Run(); + + // A protected abstraction of the unpacking so that tests can override it. + virtual void UnpackComponent(const base::FilePath& crx_file); + + // Return when |FetchOnIOThread| is done. Mainly used by tests. + void WaitForDoneExpandingCrxForTest() { done_expanding_crx_.Wait(); } + + private: + // The fetch must be done on the IO thread as it's synchronous. + void FetchOnIOThread(); + + // Thread on which the recovery component is fetched, and the CRX is unpacked. + base::Thread recovery_io_thread_; + + // Where the downloaded CRX was unzipped. + base::ScopedTempDir component_path_; + + // Signaled when the expansion of the crx is complete. + base::WaitableEvent done_expanding_crx_; + + // To check whether the component already ran or not. + bool ran_ = false; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_COMPONENTS_RECOVERY_COMPONENT_H_
diff --git a/chrome/chrome_cleaner/components/recovery_component_unittest.cc b/chrome/chrome_cleaner/components/recovery_component_unittest.cc new file mode 100644 index 0000000..71ff18a --- /dev/null +++ b/chrome/chrome_cleaner/components/recovery_component_unittest.cc
@@ -0,0 +1,186 @@ +// Copyright 2018 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/chrome_cleaner/components/recovery_component.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/files/file.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/message_loop/message_loop.h" +#include "base/test/test_simple_task_runner.h" +#include "chrome/chrome_cleaner/http/mock_http_agent_factory.h" +#include "chrome/chrome_cleaner/test/test_pup_data.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chrome_cleaner { + +namespace { + +const UwSId kRemovableUwSId = 42; +const UwSId kReportOnlyUwSId = 21; + +} // namespace + +class TestRecoveryComponent : public RecoveryComponent { + public: + TestRecoveryComponent() = default; + + using RecoveryComponent::WaitForDoneExpandingCrxForTest; + + bool run_called() const { return run_called_; } + bool unpack_component_called() const { return unpack_component_called_; } + const std::string& crx_file_contents() const { return crx_file_contents_; } + + protected: + // RecoveryComponent. + void Run() override { run_called_ = true; } + void UnpackComponent(const base::FilePath& crx_file) override { + unpack_component_called_ = true; + + if (base::PathExists(crx_file)) { + ASSERT_TRUE(base::ReadFileToString(crx_file, &crx_file_contents_)); + } + } + + private: + bool run_called_{false}; + bool unpack_component_called_{false}; + std::string crx_file_contents_; +}; + +class RecoveryComponentTest : public testing::Test { + public: + void SetUp() override { + RecoveryComponent::SetHttpAgentFactoryForTesting(factory_.get()); + } + + void TearDown() override { + RecoveryComponent::SetHttpAgentFactoryForTesting(nullptr); + } + + protected: + RecoveryComponentTest() : task_runner_(new base::TestSimpleTaskRunner) {} + + // A message loop is needed for the current task runner to be available. + base::MessageLoopForUI ui_message_loop_; + + // The recover component under test. This declaration must be after the + // |ui_message_loop_| because the |RecoveryComponent| constructor needs + // a reference to the current run loop. + TestRecoveryComponent recovery_component_; + + // A task runner and a URL fetcher factory are necessary to test URL requests. + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + + MockHttpAgentConfig config_; + std::unique_ptr<HttpAgentFactory> factory_{ + std::make_unique<MockHttpAgentFactory>(&config_)}; +}; + +TEST_F(RecoveryComponentTest, Success) { + MockHttpAgentConfig::Calls calls(HttpStatus::kOk); + config_.AddCalls(calls); + + recovery_component_.PreScan(); + recovery_component_.WaitForDoneExpandingCrxForTest(); + EXPECT_TRUE(recovery_component_.unpack_component_called()); +} + +TEST_F(RecoveryComponentTest, Failure) { + MockHttpAgentConfig::Calls calls(HttpStatus::kOk); + calls.request_succeeds = false; + config_.AddCalls(calls); + + recovery_component_.PreScan(); + recovery_component_.WaitForDoneExpandingCrxForTest(); + EXPECT_FALSE(recovery_component_.unpack_component_called()); +} + +TEST_F(RecoveryComponentTest, CrxDataSavedToDisk) { + const std::string test_data = "test data"; + + MockHttpAgentConfig::Calls calls(HttpStatus::kOk); + calls.read_data_result = test_data; + config_.AddCalls(calls); + + recovery_component_.PreScan(); + recovery_component_.WaitForDoneExpandingCrxForTest(); + EXPECT_TRUE(recovery_component_.unpack_component_called()); + EXPECT_EQ(test_data, recovery_component_.crx_file_contents()); +} + +TEST_F(RecoveryComponentTest, CrxDataPartiallySavedToDisk) { + // Ensure the buffer is large enough, so a second buffer needs to be read. + const std::string test_data = + std::string(RecoveryComponent::kReadDataFromResponseBufferSize + 1, 'x'); + + MockHttpAgentConfig::Calls calls(HttpStatus::kOk); + calls.read_data_result = test_data; + calls.read_data_success_sequence.push_back(true); + calls.read_data_success_sequence.push_back(false); + config_.AddCalls(calls); + + recovery_component_.PreScan(); + recovery_component_.WaitForDoneExpandingCrxForTest(); + EXPECT_FALSE(recovery_component_.unpack_component_called()); +} + +TEST_F(RecoveryComponentTest, RunCalledForRemovablePUP) { + const UwSId kRemovableUwSId = 42; + std::vector<UwSId> found_pups; + TestPUPData test_pup_data; + + // When a removable PUP was found, the post scan shouldn't run, it should + // wait for the post-cleanup. + test_pup_data.AddPUP(kRemovableUwSId, PUPData::FLAGS_ACTION_REMOVE, nullptr, + PUPData::kMaxFilesToRemoveSmallUwS); + found_pups.push_back(kRemovableUwSId); + recovery_component_.PostScan(found_pups); + EXPECT_FALSE(recovery_component_.run_called()); + recovery_component_.PostCleanup(RESULT_CODE_SUCCESS, nullptr); + EXPECT_TRUE(recovery_component_.run_called()); +} + +TEST_F(RecoveryComponentTest, RunCalledForNoPUPs) { + std::vector<UwSId> found_pups; + TestPUPData test_pup_data; + + // When no PUPs are found, the post scan should run, but not the post-cleanup. + found_pups.clear(); + recovery_component_.PostScan(found_pups); + EXPECT_TRUE(recovery_component_.run_called()); +} + +TEST_F(RecoveryComponentTest, RunCalledForReportOnlyUwS) { + std::vector<UwSId> found_pups; + TestPUPData test_pup_data; + + // When only report only PUPs are found, the post scan should run, but not the + // post-cleanup. + test_pup_data.AddPUP(kReportOnlyUwSId, PUPData::FLAGS_NONE, nullptr, + PUPData::kMaxFilesToRemoveSmallUwS); + found_pups.push_back(kReportOnlyUwSId); + recovery_component_.PostScan(found_pups); + EXPECT_TRUE(recovery_component_.run_called()); +} + +TEST_F(RecoveryComponentTest, RunNotCalledPreReboot) { + std::vector<UwSId> found_pups; + TestPUPData test_pup_data; + + // And finally, when a reboot will be needed, none should call run. + test_pup_data.AddPUP(kRemovableUwSId, PUPData::FLAGS_ACTION_REMOVE, nullptr, + PUPData::kMaxFilesToRemoveSmallUwS); + found_pups.push_back(kRemovableUwSId); + recovery_component_.PostScan(found_pups); + EXPECT_FALSE(recovery_component_.run_called()); + recovery_component_.PostCleanup(RESULT_CODE_PENDING_REBOOT, nullptr); + EXPECT_FALSE(recovery_component_.run_called()); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/system_report_component.cc b/chrome/chrome_cleaner/components/system_report_component.cc new file mode 100644 index 0000000..fbb003e --- /dev/null +++ b/chrome/chrome_cleaner/components/system_report_component.cc
@@ -0,0 +1,835 @@ +// Copyright 2018 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/chrome_cleaner/components/system_report_component.h" + +#include <windows.h> + +#include <psapi.h> +#include <stdint.h> +#include <winhttp.h> +#include <wrl/client.h> + +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback_helpers.h" +#include "base/command_line.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/process/process_iterator.h" +#include "base/strings/strcat.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread_restrictions.h" +#include "base/time/time.h" +#include "base/values.h" +#include "base/win/registry.h" +#include "base/win/scoped_bstr.h" +#include "base/win/scoped_handle.h" +#include "base/win/scoped_variant.h" +#include "base/win/windows_version.h" +#include "chrome/chrome_cleaner/chrome_utils/chrome_util.h" +#include "chrome/chrome_cleaner/chrome_utils/extensions_util.h" +#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" +#include "chrome/chrome_cleaner/constants/common_registry_names.h" +#include "chrome/chrome_cleaner/json_parser/json_parser_api.h" +#include "chrome/chrome_cleaner/logging/logging_service_api.h" +#include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h" +#include "chrome/chrome_cleaner/logging/scoped_timed_task_logger.h" +#include "chrome/chrome_cleaner/os/disk_util.h" +#include "chrome/chrome_cleaner/os/file_path_sanitization.h" +#include "chrome/chrome_cleaner/os/layered_service_provider_wrapper.h" +#include "chrome/chrome_cleaner/os/nt_internals.h" +#include "chrome/chrome_cleaner/os/pre_fetched_paths.h" +#include "chrome/chrome_cleaner/os/process.h" +#include "chrome/chrome_cleaner/os/registry_util.h" +#include "chrome/chrome_cleaner/os/scoped_disable_wow64_redirection.h" +#include "chrome/chrome_cleaner/os/scoped_service_handle.h" +#include "chrome/chrome_cleaner/os/system_util.h" +#include "chrome/chrome_cleaner/os/system_util_cleaner.h" +#include "chrome/chrome_cleaner/os/task_scheduler.h" +#include "components/chrome_cleaner/public/constants/constants.h" + +using base::WaitableEvent; + +namespace chrome_cleaner { +namespace { + +// The initial number of services when enumerating services. +const unsigned int kInitialNumberOfServices = 100; + +const wchar_t kServicesKeyPath[] = L"system\\currentcontrolset\\services\\"; + +const wchar_t kAbsolutePrefix[] = L"\\??\\"; +const wchar_t kSystemRootPrefix[] = L"\\systemroot\\"; + +const wchar_t kNameServerPath[] = + L"system\\currentcontrolset\\services\\tcpip\\parameters\\interfaces"; +const wchar_t kNameServer[] = L"nameserver"; + +const bool kHasFileInformation = true; +const bool kNoFileInformation = false; + +struct RegistryKey { + HKEY hkey; + const wchar_t* key_path; +}; + +struct RegistryValue { + HKEY hkey; + const wchar_t* key_path; + const wchar_t* value_name; +}; + +const RegistryKey startup_registry_keys[] = { + {HKEY_LOCAL_MACHINE, L"software\\microsoft\\windows\\currentversion\\run"}, + {HKEY_CURRENT_USER, L"software\\microsoft\\windows\\currentversion\\run"}, + {HKEY_LOCAL_MACHINE, + L"software\\microsoft\\windows\\currentversion\\runonce"}, + {HKEY_CURRENT_USER, + L"software\\microsoft\\windows\\currentversion\\runonce"}, + {HKEY_LOCAL_MACHINE, + L"software\\microsoft\\windows\\currentversion\\runonceex"}, + {HKEY_CURRENT_USER, + L"software\\microsoft\\windows\\currentversion\\runonceex"}, + {HKEY_LOCAL_MACHINE, + L"software\\microsoft\\windows\\currentversion\\runservices"}, + {HKEY_CURRENT_USER, + L"software\\microsoft\\windows\\currentversion\\runservices"}, + {HKEY_LOCAL_MACHINE, + L"software\\microsoft\\windows\\currentversion\\runservicesonce"}, + {HKEY_CURRENT_USER, + L"software\\microsoft\\windows\\currentversion\\runservicesonce"}}; + +const RegistryValue system_path_values[] = { + {HKEY_LOCAL_MACHINE, L"system\\currentcontrolset\\control\\session manager", + L"bootexecute"}, + {HKEY_LOCAL_MACHINE, L"system\\currentcontrolset\\control\\session manager", + L"setupexecute"}, + {HKEY_LOCAL_MACHINE, kAppInitDllsKeyPath, kAppInitDllsValueName}, + {HKEY_LOCAL_MACHINE, L"system\\currentcontrolset\\control\\session manager", + L"appcertdlls"}}; + +const RegistryValue system_values[] = { + {HKEY_LOCAL_MACHINE, + L"software\\policies\\microsoft\\windows\\windowsupdate", + L"disablewindowsupdateaccess"}}; + +const RegistryKey extension_policy_keys[] = { + {HKEY_LOCAL_MACHINE, kChromePoliciesWhitelistKeyPath}, + {HKEY_CURRENT_USER, kChromePoliciesWhitelistKeyPath}, + {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath}, + {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath}, + {HKEY_LOCAL_MACHINE, kChromiumPoliciesWhitelistKeyPath}, + {HKEY_CURRENT_USER, kChromiumPoliciesWhitelistKeyPath}, + {HKEY_LOCAL_MACHINE, kChromiumPoliciesForcelistKeyPath}, + {HKEY_CURRENT_USER, kChromiumPoliciesForcelistKeyPath}}; + +const int64_t kParseAttemptTimeoutMilliseconds = 10000; + +// Expand an executable path as if the launch process directory was the +// windows folder. This is used to resolve kernel module path. +bool ExpandToAbsolutePathFromWindowsFolder(const base::FilePath& path, + base::FilePath* output) { + DCHECK(output); + if (path.IsAbsolute()) { + *output = path; + return true; + } + + // Retrieve the system folder path. + base::FilePath system_folder = + PreFetchedPaths::GetInstance()->GetWindowsFolder(); + + base::FilePath absolute_path = system_folder.Append(path); + if (base::PathExists(absolute_path)) { + *output = absolute_path; + return true; + } + + LOG(ERROR) << "Cannot determine absolute path: file does not exist."; + return false; +} + +void RetrieveDetailedFileInformationFromCommandLine( + const base::string16& content, + internal::FileInformation* file_information, + bool* white_listed) { + // Handle the case where |content| contains only an executable path. + base::FilePath expanded_path( + ExtractExecutablePathFromRegistryContent(content)); + if (base::PathExists(expanded_path)) { + RetrieveDetailedFileInformation(expanded_path, file_information, + white_listed); + return; + } + + // Fallback using the original path. + RetrieveDetailedFileInformation(base::FilePath(content), file_information, + white_listed); +} + +void ReportRegistryValue(const RegKeyPath& key_path, + const wchar_t* name, + const base::string16& content, + bool has_file_information) { + DCHECK(name); + if (content.empty()) + return; + + internal::FileInformation file_information; + if (has_file_information) { + bool white_listed = false; + RetrieveDetailedFileInformationFromCommandLine(content, &file_information, + &white_listed); + if (white_listed) + return; + } + + internal::RegistryValue registry_value = {}; + std::vector<internal::FileInformation> file_informations; + registry_value.key_path = key_path.FullPath(); + registry_value.value_name = name; + registry_value.data = content; + + if (has_file_information) + file_informations.push_back(file_information); + + LoggingServiceAPI::GetInstance()->AddRegistryValue(registry_value, + file_informations); +} + +void ReportRegistryValues(const RegistryValue* report_data, + size_t report_data_length, + REGSAM access_mask, + bool has_file_information) { + DCHECK(report_data); + for (size_t offset = 0; offset < report_data_length; ++offset) { + // Retrieve the content of the registry value. + base::string16 content; + const RegKeyPath key_path(report_data[offset].hkey, + report_data[offset].key_path, access_mask); + RegistryError error; + if (!ReadRegistryValue(key_path, report_data[offset].value_name, &content, + nullptr, &error)) { + LOG_IF(WARNING, error != RegistryError::VALUE_NOT_FOUND) + << "Failed to read string registry value: '" << key_path.FullPath() + << "\\" << report_data[offset].value_name << "', error: '" + << static_cast<int>(error) << "'."; + continue; + } + ReportRegistryValue(key_path, report_data[offset].value_name, content, + has_file_information); + } +} + +void ReportRegistryKeys(const RegistryKey* report_data, + size_t length, + REGSAM access_mask, + bool has_file_information) { + DCHECK(report_data); + for (size_t offset = 0; offset < length; ++offset) { + // Enumerate values from the current registry key. + base::win::RegistryValueIterator values_it( + report_data[offset].hkey, report_data[offset].key_path, access_mask); + for (; values_it.Valid(); ++values_it) { + base::string16 content; + GetRegistryValueAsString(values_it.Value(), values_it.ValueSize(), + values_it.Type(), &content); + RegKeyPath key_path(report_data[offset].hkey, + report_data[offset].key_path); + ReportRegistryValue( + key_path, values_it.Name(), content, + // File information should only be text. + has_file_information && (values_it.Type() == REG_SZ || + values_it.Type() == REG_EXPAND_SZ || + values_it.Type() == REG_MULTI_SZ)); + } + } +} + +// Reports nameservers i.e. +// system\currentcontrolset\services\tcpip\parameters\interfaces\*\nameserver +void ReportNameServer(REGSAM access_mask) { + base::win::RegistryKeyIterator keys_it(HKEY_LOCAL_MACHINE, kNameServerPath, + access_mask); + // Check each key at this path. + for (; keys_it.Valid(); ++keys_it) { + const base::string16 full_path = + base::StrCat({kNameServerPath, L"\\", keys_it.Name()}); + + base::string16 content; + uint32_t content_type = REG_NONE; + const RegKeyPath nameserver_key_path(HKEY_LOCAL_MACHINE, full_path.c_str(), + access_mask); + // Check to see if this key has a nameserver value who's content is non + // empty. + if (!ReadRegistryValue(nameserver_key_path, kNameServer, &content, + &content_type, nullptr) || + content_type != REG_SZ || content.empty()) { + continue; + } + + ReportRegistryValue(nameserver_key_path, kNameServer, content, + kNoFileInformation); + } +} + +void ReportAppInitDllsTargets(REGSAM access_mask) { + base::string16 content; + uint32_t content_type = REG_NONE; + const RegKeyPath appinit_dlls_key_path(HKEY_LOCAL_MACHINE, + kAppInitDllsKeyPath, access_mask); + if (!ReadRegistryValue(appinit_dlls_key_path, kAppInitDllsValueName, &content, + &content_type, nullptr) || + content_type != REG_SZ) { + return; + } + + base::string16 delimiters(PUPData::kCommonDelimiters, + PUPData::kCommonDelimitersLength); + std::vector<base::string16> entries = base::SplitString( + content, delimiters, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + + bool white_listed = false; + + internal::RegistryValue registry_value = {}; + std::vector<internal::FileInformation> file_informations; + registry_value.key_path = appinit_dlls_key_path.FullPath(); + registry_value.value_name = kAppInitDllsValueName; + registry_value.data = content; + + for (const auto& entry : entries) { + base::string16 long_path; + ConvertToLongPath(entry, &long_path); + base::FilePath expanded_path( + ExpandEnvPathAndWow64Path(base::FilePath(long_path))); + internal::FileInformation file_information; + RetrieveDetailedFileInformation(expanded_path, &file_information, + &white_listed); + if (!white_listed) + file_informations.push_back(file_information); + } + LoggingServiceAPI::GetInstance()->AddRegistryValue(registry_value, + file_informations); +} + +void ReportRegistry(REGSAM access_mask) { + // Report on startup keys/values. + ReportRegistryKeys(startup_registry_keys, base::size(startup_registry_keys), + access_mask, kHasFileInformation); + ReportRegistryValues(system_path_values, base::size(system_path_values), + access_mask, kHasFileInformation); + ReportRegistryValues(system_values, base::size(system_values), access_mask, + kNoFileInformation); + + // Report on extension policy keys. + ReportRegistryKeys(extension_policy_keys, base::size(extension_policy_keys), + access_mask, kNoFileInformation); + ReportAppInitDllsTargets(access_mask); + ReportNameServer(access_mask); +} + +void ReportRegistry() { + ReportRegistry(KEY_WOW64_32KEY); + if (IsX64Architecture()) + ReportRegistry(KEY_WOW64_64KEY); +} + +void ReportFoldersUnderPath(const base::FilePath& path, const wchar_t* prefix) { + base::FileEnumerator folder_enum(path, false, + base::FileEnumerator::DIRECTORIES); + for (base::FilePath folder = folder_enum.Next(); !folder.empty(); + folder = folder_enum.Next()) { + LoggingServiceAPI::GetInstance()->AddInstalledProgram(folder); + } +} + +void ReportInstalledPrograms() { + static unsigned int install_paths[] = { + base::DIR_PROGRAM_FILES, base::DIR_PROGRAM_FILESX86, + base::DIR_PROGRAM_FILES6432, base::DIR_APP_DATA, + base::DIR_LOCAL_APP_DATA, base::DIR_COMMON_APP_DATA, + }; + std::set<base::FilePath> path_processed; + for (size_t path = 0; path < base::size(install_paths); ++path) { + base::FilePath install_path; + bool success = base::PathService::Get(install_paths[path], &install_path); + if (!success) { + LOG(ERROR) << "Can't get path from PathService."; + continue; + } + if (path_processed.insert(install_path).second) + ReportFoldersUnderPath(install_path, L"Program:"); + } +} + +void ReportRunningProcesses() { + base::ProcessIterator iter(nullptr); + while (const base::ProcessEntry* entry = iter.NextProcessEntry()) { + base::win::ScopedHandle handle( + ::OpenProcess(PROCESS_QUERY_INFORMATION, false, entry->pid())); + base::string16 exec_path; + if (handle.IsValid() && + GetProcessExecutablePath(handle.Get(), &exec_path)) { + internal::FileInformation file_information; + bool white_listed = false; + RetrieveDetailedFileInformation(base::FilePath(exec_path), + &file_information, &white_listed); + if (!white_listed) { + LoggingServiceAPI::GetInstance()->AddProcess(entry->exe_file(), + file_information); + } + } else { + LOG(WARNING) << "Unable to query process: '" << entry->exe_file() << "'"; + } + } +} + +bool RetrieveExecutablePathFromPid(DWORD pid, base::FilePath* path) { + DCHECK(path); + base::win::ScopedHandle process_handle( + ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid)); + + base::string16 exe_path; + if (!GetProcessExecutablePath(process_handle.Get(), &exe_path)) + return false; + + *path = base::FilePath(exe_path); + return true; +} + +bool RetrieveExecutablePathFromServiceName(const wchar_t* service_name, + base::FilePath* service_path) { + DCHECK(service_name); + DCHECK(service_path); + base::string16 subkey_path(kServicesKeyPath); + subkey_path += service_name; + + base::string16 content; + if (!ReadRegistryValue(RegKeyPath(HKEY_LOCAL_MACHINE, subkey_path.c_str()), + L"imagepath", &content, nullptr, nullptr)) { + return false; + } + + base::FilePath file_path = base::FilePath(content); + // Convert a NT native form ("\Device\HarddiskVolumeXX\...") to the + // equivalent path that starts with a drive letter ("C:\..."). + base::FilePath dos_file_path; + if (base::DevicePathToDriveLetterPath(file_path, &dos_file_path)) { + file_path = dos_file_path; + } else if (base::StartsWith(file_path.value(), kAbsolutePrefix, + base::CompareCase::INSENSITIVE_ASCII)) { + // Remove the prefix "\??\" in front of the path. + file_path = base::FilePath( + file_path.value().substr(base::size(kAbsolutePrefix) - 1)); + } else if (base::StartsWith(file_path.value(), kSystemRootPrefix, + base::CompareCase::INSENSITIVE_ASCII)) { + // Remove the prefix "\systemroot\" in front of the path. The path + // will be resolved from the system folder. + file_path = base::FilePath( + file_path.value().substr(base::size(kSystemRootPrefix) - 1)); + } + + // For relative path, resolve them from %systemroot%. + base::FilePath absolute_file_path; + if (ExpandToAbsolutePathFromWindowsFolder(file_path, &absolute_file_path)) + file_path = absolute_file_path; + + *service_path = file_path; + return true; +} + +void ReportRunningServices(DWORD services_type) { + ScopedScHandle service_manager; + service_manager.Set(::OpenSCManager( + nullptr, nullptr, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT)); + if (!service_manager.IsValid()) { + PLOG(ERROR) << "Cannot open service manager."; + return; + } + + std::vector<uint8_t> buffer(kInitialNumberOfServices * + sizeof(ENUM_SERVICE_STATUS_PROCESS)); + ULONG number_of_service = 0; + while (true) { + ULONG more_bytes_needed = 0; + if (::EnumServicesStatusEx(service_manager.Get(), SC_ENUM_PROCESS_INFO, + services_type, SERVICE_ACTIVE, &buffer[0], + buffer.size(), &more_bytes_needed, + &number_of_service, nullptr, nullptr) != FALSE) { + break; + } + + if (::GetLastError() == ERROR_MORE_DATA) { + buffer.resize(buffer.size() + more_bytes_needed); + } else { + PLOG(ERROR) << "Cannot enumerate running services."; + return; + } + } + + LPENUM_SERVICE_STATUS_PROCESS services = + reinterpret_cast<LPENUM_SERVICE_STATUS_PROCESS>(&buffer[0]); + for (size_t i = 0; i < number_of_service; i++) { + base::FilePath service_path; + bool service_found = false; + if (services[i].ServiceStatusProcess.dwProcessId != 0) { + service_found = RetrieveExecutablePathFromPid( + services[i].ServiceStatusProcess.dwProcessId, &service_path); + } else { + service_found = RetrieveExecutablePathFromServiceName( + services[i].lpServiceName, &service_path); + } + if (service_found) { + internal::FileInformation file_information; + bool white_listed = false; + RetrieveDetailedFileInformation(service_path, &file_information, + &white_listed); + + if (!white_listed) { + LoggingServiceAPI::GetInstance()->AddService(services[i].lpDisplayName, + services[i].lpServiceName, + file_information); + } + } + } +} + +void ReportScheduledTasks() { + std::unique_ptr<TaskScheduler> task_scheduler( + TaskScheduler::CreateInstance()); + std::vector<base::string16> task_names; + if (!task_scheduler->GetTaskNameList(&task_names)) { + LOG(ERROR) << "Failed to enumerate scheduled tasks."; + return; + } + + for (const auto& task_name : task_names) { + TaskScheduler::TaskInfo task_info; + if (!task_scheduler->GetTaskInfo(task_name.c_str(), &task_info)) { + LOG(ERROR) << "Failed to get info for task '" << task_name << "'"; + continue; + } + std::vector<internal::FileInformation> actions; + for (size_t action = 0; action < task_info.exec_actions.size(); ++action) { + bool white_listed = false; + internal::FileInformation file_information; + RetrieveDetailedFileInformation( + task_info.exec_actions[action].application_path, &file_information, + &white_listed); + if (!white_listed) + actions.push_back(file_information); + } + LoggingServiceAPI::GetInstance()->AddScheduledTask( + task_name, task_info.description, actions); + } +} + +// Report the file paths of all DLLs loaded into the process with |pid|. The +// |prefix| is prepended to the log line to qualify the running process. +// |paths_reported| contains already reported paths to avoid duplication. +// Reported paths are added to |paths_reported|. +void ReportLoadedModules(DWORD pid, + const wchar_t* prefix, + ModuleHost host, + std::set<base::FilePath>* paths_reported) { + DCHECK(prefix); + DCHECK(paths_reported); + base::win::ScopedHandle snapshot( + ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid)); + if (!snapshot.Get()) + return; + + MODULEENTRY32 module = {sizeof(module)}; + if (!::Module32First(snapshot.Get(), &module)) + return; + + do { + base::FilePath file_path(module.szExePath); + if (!paths_reported->insert(file_path).second) { + // File details are already reported. + continue; + } + + internal::FileInformation file_information; + bool white_listed = false; + RetrieveDetailedFileInformation(file_path, &file_information, + &white_listed); + if (!white_listed) { + LoggingServiceAPI::GetInstance()->AddLoadedModule(module.szModule, host, + file_information); + } + } while (::Module32Next(snapshot.Get(), &module)); +} + +void ReportLoadedModulesOfCurrentProcess() { + std::set<base::FilePath> paths_reported; + ReportLoadedModules(::GetCurrentProcessId(), L"CCT", + ModuleHost::CHROME_CLEANUP_TOOL, &paths_reported); +} + +// Report the DLLs for every running process |executable|. DLLs are reported +// only once. +void ReportLoadedModulesOfRunningProcesses(const wchar_t* executable, + ModuleHost host) { + DCHECK(executable); + + // |paths_reported| is used to avoid duplicate report of the same path for + // different running chrome processes. + std::set<base::FilePath> paths_reported; + base::NamedProcessIterator iter(executable, nullptr); + while (const base::ProcessEntry* entry = iter.NextProcessEntry()) + ReportLoadedModules(entry->pid(), executable, host, &paths_reported); +} + +void ReportLayeredServiceProviders() { + LSPPathToGUIDs providers; + GetLayeredServiceProviders(LayeredServiceProviderWrapper(), &providers); + for (LSPPathToGUIDs::const_iterator provider = providers.begin(); + provider != providers.end(); ++provider) { + const base::FilePath& path = provider->first; + + internal::FileInformation file_information; + bool white_listed = false; + RetrieveDetailedFileInformationFromCommandLine( + path.value(), &file_information, &white_listed); + + if (!white_listed) { + std::vector<base::string16> logged_guids; + const std::set<GUID, GUIDLess>& guids = provider->second; + for (std::set<GUID, GUIDLess>::const_iterator guid = guids.begin(); + guid != guids.end(); ++guid) { + base::string16 guid_str; + GUIDToString(*guid, &guid_str); + logged_guids.push_back(guid_str); + } + LoggingServiceAPI::GetInstance()->AddLayeredServiceProvider( + logged_guids, file_information); + } + } +} + +void ReportProxySettingsInformation() { + // Retrieve the default Internet Explorer proxy configuration for the current + // user. + WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_info; + if (::WinHttpGetIEProxyConfigForCurrentUser(&ie_proxy_info)) { + // Report proxy information when it's not the default configuration. + if (ie_proxy_info.lpszProxy || ie_proxy_info.lpszProxyBypass || + ie_proxy_info.lpszAutoConfigUrl || ie_proxy_info.fAutoDetect) { + base::string16 config = + (ie_proxy_info.lpszProxy ? ie_proxy_info.lpszProxy : L""); + base::string16 bypass = + (ie_proxy_info.lpszProxyBypass ? ie_proxy_info.lpszProxyBypass : L""); + base::string16 autoconfig = + (ie_proxy_info.lpszAutoConfigUrl ? ie_proxy_info.lpszAutoConfigUrl + : L""); + LoggingServiceAPI::GetInstance()->SetWinInetProxySettings( + config, bypass, autoconfig, ie_proxy_info.fAutoDetect != FALSE); + } + + if (ie_proxy_info.lpszProxy) + ::GlobalFree(ie_proxy_info.lpszProxy); + if (ie_proxy_info.lpszProxyBypass) + ::GlobalFree(ie_proxy_info.lpszProxyBypass); + if (ie_proxy_info.lpszAutoConfigUrl) + ::GlobalFree(ie_proxy_info.lpszAutoConfigUrl); + } + + // Retrieve the default WinHTTP proxy configuration from the registry. + WINHTTP_PROXY_INFO proxy_info; + if (::WinHttpGetDefaultProxyConfiguration(&proxy_info)) { + const char* access_type = nullptr; + switch (proxy_info.dwAccessType) { + case WINHTTP_ACCESS_TYPE_NO_PROXY: + access_type = "no proxy"; + break; + case WINHTTP_ACCESS_TYPE_DEFAULT_PROXY: + access_type = "default proxy"; + break; + case WINHTTP_ACCESS_TYPE_NAMED_PROXY: + access_type = "named proxy"; + break; + default: + access_type = "unknown"; + break; + } + + // Report proxy information when it's not the default configuration. + if (proxy_info.dwAccessType != WINHTTP_ACCESS_TYPE_NO_PROXY || + proxy_info.lpszProxy || proxy_info.lpszProxyBypass) { + base::string16 config = + (proxy_info.lpszProxy ? proxy_info.lpszProxy : L""); + base::string16 bypass = + (proxy_info.lpszProxyBypass ? proxy_info.lpszProxyBypass : L""); + LoggingServiceAPI::GetInstance()->SetWinHttpProxySettings(config, bypass); + } + + if (proxy_info.lpszProxy) + ::GlobalFree(proxy_info.lpszProxy); + if (proxy_info.lpszProxyBypass) + ::GlobalFree(proxy_info.lpszProxyBypass); + } +} + +void ReportForcelistExtensions() { + std::vector<ExtensionPolicyRegistryEntry> policies; + GetExtensionForcelistRegistryPolicies(&policies); + + for (const ExtensionPolicyRegistryEntry& policy : policies) { + LoggingServiceAPI::GetInstance()->AddInstalledExtension( + policy.extension_id, + ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST); + } +} + +void ReportInstalledExtensions(JsonParserAPI* json_parser) { + DCHECK(json_parser); + // TODO(proberge): Temporarily allowing syncing to avoid crashes in debug + // mode. This isn't catastrophic since the cleanup tool doesn't have a UI and + // the system report is collected at the end of the process. We also assert + // blocking is allowed here since it will block the thread. + base::AssertBlockingAllowed(); + base::ScopedAllowBaseSyncPrimitivesForTesting allow_sync; + + ReportForcelistExtensions(); + + std::vector<ExtensionPolicyRegistryEntry> extension_settings_policies; + WaitableEvent extension_settings_done( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + GetExtensionSettingsForceInstalledExtensions( + json_parser, &extension_settings_policies, &extension_settings_done); + + std::vector<ExtensionPolicyFile> master_preferences_policies; + WaitableEvent master_preferences_done( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + GetMasterPreferencesExtensions(json_parser, &master_preferences_policies, + &master_preferences_done); + + std::vector<ExtensionPolicyFile> default_extension_policies; + WaitableEvent default_extensions_done( + WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + GetNonWhitelistedDefaultExtensions(json_parser, &default_extension_policies, + &default_extensions_done); + + // Wait for all asynchronous parsing to be done + const base::TimeTicks end_time = + base::TimeTicks::Now() + + base::TimeDelta::FromMilliseconds(kParseAttemptTimeoutMilliseconds); + extension_settings_done.TimedWaitUntil(end_time); + master_preferences_done.TimedWaitUntil(end_time); + default_extensions_done.TimedWaitUntil(end_time); + + // Log extensions that were found + for (const ExtensionPolicyRegistryEntry& policy : extension_settings_policies) + LoggingServiceAPI::GetInstance()->AddInstalledExtension( + policy.extension_id, ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS); + + for (const ExtensionPolicyFile& policy : master_preferences_policies) + LoggingServiceAPI::GetInstance()->AddInstalledExtension( + policy.extension_id, ExtensionInstallMethod::POLICY_MASTER_PREFERENCES); + + for (const ExtensionPolicyFile& policy : default_extension_policies) + LoggingServiceAPI::GetInstance()->AddInstalledExtension( + policy.extension_id, ExtensionInstallMethod::DEFAULT_APPS_EXTENSION); +} + +} // namespace + +SystemReportComponent::SystemReportComponent(JsonParserAPI* json_parser) + : created_report_(false), json_parser_(json_parser) {} + +void SystemReportComponent::PreScan() {} + +void SystemReportComponent::PostScan(const std::vector<UwSId>& found_pups) { + // If no removable UwS was found, we should collect the detailed system report + // now since there won't be a post-cleanup called. + if (found_pups.size() == 0 || + !PUPData::HasFlaggedPUP(found_pups, &PUPData::HasRemovalFlag)) + CreateFullSystemReport(); +} + +void SystemReportComponent::PreCleanup() {} + +void SystemReportComponent::PostCleanup(ResultCode result_code, + RebooterAPI* rebooter) { + // If the user cancels the cleanup, don't collect system information since the + // old UI quits without giving the user a chance to opt out of uploading this. + if (result_code == RESULT_CODE_CANCELED) + return; + + CreateFullSystemReport(); +} + +void SystemReportComponent::PostValidation(ResultCode result_code) {} + +void SystemReportComponent::OnClose(ResultCode result_code) {} + +void SystemReportComponent::CreateFullSystemReport() { + LoggingServiceAPI* logging_service = LoggingServiceAPI::GetInstance(); + + // Don't collect a system report if we've already collected one + if (created_report_) + return; + + // Don't collect a system report if logs won't be uploaded. + if (!logging_service->uploads_enabled()) { + // TODO(proberge): Remove this by EOQ4 2018. + if (base::CommandLine::ForCurrentProcess()->HasSwitch(kDumpRawLogsSwitch)) { + ReportInstalledExtensions(json_parser_); + created_report_ = true; + } + + return; + } + + logging_service->SetDetailedSystemReport(true); + + ScopedTimedTaskLogger scoped_timed_task_logger( + "Logging detailed system report"); + // Make sure this process has the debug privilege to allow opening more + // running processes. If we have to obtain it, be sure to drop it again to + // leave the system in the state we found it. Some unit tests depend on not + // having debug privileges. + base::ScopedClosureRunner release_debug_rights; + if (!HasDebugRightsPrivileges() && AcquireDebugRightsPrivileges()) { + release_debug_rights.ReplaceClosure( + base::BindOnce(base::IgnoreResult(&ReleaseDebugRightsPrivileges))); + } + + ReportLoadedModulesOfCurrentProcess(); + ReportLoadedModulesOfRunningProcesses(L"chrome.exe", ModuleHost::CHROME); + ReportRunningProcesses(); + ReportRunningServices(SERVICE_WIN32); + { + // The wow64 redirection must be disabled because path are reported as + // viewed by the kernel. + ScopedDisableWow64Redirection wow64_disabled; + ReportRunningServices(SERVICE_DRIVER); + } + ReportRegistry(); + ReportScheduledTasks(); + ReportInstalledPrograms(); + ReportLayeredServiceProviders(); + ReportProxySettingsInformation(); + ReportInstalledExtensions(json_parser_); + + created_report_ = true; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/system_report_component.h b/chrome/chrome_cleaner/components/system_report_component.h new file mode 100644 index 0000000..4ec3665 --- /dev/null +++ b/chrome/chrome_cleaner/components/system_report_component.h
@@ -0,0 +1,40 @@ +// Copyright 2018 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 CHROME_CHROME_CLEANER_COMPONENTS_SYSTEM_REPORT_COMPONENT_H_ +#define CHROME_CHROME_CLEANER_COMPONENTS_SYSTEM_REPORT_COMPONENT_H_ + +#include <vector> + +#include "chrome/chrome_cleaner/components/component_api.h" +#include "chrome/chrome_cleaner/json_parser/json_parser_api.h" + +namespace chrome_cleaner { + +// This class manages the production of a system information report. +class SystemReportComponent : public ComponentAPI { + public: + explicit SystemReportComponent(JsonParserAPI* json_parser); + + // ComponentAPI methods. + void PreScan() override; + void PostScan(const std::vector<UwSId>& found_pups) override; + void PreCleanup() override; + void PostCleanup(ResultCode result_code, RebooterAPI* rebooter) override; + void PostValidation(ResultCode result_code) override; + void OnClose(ResultCode result_code) override; + + void CreateFullSystemReport(); + + // Only exposed for tests. + bool created_report() { return created_report_; } + + private: + bool created_report_; + JsonParserAPI* json_parser_; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_COMPONENTS_SYSTEM_REPORT_COMPONENT_H_
diff --git a/chrome/chrome_cleaner/components/system_report_component_unittest.cc b/chrome/chrome_cleaner/components/system_report_component_unittest.cc new file mode 100644 index 0000000..e3244778 --- /dev/null +++ b/chrome/chrome_cleaner/components/system_report_component_unittest.cc
@@ -0,0 +1,601 @@ +// Copyright 2018 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/chrome_cleaner/components/system_report_component.h" + +#include <string> +#include <vector> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/lazy_instance.h" +#include "base/path_service.h" +#include "base/strings/string16.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_command_line.h" +#include "base/test/scoped_path_override.h" +#include "base/test/test_reg_util_win.h" +#include "base/test/test_timeouts.h" +#include "base/win/registry.h" +#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" +#include "chrome/chrome_cleaner/constants/uws_id.h" +#include "chrome/chrome_cleaner/json_parser/test_json_parser.h" +#include "chrome/chrome_cleaner/logging/cleaner_logging_service.h" +#include "chrome/chrome_cleaner/logging/logging_service_api.h" +#include "chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.pb.h" +#include "chrome/chrome_cleaner/os/disk_util.h" +#include "chrome/chrome_cleaner/os/file_path_sanitization.h" +#include "chrome/chrome_cleaner/os/pre_fetched_paths.h" +#include "chrome/chrome_cleaner/os/registry_util.h" +#include "chrome/chrome_cleaner/test/test_file_util.h" +#include "chrome/chrome_cleaner/test/test_pup_data.h" +#include "chrome/chrome_cleaner/test/test_util.h" +#include "components/chrome_cleaner/public/constants/constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chrome_cleaner { +namespace { + +using google::protobuf::RepeatedPtrField; +using InstalledExtension = + ChromeCleanerReport::SystemReport::InstalledExtension; +using base::WaitableEvent; + +const int kExtensionIdLength = 32; + +const wchar_t kRunKeyPath[] = + L"software\\microsoft\\windows\\currentversion\\run"; +const wchar_t kRunTestName[] = L"test_chrome_cleanup_tool"; +const wchar_t kRunTestValue[] = L"chrome_cleanup_tool.exe"; + +const wchar_t kNameServerKeyPath[] = + L"system\\currentcontrolset\\services\\tcpip\\parameters\\interfaces\\" + L"fishy"; +const wchar_t kNameServerName[] = L"nameserver"; +const wchar_t kNameServerValue[] = L"8.8.4.4"; +const wchar_t kFakeProgramFolder[] = L"FakeProgram"; +const char kFakeProgram[] = "FakeProgram"; +const wchar_t kFakeAppDataProgramFolder[] = L"FakeAppDataProgram"; +const char kFakeAppDataProgram[] = "FakeAppDataProgram"; + +const char kExtensionPoliciesNonExistent[] = + "software\\policies\\google\\chrome\\"; + +struct ReportTestData { + HKEY hkey; + const wchar_t* key_path; + const wchar_t* name; + const wchar_t* value; +}; + +const ReportTestData kExtensionPolicyEmpty{ + HKEY_LOCAL_MACHINE, kChromePoliciesWhitelistKeyPath, L"test1", L""}; + +constexpr base::char16 kTestExtensionId1[] = + L"ababababcdcdcdcdefefefefghghghgh"; +constexpr base::char16 kTestExtensionId1WithUpdateUrl[] = + L"ababababcdcdcdcdefefefefghghghgh;https://clients2.google.com/service/" + L"update2/crx"; +constexpr base::char16 kTestExtensionId2[] = + L"aaaabbbbccccddddeeeeffffgggghhhh"; +constexpr base::char16 kTestExtensionId2WithUpdateUrl[] = + L"aaaabbbbccccddddeeeeffffgggghhhh;https://clients2.google.com/service/" + L"update2/crx"; + +const ReportTestData extension_policies[] = { + {HKEY_LOCAL_MACHINE, kChromePoliciesWhitelistKeyPath, L"test1", + kTestExtensionId1}, + {HKEY_CURRENT_USER, kChromePoliciesWhitelistKeyPath, L"test2", + kTestExtensionId1}, + {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test3", + kTestExtensionId2WithUpdateUrl}, + {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test4", + kTestExtensionId2WithUpdateUrl}, + {HKEY_LOCAL_MACHINE, kChromiumPoliciesWhitelistKeyPath, L"test5", + kTestExtensionId1}, + {HKEY_CURRENT_USER, kChromiumPoliciesWhitelistKeyPath, L"test6", + kTestExtensionId1}, + {HKEY_LOCAL_MACHINE, kChromiumPoliciesForcelistKeyPath, L"test7", + kTestExtensionId2WithUpdateUrl}, + {HKEY_CURRENT_USER, kChromiumPoliciesForcelistKeyPath, L"test8", + kTestExtensionId2WithUpdateUrl}, +}; + +const ReportTestData extension_forcelist_policies[] = { + {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test1", + kTestExtensionId1WithUpdateUrl}, + {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test2", + kTestExtensionId2WithUpdateUrl}, +}; + +const UwSId kFakePupId = 42; + +const wchar_t kFakeChromeFolder[] = L"google\\chrome\\application\\42.12.34.56"; + +const char kDefaultExtensionsJson[] = R"( + { + "ababababcdcdcdcdefefefefghghghgh" : { + "external_update_url": "https://clients2.google.com/service/update2/crx" + }, + "aaaabbbbccccddddeeeeffffgggghhhh" : { + "external_update_url": "https://clients2.google.com/service/update2/crx" + } + })"; +// Don't include the null-terminator in the length. +const int kDefaultExtensionsJsonSize = sizeof(kDefaultExtensionsJson) - 1; + +// ExtensionSettings that has two force_installed extensions and two not. +const wchar_t kExtensionSettingsJson[] = + LR"( + { + "ababababcdcdcdcdefefefefghghghgh": { + "installation_mode": "force_installed", + "update_url":"https://clients2.google.com/service/update2/crx" + }, + "aaaabbbbccccddddeeeeffffgggghhhh": { + "installation_mode": "force_installed", + "update_url":"https://clients2.google.com/service/update2/crx" + }, + "extensionwithinstallmodeblockeda": { + "installation_mode": "blocked", + "update_url":"https://clients2.google.com/service/update2/crx" + }, + "extensionwithnosettingsabcdefghi": {} + })"; +const ReportTestData extension_settings_entry = { + HKEY_LOCAL_MACHINE, kChromePoliciesKeyPath, L"ExtensionSettings", + kExtensionSettingsJson}; + +const wchar_t kChromeExePath[] = L"google\\chrome\\application"; +const wchar_t kMasterPreferencesFileName[] = L"master_preferences"; +const char kMasterPreferencesJson[] = + R"( + { + "homepage": "http://dev.chromium.org/", + "extensions": { + "settings": { + "ababababcdcdcdcdefefefefghghghgh": { + "location": 1, + "manifest": { + "name": "Test extension" + } + }, + "aaaabbbbccccddddeeeeffffgggghhhh": { + "location": 1, + "manifest": { + "name": "Another one" + } + } + } + } + })"; + +class SystemReportComponentTest : public testing::Test { + public: + SystemReportComponentTest() : component_(&json_parser_) {} + + void SetUp() override { + cleaner_logging_service_ = CleanerLoggingService::GetInstance(); + cleaner_logging_service_->Initialize(nullptr); + cleaner_logging_service_->EnableUploads(true, /*registry_logger=*/nullptr); + LoggingServiceAPI::SetInstanceForTesting(cleaner_logging_service_); + registry_override_.OverrideRegistry(HKEY_CURRENT_USER); + registry_override_.OverrideRegistry(HKEY_LOCAL_MACHINE); + } + + void TearDown() override { + LoggingServiceAPI::SetInstanceForTesting(nullptr); + cleaner_logging_service_->Terminate(); + } + + ChromeCleanerReport GetChromeCleanerReport() { + ChromeCleanerReport report; + CHECK(report.ParseFromString(cleaner_logging_service_->RawReportContent())); + return report; + } + + TestJsonParser json_parser_; + SystemReportComponent component_; + CleanerLoggingService* cleaner_logging_service_ = nullptr; + registry_util::RegistryOverrideManager registry_override_; +}; + +template <typename Component> +bool SomeComponentContainsPath(const RepeatedPtrField<Component>& components, + const base::FilePath& path) { + const std::string name = path.BaseName().MaybeAsASCII(); + const std::string sanitized_path = base::UTF16ToUTF8(SanitizePath(path)); + for (const auto component : components) { + if (component.name() == name && + component.file_information().path() == sanitized_path) { + return true; + } + } + return false; +} + +bool InstalledProgramCollected( + const RepeatedPtrField<ChromeCleanerReport::SystemReport::InstalledProgram>& + programs, + const std::string& folder_name) { + const std::string lower_case_folder_name = base::ToLowerASCII(folder_name); + for (const auto& program : programs) { + if (program.folder_information().path().find(lower_case_folder_name) != + std::string::npos) { + return true; + } + } + return false; +} + +bool RegistryEntryCollected( + const RepeatedPtrField<RegistryValue>& registry_values, + const std::string& key_path, + const std::string& value_name, + const std::string& data) { + for (const auto& registry_value : registry_values) { + if (StringContainsCaseInsensitive(registry_value.key_path(), key_path) && + registry_value.value_name() == value_name && + registry_value.data() == data) { + return true; + } + } + return false; +} + +bool RegistryKeyCollected( + const RepeatedPtrField<RegistryValue>& registry_values, + const std::string& key_path) { + for (const auto& registry_value : registry_values) { + if (StringContainsCaseInsensitive(registry_value.key_path(), key_path)) + return true; + } + return false; +} + +// Returns whether |reported_extensions| contains an entry for an extension with +// |extension_id| and |install_method|. +bool InstalledExtensionReported( + const RepeatedPtrField<InstalledExtension>& reported_extensions, + const std::wstring& extension_id, + ExtensionInstallMethod install_method) { + for (const auto& installed_extension : reported_extensions) { + if (installed_extension.extension_id() == base::WideToUTF8(extension_id) && + installed_extension.install_method() == install_method) { + return true; + } + } + return false; +} + +} // namespace + +TEST_F(SystemReportComponentTest, PreScan_NoDetailedReport) { + component_.PreScan(); + EXPECT_FALSE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, PostScanNoUwS_DetailedReport) { + std::vector<UwSId> found_pups; + component_.PostScan(found_pups); + EXPECT_TRUE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, PostScanNonRemovalableUwS_DetailedReport) { + TestPUPData test_pup_data; + test_pup_data.AddPUP(kFakePupId, PUPData::FLAGS_NONE, nullptr, + PUPData::kMaxFilesToRemoveSmallUwS); + std::vector<UwSId> found_pups; + found_pups.push_back(kFakePupId); + component_.PostScan(found_pups); + EXPECT_TRUE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, PostScanRemovalableUwS_NoDetailedReport) { + TestPUPData test_pup_data; + test_pup_data.AddPUP(kFakePupId, PUPData::FLAGS_ACTION_REMOVE, nullptr, + PUPData::kMaxFilesToRemoveSmallUwS); + std::vector<UwSId> found_pups; + found_pups.push_back(kFakePupId); + component_.PostScan(found_pups); + EXPECT_FALSE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, PreCleanup_NoDetailedReport) { + component_.PreCleanup(); + EXPECT_FALSE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, PostCleanup_DetailedReport) { + component_.PostCleanup(RESULT_CODE_SUCCESS, nullptr); + EXPECT_TRUE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, PostCleanup_canceled_NoDetailedReport) { + component_.PostCleanup(RESULT_CODE_CANCELED, nullptr); + EXPECT_FALSE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, PostValidation_NoDetailedReport) { + component_.PostValidation(RESULT_CODE_SUCCESS); + EXPECT_FALSE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, OnClose_NoDetailedReport) { + component_.OnClose(RESULT_CODE_SUCCESS); + EXPECT_FALSE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, DisableUploads) { + cleaner_logging_service_->EnableUploads(false, nullptr); + + component_.CreateFullSystemReport(); + EXPECT_FALSE(component_.created_report()); +} + +TEST_F(SystemReportComponentTest, NoRepeatedCollections) { + component_.CreateFullSystemReport(); + EXPECT_TRUE(component_.created_report()); + + // Clear the report and ensure it isn't populated again, since + // |created_report| is still true. + EXPECT_LT(0, GetChromeCleanerReport().system_report().processes_size()); + cleaner_logging_service_->Terminate(); + cleaner_logging_service_->Initialize(/*registry_logger=*/nullptr); + EXPECT_EQ(0, GetChromeCleanerReport().system_report().processes_size()); + component_.CreateFullSystemReport(); + EXPECT_EQ(0, GetChromeCleanerReport().system_report().processes_size()); +} + +TEST_F(SystemReportComponentTest, DetectFakePrograms) { + base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); + base::FilePath program_files_dir; + ASSERT_TRUE( + base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); + + base::ScopedPathOverride appdata_override(base::DIR_LOCAL_APP_DATA); + base::FilePath appdata_dir; + ASSERT_TRUE(base::PathService::Get(base::DIR_LOCAL_APP_DATA, &appdata_dir)); + + // Setup a fake program installation folder. + base::FilePath fake_program_dir(program_files_dir.Append(kFakeProgramFolder)); + ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_program_dir, nullptr)); + ASSERT_TRUE(CreateFileInFolder(fake_program_dir, L"fake.exe")); + + base::FilePath fake_appdata_dir( + appdata_dir.Append(kFakeAppDataProgramFolder)); + ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_appdata_dir, nullptr)); + ASSERT_TRUE(CreateFileInFolder(fake_appdata_dir, L"fake.exe")); + + // Setup a fake runonce keys. + base::win::RegKey run_once(HKEY_CURRENT_USER, kRunKeyPath, KEY_WRITE); + ASSERT_TRUE(run_once.Valid()); + ASSERT_EQ(run_once.WriteValue(kRunTestName, kRunTestValue), ERROR_SUCCESS); + + component_.CreateFullSystemReport(); + + ChromeCleanerReport report = GetChromeCleanerReport(); + const auto& system_report = report.system_report(); + + const base::FilePath module_path = + PreFetchedPaths::GetInstance()->GetExecutablePath(); + EXPECT_TRUE( + SomeComponentContainsPath(system_report.loaded_modules(), module_path)); + + EXPECT_TRUE( + SomeComponentContainsPath(system_report.processes(), module_path)); + + EXPECT_TRUE(RegistryEntryCollected( + system_report.registry_values(), base::UTF16ToASCII(kRunKeyPath), + base::UTF16ToASCII(kRunTestName), base::UTF16ToASCII(kRunTestValue))); + + EXPECT_TRUE(InstalledProgramCollected(system_report.installed_programs(), + kFakeProgram)); + EXPECT_TRUE(InstalledProgramCollected(system_report.installed_programs(), + kFakeAppDataProgram)); +} + +TEST_F(SystemReportComponentTest, ReportNameServer) { + // Setup a fake key that triggers nameserver check. + base::win::RegKey nameserver_key; + ASSERT_EQ(ERROR_SUCCESS, + nameserver_key.Create(HKEY_LOCAL_MACHINE, kNameServerKeyPath, + KEY_ALL_ACCESS)); + ASSERT_TRUE(nameserver_key.Valid()); + ASSERT_EQ(nameserver_key.WriteValue(kNameServerName, kNameServerValue), + ERROR_SUCCESS); + + component_.CreateFullSystemReport(); + + EXPECT_TRUE(RegistryEntryCollected( + GetChromeCleanerReport().system_report().registry_values(), + base::UTF16ToASCII(kNameServerKeyPath), + base::UTF16ToASCII(kNameServerName), + base::UTF16ToASCII(kNameServerValue))); +} + +TEST_F(SystemReportComponentTest, ReportNameServerBadValue) { + // Setup a fake key that triggers nameserver check. + base::win::RegKey nameserver_key; + ASSERT_EQ(ERROR_SUCCESS, + nameserver_key.Create(HKEY_LOCAL_MACHINE, kNameServerKeyPath, + KEY_ALL_ACCESS)); + ASSERT_TRUE(nameserver_key.Valid()); + ASSERT_EQ(nameserver_key.WriteValue(kNameServerName, L""), ERROR_SUCCESS); + + component_.CreateFullSystemReport(); + + EXPECT_FALSE(RegistryKeyCollected( + GetChromeCleanerReport().system_report().registry_values(), + base::UTF16ToASCII(kNameServerKeyPath))); +} + +TEST_F(SystemReportComponentTest, ReportNameServerNonExistent) { + component_.CreateFullSystemReport(); + + EXPECT_FALSE(RegistryKeyCollected( + GetChromeCleanerReport().system_report().registry_values(), + base::UTF16ToASCII(kNameServerKeyPath))); +} + +TEST_F(SystemReportComponentTest, ReportExtensionPolicies) { + for (const auto& extension_policy : extension_policies) { + base::win::RegKey policy_key; + ASSERT_EQ(ERROR_SUCCESS, + policy_key.Create(extension_policy.hkey, + extension_policy.key_path, KEY_ALL_ACCESS)); + ASSERT_TRUE(policy_key.Valid()); + ASSERT_EQ( + policy_key.WriteValue(extension_policy.name, extension_policy.value), + ERROR_SUCCESS); + } + + component_.CreateFullSystemReport(); + + ChromeCleanerReport report = GetChromeCleanerReport(); + const auto& system_report = report.system_report(); + for (const auto& extension_policy : extension_policies) { + EXPECT_TRUE( + RegistryEntryCollected(system_report.registry_values(), + base::UTF16ToASCII(extension_policy.key_path), + base::UTF16ToASCII(extension_policy.name), + base::UTF16ToASCII(extension_policy.value))); + } +} + +TEST_F(SystemReportComponentTest, ReportExtensionPoliciesBadValue) { + base::win::RegKey policy_key; + ASSERT_EQ(ERROR_SUCCESS, + policy_key.Create(kExtensionPolicyEmpty.hkey, + kExtensionPolicyEmpty.key_path, KEY_ALL_ACCESS)); + ASSERT_TRUE(policy_key.Valid()); + ASSERT_EQ(policy_key.WriteValue(kExtensionPolicyEmpty.name, + kExtensionPolicyEmpty.value), + ERROR_SUCCESS); + component_.CreateFullSystemReport(); + EXPECT_FALSE(RegistryKeyCollected( + GetChromeCleanerReport().system_report().registry_values(), + base::UTF16ToASCII(kExtensionPolicyEmpty.key_path))); +} + +TEST_F(SystemReportComponentTest, ReportExtensionPoliciesNonExistent) { + component_.CreateFullSystemReport(); + + EXPECT_FALSE(RegistryKeyCollected( + GetChromeCleanerReport().system_report().registry_values(), + kExtensionPoliciesNonExistent)); +} + +TEST_F(SystemReportComponentTest, ReportForcelistExtensions) { + for (const ReportTestData& policy : extension_forcelist_policies) { + base::win::RegKey policy_key; + ASSERT_EQ(ERROR_SUCCESS, + policy_key.Create(policy.hkey, policy.key_path, KEY_ALL_ACCESS)); + ASSERT_TRUE(policy_key.Valid()); + ASSERT_EQ(ERROR_SUCCESS, policy_key.WriteValue(policy.name, policy.value)); + } + + base::test::ScopedCommandLine scoped_command_line; + component_.CreateFullSystemReport(); + ChromeCleanerReport report = GetChromeCleanerReport(); + + for (const ReportTestData& expected : extension_forcelist_policies) { + std::wstring policy_value(expected.value); + EXPECT_TRUE(InstalledExtensionReported( + report.system_report().installed_extensions(), + policy_value.substr(0, kExtensionIdLength), + ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST)); + } +} + +TEST_F(SystemReportComponentTest, ReportDefaultExtensions) { + // Set up a fake default extensions JSON file. + base::ScopedPathOverride program_files_x86_override( + base::DIR_PROGRAM_FILESX86); + base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); + base::FilePath program_files_dir; + ASSERT_TRUE( + base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); + + base::FilePath fake_apps_dir( + program_files_dir.Append(kFakeChromeFolder).Append(L"default_apps")); + ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_apps_dir, nullptr)); + + base::FilePath default_extensions_file = + fake_apps_dir.Append(L"external_extensions.json"); + CreateFileWithContent(default_extensions_file, kDefaultExtensionsJson, + kDefaultExtensionsJsonSize); + ASSERT_TRUE(base::PathExists(default_extensions_file)); + + base::test::ScopedCommandLine scoped_command_line; + component_.CreateFullSystemReport(); + ChromeCleanerReport report = GetChromeCleanerReport(); + + EXPECT_EQ(2, report.system_report().installed_extensions().size()); + EXPECT_TRUE(InstalledExtensionReported( + report.system_report().installed_extensions(), kTestExtensionId1, + ExtensionInstallMethod::DEFAULT_APPS_EXTENSION)); + EXPECT_TRUE(InstalledExtensionReported( + report.system_report().installed_extensions(), kTestExtensionId2, + ExtensionInstallMethod::DEFAULT_APPS_EXTENSION)); +} + +TEST_F(SystemReportComponentTest, ReportExtensionSettings) { + // Set up a fake ExtensionSettings registry key. + base::win::RegKey settings_key; + ASSERT_EQ( + ERROR_SUCCESS, + settings_key.Create(extension_settings_entry.hkey, + extension_settings_entry.key_path, KEY_ALL_ACCESS)); + DCHECK(settings_key.Valid()); + ASSERT_EQ(ERROR_SUCCESS, + settings_key.WriteValue(extension_settings_entry.name, + extension_settings_entry.value)); + + base::test::ScopedCommandLine scoped_command_line; + component_.CreateFullSystemReport(); + ChromeCleanerReport report = GetChromeCleanerReport(); + + EXPECT_TRUE(InstalledExtensionReported( + report.system_report().installed_extensions(), kTestExtensionId1, + ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS)); + EXPECT_TRUE(InstalledExtensionReported( + report.system_report().installed_extensions(), kTestExtensionId2, + ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS)); +} + +TEST_F(SystemReportComponentTest, ReportMasterPreferencesExtensions) { + // Set up a fake master preferences file + base::ScopedPathOverride program_files_x86_override( + base::DIR_PROGRAM_FILESX86); + base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); + base::FilePath program_files_dir; + ASSERT_TRUE( + base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); + + base::FilePath chrome_dir(program_files_dir.Append(kChromeExePath)); + ASSERT_TRUE(base::CreateDirectoryAndGetError(chrome_dir, nullptr)); + + base::FilePath master_preferences = + chrome_dir.Append(kMasterPreferencesFileName); + CreateFileWithContent(master_preferences, kMasterPreferencesJson, + sizeof(kMasterPreferencesJson) - 1); + ASSERT_TRUE(base::PathExists(master_preferences)); + + base::test::ScopedCommandLine scoped_command_line; + component_.CreateFullSystemReport(); + ChromeCleanerReport report = GetChromeCleanerReport(); + + EXPECT_EQ(2, report.system_report().installed_extensions().size()); + EXPECT_TRUE(InstalledExtensionReported( + report.system_report().installed_extensions(), kTestExtensionId1, + ExtensionInstallMethod::POLICY_MASTER_PREFERENCES)); + EXPECT_TRUE(InstalledExtensionReported( + report.system_report().installed_extensions(), kTestExtensionId2, + ExtensionInstallMethod::POLICY_MASTER_PREFERENCES)); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/system_restore_point_component.cc b/chrome/chrome_cleaner/components/system_restore_point_component.cc new file mode 100644 index 0000000..3128469f --- /dev/null +++ b/chrome/chrome_cleaner/components/system_restore_point_component.cc
@@ -0,0 +1,191 @@ +// Copyright 2018 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/chrome_cleaner/components/system_restore_point_component.h" + +#include <stdint.h> +#include <windows.h> + +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "base/win/registry.h" +#include "base/win/windows_version.h" + +namespace { + +const wchar_t* kSystemRestoreKey = + L"Software\\Microsoft\\Windows NT\\CurrentVersion\\SystemRestore"; +const wchar_t* kSystemRestoreFrequencyWin8 = + L"SystemRestorePointCreationFrequency"; +const int64_t kInvalidSequenceNumber = -1; +// Name of the restore point library. +const wchar_t kRestorePointClientLibrary[] = L"srclient.dll"; + +} // namespace + +namespace chrome_cleaner { + +SystemRestorePointComponent::SystemRestorePointComponent( + const base::string16& product_fullname) + : set_restore_point_info_fn_(nullptr), + remove_restore_point_info_fn_(nullptr), + sequence_number_(kInvalidSequenceNumber), + product_fullname_(product_fullname) { + base::NativeLibraryLoadError error; + srclient_dll_ = base::LoadNativeLibrary( + base::FilePath(kRestorePointClientLibrary), &error); + if (!srclient_dll_) { + PLOG(ERROR) << "Failed to load the restore point library, error=" + << error.code; + } else { + // Force the DLL to stay loaded until program termination. + base::NativeLibrary module_handle = nullptr; + if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, + kRestorePointClientLibrary, &module_handle)) { + PLOG(ERROR) << "Failed to pin the restore point library."; + return; + } + DCHECK_EQ(srclient_dll_, module_handle); + set_restore_point_info_fn_ = reinterpret_cast<SetRestorePointInfoWFn>( + base::GetFunctionPointerFromNativeLibrary(srclient_dll_, + "SRSetRestorePointW")); + remove_restore_point_info_fn_ = reinterpret_cast<RemoveRestorePointFn>( + base::GetFunctionPointerFromNativeLibrary(srclient_dll_, + "SRRemoveRestorePoint")); + } + + if (!set_restore_point_info_fn_) + LOG(ERROR) << "Unable to find System Restore Point library."; +} + +void SystemRestorePointComponent::PreScan() {} + +void SystemRestorePointComponent::PostScan( + const std::vector<UwSId>& found_pups) {} + +void SystemRestorePointComponent::PreCleanup() { + // It is not ok to call SRSetRestorePoint recursively. Make sure this is the + // first call. + DCHECK_EQ(sequence_number_, kInvalidSequenceNumber); + if (!set_restore_point_info_fn_) + return; + + // On Windows8, a registry value needs to be created in order for restore + // points to be deterministically created. Attempt to create this value, but + // continue with the restore point anyway even if doing so fails. See + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa378941.aspx for + // more information. + if (base::win::GetVersion() >= base::win::VERSION_WIN8) { + base::win::RegKey system_restore_key(HKEY_LOCAL_MACHINE, kSystemRestoreKey, + KEY_SET_VALUE | KEY_QUERY_VALUE); + if (system_restore_key.Valid() && + !system_restore_key.HasValue(kSystemRestoreFrequencyWin8)) { + system_restore_key.WriteValue(kSystemRestoreFrequencyWin8, + static_cast<DWORD>(0)); + } + } + + // Take a system restore point before doing anything else. + RESTOREPOINTINFO restore_point_spec = {}; + STATEMGRSTATUS state_manager_status = {}; + + restore_point_spec.dwEventType = BEGIN_SYSTEM_CHANGE; + // MSDN documents few of the available values here. Use APPLICATION_INSTALL + // since that seems closest from the documented ones. The header file + // mentions a CHECKPOINT type which looks interesting, but let's stay on the + // beaten path for now. + restore_point_spec.dwRestorePtType = APPLICATION_INSTALL; + restore_point_spec.llSequenceNumber = 0; + wcsncpy(restore_point_spec.szDescription, product_fullname_.c_str(), + base::size(restore_point_spec.szDescription)); + + if (set_restore_point_info_fn_(&restore_point_spec, &state_manager_status)) { + sequence_number_ = state_manager_status.llSequenceNumber; + } else { + if (state_manager_status.nStatus == ERROR_SERVICE_DISABLED) { + LOG(WARNING) << "System Restore is disabled."; + } else { + LOG(ERROR) << "Failed to start System Restore service, error: " + << state_manager_status.nStatus; + } + } +} + +void SystemRestorePointComponent::PostCleanup(ResultCode result_code, + RebooterAPI* rebooter) { + if (!set_restore_point_info_fn_ || sequence_number_ == kInvalidSequenceNumber) + return; + + RESTOREPOINTINFO restore_point_spec = {}; + STATEMGRSTATUS state_manager_status = {}; + + restore_point_spec.dwEventType = END_SYSTEM_CHANGE; + restore_point_spec.llSequenceNumber = sequence_number_; + + if (result_code == RESULT_CODE_SUCCESS || + result_code == RESULT_CODE_PENDING_REBOOT || + result_code == RESULT_CODE_POST_REBOOT_SUCCESS || + result_code == RESULT_CODE_POST_REBOOT_ELEVATION_DENIED) { + // Success! For now... Commit the restore point. + restore_point_spec.dwRestorePtType = APPLICATION_INSTALL; + + if (!SetRestorePointInfoWrapper(&restore_point_spec, + &state_manager_status)) { + LOG(ERROR) << "Failed to commit System Restore point, error: " + << state_manager_status.nStatus; + } + } else { + // No mutations were made, either because we found nothing, the user + // canceled or an error occurred. Abort the restore point. + restore_point_spec.dwRestorePtType = CANCELLED_OPERATION; + + if (!SetRestorePointInfoWrapper(&restore_point_spec, + &state_manager_status)) { + LOG(ERROR) << "Failed to cancel System Restore point, error: " + << state_manager_status.nStatus; + } + + // I have observed, at least on Win8, that cancelling the restore point + // still leaves it behind, so explicitly remove it as well. + if (remove_restore_point_info_fn_ && + !RemoveRestorePointWrapper(sequence_number_)) { + LOG(ERROR) << "Failed to remove cancelled Restore point."; + } + } +} + +void SystemRestorePointComponent::PostValidation(ResultCode result_code) {} + +void SystemRestorePointComponent::OnClose(ResultCode result_code) {} + +bool SystemRestorePointComponent::IsLoadedRestorePointLibrary() { + base::NativeLibrary module_handle = nullptr; + if (!::GetModuleHandleExW(0, kRestorePointClientLibrary, &module_handle)) { + PLOG(ERROR) << "Restore point library no longer present."; + return false; + } + DCHECK_EQ(srclient_dll_, module_handle); + return true; +} + +bool SystemRestorePointComponent::SetRestorePointInfoWrapper( + PRESTOREPOINTINFOW info, + PSTATEMGRSTATUS status) { + if (!set_restore_point_info_fn_ || + !SystemRestorePointComponent::IsLoadedRestorePointLibrary()) { + return false; + } + return set_restore_point_info_fn_(info, status) != FALSE; +} + +bool SystemRestorePointComponent::RemoveRestorePointWrapper(DWORD sequence) { + if (!remove_restore_point_info_fn_ || + !SystemRestorePointComponent::IsLoadedRestorePointLibrary()) { + return false; + } + return remove_restore_point_info_fn_(sequence) != FALSE; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/components/system_restore_point_component.h b/chrome/chrome_cleaner/components/system_restore_point_component.h new file mode 100644 index 0000000..d261f59 --- /dev/null +++ b/chrome/chrome_cleaner/components/system_restore_point_component.h
@@ -0,0 +1,58 @@ +// Copyright 2018 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 CHROME_CHROME_CLEANER_COMPONENTS_SYSTEM_RESTORE_POINT_COMPONENT_H_ +#define CHROME_CHROME_CLEANER_COMPONENTS_SYSTEM_RESTORE_POINT_COMPONENT_H_ + +#include <windows.h> + +#include <srrestoreptapi.h> +#include <stdint.h> + +#include <vector> + +#include "base/native_library.h" +#include "base/strings/string16.h" +#include "chrome/chrome_cleaner/components/component_api.h" + +namespace chrome_cleaner { + +// This class manages the setting and clearing of a system restore point. +class SystemRestorePointComponent : public ComponentAPI { + public: + explicit SystemRestorePointComponent(const base::string16& product_fullname); + + // ComponentAPI methods. + void PreScan() override; + void PostScan(const std::vector<UwSId>& found_pups) override; + void PreCleanup() override; + void PostCleanup(ResultCode result_code, RebooterAPI* rebooter) override; + void PostValidation(ResultCode result_code) override; + void OnClose(ResultCode result_code) override; + + protected: + // The below typedefs and members have protected visibility for testing. + typedef BOOL(WINAPI* SetRestorePointInfoWFn)(PRESTOREPOINTINFOW, + PSTATEMGRSTATUS); + typedef BOOL(WINAPI* RemoveRestorePointFn)(DWORD); + + SetRestorePointInfoWFn set_restore_point_info_fn_; + RemoveRestorePointFn remove_restore_point_info_fn_; + + private: + // Perform internal sanity checks to validate the presence of the restore + // point library. + bool IsLoadedRestorePointLibrary(); + // Safe wrappers to dynamic calls to the restore point library. + bool SetRestorePointInfoWrapper(PRESTOREPOINTINFOW, PSTATEMGRSTATUS); + bool RemoveRestorePointWrapper(DWORD); + + base::NativeLibrary srclient_dll_; + int64_t sequence_number_; + base::string16 product_fullname_; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_COMPONENTS_SYSTEM_RESTORE_POINT_COMPONENT_H_
diff --git a/chrome/chrome_cleaner/components/system_restore_point_component_unittest.cc b/chrome/chrome_cleaner/components/system_restore_point_component_unittest.cc new file mode 100644 index 0000000..c013635 --- /dev/null +++ b/chrome/chrome_cleaner/components/system_restore_point_component_unittest.cc
@@ -0,0 +1,127 @@ +// Copyright 2018 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/chrome_cleaner/components/system_restore_point_component.h" + +#include "base/synchronization/lock.h" +#include "base/test/test_reg_util_win.h" +#include "chrome/chrome_cleaner/test/test_branding.h" +#include "testing/gtest/include/gtest/gtest.h" + +// TODO(robertshield): Figure out how to test this. Near as I can tell the +// only way to enumerate RestorePoints is via WMI, which is 12 kinds of ugh. + +namespace chrome_cleaner { + +namespace { + +constexpr DWORD kFakeSeqNumber = 42U; +bool g_set_called = false; +bool g_remove_called = false; + +base::Lock* SharedLock() { + static base::Lock lock; + return &lock; +} + +BOOL WINAPI FakeSetRestorePointInfoWFn(RESTOREPOINTINFOW* restore_point_info, + STATEMGRSTATUS* state_mgr_status) { + state_mgr_status->llSequenceNumber = kFakeSeqNumber; + state_mgr_status->nStatus = 0; + g_set_called = true; + return true; +} + +BOOL WINAPI FakeRemoveRestorePointFn(DWORD sequence_number) { + EXPECT_EQ(kFakeSeqNumber, sequence_number); + g_remove_called = true; + return true; +} + +BOOL WINAPI +FakeSetRestorePointInfoWFailFn(RESTOREPOINTINFOW* restore_point_info, + STATEMGRSTATUS* state_mgr_status) { + state_mgr_status->llSequenceNumber = kFakeSeqNumber; + state_mgr_status->nStatus = 0; + g_set_called = true; + return false; +} + +BOOL WINAPI FakeRemoveRestorePointFailFn(DWORD sequence_number) { + EXPECT_EQ(kFakeSeqNumber, sequence_number); + g_remove_called = true; + return false; +} + +} // namespace + +class TestSystemRestorePointComponent : public SystemRestorePointComponent { + public: + TestSystemRestorePointComponent() + : SystemRestorePointComponent(TEST_PRODUCT_FULLNAME_STRING) {} + + void OverrideSetRestorePointInfoWFn( + SystemRestorePointComponent::SetRestorePointInfoWFn func) { + set_restore_point_info_fn_ = func; + } + void OverrideRemoveRestorePointFn( + SystemRestorePointComponent::RemoveRestorePointFn func) { + remove_restore_point_info_fn_ = func; + } +}; + +class SystemRestorePointComponentTest : public testing::Test { + protected: + SystemRestorePointComponentTest() : auto_lock_(*SharedLock()) {} + + void SetUp() override { + system_restore_point_component_.OverrideSetRestorePointInfoWFn( + &FakeSetRestorePointInfoWFn); + system_restore_point_component_.OverrideRemoveRestorePointFn( + &FakeRemoveRestorePointFn); + + registry_override_.OverrideRegistry(HKEY_LOCAL_MACHINE); + g_set_called = false; + g_remove_called = false; + } + + base::AutoLock auto_lock_; + + TestSystemRestorePointComponent system_restore_point_component_; + registry_util::RegistryOverrideManager registry_override_; +}; + +TEST_F(SystemRestorePointComponentTest, CheckRestoreCallsSuccess) { + system_restore_point_component_.PreCleanup(); + system_restore_point_component_.PostCleanup(RESULT_CODE_SUCCESS, nullptr); + EXPECT_TRUE(g_set_called); + EXPECT_FALSE(g_remove_called); +} + +TEST_F(SystemRestorePointComponentTest, CheckRestoreCallsFailure) { + system_restore_point_component_.PreCleanup(); + system_restore_point_component_.PostCleanup(RESULT_CODE_FAILED, nullptr); + EXPECT_TRUE(g_set_called); + EXPECT_TRUE(g_remove_called); +} + +TEST_F(SystemRestorePointComponentTest, CheckRestoreCallsRestorePointFailure) { + system_restore_point_component_.OverrideSetRestorePointInfoWFn( + &FakeSetRestorePointInfoWFailFn); + system_restore_point_component_.PreCleanup(); + system_restore_point_component_.PostCleanup(RESULT_CODE_SUCCESS, nullptr); + EXPECT_TRUE(g_set_called); + EXPECT_FALSE(g_remove_called); +} + +TEST_F(SystemRestorePointComponentTest, CheckRestoreCommitRestorePointFailure) { + system_restore_point_component_.OverrideRemoveRestorePointFn( + &FakeRemoveRestorePointFailFn); + system_restore_point_component_.PreCleanup(); + system_restore_point_component_.PostCleanup(RESULT_CODE_FAILED, nullptr); + EXPECT_TRUE(g_set_called); + EXPECT_TRUE(g_remove_called); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/os/rebooter_api.h b/chrome/chrome_cleaner/os/rebooter_api.h index 5e51681..4fa8d97 100644 --- a/chrome/chrome_cleaner/os/rebooter_api.h +++ b/chrome/chrome_cleaner/os/rebooter_api.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/command_line.h" #include "components/chrome_cleaner/public/constants/constants.h" namespace chrome_cleaner {
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn index 98aad55..37fc2f3 100644 --- a/chrome/chrome_cleaner/test/BUILD.gn +++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -33,6 +33,20 @@ ] } +source_set("test_component") { + testonly = true + + sources = [ + "test_component.cc", + "test_component.h", + ] + + deps = [ + "//chrome/chrome_cleaner/components:components", + "//chrome/chrome_cleaner/constants:uws_id", + ] +} + source_set("test_executables") { testonly = true
diff --git a/chrome/chrome_cleaner/test/test_component.cc b/chrome/chrome_cleaner/test/test_component.cc new file mode 100644 index 0000000..a6a20f4 --- /dev/null +++ b/chrome/chrome_cleaner/test/test_component.cc
@@ -0,0 +1,44 @@ +// Copyright 2018 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/chrome_cleaner/test/test_component.h" + +namespace chrome_cleaner { + +TestComponent::Calls::Calls() = default; +TestComponent::Calls::~Calls() = default; + +TestComponent::~TestComponent() { + calls_->destroyed = true; +} + +void TestComponent::PreScan() { + calls_->pre_scan = true; +} + +void TestComponent::PostScan(const std::vector<UwSId>& found_pups) { + calls_->post_scan = true; + calls_->post_scan_found_pups = found_pups; +} + +void TestComponent::PreCleanup() { + calls_->pre_cleanup = true; +} + +void TestComponent::PostCleanup(ResultCode result_code, RebooterAPI* rebooter) { + calls_->result_code = result_code; + calls_->post_cleanup = true; +} + +void TestComponent::PostValidation(ResultCode result_code) { + calls_->result_code = result_code; + calls_->post_validation = true; +} + +void TestComponent::OnClose(ResultCode result_code) { + calls_->result_code = result_code; + calls_->on_close = true; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/test/test_component.h b/chrome/chrome_cleaner/test/test_component.h new file mode 100644 index 0000000..0a0eada --- /dev/null +++ b/chrome/chrome_cleaner/test/test_component.h
@@ -0,0 +1,48 @@ +// Copyright 2018 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 CHROME_CHROME_CLEANER_TEST_TEST_COMPONENT_H_ +#define CHROME_CHROME_CLEANER_TEST_TEST_COMPONENT_H_ + +#include <vector> + +#include "chrome/chrome_cleaner/components/component_api.h" + +namespace chrome_cleaner { + +class TestComponent : public ComponentAPI { + public: + struct Calls { + Calls(); + ~Calls(); + + bool pre_scan = false; + bool post_scan = false; + bool pre_cleanup = false; + bool post_cleanup = false; + bool post_validation = false; + bool on_close = false; + bool destroyed = false; + std::vector<UwSId> post_scan_found_pups; + ResultCode result_code = RESULT_CODE_INVALID; + }; + + explicit TestComponent(Calls* calls) : calls_(calls) {} + ~TestComponent() override; + + // ComponentAPI. + void PreScan() override; + void PostScan(const std::vector<UwSId>& found_pups) override; + void PreCleanup() override; + void PostCleanup(ResultCode result_code, RebooterAPI* rebooter) override; + void PostValidation(ResultCode result_code) override; + void OnClose(ResultCode result_code) override; + + private: + Calls* calls_; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_TEST_TEST_COMPONENT_H_
diff --git a/chrome/common/apps/platform_apps/api/BUILD.gn b/chrome/common/apps/platform_apps/api/BUILD.gn index 0938bb8..027709b3 100644 --- a/chrome/common/apps/platform_apps/api/BUILD.gn +++ b/chrome/common/apps/platform_apps/api/BUILD.gn
@@ -32,7 +32,7 @@ # Private Targets generated_json_strings("generated_api_json_strings") { - sources = chrome_apps_api_schema_files + sources = chrome_apps_api_schema_files + chrome_apps_uncompiled_schema_files bundle_name = "ChromeApps" root_namespace = apps_api_root_namespace deps = [
diff --git a/chrome/common/apps/platform_apps/api/_api_features.json b/chrome/common/apps/platform_apps/api/_api_features.json index 19c51f9..5878b6e 100644 --- a/chrome/common/apps/platform_apps/api/_api_features.json +++ b/chrome/common/apps/platform_apps/api/_api_features.json
@@ -14,5 +14,9 @@ "easyUnlockPrivate": { "dependencies": ["permission:easyUnlockPrivate"], "contexts": ["blessed_extension"] + }, + "musicManagerPrivate": { + "dependencies": ["permission:musicManagerPrivate"], + "contexts": ["blessed_extension"] } }
diff --git a/chrome/common/apps/platform_apps/api/_permission_features.json b/chrome/common/apps/platform_apps/api/_permission_features.json index 2e5469f..1b54c437 100644 --- a/chrome/common/apps/platform_apps/api/_permission_features.json +++ b/chrome/common/apps/platform_apps/api/_permission_features.json
@@ -16,5 +16,18 @@ "extension_types": ["platform_app"], "location": "component", "platforms": ["chromeos"] + }, + "musicManagerPrivate": { + "channel": "stable", + "extension_types": ["platform_app"], + "whitelist": [ + "4B1D0E19C6C43C008C44A8278C8B5BFE15ABEB3C", // Music Manager + "B8F61FD1B25DE03706DBB8906A73261E4DBB992A", // Test + "F7FA7ABC1ECB89BA8EE6656847EFABBF43BB9BCA", + "4FE45FA56EF6A25FDE8C302C44045CA9CE8A605A", + "3D14248405B8A59043420AAC160077C99E7788A9", + "A6C87307BBE5886CC5F1393025000E2FE8060BF2", + "3407516021EA3669C0EC8E65E6B9837E5A521B9C" + ] } }
diff --git a/chrome/common/apps/platform_apps/api/api_sources.gni b/chrome/common/apps/platform_apps/api/api_sources.gni index dd8dcff..dd1b8472 100644 --- a/chrome/common/apps/platform_apps/api/api_sources.gni +++ b/chrome/common/apps/platform_apps/api/api_sources.gni
@@ -13,7 +13,11 @@ chrome_apps_api_schema_files_ += [ "easy_unlock_private.idl" ] } +chrome_apps_uncompiled_schema_files_ = [ "music_manager_private.idl" ] + chrome_apps_api_schema_files = get_path_info(chrome_apps_api_schema_files_, "abspath") +chrome_apps_uncompiled_schema_files = + get_path_info(chrome_apps_uncompiled_schema_files_, "abspath") apps_api_root_namespace = "chrome_apps::api::%(namespace)s"
diff --git a/chrome/common/extensions/api/music_manager_private.idl b/chrome/common/apps/platform_apps/api/music_manager_private.idl similarity index 100% rename from chrome/common/extensions/api/music_manager_private.idl rename to chrome/common/apps/platform_apps/api/music_manager_private.idl
diff --git a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc index 9afa445f..493be62a 100644 --- a/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc +++ b/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
@@ -13,6 +13,8 @@ constexpr extensions::APIPermissionInfo::InitInfo permissions_to_register[] = { {extensions::APIPermission::kBrowser, "browser"}, {extensions::APIPermission::kEasyUnlockPrivate, "easyUnlockPrivate"}, + {extensions::APIPermission::kMusicManagerPrivate, "musicManagerPrivate", + extensions::APIPermissionInfo::kFlagCannotBeOptional}, }; } // namespace
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index 4c2b3ec0..6095648 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -588,10 +588,6 @@ "channel": "stable", "matches": ["<all_urls>"] }, - "musicManagerPrivate": { - "dependencies": ["permission:musicManagerPrivate"], - "contexts": ["blessed_extension"] - }, "networking.castPrivate": { "channel": "stable", "contexts": ["blessed_extension"],
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index a0b761e..010832c4 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json
@@ -566,19 +566,6 @@ "channel": "stable", "extension_types": ["platform_app"] }], - "musicManagerPrivate": { - "channel": "stable", - "extension_types": ["platform_app"], - "whitelist": [ - "4B1D0E19C6C43C008C44A8278C8B5BFE15ABEB3C", // Music Manager - "B8F61FD1B25DE03706DBB8906A73261E4DBB992A", // Test - "F7FA7ABC1ECB89BA8EE6656847EFABBF43BB9BCA", - "4FE45FA56EF6A25FDE8C302C44045CA9CE8A605A", - "3D14248405B8A59043420AAC160077C99E7788A9", - "A6C87307BBE5886CC5F1393025000E2FE8060BF2", - "3407516021EA3669C0EC8E65E6B9837E5A521B9C" - ] - }, "notifications": { // The chrome.notifications functionality listed in notifications.idl is // available only to extension/platform_app types. The implementation of
diff --git a/chrome/common/extensions/api/api_sources.gni b/chrome/common/extensions/api/api_sources.gni index 7abf8a9b..97f8b43e 100644 --- a/chrome/common/extensions/api/api_sources.gni +++ b/chrome/common/extensions/api/api_sources.gni
@@ -136,7 +136,6 @@ "browsing_data.json", "extension.json", "idltest.idl", - "music_manager_private.idl", "top_sites.json", ]
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index e3ff3d8a..a7d8e6a 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -104,6 +104,8 @@ callback IsAppShownCallback = void (boolean appShown); + callback TakeScreenshotCallback = void (DOMString base64Png); + callback VoidCallback = void (); interface Functions { @@ -208,6 +210,9 @@ // |callback|: Called when the operation has completed. static void setCrostiniEnabled(boolean enabled, VoidCallback callback); + // Takes a screenshot and returns the data in base64 encoded PNG format. + static void takeScreenshot(TakeScreenshotCallback callback); + // Makes a basic request to ML Service, triggering 1. ML Service // daemon startup, and 2. the initial D-Bus -> Mojo IPC bootstrap. // |callback|: Called when the operation has completed.
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc index 0bf08a2..d9bbc2f 100644 --- a/chrome/common/extensions/permissions/chrome_api_permissions.cc +++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -125,8 +125,6 @@ APIPermissionInfo::kFlagCannotBeOptional}, {APIPermission::kMediaRouterPrivate, "mediaRouterPrivate", APIPermissionInfo::kFlagCannotBeOptional}, - {APIPermission::kMusicManagerPrivate, "musicManagerPrivate", - APIPermissionInfo::kFlagCannotBeOptional}, {APIPermission::kNetworkingCastPrivate, "networking.castPrivate"}, {APIPermission::kPreferencesPrivate, "preferencesPrivate", APIPermissionInfo::kFlagCannotBeOptional},
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index aba2ebe..826469f3c 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -829,19 +829,6 @@ // system volume, and higher than 1.0 is louder. const char kTextToSpeechVolume[] = "settings.tts.speech_volume"; -// This is a timestamp to keep track of the screen start time when a unichrome -// user starts using the device for the first time of the day. Used to calculate -// the screen time limit and this will be refreshed daily. -const char kFirstScreenStartTime[] = "screen_time.first_screen.start_time"; - -// This is a timestamp to keep track of the screen start time for the current -// active screen. The pref is used to restore the screen start time after -// browser crashes and device reboots. -const char kCurrentScreenStartTime[] = "screen_time.current_screen.start_time"; - -// How much screen time in minutes has been used. -const char kScreenTimeMinutesUsed[] = "screen_time.time_usage"; - // A dictionary preference holding the usage time limit definitions for a user. const char kUsageTimeLimit[] = "screen_time.limit"; @@ -873,6 +860,15 @@ const char kNetBiosShareDiscoveryEnabled[] = "network_file_shares.netbios_discovery.enabled"; +// Amount of screen time that a child user has used in the current day. +const char kChildScreenTimeMilliseconds[] = "child_screen_time"; + +// Last time the kChildScreenTimeMilliseconds was saved. +const char kLastChildScreenTimeSaved[] = "last_child_screen_time_saved"; + +// Last time that the kChildScreenTime pref was reset. +const char kLastChildScreenTimeReset[] = "last_child_screen_time_reset"; + #endif // defined(OS_CHROMEOS) // A boolean pref set to true if a Home button to open the Home pages should be
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 6ba77e8..ad0e63f 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -270,9 +270,6 @@ extern const char kTextToSpeechRate[]; extern const char kTextToSpeechPitch[]; extern const char kTextToSpeechVolume[]; -extern const char kFirstScreenStartTime[]; -extern const char kCurrentScreenStartTime[]; -extern const char kScreenTimeMinutesUsed[]; extern const char kUsageTimeLimit[]; extern const char kScreenTimeLastState[]; extern const char kEnableSyncConsent[]; @@ -280,6 +277,9 @@ extern const char kManagedSessionEnabled[]; extern const char kTPMFirmwareUpdateCleanupDismissed[]; extern const char kNetBiosShareDiscoveryEnabled[]; +extern const char kChildScreenTimeMilliseconds[]; +extern const char kLastChildScreenTimeSaved[]; +extern const char kLastChildScreenTimeReset[]; #endif // defined(OS_CHROMEOS) extern const char kShowHomeButton[]; extern const char kSpeechRecognitionFilterProfanities[];
diff --git a/chrome/common/secure_origin_whitelist.cc b/chrome/common/secure_origin_whitelist.cc index 3319df1..b70d6ce 100644 --- a/chrome/common/secure_origin_whitelist.cc +++ b/chrome/common/secure_origin_whitelist.cc
@@ -126,7 +126,7 @@ // Drop .unique() origins, as they are unequal to any other origins. url::Origin origin(url::Origin::Create(GURL(origin_str))); - if (!origin.unique()) + if (!origin.opaque()) origin_patterns.push_back(origin.Serialize()); }
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 7a1395c..cfaf2746 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -316,6 +316,9 @@ const char kTimeZoneSettingsLearnMoreURL[] = "https://support.google.com/chromebook?p=chromebook_timezone&hl=%s"; + +const char kSmbSharesLearnMoreURL[] = + "https://support.google.com/chromebook?p=network_file_shares"; #endif // defined(OS_CHROMEOS) #if defined(OS_MACOSX)
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 7ddffa8e..5e3098f 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -273,6 +273,9 @@ // The URL for the "Learn more" page for the time zone settings page. extern const char kTimeZoneSettingsLearnMoreURL[]; + +// The URL for the "Learn more" page for the network file shares settings page. +extern const char kSmbSharesLearnMoreURL[]; #endif // defined(OS_CHROMEOS) #if defined(OS_MACOSX)
diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc index 3c538c9..6901a9d 100644 --- a/chrome/renderer/content_settings_observer.cc +++ b/chrome/renderer/content_settings_observer.cc
@@ -65,7 +65,7 @@ // TODO(alexmos): This is broken for --site-per-process, since top() can be a // WebRemoteFrame which does not have a document(), and the WebRemoteFrame's // URL is not replicated. See https://crbug.com/628759. - if (top_origin.unique() && frame->Top()->IsWebLocalFrame()) + if (top_origin.opaque() && frame->Top()->IsWebLocalFrame()) return frame->Top()->ToWebLocalFrame()->GetDocument().Url(); return top_origin.GetURL(); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 252ed9d..6e7bb4c 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1203,6 +1203,7 @@ sources += [ "../browser/accessibility/accessibility_extension_api_browsertest.cc", "../browser/apps/platform_apps/api/browser/browser_apitest.cc", + "../browser/apps/platform_apps/api/music_manager_private/music_manager_private_browsertest.cc", "../browser/apps/platform_apps/app_browsertest_util.cc", "../browser/apps/platform_apps/app_browsertest_util.h", "../browser/extensions/active_tab_apitest.cc", @@ -1265,7 +1266,6 @@ "../browser/extensions/api/messaging/native_messaging_apitest.cc", "../browser/extensions/api/metrics_private/metrics_apitest.cc", "../browser/extensions/api/module/module_apitest.cc", - "../browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc", "../browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc", "../browser/extensions/api/omnibox/omnibox_api_browsertest.cc", "../browser/extensions/api/page_capture/page_capture_apitest.cc", @@ -3996,7 +3996,6 @@ sources += [ "../browser/printing/print_job_unittest.cc", "../browser/printing/print_preview_dialog_controller_unittest.cc", - "../browser/printing/print_preview_message_handler_unittest.cc", "../browser/printing/print_preview_test.cc", "../browser/printing/print_preview_test.h", "../browser/printing/print_test_utils.cc",
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index b32a606e..2ffa1ca 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc
@@ -155,41 +155,6 @@ // Default profile name const char kTestingProfile[] = "testing_profile"; -class TestExtensionURLRequestContext : public net::URLRequestContext { - public: - TestExtensionURLRequestContext() { - content::CookieStoreConfig cookie_config; - cookie_config.cookieable_schemes.push_back(extensions::kExtensionScheme); - cookie_store_ = - content::CreateCookieStore(cookie_config, nullptr /* netlog */); - set_cookie_store(cookie_store_.get()); - } - - std::unique_ptr<net::CookieStore> cookie_store_; - - ~TestExtensionURLRequestContext() override { AssertNoURLRequests(); } -}; - -class TestExtensionURLRequestContextGetter - : public net::URLRequestContextGetter { - public: - net::URLRequestContext* GetURLRequestContext() override { - if (!context_.get()) - context_.reset(new TestExtensionURLRequestContext()); - return context_.get(); - } - scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() - const override { - return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}); - } - - protected: - ~TestExtensionURLRequestContextGetter() override {} - - private: - std::unique_ptr<net::URLRequestContext> context_; -}; - std::unique_ptr<KeyedService> BuildHistoryService( content::BrowserContext* context) { return std::make_unique<history::HistoryService>( @@ -852,10 +817,23 @@ return GetDefaultStoragePartition(this)->GetURLRequestContext(); } -net::URLRequestContextGetter* TestingProfile::GetRequestContextForExtensions() { - if (!extensions_request_context_.get()) - extensions_request_context_ = new TestExtensionURLRequestContextGetter(); - return extensions_request_context_.get(); +base::OnceCallback<net::CookieStore*()> +TestingProfile::GetExtensionsCookieStoreGetter() { + return base::BindOnce( + [](std::unique_ptr<net::CookieStore, + content::BrowserThread::DeleteOnIOThread>* + cookie_store) { + if (!*cookie_store) { + content::CookieStoreConfig cookie_config; + cookie_config.cookieable_schemes.push_back( + extensions::kExtensionScheme); + cookie_store->reset( + content::CreateCookieStore(cookie_config, nullptr /* netlog */) + .release()); + } + return cookie_store->get(); + }, + &extensions_cookie_store_); } scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h index 7c56cc1..1e27ef2 100644 --- a/chrome/test/base/testing_profile.h +++ b/chrome/test/base/testing_profile.h
@@ -18,6 +18,7 @@ #include "chrome/browser/profiles/profile.h" #include "components/domain_reliability/clear_mode.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" +#include "content/public/browser/browser_thread.h" #include "extensions/buildflags/buildflags.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_service.mojom.h" @@ -323,7 +324,8 @@ ChromeZoomLevelPrefs* GetZoomLevelPrefs() override; #endif // !defined(OS_ANDROID) net::URLRequestContextGetter* GetRequestContext() override; - net::URLRequestContextGetter* GetRequestContextForExtensions() override; + base::OnceCallback<net::CookieStore*()> GetExtensionsCookieStoreGetter() + override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; void set_last_session_exited_cleanly(bool value) { @@ -401,9 +403,8 @@ // maps to this profile. void CreateProfilePolicyConnector(); - // Internally, this is a TestURLRequestContextGetter that creates a dummy - // request context. Currently, only the CookieMonster is hooked up. - scoped_refptr<net::URLRequestContextGetter> extensions_request_context_; + std::unique_ptr<net::CookieStore, content::BrowserThread::DeleteOnIOThread> + extensions_cookie_store_; // Holds a dummy network context request to avoid triggering connection error // handler.
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc index 65bdc998..39e420ad 100644 --- a/chrome/test/chromedriver/element_commands.cc +++ b/chrome/test/chromedriver/element_commands.cc
@@ -289,6 +289,21 @@ const std::string& element_id, const base::DictionaryValue& params, std::unique_ptr<base::Value>* value) { + // Scrolling to element is done by webdriver::atoms::CLEAR + bool is_displayed = false; + base::TimeTicks start_time = base::TimeTicks::Now(); + while (true) { + Status status = IsElementDisplayed( + session, web_view, element_id, true, &is_displayed); + if (status.IsError()) + return status; + if (is_displayed) + break; + if (base::TimeTicks::Now() - start_time >= session->implicit_wait) { + return Status(kElementNotVisible); + } + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); + } base::ListValue args; args.Append(CreateElement(element_id)); std::unique_ptr<base::Value> result;
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js index e14b825..7e3e2e92e 100644 --- a/chrome/test/data/extensions/api_test/autotest_private/test.js +++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -193,6 +193,15 @@ chrome.autotestPrivate.runCrostiniUninstaller(chrome.test.callbackFail( 'Crostini is not available for the current user')); }, + function takeScreenshot() { + chrome.autotestPrivate.takeScreenshot( + function(base64Png) { + chrome.test.assertTrue(base64Png.length > 0); + chrome.test.assertNoLastError(); + chrome.test.succeed(); + } + ) + }, function getPrinterList() { chrome.autotestPrivate.getPrinterList(function(){ chrome.test.succeed();
diff --git a/chromecast/common/extensions_api/accessibility_private.json b/chromecast/common/extensions_api/accessibility_private.json index 9ad01ec..0bee8ca 100644 --- a/chromecast/common/extensions_api/accessibility_private.json +++ b/chromecast/common/extensions_api/accessibility_private.json
@@ -35,7 +35,7 @@ { "id": "Gesture", "type": "string", - "enum": [ "click", "swipeLeft1", "swipeUp1", "swipeRight1", "swipeDown1", "swipeLeft2", "swipeUp2", "swipeRight2", "swipeDown2", "swipeLeft3", "swipeUp3", "swipeRight3", "swipeDown3", "swipeLeft4", "swipeUp4", "swipeRight4", "swipeDown4" ], + "enum": [ "click", "swipeLeft1", "swipeUp1", "swipeRight1", "swipeDown1", "swipeLeft2", "swipeUp2", "swipeRight2", "swipeDown2", "swipeLeft3", "swipeUp3", "swipeRight3", "swipeDown3", "swipeLeft4", "swipeUp4", "swipeRight4", "swipeDown4", "tap2", "tap3", "tap4" ], "description": "Accessibility gestures fired by the touch exploration controller." }, {
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index a5144da..1f4a57a 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -782,6 +782,14 @@ ] } + tast_test("chrome_login_tast_tests") { + tast_tests = [ + "ui.ChromeLogin", + "ui.ChromeCrashLoggedIn", + "ui.ChromeCrashNotLoggedIn", + ] + } + group("cros_chrome_deploy") { # The following run-time dependencies are needed to deploy chrome to a # ChromeOS device. See the link for the full list:
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc index c745fff..0c365aa1 100644 --- a/chromeos/login/auth/cryptohome_authenticator.cc +++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -76,6 +76,67 @@ CryptohomeMigrationToGaiaId::ENTRIES_COUNT); } +// Returns a human-readable string describing |state|. +const char* AuthStateToString(CryptohomeAuthenticator::AuthState state) { + switch (state) { + case CryptohomeAuthenticator::CONTINUE: + return "CONTINUE"; + case CryptohomeAuthenticator::NO_MOUNT: + return "NO_MOUNT"; + case CryptohomeAuthenticator::FAILED_MOUNT: + return "FAILED_MOUNT"; + case CryptohomeAuthenticator::FAILED_REMOVE: + return "FAILED_REMOVE"; + case CryptohomeAuthenticator::FAILED_TMPFS: + return "FAILED_TMPFS"; + case CryptohomeAuthenticator::FAILED_TPM: + return "FAILED_TPM"; + case CryptohomeAuthenticator::CREATE_NEW: + return "CREATE_NEW"; + case CryptohomeAuthenticator::RECOVER_MOUNT: + return "RECOVER_MONUT"; + case CryptohomeAuthenticator::POSSIBLE_PW_CHANGE: + return "POSSIBLE_PW_CHANGE"; + case CryptohomeAuthenticator::NEED_NEW_PW: + return "NEED_NEW_PW"; + case CryptohomeAuthenticator::NEED_OLD_PW: + return "NEED_OLD_PW"; + case CryptohomeAuthenticator::HAVE_NEW_PW: + return "HAVE_NEW_PW"; + case CryptohomeAuthenticator::OFFLINE_LOGIN: + return "OFFLINE_LOGIN"; + case CryptohomeAuthenticator::ONLINE_LOGIN: + return "ONLINE_LOGIN"; + case CryptohomeAuthenticator::UNLOCK: + return "UNLOCK"; + case CryptohomeAuthenticator::ONLINE_FAILED: + return "ONLINE_FAILED"; + case CryptohomeAuthenticator::GUEST_LOGIN: + return "GUEST_LOGIN"; + case CryptohomeAuthenticator::PUBLIC_ACCOUNT_LOGIN: + return "PUBLIC_ACCOUNT_LOGIN"; + case CryptohomeAuthenticator::SUPERVISED_USER_LOGIN: + return "SUPERVISED_USER_LOGIN"; + case CryptohomeAuthenticator::LOGIN_FAILED: + return "LOGIN_FAILED"; + case CryptohomeAuthenticator::OWNER_REQUIRED: + return "OWNER_REQUIRED"; + case CryptohomeAuthenticator::FAILED_USERNAME_HASH: + return "FAILED_USERNAME_HASH"; + case CryptohomeAuthenticator::KIOSK_ACCOUNT_LOGIN: + return "KIOSK_ACCOUNT_LOGIN"; + case CryptohomeAuthenticator::REMOVED_DATA_AFTER_FAILURE: + return "REMOVED_DATA_AFTER_FAILURE"; + case CryptohomeAuthenticator::FAILED_OLD_ENCRYPTION: + return "FAILED_OLD_ENCRYPTION"; + case CryptohomeAuthenticator::FAILED_PREVIOUS_MIGRATION_INCOMPLETE: + return "FAILED_PREVIOUS_MIGRATION_INCOMPLETE"; + case CryptohomeAuthenticator::OFFLINE_NO_MOUNT: + return "OFFLINE_NO_MOUNT"; + } + return "UNKNOWN"; +} + // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN. // Returns the keys unmodified otherwise. std::unique_ptr<Key> TransformKeyIfNeeded(const Key& key, @@ -808,7 +869,8 @@ DCHECK(task_runner_->RunsTasksInCurrentSequence()); bool create_if_nonexistent = false; CryptohomeAuthenticator::AuthState state = ResolveState(); - VLOG(1) << "Resolved state to: " << state; + VLOG(1) << "Resolved state to " << state << " (" << AuthStateToString(state) + << ")"; switch (state) { case CONTINUE: case POSSIBLE_PW_CHANGE:
diff --git a/components/arc/arc_prefs.cc b/components/arc/arc_prefs.cc index db86fb7..f13fdbc 100644 --- a/components/arc/arc_prefs.cc +++ b/components/arc/arc_prefs.cc
@@ -93,17 +93,21 @@ // control settings. const char kVoiceInteractionActivityControlAccepted[] = "settings.voice_interaction.activity_control.accepted"; -// A preference that indicates the user has enabled voice interaction services. -const char kVoiceInteractionEnabled[] = "settings.voice_interaction.enabled"; // A preference that indicates the user has allowed voice interaction services // to access the "context" (text and graphic content that is currently on // screen). const char kVoiceInteractionContextEnabled[] = "settings.voice_interaction.context.enabled"; +// A preference that indicates the user has enabled voice interaction services. +const char kVoiceInteractionEnabled[] = "settings.voice_interaction.enabled"; // A preference that indicates the user has allowed voice interaction services // to use hotword listening. const char kVoiceInteractionHotwordEnabled[] = "settings.voice_interaction.hotword.enabled"; +// A preference that indicates whether microphone should be open when the voice +// interaction launches. +const char kVoiceInteractionLaunchWithMicOpen[] = + "settings.voice_interaction.launch_with_mic_open"; // A preference that indicates the user has allowed voice interaction services // to send notification. const char kVoiceInteractionNotificationEnabled[] = @@ -152,6 +156,7 @@ registry->RegisterBooleanPref(kVoiceInteractionEnabled, false); registry->RegisterBooleanPref(kVoiceInteractionHotwordEnabled, false); registry->RegisterBooleanPref(kVoiceInteractionNotificationEnabled, true); + registry->RegisterBooleanPref(kVoiceInteractionLaunchWithMicOpen, false); } } // namespace prefs
diff --git a/components/arc/arc_prefs.h b/components/arc/arc_prefs.h index 209098c..2a900ca 100644 --- a/components/arc/arc_prefs.h +++ b/components/arc/arc_prefs.h
@@ -41,9 +41,10 @@ // TODO(b/110211045): Move Assistant related prefs to ash. ARC_EXPORT extern const char kVoiceInteractionActivityControlAccepted[]; -ARC_EXPORT extern const char kVoiceInteractionEnabled[]; ARC_EXPORT extern const char kVoiceInteractionContextEnabled[]; +ARC_EXPORT extern const char kVoiceInteractionEnabled[]; ARC_EXPORT extern const char kVoiceInteractionHotwordEnabled[]; +ARC_EXPORT extern const char kVoiceInteractionLaunchWithMicOpen[]; ARC_EXPORT extern const char kVoiceInteractionNotificationEnabled[]; void RegisterProfilePrefs(PrefRegistrySimple* registry);
diff --git a/components/browser_sync/sync_auth_manager.cc b/components/browser_sync/sync_auth_manager.cc index b559018..8f6edaf 100644 --- a/components/browser_sync/sync_auth_manager.cc +++ b/components/browser_sync/sync_auth_manager.cc
@@ -113,8 +113,17 @@ return sync_account_; } -const syncer::SyncTokenStatus& SyncAuthManager::GetSyncTokenStatus() const { - return token_status_; +syncer::SyncTokenStatus SyncAuthManager::GetSyncTokenStatus() const { + DCHECK(partial_token_status_.next_token_request_time.is_null()); + + syncer::SyncTokenStatus token_status = partial_token_status_; + if (request_access_token_retry_timer_.IsRunning()) { + base::TimeDelta delta = + request_access_token_retry_timer_.desired_run_time() - + base::TimeTicks::Now(); + token_status.next_token_request_time = base::Time::Now() + delta; + } + return token_status; } syncer::SyncCredentials SyncAuthManager::GetCredentials() const { @@ -132,8 +141,8 @@ } void SyncAuthManager::ConnectionStatusChanged(syncer::ConnectionStatus status) { - token_status_.connection_status_update_time = base::Time::Now(); - token_status_.connection_status = status; + partial_token_status_.connection_status_update_time = base::Time::Now(); + partial_token_status_.connection_status = status; switch (status) { case syncer::CONNECTION_AUTH_ERROR: @@ -160,14 +169,11 @@ // this point. DCHECK(access_token_.empty()); DCHECK(!request_access_token_retry_timer_.IsRunning()); - DCHECK(token_status_.next_token_request_time.is_null()); } else if (request_access_token_retry_timer_.IsRunning()) { // The timer to perform a request later is already running; nothing // further needs to be done at this point. DCHECK(access_token_.empty()); - DCHECK(!token_status_.next_token_request_time.is_null()); } else if (request_access_token_backoff_.failure_count() == 0) { - DCHECK(token_status_.next_token_request_time.is_null()); // First time request without delay. Currently invalid token is used // to initialize sync engine and we'll always end up here. We don't // want to delay initialization. @@ -189,7 +195,6 @@ // thus hammers token server. To be safe, only reset backoff delay when // no scheduled request. if (!request_access_token_retry_timer_.IsRunning()) { - DCHECK(token_status_.next_token_request_time.is_null()); request_access_token_backoff_.Reset(); } last_auth_error_ = GoogleServiceAuthError::AuthErrorNone(); @@ -224,7 +229,6 @@ void SyncAuthManager::ClearAccessTokenAndRequest() { access_token_.clear(); request_access_token_retry_timer_.Stop(); - token_status_.next_token_request_time = base::Time(); ongoing_access_token_fetch_.reset(); weak_ptr_factory_.InvalidateWeakPtrs(); } @@ -233,12 +237,9 @@ DCHECK(access_token_.empty()); DCHECK(!ongoing_access_token_fetch_); DCHECK(!request_access_token_retry_timer_.IsRunning()); - DCHECK(token_status_.next_token_request_time.is_null()); - base::TimeDelta delay = request_access_token_backoff_.GetTimeUntilRelease(); - token_status_.next_token_request_time = base::Time::Now() + delay; request_access_token_retry_timer_.Start( - FROM_HERE, delay, + FROM_HERE, request_access_token_backoff_.GetTimeUntilRelease(), base::BindRepeating(&SyncAuthManager::RequestAccessToken, weak_ptr_factory_.GetWeakPtr())); } @@ -412,12 +413,6 @@ } void SyncAuthManager::RequestAccessToken() { - // First reset the next request time: Either we were called back by the retry - // timer, in which case this is now obsolete, or we'll cancel the timer below. - // Note that if we were called back by the retry timer, then it's already - // considered not running, so we reset this time unconditionally. - token_status_.next_token_request_time = base::Time(); - // Only one active request at a time. if (ongoing_access_token_fetch_) { DCHECK(access_token_.empty()); @@ -439,8 +434,8 @@ InvalidateAccessToken(); // Finally, kick off a new access token fetch. - token_status_.token_request_time = base::Time::Now(); - token_status_.token_receive_time = base::Time(); + partial_token_status_.token_request_time = base::Time::Now(); + partial_token_status_.token_receive_time = base::Time(); ongoing_access_token_fetch_ = identity_manager_->CreateAccessTokenFetcherForAccount( sync_account_.account_info.account_id, kSyncOAuthConsumerName, @@ -458,14 +453,14 @@ DCHECK(!request_access_token_retry_timer_.IsRunning()); access_token_ = access_token_info.token; - token_status_.last_get_token_error = error; + partial_token_status_.last_get_token_error = error; DCHECK_EQ(access_token_.empty(), error.state() != GoogleServiceAuthError::NONE); switch (error.state()) { case GoogleServiceAuthError::NONE: - token_status_.token_receive_time = base::Time::Now(); + partial_token_status_.token_receive_time = base::Time::Now(); sync_prefs_->SetSyncAuthError(false); last_auth_error_ = GoogleServiceAuthError::AuthErrorNone(); break;
diff --git a/components/browser_sync/sync_auth_manager.h b/components/browser_sync/sync_auth_manager.h index 745919ad..4cc43ec 100644 --- a/components/browser_sync/sync_auth_manager.h +++ b/components/browser_sync/sync_auth_manager.h
@@ -85,7 +85,7 @@ // Returns the state of the access token and token request, for display in // internals UI. - const syncer::SyncTokenStatus& GetSyncTokenStatus() const; + syncer::SyncTokenStatus GetSyncTokenStatus() const; // Called by ProfileSyncService when the status of the connection to the Sync // server changed. Updates auth error state accordingly. @@ -136,7 +136,7 @@ // Immediately starts an access token request, unless one is already ongoing. // If another request is scheduled for later, it is canceled. Any access token - // we currently have is dropped and removed from IdentityManager's cache. + // we currently have is invalidated. void RequestAccessToken(); void AccessTokenFetched(GoogleServiceAuthError error, @@ -179,7 +179,9 @@ net::BackoffEntry request_access_token_backoff_; // Info about the state of our access token, for display in the internals UI. - syncer::SyncTokenStatus token_status_; + // "Partial" because this instance is not fully populated - in particular, + // |next_token_request_time| gets computed on demand. + syncer::SyncTokenStatus partial_token_status_; base::WeakPtrFactory<SyncAuthManager> weak_ptr_factory_;
diff --git a/components/cdm/browser/media_drm_storage_impl.cc b/components/cdm/browser/media_drm_storage_impl.cc index 480e3e1..5a1b2219 100644 --- a/components/cdm/browser/media_drm_storage_impl.cc +++ b/components/cdm/browser/media_drm_storage_impl.cc
@@ -397,7 +397,7 @@ DVLOG(1) << __func__ << ": origin = " << origin(); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(pref_service_); - DCHECK(!origin().unique()); + DCHECK(!origin().opaque()); } MediaDrmStorageImpl::~MediaDrmStorageImpl() {
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc index 59801251..f7b6cd2 100644 --- a/components/error_page/common/localized_error.cc +++ b/components/error_page/common/localized_error.cc
@@ -664,7 +664,7 @@ DCHECK(suggestions_summary_list->empty()); DCHECK(!(suggestions & ~SUGGEST_NAVIGATE_TO_ORIGIN)); url::Origin failed_origin = url::Origin::Create(failed_url); - if (failed_origin.unique()) + if (failed_origin.opaque()) return; auto suggestion = std::make_unique<base::DictionaryValue>();
diff --git a/components/leveldb_proto/leveldb_database.cc b/components/leveldb_proto/leveldb_database.cc index 7157518c..29b8f60 100644 --- a/components/leveldb_proto/leveldb_database.cc +++ b/components/leveldb_proto/leveldb_database.cc
@@ -4,6 +4,7 @@ #include "components/leveldb_proto/leveldb_database.h" +#include <map> #include <string> #include <vector> @@ -178,6 +179,34 @@ std::vector<std::string>* entries, const leveldb::ReadOptions& options, const std::string& target_prefix) { + std::map<std::string, std::string> keys_entries; + bool result = LoadKeysAndEntriesWithFilter(filter, &keys_entries, options, + target_prefix); + if (!result) + return false; + + for (const auto& pair : keys_entries) + entries->push_back(pair.second); + return true; +} + +bool LevelDB::LoadKeysAndEntries( + std::map<std::string, std::string>* keys_entries) { + return LoadKeysAndEntriesWithFilter(KeyFilter(), keys_entries); +} + +bool LevelDB::LoadKeysAndEntriesWithFilter( + const KeyFilter& filter, + std::map<std::string, std::string>* keys_entries) { + return LoadKeysAndEntriesWithFilter(filter, keys_entries, + leveldb::ReadOptions(), std::string()); +} + +bool LevelDB::LoadKeysAndEntriesWithFilter( + const KeyFilter& filter, + std::map<std::string, std::string>* keys_entries, + const leveldb::ReadOptions& options, + const std::string& target_prefix) { DFAKE_SCOPED_LOCK(thread_checker_); if (!db_) return false; @@ -187,30 +216,30 @@ for (db_iterator->Seek(target); db_iterator->Valid() && db_iterator->key().starts_with(target); db_iterator->Next()) { - if (!filter.is_null()) { - leveldb::Slice key_slice = db_iterator->key(); - if (!filter.Run(std::string(key_slice.data(), key_slice.size()))) - continue; + leveldb::Slice key_slice = db_iterator->key(); + std::string key_slice_str(key_slice.data(), key_slice.size()); + if (!filter.is_null() && !filter.Run(key_slice_str)) { + continue; } + leveldb::Slice value_slice = db_iterator->value(); - std::string entry(value_slice.data(), value_slice.size()); - entries->push_back(entry); + keys_entries->insert(std::make_pair( + key_slice_str, std::string(value_slice.data(), value_slice.size()))); } return true; } bool LevelDB::LoadKeys(std::vector<std::string>* keys) { - DFAKE_SCOPED_LOCK(thread_checker_); - if (!db_) - return false; - leveldb::ReadOptions options; options.fill_cache = false; - std::unique_ptr<leveldb::Iterator> db_iterator(db_->NewIterator(options)); - for (db_iterator->SeekToFirst(); db_iterator->Valid(); db_iterator->Next()) { - leveldb::Slice key_slice = db_iterator->key(); - keys->push_back(std::string(key_slice.data(), key_slice.size())); - } + std::map<std::string, std::string> keys_entries; + bool result = LoadKeysAndEntriesWithFilter(KeyFilter(), &keys_entries, + options, std::string()); + if (!result) + return false; + + for (const auto& pair : keys_entries) + keys->push_back(pair.first); return true; }
diff --git a/components/leveldb_proto/leveldb_database.h b/components/leveldb_proto/leveldb_database.h index 229afdb..2444e38 100644 --- a/components/leveldb_proto/leveldb_database.h +++ b/components/leveldb_proto/leveldb_database.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_LEVELDB_PROTO_LEVELDB_DATABASE_H_ #define COMPONENTS_LEVELDB_PROTO_LEVELDB_DATABASE_H_ +#include <map> #include <memory> #include <string> #include <vector> @@ -55,6 +56,7 @@ const std::vector<std::string>& keys_to_remove); virtual bool UpdateWithRemoveFilter(const base::StringPairs& entries_to_save, const KeyFilter& delete_key_filter); + virtual bool Load(std::vector<std::string>* entries); virtual bool LoadWithFilter(const KeyFilter& filter, std::vector<std::string>* entries); @@ -62,6 +64,18 @@ std::vector<std::string>* entries, const leveldb::ReadOptions& options, const std::string& target_prefix); + + virtual bool LoadKeysAndEntries( + std::map<std::string, std::string>* keys_entries); + virtual bool LoadKeysAndEntriesWithFilter( + const KeyFilter& filter, + std::map<std::string, std::string>* keys_entries); + virtual bool LoadKeysAndEntriesWithFilter( + const KeyFilter& filter, + std::map<std::string, std::string>* keys_entries, + const leveldb::ReadOptions& options, + const std::string& target_prefix); + virtual bool LoadKeys(std::vector<std::string>* keys); virtual bool Get(const std::string& key, bool* found, std::string* entry); // Close (if currently open) and then destroy (i.e. delete) the database
diff --git a/components/leveldb_proto/proto_database.h b/components/leveldb_proto/proto_database.h index 1d0e543..b62bd4f 100644 --- a/components/leveldb_proto/proto_database.h +++ b/components/leveldb_proto/proto_database.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_H_ #define COMPONENTS_LEVELDB_PROTO_PROTO_DATABASE_H_ +#include <map> #include <memory> #include <string> #include <utility> @@ -32,6 +33,9 @@ using LoadKeysCallback = base::OnceCallback<void(bool success, std::unique_ptr<std::vector<std::string>>)>; + using LoadKeysAndEntriesCallback = + base::OnceCallback<void(bool success, + std::unique_ptr<std::map<std::string, T>>)>; using GetCallback = base::OnceCallback<void(bool success, std::unique_ptr<T>)>; using DestroyCallback = base::OnceCallback<void(bool success)>; @@ -79,6 +83,17 @@ const std::string& target_prefix, LoadCallback callback) = 0; + virtual void LoadKeysAndEntries( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) = 0; + virtual void LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& filter, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) = 0; + virtual void LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& filter, + const leveldb::ReadOptions& options, + const std::string& target_prefix, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) = 0; + // Asynchronously loads all keys from the database and invokes |callback| with // those keys when complete. virtual void LoadKeys(LoadKeysCallback callback) = 0;
diff --git a/components/leveldb_proto/proto_database_impl.h b/components/leveldb_proto/proto_database_impl.h index f7bc921..b7a2202 100644 --- a/components/leveldb_proto/proto_database_impl.h +++ b/components/leveldb_proto/proto_database_impl.h
@@ -64,6 +64,16 @@ const leveldb::ReadOptions& options, const std::string& target_prefix, typename ProtoDatabase<T>::LoadCallback callback) override; + void LoadKeysAndEntries( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override; + void LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& filter, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override; + void LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& filter, + const leveldb::ReadOptions& options, + const std::string& target_prefix, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override; void LoadKeys(typename ProtoDatabase<T>::LoadKeysCallback callback) override; void GetEntry(const std::string& key, typename ProtoDatabase<T>::GetCallback callback) override; @@ -110,6 +120,14 @@ } template <typename T> +void RunLoadKeysAndEntriesCallback( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback, + bool* success, + std::unique_ptr<std::map<std::string, T>> keys_entries) { + std::move(callback).Run(*success, std::move(keys_entries)); +} + +template <typename T> void RunLoadKeysCallback(typename ProtoDatabase<T>::LoadKeysCallback callback, std::unique_ptr<bool> success, std::unique_ptr<std::vector<std::string>> keys) { @@ -184,30 +202,46 @@ } template <typename T> +void LoadKeysAndEntriesFromTaskRunner(LevelDB* database, + const LevelDB::KeyFilter& filter, + const leveldb::ReadOptions& options, + const std::string& target_prefix, + std::map<std::string, T>* keys_entries, + bool* success) { + DCHECK(success); + DCHECK(keys_entries); + + keys_entries->clear(); + + std::map<std::string, std::string> loaded_entries; + *success = database->LoadKeysAndEntriesWithFilter(filter, &loaded_entries, + options, target_prefix); + + for (const auto& pair : loaded_entries) { + T entry; + if (!entry.ParseFromString(pair.second)) { + DLOG(WARNING) << "Unable to parse leveldb_proto entry"; + // TODO(cjhopman): Decide what to do about un-parseable entries. + } + + keys_entries->insert(std::make_pair(pair.first, entry)); + } +} + +template <typename T> void LoadEntriesFromTaskRunner(LevelDB* database, const LevelDB::KeyFilter& filter, const leveldb::ReadOptions& options, const std::string& target_prefix, std::vector<T>* entries, bool* success) { - DCHECK(success); - DCHECK(entries); - entries->clear(); - std::vector<std::string> loaded_entries; - *success = - database->LoadWithFilter(filter, &loaded_entries, options, target_prefix); - - for (const auto& serialized_entry : loaded_entries) { - T entry; - if (!entry.ParseFromString(serialized_entry)) { - DLOG(WARNING) << "Unable to parse leveldb_proto entry"; - // TODO(cjhopman): Decide what to do about un-parseable entries. - } - - entries->push_back(entry); - } + std::map<std::string, T> keys_entries; + LoadKeysAndEntriesFromTaskRunner<T>(database, filter, options, target_prefix, + &keys_entries, success); + for (const auto& pair : keys_entries) + entries->push_back(pair.second); } inline void LoadKeysFromTaskRunner(LevelDB* database, @@ -360,7 +394,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); bool* success = new bool(false); - std::unique_ptr<std::vector<T>> entries(new std::vector<T>()); + auto entries = std::make_unique<std::vector<T>>(); // Get this pointer before entries is std::move()'d so we can use it below. std::vector<T>* entries_ptr = entries.get(); @@ -373,6 +407,42 @@ } template <typename T> +void ProtoDatabaseImpl<T>::LoadKeysAndEntries( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) { + LoadKeysAndEntriesWithFilter(LevelDB::KeyFilter(), std::move(callback)); +} + +template <typename T> +void ProtoDatabaseImpl<T>::LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& key_filter, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) { + LoadKeysAndEntriesWithFilter(key_filter, leveldb::ReadOptions(), + std::string(), std::move(callback)); +} + +template <typename T> +void ProtoDatabaseImpl<T>::LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& key_filter, + const leveldb::ReadOptions& options, + const std::string& target_prefix, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + bool* success = new bool(false); + + auto keys_entries = std::make_unique<std::map<std::string, T>>(); + // Get this pointer before entries is std::move()'d so we can use it below. + std::map<std::string, T>* keys_entries_ptr = keys_entries.get(); + + task_runner_->PostTaskAndReply( + FROM_HERE, + base::BindOnce(LoadKeysAndEntriesFromTaskRunner<T>, + base::Unretained(db_.get()), key_filter, options, + target_prefix, keys_entries_ptr, success), + base::BindOnce(RunLoadKeysAndEntriesCallback<T>, std::move(callback), + base::Owned(success), std::move(keys_entries))); +} + +template <typename T> void ProtoDatabaseImpl<T>::LoadKeys( typename ProtoDatabase<T>::LoadKeysCallback callback) { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/components/leveldb_proto/proto_database_impl_unittest.cc b/components/leveldb_proto/proto_database_impl_unittest.cc index 3da34f1..5ecf6a7d 100644 --- a/components/leveldb_proto/proto_database_impl_unittest.cc +++ b/components/leveldb_proto/proto_database_impl_unittest.cc
@@ -62,6 +62,14 @@ std::vector<std::string>*, const leveldb::ReadOptions&, const std::string&)); + MOCK_METHOD1(LoadKeysAndEntries, bool(std::map<std::string, std::string>*)); + MOCK_METHOD2(LoadKeysAndEntriesWithFilter, + bool(const KeyFilter&, std::map<std::string, std::string>*)); + MOCK_METHOD4(LoadKeysAndEntriesWithFilter, + bool(const KeyFilter&, + std::map<std::string, std::string>*, + const leveldb::ReadOptions&, + const std::string&)); MOCK_METHOD3(Get, bool(const std::string&, bool*, std::string*)); MOCK_METHOD0(Destroy, bool()); @@ -78,6 +86,13 @@ LoadCallback1(success, entries.get()); } MOCK_METHOD2(LoadCallback1, void(bool, std::vector<TestProto>*)); + void LoadKeysAndEntriesCallback( + bool success, + std::unique_ptr<std::map<std::string, TestProto>> keys_entries) { + LoadKeysAndEntriesCallback1(success, keys_entries.get()); + } + MOCK_METHOD2(LoadKeysAndEntriesCallback1, + void(bool, std::map<std::string, TestProto>*)); void GetCallback(bool success, std::unique_ptr<TestProto> entry) { GetCallback1(success, entry.get()); } @@ -265,11 +280,27 @@ return true; } +ACTION_P(AppendLoadKeysAndEntries, model) { + std::map<std::string, std::string>* output = arg1; + for (const auto& pair : model) + output->insert(std::make_pair(pair.first, pair.second.SerializeAsString())); + + return true; +} + ACTION_P(VerifyLoadEntries, expected) { std::vector<TestProto>* actual = arg1; ExpectEntryPointersEquals(expected, *actual); } +ACTION_P(VerifyLoadKeysAndEntries, expected) { + std::map<std::string, TestProto>* actual_map = arg1; + std::vector<TestProto> actual; + for (const auto& pair : *actual_map) + actual.push_back(pair.second); + ExpectEntryPointersEquals(expected, actual); +} + // Test that ProtoDatabaseImpl calls Load on the underlying database and that // the caller's LoadCallback is called with the correct success value. Also // confirms that on success, the expected entries are passed to the caller's @@ -287,8 +318,8 @@ base::BindOnce(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); - EXPECT_CALL(*mock_db, LoadWithFilter(_, _, _, _)) - .WillOnce(AppendLoadEntries(model)); + EXPECT_CALL(*mock_db, LoadKeysAndEntriesWithFilter(_, _, _, _)) + .WillOnce(AppendLoadKeysAndEntries(model)); EXPECT_CALL(caller, LoadCallback1(true, _)) .WillOnce(VerifyLoadEntries(testing::ByRef(model))); db_->LoadEntries(base::BindOnce(&MockDatabaseCaller::LoadCallback, @@ -309,7 +340,8 @@ base::BindOnce(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); - EXPECT_CALL(*mock_db, LoadWithFilter(_, _, _, _)).WillOnce(Return(false)); + EXPECT_CALL(*mock_db, LoadKeysAndEntriesWithFilter(_, _, _, _)) + .WillOnce(Return(false)); EXPECT_CALL(caller, LoadCallback1(false, _)); db_->LoadEntries(base::BindOnce(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller))); @@ -738,6 +770,35 @@ EXPECT_EQ(entry.SerializeAsString(), model["0"].SerializeAsString()); } +TEST_F(ProtoDatabaseImplLevelDBTest, TestDBLoadKeysAndEntries) { + ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + EntryMap model = GetSmallModel(); + + KeyValueVector save_entries; + std::map<std::string, std::string> load_keys_entries; + KeyVector remove_keys; + + for (const auto& pair : model) { + save_entries.push_back( + std::make_pair(pair.second.id(), pair.second.SerializeAsString())); + } + + std::unique_ptr<LevelDB> db(new LevelDB(kTestLevelDBClientName)); + EXPECT_TRUE(db->Init(temp_dir.GetPath(), CreateSimpleOptions())); + EXPECT_TRUE(db->Save(save_entries, remove_keys)); + + EXPECT_TRUE(db->LoadKeysAndEntries(&load_keys_entries)); + + EXPECT_EQ(load_keys_entries.size(), model.size()); + for (const auto& pair : load_keys_entries) { + TestProto entry; + ASSERT_TRUE(entry.ParseFromString(pair.second)); + EXPECT_EQ(entry.SerializeAsString(), model[pair.first].SerializeAsString()); + } +} + TEST_F(ProtoDatabaseImplLevelDBTest, TestDBInitFail) { ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/components/leveldb_proto/proto_database_perftest.cc b/components/leveldb_proto/proto_database_perftest.cc index dacd07e0..45e5825b 100644 --- a/components/leveldb_proto/proto_database_perftest.cc +++ b/components/leveldb_proto/proto_database_perftest.cc
@@ -48,8 +48,6 @@ namespace { -static const std::string kSingleDBName = "singledb"; - using KeyEntryVector = ProtoDatabase<TestProto>::KeyEntryVector; using KeyEntryVectorMap = std::map<std::string, std::unique_ptr<KeyEntryVector>>; @@ -68,6 +66,20 @@ int num_runs = 0; }; +static const std::string kSingleDBName = "singledb"; + +static const std::vector<TestParams> kFewEntriesDistributionTestParams = { + {20, 10, 1, false}, {10, 10, 1, false}, {10, 10, 1, false}, + {25, 10, 1, false}, {40, 10, 1, false}, {50, 10, 1, false}, + {80, 10, 1, false}, {100, 10, 1, false}, {100, 10, 1, false}, +}; + +static const std::vector<TestParams> kManyEntriesDistributionTestParams = { + {200, 10, 1, false}, {100, 10, 1, false}, {100, 10, 1, false}, + {250, 10, 1, false}, {400, 10, 1, false}, {500, 10, 1, false}, + {800, 10, 1, false}, {1000, 10, 1, false}, {1000, 10, 1, false}, +}; + class TestDatabase { public: TestDatabase(const std::string& name, @@ -530,267 +542,322 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner_; }; -// Timed out on Win. http://crbug.com/879922 -#if defined(OS_WIN) -#define MAYBE_InsertMultipleDBsAlternating_Individual \ - DISABLED_InsertMultipleDBsAlternating_Individual -#else -#define MAYBE_InsertMultipleDBsAlternating_Individual \ - InsertMultipleDBsAlternating_Individual -#endif - -TEST_F(ProtoDBPerfTest, MAYBE_InsertMultipleDBsAlternating_Individual) { +TEST_F(ProtoDBPerfTest, InsertMultipleDBsAlternating_Individual_100b) { // num_entries, data_size, batch_size, single_db. - std::vector<TestParams> params = { - {500, 100, 1, false}, {500, 1000, 1, false}, - }; - RunAlternatingInsertTests(params, "InsertMultipleDBsAlternating_Individual", - 10); + TestParams params = {200, 100, 1, false}; + RunAlternatingInsertTests({params}, "InsertMultipleDBsAlternating_Individual", + 5); } -// Timed out on Win. http://crbug.com/879922 -#if defined(OS_WIN) -#define MAYBE_InsertSingleDBAlternating_Individual \ - DISABLED_InsertSingleDBAlternating_Individual -#else -#define MAYBE_InsertSingleDBAlternating_Individual \ - InsertSingleDBAlternating_Individual -#endif - -TEST_F(ProtoDBPerfTest, MAYBE_InsertSingleDBAlternating_Individual) { +TEST_F(ProtoDBPerfTest, InsertMultipleDBsAlternating_Individual_1000b) { // num_entries, data_size, batch_size, single_db. - std::vector<TestParams> params = { - {500, 100, 1, true}, {500, 1000, 1, true}, - }; - RunAlternatingInsertTests(params, "InsertSingleDBAlternating_Individual", 10); + TestParams params = {200, 1000, 1, false}; + RunAlternatingInsertTests({params}, "InsertMultipleDBsAlternating_Individual", + 5); } -TEST_F(ProtoDBPerfTest, InsertMultipleDBsAlternating_LargeBatch) { +TEST_F(ProtoDBPerfTest, InsertSingleDBAlternating_Individual_100b) { // num_entries, data_size, batch_size, single_db. - std::vector<TestParams> params = { - {500, 100, 500, false}, {500, 1000, 500, false}, - }; - RunAlternatingInsertTests(params, "InsertMultipleDBsAlternating_LargeBatch", - 10); + TestParams params = {200, 100, 1, true}; + RunAlternatingInsertTests({params}, "InsertSingleDBAlternating_Individual", + 5); } -TEST_F(ProtoDBPerfTest, InsertSingleDBAlternating_LargeBatch) { +TEST_F(ProtoDBPerfTest, InsertSingleDBAlternating_Individual_1000b) { // num_entries, data_size, batch_size, single_db. - std::vector<TestParams> params = { - {500, 100, 500, true}, {500, 1000, 500, true}, - }; - RunAlternatingInsertTests(params, "InsertSingleDBAlternating_LargeBatch", 10); + TestParams params = {200, 1000, 1, true}; + RunAlternatingInsertTests({params}, "InsertSingleDBAlternating_Individual", + 5); } -TEST_F(ProtoDBPerfTest, DistributionTestSmall_FewEntries) { - std::vector<TestParams> params = { - {20, 10, 1, false}, {10, 10, 1, false}, {10, 10, 1, false}, - {25, 10, 1, false}, {40, 10, 1, false}, {50, 10, 1, false}, - {80, 10, 1, false}, {100, 10, 1, false}, {100, 10, 1, false}, - }; - RunDistributionTestAndCleanup("DistributionTestSmall_FewEntries", "Multi", - params, false); +TEST_F(ProtoDBPerfTest, InsertMultipleDBsAlternating_LargeBatch_100b) { + // num_entries, data_size, batch_size, single_db. + TestParams params = {200, 100, 200, false}; + RunAlternatingInsertTests({params}, "InsertMultipleDBsAlternating_LargeBatch", + 5); +} + +TEST_F(ProtoDBPerfTest, InsertMultipleDBsAlternating_LargeBatch_1000b) { + // num_entries, data_size, batch_size, single_db. + TestParams params = {200, 1000, 200, false}; + RunAlternatingInsertTests({params}, "InsertMultipleDBsAlternating_LargeBatch", + 5); +} + +TEST_F(ProtoDBPerfTest, InsertSingleDBAlternating_LargeBatch_100b) { + // num_entries, data_size, batch_size, single_db. + TestParams params = {200, 100, 200, true}; + RunAlternatingInsertTests({params}, "InsertSingleDBAlternating_LargeBatch", + 5); +} + +TEST_F(ProtoDBPerfTest, InsertSingleDBAlternating_LargeBatch_1000b) { + // num_entries, data_size, batch_size, single_db. + TestParams params = {200, 1000, 200, true}; + RunAlternatingInsertTests({params}, "InsertSingleDBAlternating_LargeBatch", + 5); +} + +TEST_F(ProtoDBPerfTest, DistributionTestSmall_FewEntries_Single) { RunDistributionTestAndCleanup("DistributionTestSmall_FewEntries", "Single", - params, true); + kFewEntriesDistributionTestParams, true); } -// Timed out on Win. http://crbug.com/879922 -#if defined(OS_WIN) -#define MAYBE_DistributionTestSmall_ManyEntries \ - DISABLED_DistributionTestSmall_ManyEntries -#else -#define MAYBE_DistributionTestSmall_ManyEntries \ - DistributionTestSmall_ManyEntries -#endif +TEST_F(ProtoDBPerfTest, DistributionTestSmall_FewEntries_Multi) { + RunDistributionTestAndCleanup("DistributionTestSmall_FewEntries", "Multi", + kFewEntriesDistributionTestParams, false); +} -TEST_F(ProtoDBPerfTest, MAYBE_DistributionTestSmall_ManyEntries) { - std::vector<TestParams> params = { - {200, 10, 1, false}, {100, 10, 1, false}, {100, 10, 1, false}, - {250, 10, 1, false}, {400, 10, 1, false}, {500, 10, 1, false}, - {800, 10, 1, false}, {1000, 10, 1, false}, {1000, 10, 1, false}, - }; - RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries", "Multi", - params, false); +TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Single) { RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries", "Single", - params, true); + kManyEntriesDistributionTestParams, true); } -TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Batch) { - std::vector<TestParams> params = { - {200, 10, 200, false}, {100, 10, 100, false}, {100, 10, 100, false}, - {250, 10, 250, false}, {400, 10, 400, false}, {500, 10, 500, false}, - {800, 10, 800, false}, {1000, 10, 1000, false}, {1000, 10, 1000, false}, - }; - RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries_Batch", - "Multi", params, false); - RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries_Batch", - "Single", params, true); +TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Multi) { + RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries", "Multi", + kManyEntriesDistributionTestParams, false); } -TEST_F(ProtoDBPerfTest, LoadEntriesSingle) { +TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Batch_Single) { + RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries_Batch", + "Single", kManyEntriesDistributionTestParams, + true); +} + +TEST_F(ProtoDBPerfTest, DistributionTestSmall_ManyEntries_Batch_Multi) { + RunDistributionTestAndCleanup("DistributionTestSmall_ManyEntries_Batch", + "Multi", kManyEntriesDistributionTestParams, + false); +} + +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_Small) { unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup(10, 3000, 10, {}, "LoadEntriesSingle", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_Medium) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup(10, 30000, 10, {}, "LoadEntriesSingle", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_Large) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup(10, 30000, 100, {}, "LoadEntriesSingle", &num_entries); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix) { +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_Small) { // Load only the entries that start with a particular prefix. unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_Medium) { + // Load only the entries that start with a particular prefix. + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 30000, 10, {1}, "LoadEntriesSingle_OnePrefix", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_Large) { + // Load only the entries that start with a particular prefix. + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 30000, 100, {1}, "LoadEntriesSingle_OnePrefix", &num_entries); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesMulti) { +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 3000, 10, {}, "LoadEntriesMulti", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 10, {}, "LoadEntriesMulti", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 100, {}, "LoadEntriesMulti", &num_entries); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix) { +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 10, {1}, "LoadEntriesMulti_OnePrefix", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 100, {1}, "LoadEntriesMulti_OnePrefix", &num_entries); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesSingle_SkipReadCache) { +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_SkipReadCache_Small) { unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup(10, 3000, 10, {}, "LoadEntriesSingle_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_SkipReadCache_Medium) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup(10, 30000, 10, {}, "LoadEntriesSingle_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_SkipReadCache_Large) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup(10, 30000, 100, {}, "LoadEntriesSingle_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_SkipReadCache) { +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_SkipReadCache_Small) { // Load only the entries that start with a particular prefix. unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_SkipReadCache_Medium) { + // Load only the entries that start with a particular prefix. + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 30000, 10, {1}, "LoadEntriesSingle_OnePrefix_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_SkipReadCache_Large) { + // Load only the entries that start with a particular prefix. + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 30000, 100, {1}, "LoadEntriesSingle_OnePrefix_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesMulti_SkipReadCache) { +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_SkipReadCache_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 3000, 10, {}, "LoadEntriesMulti_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_SkipReadCache_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 10, {}, "LoadEntriesMulti_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_SkipReadCache_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 100, {}, "LoadEntriesMulti_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_SkipReadCache) { +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_SkipReadCache_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_SkipReadCache_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 10, {1}, "LoadEntriesMulti_OnePrefix_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_SkipReadCache_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup(10, 30000, 100, {1}, "LoadEntriesMulti_OnePrefix_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_DifferingNumDBs) { +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_DifferingNumDBs_Small) { unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_DifferingNumDBs_Medium) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 25, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_OnePrefix_DifferingNumDBs_Large) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 100, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_DifferingNumDBs) { +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_DifferingNumDBs_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 10, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_DifferingNumDBs_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 25, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_OnePrefix_DifferingNumDBs_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 100, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix_DifferingNumDBs", &num_entries); @@ -798,20 +865,28 @@ } TEST_F(ProtoDBPerfTest, - LoadEntriesSingle_OnePrefix_DifferingNumDBs_SkipReadCache) { + LoadEntriesSingle_OnePrefix_DifferingNumDBs_SkipReadCache_Small) { unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, + LoadEntriesSingle_OnePrefix_DifferingNumDBs_SkipReadCache_Medium) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 25, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, + LoadEntriesSingle_OnePrefix_DifferingNumDBs_SkipReadCache_Large) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 100, 3000, 10, {1}, "LoadEntriesSingle_OnePrefix_DifferingNumDBs_SkipReadCache", &num_entries, @@ -820,20 +895,28 @@ } TEST_F(ProtoDBPerfTest, - LoadEntriesMulti_OnePrefix_DifferingNumDBs_SkipReadCache) { + LoadEntriesMulti_OnePrefix_DifferingNumDBs_SkipReadCache_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 10, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, + LoadEntriesMulti_OnePrefix_DifferingNumDBs_SkipReadCache_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 25, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, + LoadEntriesMulti_OnePrefix_DifferingNumDBs_SkipReadCache_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 100, 3000, 10, {1}, "LoadEntriesMulti_OnePrefix_DifferingNumDBs_SkipReadCache", &num_entries, @@ -841,66 +924,91 @@ ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesSingle_DifferingNumDBs) { +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_DifferingNumDBs_Small) { unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 3000, 10, {}, "LoadEntriesSingle_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_DifferingNumDBs_Medium) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 25, 3000, 10, {}, "LoadEntriesSingle_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_DifferingNumDBs_Large) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 100, 3000, 10, {}, "LoadEntriesSingle_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs) { +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 10, 3000, 10, {}, "LoadEntriesMulti_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 25, 3000, 10, {}, "LoadEntriesMulti_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 100, 3000, 10, {}, "LoadEntriesMulti_DifferingNumDBs", &num_entries); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesSingle_DifferingNumDBs_SkipReadCache) { +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_DifferingNumDBs_SkipReadCache_Small) { unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 10, 3000, 10, {}, "LoadEntriesSingle_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, + LoadEntriesSingle_DifferingNumDBs_SkipReadCache_Medium) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 25, 3000, 10, {}, "LoadEntriesSingle_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesSingle_DifferingNumDBs_SkipReadCache_Large) { + unsigned int num_entries = 0; RunLoadEntriesSingleTestAndCleanup( 100, 3000, 10, {}, "LoadEntriesSingle_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); } -TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs_SkipReadCache) { +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs_SkipReadCache_Small) { unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 10, 3000, 10, {}, "LoadEntriesMulti_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs_SkipReadCache_Medium) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 25, 3000, 10, {}, "LoadEntriesMulti_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */); ASSERT_NE(num_entries, 0U); +} +TEST_F(ProtoDBPerfTest, LoadEntriesMulti_DifferingNumDBs_SkipReadCache_Large) { + unsigned int num_entries = 0; RunLoadEntriesMultiTestAndCleanup( 100, 3000, 10, {}, "LoadEntriesMulti_DifferingNumDBs_SkipReadCache", &num_entries, false /* fill_read_cache */);
diff --git a/components/leveldb_proto/testing/fake_db.h b/components/leveldb_proto/testing/fake_db.h index bfce3cd..56ed635 100644 --- a/components/leveldb_proto/testing/fake_db.h +++ b/components/leveldb_proto/testing/fake_db.h
@@ -53,6 +53,16 @@ const leveldb::ReadOptions& options, const std::string& target_prefix, typename ProtoDatabase<T>::LoadCallback callback) override; + void LoadKeysAndEntries( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override; + void LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& filter, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override; + void LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& filter, + const leveldb::ReadOptions& options, + const std::string& target_prefix, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) override; void LoadKeys(typename ProtoDatabase<T>::LoadKeysCallback callback) override; void GetEntry(const std::string& key, typename ProtoDatabase<T>::GetCallback callback) override; @@ -78,6 +88,10 @@ static void RunLoadCallback(typename ProtoDatabase<T>::LoadCallback callback, std::unique_ptr<typename std::vector<T>> entries, bool success); + static void RunLoadKeysAndEntriesCallback( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback, + std::unique_ptr<typename std::map<std::string, T>> entries, + bool success); static void RunLoadKeysCallback( typename ProtoDatabase<T>::LoadKeysCallback callback, @@ -180,6 +194,38 @@ } template <typename T> +void FakeDB<T>::LoadKeysAndEntries( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) { + LoadKeysAndEntriesWithFilter(LevelDB::KeyFilter(), std::move(callback)); +} + +template <typename T> +void FakeDB<T>::LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& key_filter, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) { + LoadKeysAndEntriesWithFilter(key_filter, leveldb::ReadOptions(), + std::string(), std::move(callback)); +} + +template <typename T> +void FakeDB<T>::LoadKeysAndEntriesWithFilter( + const LevelDB::KeyFilter& key_filter, + const leveldb::ReadOptions& options, + const std::string& target_prefix, + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback) { + auto keys_entries = std::make_unique<std::map<std::string, T>>(); + for (const auto& pair : *db_) { + if (key_filter.is_null() || key_filter.Run(pair.first)) { + if (pair.first.compare(0, target_prefix.length(), target_prefix) == 0) + keys_entries->insert(pair); + } + } + + load_callback_ = base::BindOnce(RunLoadKeysAndEntriesCallback, + std::move(callback), std::move(keys_entries)); +} + +template <typename T> void FakeDB<T>::LoadKeys(typename ProtoDatabase<T>::LoadKeysCallback callback) { std::unique_ptr<std::vector<std::string>> keys( new std::vector<std::string>()); @@ -254,6 +300,15 @@ // static template <typename T> +void FakeDB<T>::RunLoadKeysAndEntriesCallback( + typename ProtoDatabase<T>::LoadKeysAndEntriesCallback callback, + std::unique_ptr<typename std::map<std::string, T>> keys_entries, + bool success) { + std::move(callback).Run(success, std::move(keys_entries)); +} + +// static +template <typename T> void FakeDB<T>::RunLoadKeysCallback( typename ProtoDatabase<T>::LoadKeysCallback callback, std::unique_ptr<std::vector<std::string>> keys,
diff --git a/components/os_crypt/os_crypt_features_mac.cc b/components/os_crypt/os_crypt_features_mac.cc index cdbc7b7..6e9351a 100644 --- a/components/os_crypt/os_crypt_features_mac.cc +++ b/components/os_crypt/os_crypt_features_mac.cc
@@ -11,7 +11,7 @@ // unavailable, but there is a preference set that the key was created in the // past. const base::Feature kPreventEncryptionKeyOverwrites = { - "PreventEncryptionKeyOverwrites", base::FEATURE_DISABLED_BY_DEFAULT}; + "PreventEncryptionKeyOverwrites", base::FEATURE_ENABLED_BY_DEFAULT}; } // namespace features } // namespace os_crypt
diff --git a/components/password_manager/core/browser/credential_manager_impl.cc b/components/password_manager/core/browser/credential_manager_impl.cc index 16baac0..f1e53b7 100644 --- a/components/password_manager/core/browser/credential_manager_impl.cc +++ b/components/password_manager/core/browser/credential_manager_impl.cc
@@ -177,7 +177,7 @@ CredentialInfo info; if (form) { password_manager::CredentialType type_to_return = - form->federation_origin.unique() + form->federation_origin.opaque() ? CredentialType::CREDENTIAL_TYPE_PASSWORD : CredentialType::CREDENTIAL_TYPE_FEDERATED; info = CredentialInfo(*form, type_to_return); @@ -227,7 +227,7 @@ return; } - if (!form.federation_origin.unique()) { + if (!form.federation_origin.opaque()) { // If this is a federated credential, check it against the federated matches // produced by the PasswordFormManager. If a match is found, update it and // return.
diff --git a/components/password_manager/core/browser/credential_manager_impl_unittest.cc b/components/password_manager/core/browser/credential_manager_impl_unittest.cc index 4de1873..539121a 100644 --- a/components/password_manager/core/browser/credential_manager_impl_unittest.cc +++ b/components/password_manager/core/browser/credential_manager_impl_unittest.cc
@@ -386,7 +386,7 @@ EXPECT_EQ(form_.password_value, new_form.password_value); EXPECT_EQ(form_.origin, new_form.origin); EXPECT_EQ(form_.signon_realm, new_form.signon_realm); - EXPECT_TRUE(new_form.federation_origin.unique()); + EXPECT_TRUE(new_form.federation_origin.opaque()); EXPECT_EQ(form_.icon_url, new_form.icon_url); EXPECT_FALSE(form_.skip_zero_click); EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, new_form.scheme);
diff --git a/components/password_manager/core/browser/credential_manager_pending_request_task.cc b/components/password_manager/core/browser/credential_manager_pending_request_task.cc index 72030d4..ea4f5da 100644 --- a/components/password_manager/core/browser/credential_manager_pending_request_task.cc +++ b/components/password_manager/core/browser/credential_manager_pending_request_task.cc
@@ -72,7 +72,7 @@ std::unique_ptr<autofill::PasswordForm>> credentials; for (auto& form : *forms) { - if (!form->federation_origin.unique()) { + if (!form->federation_origin.opaque()) { federated_forms.push_back(std::move(form)); } else { auto key = std::make_pair( @@ -168,8 +168,8 @@ for (auto& form : results) { // Ensure that the form we're looking at matches the password and // federation filters provided. - if (!((form->federation_origin.unique() && include_passwords_) || - (!form->federation_origin.unique() && + if (!((form->federation_origin.opaque() && include_passwords_) || + (!form->federation_origin.opaque() && federations_.count(form->federation_origin.Serialize())))) { continue; } @@ -205,7 +205,7 @@ !password_bubble_experiment::ShouldShowAutoSignInPromptFirstRunExperience( delegate_->client()->GetPrefs())) { CredentialInfo info(*local_results[0], - local_results[0]->federation_origin.unique() + local_results[0]->federation_origin.opaque() ? CredentialType::CREDENTIAL_TYPE_PASSWORD : CredentialType::CREDENTIAL_TYPE_FEDERATED); delegate_->client()->NotifyUserAutoSignin(std::move(local_results),
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc index d1f5515..f095ecf 100644 --- a/components/password_manager/core/browser/form_fetcher_impl.cc +++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -35,7 +35,7 @@ const auto first_federated = std::partition( store_results->begin(), store_results->end(), [](const std::unique_ptr<PasswordForm>& form) { - return form->federation_origin.unique(); // False means federated. + return form->federation_origin.opaque(); // False means federated. }); // Move out federated matches.
diff --git a/components/password_manager/core/browser/http_credentials_cleaner.cc b/components/password_manager/core/browser/http_credentials_cleaner.cc index 0119b85..73fd3e16 100644 --- a/components/password_manager/core/browser/http_credentials_cleaner.cc +++ b/components/password_manager/core/browser/http_credentials_cleaner.cc
@@ -5,7 +5,10 @@ #include "components/password_manager/core/browser/http_credentials_cleaner.h" #include "base/metrics/histogram_functions.h" +#include "components/password_manager/core/browser/http_password_store_migrator.h" #include "components/password_manager/core/browser/password_manager_util.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_service.h" #include "url/gurl.h" namespace password_manager { @@ -13,13 +16,20 @@ HttpCredentialCleaner::HttpCredentialCleaner( scoped_refptr<PasswordStore> store, base::RepeatingCallback<network::mojom::NetworkContext*()> - network_context_getter) + network_context_getter, + PrefService* prefs) : store_(std::move(store)), - network_context_getter_(network_context_getter) { -} + network_context_getter_(network_context_getter), + prefs_(prefs) {} HttpCredentialCleaner::~HttpCredentialCleaner() = default; +bool HttpCredentialCleaner::ShouldRunCleanUp(PrefService* prefs) { + auto last = base::Time::FromDoubleT(prefs->GetDouble( + password_manager::prefs::kLastTimeObsoleteHttpCredentialsRemoved)); + return ((base::Time::Now() - last).InDays() >= kCleanUpDelayInDays); +} + void HttpCredentialCleaner::StartCleaning(Observer* observer) { DCHECK(observer); DCHECK(!observer_); @@ -40,10 +50,11 @@ password_manager_util::GetSignonRealmWithProtocolExcluded(*form)), form->scheme, form->username_value}); if (form->origin.SchemeIs(url::kHttpScheme)) { + const GURL origin = form->origin; PostHSTSQueryForHostAndNetworkContext( - form->origin, network_context_getter_.Run(), + origin, network_context_getter_.Run(), base::Bind(&HttpCredentialCleaner::OnHSTSQueryResult, - base::Unretained(this), form_key, form->password_value)); + base::Unretained(this), base::Passed(&form), form_key)); ++total_http_credentials_; } else { // HTTPS https_credentials_map_[form_key].insert(form->password_value); @@ -54,11 +65,10 @@ ReportMetrics(); } -// |key| and |password_value| was created from the same form. void HttpCredentialCleaner::OnHSTSQueryResult( + std::unique_ptr<autofill::PasswordForm> form, FormKey key, - base::string16 password_value, - password_manager::HSTSResult hsts_result) { + HSTSResult hsts_result) { ++processed_results_; base::ScopedClosureRunner report(base::BindOnce( &HttpCredentialCleaner::ReportMetrics, base::Unretained(this))); @@ -72,13 +82,23 @@ if (user_it == https_credentials_map_.end()) { // Credentials are not migrated yet. ++https_credential_not_found_[is_hsts]; + if (is_hsts) { + // Migrate credentials to HTTPS, by moving them. + store_->AddLogin( + HttpPasswordStoreMigrator::MigrateHttpFormToHttps(*form)); + store_->RemoveLogin(*form); + } return; } - if (base::ContainsKey(user_it->second, password_value)) { + if (base::ContainsKey(user_it->second, form->password_value)) { // The password store contains the same credentials (signon_realm, scheme, - // username and password) on HTTP version of the form. + // username and password) on HTTPS version of the form. ++same_password_[is_hsts]; + if (is_hsts) { + // This HTTP credential is no more used. + store_->RemoveLogin(*form); + } } else { ++different_password_[is_hsts]; } @@ -109,6 +129,8 @@ https_credential_not_found_[is_hsts_enabled]); } + prefs_->SetDouble(prefs::kLastTimeObsoleteHttpCredentialsRemoved, + base::Time::Now().ToDoubleT()); observer_->CleaningCompleted(); }
diff --git a/components/password_manager/core/browser/http_credentials_cleaner.h b/components/password_manager/core/browser/http_credentials_cleaner.h index ec01e306..bd1bd97 100644 --- a/components/password_manager/core/browser/http_credentials_cleaner.h +++ b/components/password_manager/core/browser/http_credentials_cleaner.h
@@ -25,26 +25,46 @@ } // namespace mojom } // namespace network +class PrefService; + namespace password_manager { class PasswordStore; -// This class is responsible for reporting metrics about HTTP to HTTPS -// migration. +// This class is responsible for removing obsolete HTTP credentials that can +// safely be deleted and reporting metrics about HTTP to HTTPS migration. This +// class will delete HTTP credentials with HSTS enabled for that site and for +// which an equivalent (i.e. same signon_realm excluding protocol, +// PasswordForm::scheme (i.e. HTML, BASIC, etc.), username and password) HTTPS +// credential exists in the password store. Also it replace HTTP credentials for +// which no HTTPS credential with same signon_realm excluding protocol, +// PasswordForm::scheme and username exists and site has +// HSTS enabled, by an HTTPS version of that form. class HttpCredentialCleaner : public PasswordStoreConsumer, public CredentialsCleaner { public: + // The cleaning will be made for credentials from |store|. // |network_context_getter| should return nullptr if it can't get the network // context because whatever owns it is dead. + // A preference from |prefs| is used to set the last time (in seconds) when + // the cleaning was performed. HttpCredentialCleaner( scoped_refptr<PasswordStore> store, base::RepeatingCallback<network::mojom::NetworkContext*()> - network_context_getter); + network_context_getter, + PrefService* prefs); ~HttpCredentialCleaner() override; + // Indicate whether there are at least |kCleanUpDelayInDays| days passed in + // order to run the clean-up. + static bool ShouldRunCleanUp(PrefService* prefs); + // CredentialsCleaner: void StartCleaning(Observer* observer) override; + // The time that should pass in order to do the clean-up again. + static constexpr int kCleanUpDelayInDays = 90; + private: // This type define a subset of PasswordForm where first argument is the // signon-realm excluding the protocol, the second argument is @@ -57,20 +77,30 @@ void OnGetPasswordStoreResults( std::vector<std::unique_ptr<autofill::PasswordForm>> results) override; - void OnHSTSQueryResult(FormKey key, - base::string16 password_value, + // This function will inform us using |hsts_result| parameter if the |form|'s + // host has HSTS enabled. |key| is |form|'s encoding which is used for + // matching |form| with an HTTPS credential with the same FormKey. + // Inside the function the metric counters are updated and, if needed, the + // |form| is removed or migrated to HTTPS. + void OnHSTSQueryResult(std::unique_ptr<autofill::PasswordForm> form, + FormKey key, HSTSResult hsts_result); // After metrics are reported, this function will inform the |observer_| about // completion. void ReportMetrics(); + // Clean-up is performed on |store_|. scoped_refptr<PasswordStore> store_; // Needed to create HSTS request. base::RepeatingCallback<network::mojom::NetworkContext*()> network_context_getter_; + // |prefs_| is not an owning pointer. It is used to record he last time (in + // seconds) when the cleaning was performed. + PrefService* prefs_; + // Map from (signon-realm excluding the protocol, Password::Scheme, username) // tuples of HTTPS forms to a list of passwords for that pair. std::map<FormKey, base::flat_set<base::string16>> https_credentials_map_;
diff --git a/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc b/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc index 1720124..e256ed28 100644 --- a/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc +++ b/components/password_manager/core/browser/http_credentials_cleaner_unittest.cc
@@ -10,6 +10,8 @@ #include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_task_environment.h" +#include "base/time/time.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/test_password_store.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_registry_simple.h" @@ -181,6 +183,12 @@ scoped_task_environment.RunUntilIdle(); base::HistogramTester histogram_tester; + const TestPasswordStore::PasswordMap passwords_before_cleaning = + store_->stored_passwords(); + + TestingPrefServiceSimple prefs; + prefs.registry()->RegisterDoublePref( + prefs::kLastTimeObsoleteHttpCredentialsRemoved, 0.0); MockCredentialsCleanerObserver observer; HttpCredentialCleaner cleaner( @@ -193,7 +201,8 @@ // StoragePartition::GetNetworkContext will return a mojo pipe // even in the in-process case. return network_context_pipe.get(); - })); + }), + &prefs); EXPECT_CALL(observer, CleaningCompleted); cleaner.StartCleaning(&observer); scoped_task_environment.RunUntilIdle(); @@ -222,6 +231,22 @@ histogram_tester.ExpectUniqueSample(histogram.histogram_name, sample, 1); } + const TestPasswordStore::PasswordMap current_store = + store_->stored_passwords(); + if (test.is_hsts_enabled && + test.expected != HttpCredentialType::kConflicting) { + // HTTP credentials have to be removed. + EXPECT_TRUE(current_store.find(http_form.signon_realm)->second.empty()); + + // For no matching case https credentials were added and for an equivalent + // case they already existed. + EXPECT_TRUE(base::ContainsKey(current_store, "https://example.org/")); + } else { + // Hsts not enabled or credentials are have different passwords, so + // nothing should change in the password store. + EXPECT_EQ(current_store, passwords_before_cleaning); + } + store_->ShutdownOnUIThread(); scoped_task_environment.RunUntilIdle(); } @@ -230,4 +255,75 @@ HttpCredentialCleanerTest, ::testing::ValuesIn(kCases)); +TEST(HttpCredentialCleaner, StartCleanUpTest) { + for (bool should_start_clean_up : {false, true}) { + SCOPED_TRACE(testing::Message() + << "should_start_clean_up=" << should_start_clean_up); + + base::test::ScopedTaskEnvironment scoped_task_environment; + auto password_store = base::MakeRefCounted<TestPasswordStore>(); + ASSERT_TRUE(password_store->Init(syncer::SyncableService::StartSyncFlare(), + nullptr)); + + double last_time = + (base::Time::Now() - base::TimeDelta::FromMinutes(10)).ToDoubleT(); + if (should_start_clean_up) { + // Simulate that the clean-up was performed + // (HttpCredentialCleaner::kCleanUpDelayInDays + 1) days ago. + // We have to simulate this because the cleaning of obsolete HTTP + // credentials is done with low frequency (with a delay of + // |HttpCredentialCleaner::kCleanUpDelayInDays| days between two + // clean-ups) + last_time = (base::Time::Now() - + base::TimeDelta::FromDays( + HttpCredentialCleaner::kCleanUpDelayInDays + 1)) + .ToDoubleT(); + } + + TestingPrefServiceSimple prefs; + prefs.registry()->RegisterDoublePref( + prefs::kLastTimeObsoleteHttpCredentialsRemoved, last_time); + + EXPECT_EQ(should_start_clean_up, + HttpCredentialCleaner::ShouldRunCleanUp(&prefs)); + + if (!should_start_clean_up) { + password_store->ShutdownOnUIThread(); + scoped_task_environment.RunUntilIdle(); + continue; + } + + auto request_context = + base::MakeRefCounted<net::TestURLRequestContextGetter>( + base::ThreadTaskRunnerHandle::Get()); + network::mojom::NetworkContextPtr network_context_pipe; + auto network_context = std::make_unique<network::NetworkContext>( + nullptr, mojo::MakeRequest(&network_context_pipe), + request_context->GetURLRequestContext()); + + MockCredentialsCleanerObserver observer; + HttpCredentialCleaner cleaner( + password_store, + base::BindLambdaForTesting([&]() -> network::mojom::NetworkContext* { + // This needs to be network_context_pipe.get() and + // not network_context.get() to make HSTS queries asynchronous, which + // is what the progress tracking logic in HttpMetricsMigrationReporter + // assumes. This also matches reality, since + // StoragePartition::GetNetworkContext will return a mojo pipe + // even in the in-process case. + return network_context_pipe.get(); + }), + &prefs); + EXPECT_CALL(observer, CleaningCompleted); + cleaner.StartCleaning(&observer); + scoped_task_environment.RunUntilIdle(); + + EXPECT_NE(prefs.GetDouble(prefs::kLastTimeObsoleteHttpCredentialsRemoved), + last_time); + + password_store->ShutdownOnUIThread(); + scoped_task_environment.RunUntilIdle(); + } +} + } // namespace password_manager \ No newline at end of file
diff --git a/components/password_manager/core/browser/http_password_store_migrator.cc b/components/password_manager/core/browser/http_password_store_migrator.cc index 73ccdf5c..5882823 100644 --- a/components/password_manager/core/browser/http_password_store_migrator.cc +++ b/components/password_manager/core/browser/http_password_store_migrator.cc
@@ -4,10 +4,14 @@ #include "components/password_manager/core/browser/http_password_store_migrator.h" +#include <string> +#include <utility> + #include "base/memory/weak_ptr.h" #include "base/stl_util.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/password_store.h" #include "url/gurl.h" #include "url/url_constants.h" @@ -51,6 +55,29 @@ HttpPasswordStoreMigrator::~HttpPasswordStoreMigrator() = default; +autofill::PasswordForm HttpPasswordStoreMigrator::MigrateHttpFormToHttps( + const autofill::PasswordForm& http_form) { + DCHECK(http_form.origin.SchemeIs(url::kHttpScheme)); + + autofill::PasswordForm https_form = http_form; + GURL::Replacements rep; + rep.SetSchemeStr(url::kHttpsScheme); + https_form.origin = http_form.origin.ReplaceComponents(rep); + https_form.signon_realm = + std::string(url::kHttpsScheme) + + std::string(url::kStandardSchemeSeparator) + + std::string( + password_manager_util::GetSignonRealmWithProtocolExcluded(http_form)); + // If |action| is not HTTPS then it's most likely obsolete. Otherwise, it + // may still be valid. + if (!http_form.action.SchemeIs(url::kHttpsScheme)) + https_form.action = https_form.origin; + https_form.form_data = autofill::FormData(); + https_form.generation_upload_status = autofill::PasswordForm::NO_SIGNAL_SENT; + https_form.skip_zero_click = false; + return https_form; +} + void HttpPasswordStoreMigrator::OnGetPasswordStoreResults( std::vector<std::unique_ptr<autofill::PasswordForm>> results) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -84,19 +111,8 @@ // Add the new credentials to the password store. The HTTP forms are // removed iff |mode_| == MigrationMode::MOVE. for (const auto& form : results_) { - autofill::PasswordForm new_form = *form; - - GURL::Replacements rep; - rep.SetSchemeStr(url::kHttpsScheme); - new_form.origin = form->origin.ReplaceComponents(rep); - new_form.signon_realm = new_form.origin.GetOrigin().spec(); - // If |action| is not HTTPS then it's most likely obsolete. Otherwise, it - // may still be valid. - if (!form->action.SchemeIs(url::kHttpsScheme)) - new_form.action = new_form.origin; - new_form.form_data = autofill::FormData(); - new_form.generation_upload_status = autofill::PasswordForm::NO_SIGNAL_SENT; - new_form.skip_zero_click = false; + autofill::PasswordForm new_form = + HttpPasswordStoreMigrator::MigrateHttpFormToHttps(*form); client_->GetPasswordStore()->AddLogin(new_form); if (mode_ == MigrationMode::MOVE)
diff --git a/components/password_manager/core/browser/http_password_store_migrator.h b/components/password_manager/core/browser/http_password_store_migrator.h index 55c6865..91bf4dc 100644 --- a/components/password_manager/core/browser/http_password_store_migrator.h +++ b/components/password_manager/core/browser/http_password_store_migrator.h
@@ -50,6 +50,10 @@ Consumer* consumer); ~HttpPasswordStoreMigrator() override; + // Creates HTTPS version of |http_form|. + static autofill::PasswordForm MigrateHttpFormToHttps( + const autofill::PasswordForm& http_form); + // PasswordStoreConsumer: void OnGetPasswordStoreResults( std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
diff --git a/components/password_manager/core/browser/http_password_store_migrator_unittest.cc b/components/password_manager/core/browser/http_password_store_migrator_unittest.cc index f2dd806..8cc337ad 100644 --- a/components/password_manager/core/browser/http_password_store_migrator_unittest.cc +++ b/components/password_manager/core/browser/http_password_store_migrator_unittest.cc
@@ -242,4 +242,37 @@ TestMigratorDeletionByConsumer(false); } +TEST(HttpPasswordStoreMigrator, MigrateHttpFormToHttpsTestSignonRealm) { + const GURL kOrigins[] = {GURL("http://example.org/"), + GURL("http://example.org/path/")}; + + for (bool origin_has_paths : {true, false}) { + PasswordForm http_html_form; + http_html_form.origin = kOrigins[origin_has_paths]; + http_html_form.signon_realm = "http://example.org/"; + http_html_form.scheme = PasswordForm::Scheme::SCHEME_HTML; + + PasswordForm non_html_empty_realm_form; + non_html_empty_realm_form.origin = kOrigins[origin_has_paths]; + non_html_empty_realm_form.signon_realm = "http://example.org/"; + non_html_empty_realm_form.scheme = PasswordForm::Scheme::SCHEME_BASIC; + + PasswordForm non_html_form; + non_html_form.origin = kOrigins[origin_has_paths]; + non_html_form.signon_realm = "http://example.org/realm"; + non_html_form.scheme = PasswordForm::Scheme::SCHEME_BASIC; + + EXPECT_EQ(HttpPasswordStoreMigrator::MigrateHttpFormToHttps(http_html_form) + .signon_realm, + "https://example.org/"); + EXPECT_EQ(HttpPasswordStoreMigrator::MigrateHttpFormToHttps( + non_html_empty_realm_form) + .signon_realm, + "https://example.org/"); + EXPECT_EQ(HttpPasswordStoreMigrator::MigrateHttpFormToHttps(non_html_form) + .signon_realm, + "https://example.org/realm"); + } +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index 060e093b..693f619 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -154,7 +154,7 @@ s->BindString(COLUMN_ICON_URL, form.icon_url.spec()); // An empty Origin serializes as "null" which would be strange to store here. s->BindString(COLUMN_FEDERATION_URL, - form.federation_origin.unique() + form.federation_origin.opaque() ? std::string() : form.federation_origin.Serialize()); s->BindInt(COLUMN_SKIP_ZERO_CLICK, form.skip_zero_click); @@ -953,7 +953,7 @@ s.BindString16(next_param++, form.display_name); s.BindString(next_param++, form.icon_url.spec()); // An empty Origin serializes as "null" which would be strange to store here. - s.BindString(next_param++, form.federation_origin.unique() + s.BindString(next_param++, form.federation_origin.opaque() ? std::string() : form.federation_origin.Serialize()); s.BindInt(next_param++, form.skip_zero_click);
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc index debc221..4a9d1398 100644 --- a/components/password_manager/core/browser/login_database_unittest.cc +++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -2111,6 +2111,12 @@ } TEST_F(LoginDatabaseUndecryptableLoginsTest, DeleteUndecryptableLoginsTest) { + // Disable feature for deleting corrupted passwords, so GetAutofillableLogins + // doesn't remove any passwords. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + features::kDeleteCorruptedPasswords); + auto form1 = AddDummyLogin("foo1", GURL("https://foo1.com/"), false); auto form2 = AddDummyLogin("foo2", GURL("https://foo2.com/"), true); auto form3 = AddDummyLogin("foo3", GURL("https://foo3.com/"), false);
diff --git a/components/password_manager/core/browser/new_password_form_manager.cc b/components/password_manager/core/browser/new_password_form_manager.cc index a1db4f6..ea1479e 100644 --- a/components/password_manager/core/browser/new_password_form_manager.cc +++ b/components/password_manager/core/browser/new_password_form_manager.cc
@@ -695,7 +695,7 @@ const PasswordForm* NewPasswordFormManager::FindBestSavedMatch( const PasswordForm* submitted_form) const { - if (!submitted_form->federation_origin.unique()) + if (!submitted_form->federation_origin.opaque()) return nullptr; // Return form with matching |username_value|. @@ -762,7 +762,7 @@ void NewPasswordFormManager::ProcessUpdate() { DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState()); - DCHECK(preferred_match_ || !pending_credentials_.federation_origin.unique()); + DCHECK(preferred_match_ || !pending_credentials_.federation_origin.opaque()); // If we're doing an Update, we either autofilled correctly and need to // update the stats, or the user typed in a new password for autofilled // username, or the user selected one of the non-preferred matches, @@ -793,7 +793,7 @@ std::vector<PasswordForm> NewPasswordFormManager::FindOtherCredentialsToUpdate() { std::vector<autofill::PasswordForm> credentials_to_update; - if (!pending_credentials_.federation_origin.unique()) + if (!pending_credentials_.federation_origin.opaque()) return credentials_to_update; auto updated_password_it =
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 3a82997..a1568f7 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -589,7 +589,7 @@ void PasswordFormManager::ProcessUpdate() { DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState()); - DCHECK(preferred_match_ || !pending_credentials_.federation_origin.unique()); + DCHECK(preferred_match_ || !pending_credentials_.federation_origin.opaque()); // If we're doing an Update, we either autofilled correctly and need to // update the stats, or the user typed in a new password for autofilled // username, or the user selected one of the non-preferred matches, @@ -792,7 +792,7 @@ const PasswordForm* PasswordFormManager::FindBestSavedMatch( const PasswordForm* submitted_form) const { - if (!submitted_form->federation_origin.unique()) + if (!submitted_form->federation_origin.opaque()) return nullptr; // Return form with matching |username_value|. @@ -1035,7 +1035,7 @@ std::vector<PasswordForm> PasswordFormManager::FindOtherCredentialsToUpdate() { std::vector<autofill::PasswordForm> credentials_to_update; - if (!pending_credentials_.federation_origin.unique()) + if (!pending_credentials_.federation_origin.opaque()) return credentials_to_update; auto updated_password_it =
diff --git a/components/password_manager/core/browser/password_list_sorter.cc b/components/password_manager/core/browser/password_list_sorter.cc index a1c029a..223cb0e 100644 --- a/components/password_manager/core/browser/password_list_sorter.cc +++ b/components/password_manager/core/browser/password_list_sorter.cc
@@ -65,7 +65,7 @@ kSortKeyPartsSeparator + base::UTF16ToUTF8(form.password_value); key += kSortKeyPartsSeparator; - if (!form.federation_origin.unique()) + if (!form.federation_origin.opaque()) key += form.federation_origin.host(); else key += kSortKeyNoFederationSymbol;
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 5f9cdd29..6ee3211 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -347,6 +347,8 @@ false); registry->RegisterBooleanPref(prefs::kCredentialsWithWrongSignonRealmRemoved, false); + registry->RegisterDoublePref(prefs::kLastTimeObsoleteHttpCredentialsRemoved, + 0.0); #if defined(OS_MACOSX) registry->RegisterIntegerPref(
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index abf7c44..99341ff 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -181,13 +181,6 @@ REAUTH_COUNT }; -// Metrics: PasswordManager.IE7LookupResult -enum IE7LookupResultStatus { - IE7_RESULTS_ABSENT = 0, - IE7_RESULTS_PRESENT = 1, - IE7_RESULTS_COUNT -}; - // Specifies the type of PasswordFormManagers and derived classes to distinguish // the context in which a PasswordFormManager is being created and used. enum class CredentialSourceType {
diff --git a/components/password_manager/core/browser/password_manager_util.cc b/components/password_manager/core/browser/password_manager_util.cc index 49314ba..4d2e1b3 100644 --- a/components/password_manager/core/browser/password_manager_util.cc +++ b/components/password_manager/core/browser/password_manager_util.cc
@@ -10,6 +10,7 @@ #include "base/metrics/histogram_functions.h" #include "base/stl_util.h" +#include "base/time/time.h" #include "build/build_config.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/popup_item_ids.h" @@ -120,7 +121,7 @@ base::EraseIf(*android_credentials, [](const std::unique_ptr<PasswordForm>& form) { return form->scheme == PasswordForm::SCHEME_USERNAME_ONLY && - form->federation_origin.unique(); + form->federation_origin.opaque(); }); // Set "skip_zero_click" on federated credentials. @@ -186,6 +187,8 @@ autofill::password_generation::PASSWORD_GENERATION_CONTEXT_MENU_PRESSED); } +// TODO(http://crbug.com/890318): Add unitests to check cleaners are correctly +// created. void RemoveUselessCredentials( scoped_refptr<password_manager::PasswordStore> store, PrefService* prefs, @@ -229,10 +232,11 @@ #if !defined(OS_IOS) // Can be null for some unittests. - if (!network_context_getter.is_null()) { + if (!network_context_getter.is_null() && + password_manager::HttpCredentialCleaner::ShouldRunCleanUp(prefs)) { cleaning_tasks_runner->AddCleaningTask( std::make_unique<password_manager::HttpCredentialCleaner>( - store, network_context_getter)); + store, network_context_getter, prefs)); } #endif // !defined(OS_IOS)
diff --git a/components/password_manager/core/browser/password_manager_util.h b/components/password_manager/core/browser/password_manager_util.h index e6b75d65..3e64fe7 100644 --- a/components/password_manager/core/browser/password_manager_util.h +++ b/components/password_manager/core/browser/password_manager_util.h
@@ -100,10 +100,10 @@ // hence blacklisted duplicates need to be removed. // (2) Removing or fixing of HTTPS credentials with wrong signon_realm. See // https://crbug.com/881731 for details. -// (3) Report metrics about HTTP to HTTPS migration process. This feature -// is not available on iOS platform because the HSTS query is not supported. -// |network_context_getter| is always null for iOS and it can also be null for -// some unittests. +// (3) Report metrics about HTTP to HTTPS migration process and remove obsolete +// HTTP credentials. This feature is not available on iOS platform because the +// HSTS query is not supported. |network_context_getter| is always null for iOS +// and it can also be null for some unittests. void RemoveUselessCredentials( scoped_refptr<password_manager::PasswordStore> store, PrefService* prefs,
diff --git a/components/password_manager/core/browser/password_syncable_service.cc b/components/password_manager/core/browser/password_syncable_service.cc index 11d37104..02fc3ce 100644 --- a/components/password_manager/core/browser/password_syncable_service.cc +++ b/components/password_manager/core/browser/password_syncable_service.cc
@@ -464,7 +464,7 @@ CopyStringField(display_name); password_specifics->set_avatar_url(password_form.icon_url.spec()); password_specifics->set_federation_url( - password_form.federation_origin.unique() + password_form.federation_origin.opaque() ? std::string() : password_form.federation_origin.Serialize()); #undef CopyStringField
diff --git a/components/password_manager/core/browser/password_syncable_service_unittest.cc b/components/password_manager/core/browser/password_syncable_service_unittest.cc index 61467bf8..417eec1 100644 --- a/components/password_manager/core/browser/password_syncable_service_unittest.cc +++ b/components/password_manager/core/browser/password_syncable_service_unittest.cc
@@ -495,11 +495,8 @@ syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, "Failed to get passwords from store.", syncer::PASSWORDS); - EXPECT_CALL(*password_store(), DeleteUndecryptableLogins()) - .WillOnce(Return(DatabaseCleanupResult::kSuccess)); EXPECT_CALL(*password_store(), FillAutofillableLogins(_)) - .Times(2) - .WillRepeatedly(Return(false)); + .WillOnce(Return(false)); EXPECT_CALL(*error_factory, CreateAndUploadError(_, _)) .WillOnce(Return(error)); // ActOnPasswordStoreChanges() below shouldn't generate any changes for Sync. @@ -539,11 +536,15 @@ EXPECT_TRUE(result.error().IsSet()); } -// Enable feature for deleting undecryptable logins. +// Test that passwords are recovered for Sync users using the older feature +// (kRecoverPasswordsForSyncUsers) when feature for recovering passwords for +// Sync users is enabled, while feature for deleting corrupted passwords for +// all users is disabled. TEST_F(PasswordSyncableServiceTest, RecoverPasswordsForSyncUsersEnabled) { base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - features::kRecoverPasswordsForSyncUsers); + scoped_feature_list.InitWithFeatures( + {features::kRecoverPasswordsForSyncUsers}, + {features::kDeleteCorruptedPasswords}); EXPECT_CALL(*processor_, ProcessSyncChanges(_, IsEmpty())); EXPECT_CALL(*password_store(), FillAutofillableLogins(_)) @@ -560,8 +561,10 @@ EXPECT_FALSE(result.error().IsSet()); } -// Test that corrupted logins are not removed when merging data if features -// for recovering passwords for both Sync and non-Sync users are enabled. +// Test that passwords are not recovered using the older feature +// (kRecoverPasswordForSyncUsers) when merging data if both features for +// recovering passwords for Sync users and deleting passwords for all users +// are enabled. TEST_F(PasswordSyncableServiceTest, PasswordRecoveryForAllUsersEnabled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures({features::kRecoverPasswordsForSyncUsers, @@ -588,8 +591,9 @@ // Database cleanup fails because encryption is unavailable. TEST_F(PasswordSyncableServiceTest, FailedDeleteUndecryptableLogins) { base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - features::kRecoverPasswordsForSyncUsers); + scoped_feature_list.InitWithFeatures( + {features::kRecoverPasswordsForSyncUsers}, + {features::kDeleteCorruptedPasswords}); auto error_factory = std::make_unique<syncer::SyncErrorFactoryMock>(); syncer::SyncError error( FROM_HERE, syncer::SyncError::DATATYPE_ERROR, @@ -644,7 +648,7 @@ // string. TEST_F(PasswordSyncableServiceTest, SerializeEmptyFederation) { autofill::PasswordForm form; - EXPECT_TRUE(form.federation_origin.unique()); + EXPECT_TRUE(form.federation_origin.opaque()); syncer::SyncData data = SyncDataFromPassword(form); const sync_pb::PasswordSpecificsData& specifics = GetPasswordSpecifics(data); EXPECT_TRUE(specifics.has_federation_url()); @@ -652,7 +656,7 @@ // Deserialize back. form = PasswordFromSpecifics(specifics); - EXPECT_TRUE(form.federation_origin.unique()); + EXPECT_TRUE(form.federation_origin.opaque()); // Make sure that the Origins uploaded incorrectly are still deserialized // correctly. @@ -660,7 +664,7 @@ sync_pb::PasswordSpecificsData specifics1; specifics1.set_federation_url("null"); form = PasswordFromSpecifics(specifics1); - EXPECT_TRUE(form.federation_origin.unique()); + EXPECT_TRUE(form.federation_origin.opaque()); } // Serialize empty PasswordForm and make sure the Sync representation is
diff --git a/components/password_manager/core/browser/psl_matching_helper.cc b/components/password_manager/core/browser/psl_matching_helper.cc index 6cbb305..d660f23 100644 --- a/components/password_manager/core/browser/psl_matching_helper.cc +++ b/components/password_manager/core/browser/psl_matching_helper.cc
@@ -66,7 +66,7 @@ const bool allow_psl_match = ShouldPSLDomainMatchingApply( GetRegistryControlledDomain(GURL(form_digest.signon_realm))); - const bool allow_federated_match = !form.federation_origin.unique(); + const bool allow_federated_match = !form.federation_origin.opaque(); if (allow_psl_match && IsPublicSuffixDomainMatch(form.signon_realm, form_digest.signon_realm))
diff --git a/components/password_manager/core/common/credential_manager_types_unittest.cc b/components/password_manager/core/common/credential_manager_types_unittest.cc index 7d25d7b..54dc23d 100644 --- a/components/password_manager/core/common/credential_manager_types_unittest.cc +++ b/components/password_manager/core/common/credential_manager_types_unittest.cc
@@ -81,7 +81,7 @@ // Local credentials have empty federation_origins, non-empty passwords, and // a signon realm that matches the origin. - EXPECT_TRUE(form->federation_origin.unique()); + EXPECT_TRUE(form->federation_origin.opaque()); EXPECT_EQ(info.password, form->password_value); EXPECT_EQ(origin_.spec(), form->signon_realm); } @@ -95,7 +95,7 @@ EXPECT_EQ(base::string16(), form->display_name); EXPECT_EQ(origin_, form->origin); EXPECT_EQ(autofill::PasswordForm::SCHEME_HTML, form->scheme); - EXPECT_TRUE(form->federation_origin.unique()); + EXPECT_TRUE(form->federation_origin.opaque()); EXPECT_EQ(base::string16(), form->password_value); EXPECT_EQ(origin_.spec(), form->signon_realm); }
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index 14af7d2..dc449da 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -19,10 +19,10 @@ const base::Feature kAutofillHome = {"AutofillHome", base::FEATURE_ENABLED_BY_DEFAULT}; -// Recovers lost passwords on Mac by deleting ones that cannot be decrypted +// Recovers lost passwords on Mac by deleting the ones that cannot be decrypted // with the present encryption key from the Keychain. const base::Feature kDeleteCorruptedPasswords = { - "DeleteCorruptedPasswords", base::FEATURE_DISABLED_BY_DEFAULT}; + "DeleteCorruptedPasswords", base::FEATURE_ENABLED_BY_DEFAULT}; // Use HTML based username detector. const base::Feature kHtmlBasedUsernameDetector = { @@ -58,7 +58,7 @@ // Deletes entries from local database on Mac which cannot be decrypted when // merging data with Sync. const base::Feature kRecoverPasswordsForSyncUsers = { - "RecoverPasswordsForSyncUsers", base::FEATURE_ENABLED_BY_DEFAULT}; + "RecoverPasswordsForSyncUsers", base::FEATURE_DISABLED_BY_DEFAULT}; // Enables the experiment for the password manager to only fill on account // selection, rather than autofilling on page load, with highlighting of fields.
diff --git a/components/password_manager/core/common/password_manager_pref_names.cc b/components/password_manager/core/common/password_manager_pref_names.cc index 9a99340b..10ec887 100644 --- a/components/password_manager/core/common/password_manager_pref_names.cc +++ b/components/password_manager/core/common/password_manager_pref_names.cc
@@ -47,6 +47,9 @@ const char kCredentialsWithWrongSignonRealmRemoved[] = "profile.credentials_with_wrong_signon_realm_removed"; +const char kLastTimeObsoleteHttpCredentialsRemoved[] = + "profile.last_time_obsolete_http_credentials_removed"; + const char kPasswordHashDataList[] = "profile.password_hash_data_list"; } // namespace prefs
diff --git a/components/password_manager/core/common/password_manager_pref_names.h b/components/password_manager/core/common/password_manager_pref_names.h index a978d6e7..cd493d4 100644 --- a/components/password_manager/core/common/password_manager_pref_names.h +++ b/components/password_manager/core/common/password_manager_pref_names.h
@@ -76,6 +76,10 @@ // Whether Chrome deleted credentials that had wrong signon_realm. extern const char kCredentialsWithWrongSignonRealmRemoved[]; +// Indicates the time (in seconds) when last cleaning of obsolete HTTP +// credentials was performed. +extern const char kLastTimeObsoleteHttpCredentialsRemoved[]; + // List that contains captured password hashes. extern const char kPasswordHashDataList[];
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc index dcfc28b..cfd2697 100644 --- a/components/policy/core/common/cloud/cloud_policy_client.cc +++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -150,9 +150,6 @@ CloudPolicyClient::Observer::~Observer() {} -void CloudPolicyClient::Observer::OnRobotAuthCodesFetched( - CloudPolicyClient* client) {} - CloudPolicyClient::CloudPolicyClient( const std::string& machine_id, const std::string& machine_model, @@ -461,7 +458,8 @@ request_jobs_.back()->Start(job_callback); } -void CloudPolicyClient::FetchRobotAuthCodes(std::unique_ptr<DMAuth> auth) { +void CloudPolicyClient::FetchRobotAuthCodes(std::unique_ptr<DMAuth> auth, + RobotAuthCodeCallback callback) { CHECK(is_registered()); DCHECK(auth->has_dm_token()); @@ -479,9 +477,9 @@ request->add_auth_scope(GaiaConstants::kAnyApiOAuth2Scope); request->set_device_type(em::DeviceServiceApiAccessRequest::CHROME_OS); - policy_fetch_request_job_->Start( - base::Bind(&CloudPolicyClient::OnFetchRobotAuthCodesCompleted, - weak_ptr_factory_.GetWeakPtr())); + policy_fetch_request_job_->Start(base::AdaptCallbackForRepeating( + base::BindOnce(&CloudPolicyClient::OnFetchRobotAuthCodesCompleted, + weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); } void CloudPolicyClient::Unregister() { @@ -870,6 +868,7 @@ } void CloudPolicyClient::OnFetchRobotAuthCodesCompleted( + RobotAuthCodeCallback callback, DeviceManagementStatus status, int net_error, const em::DeviceManagementResponse& response) { @@ -878,16 +877,14 @@ LOG(WARNING) << "Invalid service api access response."; status = DM_STATUS_RESPONSE_DECODING_ERROR; } - status_ = status; if (status == DM_STATUS_SUCCESS) { - robot_api_auth_code_ = response.service_api_access_response().auth_code(); DVLOG(1) << "Device robot account auth code fetch complete - code = " - << robot_api_auth_code_; - - NotifyRobotAuthCodesFetched(); + << response.service_api_access_response().auth_code(); + std::move(callback).Run(status, + response.service_api_access_response().auth_code()); } else { - NotifyClientError(); + std::move(callback).Run(status, std::string()); } } @@ -1142,11 +1139,6 @@ observer.OnRegistrationStateChanged(this); } -void CloudPolicyClient::NotifyRobotAuthCodesFetched() { - for (auto& observer : observers_) - observer.OnRobotAuthCodesFetched(this); -} - void CloudPolicyClient::NotifyClientError() { for (auto& observer : observers_) observer.OnClientError(this);
diff --git a/components/policy/core/common/cloud/cloud_policy_client.h b/components/policy/core/common/cloud/cloud_policy_client.h index 0954062..e205e8a01 100644 --- a/components/policy/core/common/cloud/cloud_policy_client.h +++ b/components/policy/core/common/cloud/cloud_policy_client.h
@@ -71,6 +71,11 @@ DeviceManagementStatus, const std::vector<enterprise_management::RemoteCommand>&)>; + // A callback for fetching device robot OAuth2 authorization tokens. + // Only occurs during enrollment, after the device is registered. + using RobotAuthCodeCallback = + base::OnceCallback<void(DeviceManagementStatus, const std::string&)>; + // A callback which fetches device dm_token based on user affiliation. // Should be called once per registration. using DeviceDMTokenCallback = base::RepeatingCallback<std::string( @@ -89,11 +94,6 @@ // successful completion of registration and unregistration requests. virtual void OnRegistrationStateChanged(CloudPolicyClient* client) = 0; - // Called when a request for device robot OAuth2 authorization tokens - // returns successfully. Only occurs during enrollment. Optional - // (default implementation is a noop). - virtual void OnRobotAuthCodesFetched(CloudPolicyClient* client); - // Indicates there's been an error in a previously-issued request. virtual void OnClientError(CloudPolicyClient* client) = 0; }; @@ -183,7 +183,9 @@ // Requests OAuth2 auth codes for the device robot account. The client being // registered is a prerequisite to this operation and this call will CHECK if // the client is not in registered state. - virtual void FetchRobotAuthCodes(std::unique_ptr<DMAuth> auth); + // The |callback| will be called when the operation completes. + virtual void FetchRobotAuthCodes(std::unique_ptr<DMAuth> auth, + RobotAuthCodeCallback callback); // Sends an unregistration request to the server. virtual void Unregister(); @@ -349,10 +351,6 @@ return status_; } - const std::string& robot_api_auth_code() const { - return robot_api_auth_code_; - } - // Returns the invalidation version that was used for the last FetchPolicy. // Observers can call this method from their OnPolicyFetched method to // determine which at which invalidation version the policy was fetched. @@ -403,6 +401,7 @@ // Callback for robot account api authorization requests. void OnFetchRobotAuthCodesCompleted( + RobotAuthCodeCallback callback, DeviceManagementStatus status, int net_error, const enterprise_management::DeviceManagementResponse& response); @@ -475,7 +474,6 @@ // Observer notification helpers. void NotifyPolicyFetched(); void NotifyRegistrationStateChanged(); - void NotifyRobotAuthCodesFetched(); void NotifyClientError(); // Data necessary for constructing policy requests. @@ -492,7 +490,6 @@ base::Time last_policy_timestamp_; int public_key_version_ = -1; bool public_key_version_valid_ = false; - std::string robot_api_auth_code_; // Device DMToken for affiliated user policy requests. // Retrieved from |device_dm_token_callback_| on registration. std::string device_dm_token_;
diff --git a/components/policy/core/common/cloud/cloud_policy_validator.cc b/components/policy/core/common/cloud/cloud_policy_validator.cc index 485c526..84cb9ef 100644 --- a/components/policy/core/common/cloud/cloud_policy_validator.cc +++ b/components/policy/core/common/cloud/cloud_policy_validator.cc
@@ -64,6 +64,45 @@ } // namespace +// static +const char* CloudPolicyValidatorBase::StatusToString(Status status) { + switch (status) { + case VALIDATION_OK: + return "OK"; + case VALIDATION_BAD_INITIAL_SIGNATURE: + return "BAD_INITIAL_SIGNATURE"; + case VALIDATION_BAD_SIGNATURE: + return "BAD_SIGNATURE"; + case VALIDATION_ERROR_CODE_PRESENT: + return "ERROR_CODE_PRESENT"; + case VALIDATION_PAYLOAD_PARSE_ERROR: + return "PAYLOAD_PARSE_ERROR"; + case VALIDATION_WRONG_POLICY_TYPE: + return "WRONG_POLICY_TYPE"; + case VALIDATION_WRONG_SETTINGS_ENTITY_ID: + return "WRONG_SETTINGS_ENTITY_ID"; + case VALIDATION_BAD_TIMESTAMP: + return "BAD_TIMESTAMP"; + case VALIDATION_BAD_DM_TOKEN: + return "BAD_DM_TOKEN"; + case VALIDATION_BAD_DEVICE_ID: + return "BAD_DEVICE_ID"; + case VALIDATION_BAD_USER: + return "BAD_USER"; + case VALIDATION_POLICY_PARSE_ERROR: + return "POLICY_PARSE_ERROR"; + case VALIDATION_BAD_KEY_VERIFICATION_SIGNATURE: + return "BAD_KEY_VERIFICATION_SIGNATURE"; + case VALIDATION_VALUE_WARNING: + return "VALUE_WARNING"; + case VALIDATION_VALUE_ERROR: + return "VALUE_ERROR"; + case VALIDATION_STATUS_SIZE: + return "UNKNOWN"; + } + return "UNKNOWN"; +} + CloudPolicyValidatorBase::ValidationResult::ValidationResult() = default; CloudPolicyValidatorBase::ValidationResult::~ValidationResult() = default;
diff --git a/components/policy/core/common/cloud/cloud_policy_validator.h b/components/policy/core/common/cloud/cloud_policy_validator.h index 75c167f6..5c4a231d 100644 --- a/components/policy/core/common/cloud/cloud_policy_validator.h +++ b/components/policy/core/common/cloud/cloud_policy_validator.h
@@ -138,6 +138,9 @@ ~ValidationResult(); }; + // Returns a human-readable representation of |status|. + static const char* StatusToString(Status status); + virtual ~CloudPolicyValidatorBase(); // Validation status which can be read after completion has been signaled.
diff --git a/components/policy/core/common/cloud/mock_cloud_policy_client.h b/components/policy/core/common/cloud/mock_cloud_policy_client.h index 463ea18d..50bc3f0 100644 --- a/components/policy/core/common/cloud/mock_cloud_policy_client.h +++ b/components/policy/core/common/cloud/mock_cloud_policy_client.h
@@ -105,7 +105,6 @@ MOCK_METHOD1(OnPolicyFetched, void(CloudPolicyClient*)); MOCK_METHOD1(OnRegistrationStateChanged, void(CloudPolicyClient*)); - MOCK_METHOD1(OnRobotAuthCodesFetched, void(CloudPolicyClient*)); MOCK_METHOD1(OnClientError, void(CloudPolicyClient*)); private:
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc index ff07af8..cfeddd1 100644 --- a/components/signin/core/browser/account_reconcilor.cc +++ b/components/signin/core/browser/account_reconcilor.cc
@@ -422,8 +422,9 @@ OnSetAccountsInCookieCompleted(GoogleServiceAuthError::AuthErrorNone()); } // TODO(valeriyas): Log operation here. + // TODO (valeriyas): Write correct first gaia account to cache for desktop. if (!is_reconcile_started_) - delegate_->OnReconcileFinished(gaia_accounts[0].id, reconcile_is_noop_); + delegate_->OnReconcileFinished(primary_account, reconcile_is_noop_); first_execution_ = false; ScheduleStartReconcileIfChromeAccountsChanged(); }
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index afc33597..134b601d 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -1005,6 +1005,9 @@ void GaiaCookieManagerService::OnSetAccountsFinished( const GoogleServiceAuthError& error) { + // Set ListAccounts result to stale manually because on iOS + // GaiaCookieManagerService is not notified about changes in cookie storage. + list_accounts_stale_ = true; access_tokens_.clear(); token_requests_.clear(); cookies_to_set_.clear();
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.cc b/components/subresource_filter/content/browser/async_document_subresource_filter.cc index 212d823..86ff5b64 100644 --- a/components/subresource_filter/content/browser/async_document_subresource_filter.cc +++ b/components/subresource_filter/content/browser/async_document_subresource_filter.cc
@@ -32,12 +32,12 @@ "SubresourceFilter.DocumentLoad.Activation.CPUDuration"); auto page_wall_duration_timer = ScopedTimers::StartIf( - parent_document_origin.unique(), [](base::TimeDelta delta) { + parent_document_origin.opaque(), [](base::TimeDelta delta) { UMA_HISTOGRAM_MICRO_TIMES( "SubresourceFilter.PageLoad.Activation.WallDuration", delta); }); auto page_cpu_duration_timer = ScopedThreadTimers::StartIf( - parent_document_origin.unique(), [](base::TimeDelta delta) { + parent_document_origin.opaque(), [](base::TimeDelta delta) { UMA_HISTOGRAM_MICRO_TIMES( "SubresourceFilter.PageLoad.Activation.CPUDuration", delta); });
diff --git a/components/subresource_filter/core/common/first_party_origin.cc b/components/subresource_filter/core/common/first_party_origin.cc index 46a218f..9a1580ab 100644 --- a/components/subresource_filter/core/common/first_party_origin.cc +++ b/components/subresource_filter/core/common/first_party_origin.cc
@@ -22,7 +22,7 @@ : document_origin_(std::move(document_origin)) {} bool FirstPartyOrigin::IsThirdParty(const GURL& url) const { - if (document_origin_.unique()) + if (document_origin_.opaque()) return true; base::StringPiece host_piece = url.host_piece(); if (!last_checked_host_.empty() && host_piece == last_checked_host_) @@ -35,7 +35,7 @@ bool FirstPartyOrigin::IsThirdParty(const GURL& url, const url::Origin& first_party_origin) { - return first_party_origin.unique() || + return first_party_origin.opaque() || IsThirdPartyImpl(url, first_party_origin); }
diff --git a/components/ui_devtools/devtools_server.cc b/components/ui_devtools/devtools_server.cc index 6827164..f7808b0 100644 --- a/components/ui_devtools/devtools_server.cc +++ b/components/ui_devtools/devtools_server.cc
@@ -104,7 +104,8 @@ i++) { pairs.push_back(std::pair<std::string, std::string>( devtools_server_->clients_[i]->name(), - base::StringPrintf("%s0.0.0.0:%d/%" PRIuS, kChromeDeveloperToolsPrefix, + base::StringPrintf("%s127.0.0.1:%d/%" PRIuS, + kChromeDeveloperToolsPrefix, devtools_server_->port(), i))); } return pairs;
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc index 75e1dca..7ec8caf 100644 --- a/components/url_pattern_index/url_pattern_index.cc +++ b/components/url_pattern_index/url_pattern_index.cc
@@ -502,7 +502,7 @@ } // Otherwise look for each subdomain of the |origin| using binary search. - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); base::StringPiece canonicalized_host(origin.host()); if (canonicalized_host.empty()) return 0; @@ -559,7 +559,7 @@ return false; // Unique |origin| matches lists of exception domains only. - if (origin.unique()) + if (origin.opaque()) return is_generic; size_t longest_matching_included_domain_length = 1;
diff --git a/components/url_pattern_index/url_rule_test_support.cc b/components/url_pattern_index/url_rule_test_support.cc index dd3a0a3..77701e5 100644 --- a/components/url_pattern_index/url_rule_test_support.cc +++ b/components/url_pattern_index/url_rule_test_support.cc
@@ -46,7 +46,7 @@ } bool IsThirdParty(const GURL& url, const url::Origin& first_party_origin) { - return first_party_origin.unique() || + return first_party_origin.opaque() || !net::registry_controlled_domains::SameDomainOrHost( url, first_party_origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
diff --git a/components/web_modal/web_contents_modal_dialog_manager.cc b/components/web_modal/web_contents_modal_dialog_manager.cc index 4669249e..2874a931 100644 --- a/components/web_modal/web_contents_modal_dialog_manager.cc +++ b/components/web_modal/web_contents_modal_dialog_manager.cc
@@ -61,11 +61,10 @@ } void WebContentsModalDialogManager::WillClose(gfx::NativeWindow dialog) { - WebContentsModalDialogList::iterator dlg = - std::find_if(child_dialogs_.begin(), child_dialogs_.end(), - [dialog](const DialogState& child_dialog) { - return child_dialog.dialog == dialog; - }); + auto dlg = std::find_if(child_dialogs_.begin(), child_dialogs_.end(), + [dialog](const DialogState& child_dialog) { + return child_dialog.dialog == dialog; + }); // The Views tab contents modal dialog calls WillClose twice. Ignore the // second invocation. @@ -106,10 +105,6 @@ // then set the block state. Advantage: could restrict some of the // WCMDM delegate methods, then, and pass them behind the scenes. void WebContentsModalDialogManager::BlockWebContentsInteraction(bool blocked) { - if (blocked == web_contents_is_blocked_) - return; - web_contents_is_blocked_ = blocked; - WebContents* contents = web_contents(); if (!contents) { // The WebContents has already disconnected. @@ -128,7 +123,6 @@ while (!child_dialogs_.empty()) { child_dialogs_.front().manager->Close(); } - BlockWebContentsInteraction(false); closing_all_dialogs_ = false; }
diff --git a/components/web_modal/web_contents_modal_dialog_manager.h b/components/web_modal/web_contents_modal_dialog_manager.h index 844003c..ca0bcbe 100644 --- a/components/web_modal/web_contents_modal_dialog_manager.h +++ b/components/web_modal/web_contents_modal_dialog_manager.h
@@ -82,8 +82,6 @@ std::unique_ptr<SingleWebContentsDialogManager> manager; }; - using WebContentsModalDialogList = base::circular_deque<DialogState>; - // Blocks/unblocks interaction with renderer process. void BlockWebContentsInteraction(bool blocked); @@ -101,7 +99,7 @@ WebContentsModalDialogManagerDelegate* delegate_; // All active dialogs. - WebContentsModalDialogList child_dialogs_; + base::circular_deque<DialogState> child_dialogs_; // Whether the WebContents' visibility is content::Visibility::HIDDEN. bool web_contents_is_hidden_; @@ -109,9 +107,6 @@ // True while closing the dialogs on WebContents close. bool closing_all_dialogs_; - // True if the WebContents is blocked. - bool web_contents_is_blocked_ = false; - DISALLOW_COPY_AND_ASSIGN(WebContentsModalDialogManager); };
diff --git a/content/browser/appcache/appcache_host.cc b/content/browser/appcache/appcache_host.cc index f82d1f76..bbc891b 100644 --- a/content/browser/appcache/appcache_host.cc +++ b/content/browser/appcache/appcache_host.cc
@@ -83,7 +83,7 @@ if (group_being_updated_.get()) group_being_updated_->RemoveUpdateObserver(this); storage()->CancelDelegateCallbacks(this); - if (service()->quota_manager_proxy() && !origin_in_use_.unique()) + if (service()->quota_manager_proxy() && !origin_in_use_.opaque()) service()->quota_manager_proxy()->NotifyOriginNoLongerInUse(origin_in_use_); } @@ -113,7 +113,7 @@ } origin_in_use_ = url::Origin::Create(document_url); - if (service()->quota_manager_proxy() && !origin_in_use_.unique()) + if (service()->quota_manager_proxy() && !origin_in_use_.opaque()) service()->quota_manager_proxy()->NotifyOriginInUse(origin_in_use_); if (main_resource_blocked_)
diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter.cc b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc index 120b53c..50d79fe 100644 --- a/content/browser/background_fetch/background_fetch_cross_origin_filter.cc +++ b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
@@ -37,7 +37,7 @@ for (const std::string& origin_string : origin_vector) { url::Origin origin = url::Origin::Create(GURL(origin_string)); - if (origin.unique()) + if (origin.opaque()) return false; candidate_origins.insert(origin);
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc index b84fd49..fc33a75 100644 --- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc +++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -111,7 +111,7 @@ // Fill |request_info| with a failed result. request_info->SetResult(std::make_unique<BackgroundFetchResult>( std::move(response), base::Time::Now(), - BackgroundFetchResult::FailureReason::UNKNOWN)); + BackgroundFetchResult::FailureReason::FETCH_ERROR)); return; }
diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc index 7b06a6d5..aed7bec 100644 --- a/content/browser/background_fetch/background_fetch_job_controller.cc +++ b/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "content/browser/background_fetch/background_fetch_job_controller.h" +#include "content/public/common/origin_util.h" #include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h" #include <utility> @@ -74,6 +75,15 @@ return completed_downloads_ < total_downloads_; } +bool BackgroundFetchJobController::IsMixedContent( + const BackgroundFetchRequestInfo& request) { + // Empty request is valid, it shouldn't fail the mixed content check. + if (request.fetch_request().url.is_empty()) + return false; + + return !IsOriginSecure(request.fetch_request().url); +} + void BackgroundFetchJobController::StartRequest( scoped_refptr<BackgroundFetchRequestInfo> request, RequestFinishedCallback request_finished_callback) { @@ -85,6 +95,15 @@ active_request_downloaded_bytes_ = 0; active_request_finished_callback_ = std::move(request_finished_callback); + if (IsMixedContent(*request.get())) { + request->SetEmptyResultWithFailureReason( + BackgroundFetchResult::FailureReason::FETCH_ERROR); + + ++completed_downloads_; + std::move(active_request_finished_callback_).Run(request); + return; + } + delegate_proxy_->StartRequest(registration_id().unique_id(), registration_id().origin(), request); }
diff --git a/content/browser/background_fetch/background_fetch_job_controller.h b/content/browser/background_fetch/background_fetch_job_controller.h index ada556c..254d69c 100644 --- a/content/browser/background_fetch/background_fetch_job_controller.h +++ b/content/browser/background_fetch/background_fetch_job_controller.h
@@ -116,6 +116,13 @@ blink::mojom::BackgroundFetchFailureReason reason_to_abort) override; private: + // Performs mixed content checks on the |request| for Background Fetch. + // Background Fetch depends on Service Workers, which are restricted for use + // on secure origins. We can therefore assume that the registration's origin + // is secure. This test ensures that the origin for the url of every + // request is also secure. + bool IsMixedContent(const BackgroundFetchRequestInfo& request); + // Options for the represented background fetch registration. BackgroundFetchOptions options_;
diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc index 8d2003d..1807219 100644 --- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc +++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -78,6 +78,20 @@ pending_requests_counts_[registration_id]--; } + // To be called when a request for |registration_id| has finished. + // Moves |request_info| to |out_request_info|. + void GetRequestInfoOnRequestFinished( + const BackgroundFetchRegistrationId& registration_id, + scoped_refptr<content::BackgroundFetchRequestInfo>* out_request_info, + scoped_refptr<content::BackgroundFetchRequestInfo> request_info) { + DCHECK(pending_requests_counts_.count(registration_id)); + DCHECK(out_request_info); + + EXPECT_GE(pending_requests_counts_[registration_id], 1); + pending_requests_counts_[registration_id]--; + *out_request_info = request_info; + } + // Creates a new Background Fetch registration, whose id will be stored in the // |*registration_id|, and registers it with the DataManager for the included // |request_data|. If |auto_complete_requests| is true, the request will @@ -238,6 +252,32 @@ GetCompletionStatus(registration_id)); } +TEST_F(BackgroundFetchJobControllerTest, SingleRequestJobWithInsecureOrigin) { + BackgroundFetchRegistrationId registration_id; + + auto requests = CreateRegistrationForRequests( + ®istration_id, {{GURL("http://example.com/funny_cat.png"), "GET"}}, + true /* auto_complete_requests */); + + EXPECT_EQ(JobCompletionStatus::kRunning, + GetCompletionStatus(registration_id)); + + std::unique_ptr<BackgroundFetchJobController> controller = + CreateJobController(registration_id, requests.size()); + + controller->StartRequest( + requests[0], + base::BindOnce( + &BackgroundFetchJobControllerTest::GetRequestInfoOnRequestFinished, + base::Unretained(this), registration_id, &requests[0])); + + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(JobCompletionStatus::kCompleted, + GetCompletionStatus(registration_id)); + EXPECT_FALSE(requests[0]->IsResultSuccess()); +} + TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) { BackgroundFetchRegistrationId registration_id; @@ -285,6 +325,46 @@ GetCompletionStatus(registration_id)); } +TEST_F(BackgroundFetchJobControllerTest, MultipleRequestsJobWithMixedContent) { + BackgroundFetchRegistrationId registration_id; + + auto requests = CreateRegistrationForRequests( + ®istration_id, + {{GURL("http://example.com/funny_cat.png"), "GET"}, + {GURL("https://example.com/scary_cat.png"), "GET"}}, + true /* auto_complete_requests */); + + EXPECT_EQ(JobCompletionStatus::kRunning, + GetCompletionStatus(registration_id)); + + std::unique_ptr<BackgroundFetchJobController> controller = + CreateJobController(registration_id, requests.size()); + + controller->StartRequest( + requests[0], + base::BindOnce( + &BackgroundFetchJobControllerTest::GetRequestInfoOnRequestFinished, + base::Unretained(this), registration_id, &requests[0])); + + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(JobCompletionStatus::kRunning, + GetCompletionStatus(registration_id)); + EXPECT_FALSE(requests[0]->IsResultSuccess()); + + controller->StartRequest( + requests[1], + base::BindOnce( + &BackgroundFetchJobControllerTest::GetRequestInfoOnRequestFinished, + base::Unretained(this), registration_id, &requests[1])); + + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(JobCompletionStatus::kCompleted, + GetCompletionStatus(registration_id)); + EXPECT_TRUE(requests[1]->IsResultSuccess()); +} + TEST_F(BackgroundFetchJobControllerTest, Abort) { BackgroundFetchRegistrationId registration_id;
diff --git a/content/browser/background_fetch/background_fetch_request_info.cc b/content/browser/background_fetch/background_fetch_request_info.cc index c2326fb0..d2103e65 100644 --- a/content/browser/background_fetch/background_fetch_request_info.cc +++ b/content/browser/background_fetch/background_fetch_request_info.cc
@@ -51,6 +51,14 @@ PopulateWithResponse(std::move(result_->response)); } +void BackgroundFetchRequestInfo::SetEmptyResultWithFailureReason( + BackgroundFetchResult::FailureReason failure_reason) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + result_ = std::make_unique<BackgroundFetchResult>( + nullptr /* response */, base::Time::Now(), failure_reason); +} + void BackgroundFetchRequestInfo::PopulateWithResponse( std::unique_ptr<BackgroundFetchResponse> response) { DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/content/browser/background_fetch/background_fetch_request_info.h b/content/browser/background_fetch/background_fetch_request_info.h index 17cff434..3b359aa 100644 --- a/content/browser/background_fetch/background_fetch_request_info.h +++ b/content/browser/background_fetch/background_fetch_request_info.h
@@ -20,6 +20,7 @@ #include "content/browser/background_fetch/background_fetch_constants.h" #include "content/common/content_export.h" #include "content/common/service_worker/service_worker_types.h" +#include "content/public/browser/background_fetch_response.h" #include "url/gurl.h" namespace storage { @@ -50,6 +51,11 @@ void SetResult(std::unique_ptr<BackgroundFetchResult> result); + // Creates an empty result, with no response, and assigns |failure_reason| + // as its failure_reason. + void SetEmptyResultWithFailureReason( + BackgroundFetchResult::FailureReason failure_reason); + // Returns the index of this request within a Background Fetch registration. int request_index() const { return request_index_; }
diff --git a/content/browser/background_fetch/mock_background_fetch_delegate.cc b/content/browser/background_fetch/mock_background_fetch_delegate.cc index 75e026c..5a165cf 100644 --- a/content/browser/background_fetch/mock_background_fetch_delegate.cc +++ b/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -147,7 +147,7 @@ std::vector<GURL>({url}), test_response->headers); auto result = std::make_unique<BackgroundFetchResult>( std::move(response), base::Time::Now(), - BackgroundFetchResult::FailureReason::UNKNOWN); + BackgroundFetchResult::FailureReason::FETCH_ERROR); PostAbortCheckingTask( job_unique_id, base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadComplete,
diff --git a/content/browser/bluetooth/bluetooth_allowed_devices_map.cc b/content/browser/bluetooth/bluetooth_allowed_devices_map.cc index 4b4ce9a..1c275f34 100644 --- a/content/browser/bluetooth/bluetooth_allowed_devices_map.cc +++ b/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
@@ -19,7 +19,7 @@ const url::Origin& origin) { // "Unique" Origins generate the same key in maps, therefore are not // supported. - CHECK(!origin.unique()); + CHECK(!origin.opaque()); auto iter = origin_to_allowed_devices_map_.find(origin); if (iter == origin_to_allowed_devices_map_.end()) { iter = origin_to_allowed_devices_map_.insert(
diff --git a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc index bea7677..b561ce3 100644 --- a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc +++ b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -344,9 +344,9 @@ REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME); return; } - // The above also excludes unique origins, which are not even same-origin with + // The above also excludes opaque origins, which are not even same-origin with // themselves. - DCHECK(!requesting_origin.unique()); + DCHECK(!requesting_origin.opaque()); if (!adapter_->IsPresent()) { DVLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
diff --git a/content/browser/browsing_data/browsing_data_filter_builder_impl.cc b/content/browser/browsing_data/browsing_data_filter_builder_impl.cc index e569410d..b06695a 100644 --- a/content/browser/browsing_data/browsing_data_filter_builder_impl.cc +++ b/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
@@ -100,7 +100,7 @@ // This means that std::set::find() will use the same semantics for // origin comparison as Origin::IsSameOriginWith(). Furthermore, this // means that two filters are equal iff they are equal element-wise. - DCHECK(!origin.unique()) << "Invalid origin passed into OriginFilter."; + DCHECK(!origin.opaque()) << "Invalid origin passed into OriginFilter."; // TODO(msramek): All urls with file scheme currently map to the same // origin. This is currently not a problem, but if it becomes one,
diff --git a/content/browser/browsing_data/clear_site_data_handler.cc b/content/browser/browsing_data/clear_site_data_handler.cc index fc99ea9..902c6b6 100644 --- a/content/browser/browsing_data/clear_site_data_handler.cc +++ b/content/browser/browsing_data/clear_site_data_handler.cc
@@ -290,7 +290,7 @@ } url::Origin origin = url::Origin::Create(url_); - if (origin.unique()) { + if (origin.opaque()) { delegate_->AddMessage(url_, "Not supported for unique origins.", CONSOLE_MESSAGE_LEVEL_ERROR); return false;
diff --git a/content/browser/browsing_data/clear_site_data_throttle.cc b/content/browser/browsing_data/clear_site_data_throttle.cc index d8b32084..d1a6df3 100644 --- a/content/browser/browsing_data/clear_site_data_throttle.cc +++ b/content/browser/browsing_data/clear_site_data_throttle.cc
@@ -369,7 +369,7 @@ } url::Origin origin = url::Origin::Create(GetCurrentURL()); - if (origin.unique()) { + if (origin.opaque()) { delegate_->AddMessage(GetCurrentURL(), "Not supported for unique origins.", CONSOLE_MESSAGE_LEVEL_ERROR); return false;
diff --git a/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc b/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc index d4a80f9..68e6527 100644 --- a/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc +++ b/content/browser/browsing_data/storage_partition_http_cache_data_remover.cc
@@ -174,18 +174,19 @@ } case CacheState::DELETE_CODE: { next_cache_state_ = CacheState::DONE; - // Embedders can disable code caches. if (generated_code_cache_context_) { - GeneratedCodeCache* code_cache = - generated_code_cache_context_->generated_code_cache(); - if (code_cache) { - auto callback = base::BindRepeating( - &StoragePartitionHttpCacheDataRemover::DoClearCache, - base::Unretained(this)); - // TODO(crbug.com/866419): Currently we just clear the entire cache. - // Change it to conditionally clear the entries based on the - // filters. - rv = code_cache->ClearCache(callback); + // TODO(crbug.com/866419): Currently we just clear entire caches. + // Change it to conditionally clear entries based on the filters. + auto callback = base::BindRepeating( + &StoragePartitionHttpCacheDataRemover::DoClearCache, + base::Unretained(this)); + if (generated_code_cache_context_->generated_js_code_cache()) { + rv = generated_code_cache_context_->generated_js_code_cache() + ->ClearCache(callback); + } + if (generated_code_cache_context_->generated_wasm_code_cache()) { + rv = generated_code_cache_context_->generated_wasm_code_cache() + ->ClearCache(callback); } } break;
diff --git a/content/browser/cache_storage/cache_storage.cc b/content/browser/cache_storage/cache_storage.cc index c724523..6ac6747 100644 --- a/content/browser/cache_storage/cache_storage.cc +++ b/content/browser/cache_storage/cache_storage.cc
@@ -133,7 +133,7 @@ cache_storage_(cache_storage), origin_(origin), owner_(owner) { - DCHECK(!origin_.unique()); + DCHECK(!origin_.opaque()); } virtual ~CacheLoader() {}
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index 6ad59b6..030b08a 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -929,7 +929,7 @@ cache_observer_(nullptr), memory_only_(path.empty()), weak_ptr_factory_(this) { - DCHECK(!origin_.unique()); + DCHECK(!origin_.opaque()); DCHECK(quota_manager_proxy_.get()); DCHECK(cache_padding_key_.get());
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/content/browser/cache_storage/cache_storage_dispatcher_host.cc index 035fbe0..9394792 100644 --- a/content/browser/cache_storage/cache_storage_dispatcher_host.cc +++ b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -41,7 +41,7 @@ // TODO(lucmult): Check this before binding. bool OriginCanAccessCacheStorage(const url::Origin& origin) { - return !origin.unique() && IsOriginSecure(origin.GetURL()); + return !origin.opaque() && IsOriginSecure(origin.GetURL()); } void StopPreservingCache(CacheStorageCacheHandle cache_handle) {}
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index 09ebf9c..f444e2d 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc
@@ -120,13 +120,13 @@ // Grant permission to request and commit URLs with the specified origin. void GrantCommitOrigin(const url::Origin& origin) { - if (origin.unique()) + if (origin.opaque()) return; origin_map_[origin] = CommitRequestPolicy::kCommitAndRequest; } void GrantRequestOrigin(const url::Origin& origin) { - if (origin.unique()) + if (origin.opaque()) return; // Anything already in |origin_map_| must have at least request permission // already. In that case, the emplace() below will be a no-op. @@ -510,7 +510,7 @@ // TODO(dcheng): In the future, URLs with opaque origins would ideally carry // around an origin with them, so we wouldn't need to grant commit access to // the entire scheme. - if (!origin.unique()) + if (!origin.opaque()) GrantCommitOrigin(child_id, origin); // The scheme has already been whitelisted for every child process, so no need @@ -524,7 +524,7 @@ if (state == security_state_.end()) return; - if (origin.unique()) { + if (origin.opaque()) { // If it's impossible to grant commit rights to just the origin (among other // things, URLs with non-standard schemes will be treated as opaque // origins), then grant access to commit all URLs of that scheme. @@ -742,7 +742,7 @@ return false; url::Origin origin = url::Origin::Create(url); - return origin.unique() || CanRequestURL(child_id, GURL(origin.Serialize())); + return origin.opaque() || CanRequestURL(child_id, GURL(origin.Serialize())); } if (IsWebSafeScheme(scheme)) @@ -814,7 +814,7 @@ return false; url::Origin origin = url::Origin::Create(url); - return origin.unique() || + return origin.opaque() || CanCommitURL(child_id, GURL(origin.Serialize()), check_origin_locks); }
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc index f584b132..d571d8e9 100644 --- a/content/browser/child_process_security_policy_unittest.cc +++ b/content/browser/child_process_security_policy_unittest.cc
@@ -498,8 +498,8 @@ const GURL url("httpxml://awesome"); const GURL url2("httpxml://also-awesome"); - ASSERT_TRUE(url::Origin::Create(url).unique()); - ASSERT_TRUE(url::Origin::Create(url2).unique()); + ASSERT_TRUE(url::Origin::Create(url).opaque()); + ASSERT_TRUE(url::Origin::Create(url2).opaque()); RegisterTestScheme("httpxml"); p->Add(kRendererID);
diff --git a/content/browser/code_cache/generated_code_cache.cc b/content/browser/code_cache/generated_code_cache.cc index c81475e4..b7094c1c 100644 --- a/content/browser/code_cache/generated_code_cache.cc +++ b/content/browser/code_cache/generated_code_cache.cc
@@ -25,7 +25,7 @@ // Don't cache the code corresponding to unique origins. The same-origin // checks should always fail for unique origins but the serialized value of // unique origins does not ensure this. - if (requesting_origin.unique()) + if (requesting_origin.opaque()) return false; // If the resource url or requesting url is invalid don't cache the code. @@ -40,7 +40,7 @@ // serialized url and origin with a separator in between. std::string GetCacheKey(const GURL& resource_url, const url::Origin& requesting_origin) { - DCHECK(!requesting_origin.unique()); + DCHECK(!requesting_origin.opaque()); DCHECK(resource_url.is_valid()); // Add a prefix _ so it can't be parsed as a valid URL. std::string key = "_key";
diff --git a/content/browser/code_cache/generated_code_cache_context.cc b/content/browser/code_cache/generated_code_cache_context.cc index 97cc2a4..03f426f 100644 --- a/content/browser/code_cache/generated_code_cache_context.cc +++ b/content/browser/code_cache/generated_code_cache_context.cc
@@ -26,12 +26,19 @@ void GeneratedCodeCacheContext::InitializeOnIO(const base::FilePath& path, int max_bytes) { - generated_code_cache_.reset(new GeneratedCodeCache(path, max_bytes)); + generated_js_code_cache_.reset(new GeneratedCodeCache(path, max_bytes)); + generated_wasm_code_cache_.reset(new GeneratedCodeCache(path, max_bytes)); } -GeneratedCodeCache* GeneratedCodeCacheContext::generated_code_cache() const { +GeneratedCodeCache* GeneratedCodeCacheContext::generated_js_code_cache() const { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return generated_code_cache_.get(); + return generated_js_code_cache_.get(); +} + +GeneratedCodeCache* GeneratedCodeCacheContext::generated_wasm_code_cache() + const { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + return generated_wasm_code_cache_.get(); } GeneratedCodeCacheContext::~GeneratedCodeCacheContext() = default;
diff --git a/content/browser/code_cache/generated_code_cache_context.h b/content/browser/code_cache/generated_code_cache_context.h index 4a42beb..7e26e326 100644 --- a/content/browser/code_cache/generated_code_cache_context.h +++ b/content/browser/code_cache/generated_code_cache_context.h
@@ -30,8 +30,9 @@ // being setup. void Initialize(const base::FilePath& path, int max_bytes); - // Call on the IO thread to get the code cache instance. - GeneratedCodeCache* generated_code_cache() const; + // Call on the IO thread to get the code cache instances. + GeneratedCodeCache* generated_js_code_cache() const; + GeneratedCodeCache* generated_wasm_code_cache() const; private: friend class base::RefCountedThreadSafe<GeneratedCodeCacheContext>; @@ -41,7 +42,9 @@ // Created, used and deleted on the IO thread. std::unique_ptr<GeneratedCodeCache, BrowserThread::DeleteOnIOThread> - generated_code_cache_; + generated_js_code_cache_; + std::unique_ptr<GeneratedCodeCache, BrowserThread::DeleteOnIOThread> + generated_wasm_code_cache_; DISALLOW_COPY_AND_ASSIGN(GeneratedCodeCacheContext); };
diff --git a/content/browser/frame_host/frame_tree_browsertest.cc b/content/browser/frame_host/frame_tree_browsertest.cc index 6a2c55f4..7159859c 100644 --- a/content/browser/frame_host/frame_tree_browsertest.cc +++ b/content/browser/frame_host/frame_tree_browsertest.cc
@@ -275,7 +275,7 @@ // Navigating to a data URL should set a unique origin. This is represented // as "null" per RFC 6454. EXPECT_EQ("null", root->current_origin().Serialize()); - EXPECT_TRUE(contents->GetMainFrame()->GetLastCommittedOrigin().unique()); + EXPECT_TRUE(contents->GetMainFrame()->GetLastCommittedOrigin().opaque()); EXPECT_EQ("null", GetOriginFromRenderer(root)); // Re-navigating to a normal URL should update the origin. @@ -285,7 +285,7 @@ EXPECT_EQ( main_url.GetOrigin().spec(), contents->GetMainFrame()->GetLastCommittedOrigin().Serialize() + '/'); - EXPECT_FALSE(contents->GetMainFrame()->GetLastCommittedOrigin().unique()); + EXPECT_FALSE(contents->GetMainFrame()->GetLastCommittedOrigin().opaque()); EXPECT_EQ(root->current_origin().Serialize(), GetOriginFromRenderer(root)); } @@ -334,7 +334,7 @@ deleted_observer.WaitUntilDeleted(); EXPECT_EQ(GURL(blob_url_string), target->current_url()); EXPECT_EQ(url::kBlobScheme, target->current_url().scheme()); - EXPECT_FALSE(target->current_origin().unique()); + EXPECT_FALSE(target->current_origin().opaque()); EXPECT_EQ("a.com", target->current_origin().host()); EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme()); EXPECT_EQ("This is blob content.", @@ -379,7 +379,7 @@ EXPECT_EQ(target->current_origin(), about_blank_origin); EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url()); EXPECT_EQ(url::kAboutScheme, target->current_url().scheme()); - EXPECT_FALSE(target->current_origin().unique()); + EXPECT_FALSE(target->current_origin().opaque()); EXPECT_EQ("b.com", target->current_origin().host()); EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme()); @@ -427,7 +427,7 @@ EXPECT_EQ(target->current_origin(), about_blank_origin); EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url()); EXPECT_EQ(url::kAboutScheme, target->current_url().scheme()); - EXPECT_FALSE(target->current_origin().unique()); + EXPECT_FALSE(target->current_origin().opaque()); EXPECT_EQ("a.com", target->current_origin().host()); EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc index 7d748ab..abda7b16 100644 --- a/content/browser/frame_host/navigator_impl_unittest.cc +++ b/content/browser/frame_host/navigator_impl_unittest.cc
@@ -1301,7 +1301,7 @@ blink::FeaturePolicy* subframe_feature_policy = subframe_rfh->feature_policy(); ASSERT_TRUE(subframe_feature_policy); - ASSERT_FALSE(subframe_feature_policy->GetOriginForTest().unique()); + ASSERT_FALSE(subframe_feature_policy->GetOriginForTest().opaque()); } TEST_F(NavigatorTestWithBrowserSideNavigation, TwoNavigationsRacingCommit) {
diff --git a/content/browser/frame_host/origin_policy_throttle.cc b/content/browser/frame_host/origin_policy_throttle.cc index 1ab06ea..724d4f8 100644 --- a/content/browser/frame_host/origin_policy_throttle.cc +++ b/content/browser/frame_host/origin_policy_throttle.cc
@@ -118,7 +118,7 @@ url::Origin origin = GetRequestOrigin(); DCHECK(!origin.Serialize().empty()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); KnownVersionMap& versions = GetKnownVersions(); KnownVersionMap::iterator iter = versions.find(origin);
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index b676e3ea..d700994 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -424,6 +424,24 @@ base::debug::SetCrashKeyString(site_url_key, site_url.spec()); } +url::Origin GetOriginForURLLoaderFactory(GURL target_url, + SiteInstanceImpl* site_instance) { + // Calculate the origin that will be used as a fallback for URLs such as + // about:blank and/or data:. If full site isolation is enabled, then + // |site_instance|-based origin will be correct. Otherwise, falling back to a + // unique/opaque origin should be safe. + // + // TODO(lukasza, nasko): https://crbug.com/888079: Do not fall back to + // |site_instance| - instead the browser process should already know at + // ready-to-commit time the origin to be committed. + url::Origin fallback_origin = + SiteIsolationPolicy::UseDedicatedProcessesForAllSites() + ? url::Origin::Create(site_instance->GetSiteURL()) + : url::Origin(); + + return url::Origin::Resolve(target_url, fallback_origin); +} + } // namespace class RenderFrameHostImpl::DroppedInterfaceRequestLogger @@ -864,7 +882,7 @@ bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactory( network::mojom::URLLoaderFactoryRequest default_factory_request) { return CreateNetworkServiceDefaultFactoryInternal( - last_committed_url_, std::move(default_factory_request)); + last_committed_origin_, std::move(default_factory_request)); } gfx::NativeView RenderFrameHostImpl::GetNativeView() { @@ -3642,7 +3660,7 @@ // It is safe to commit into a unique origin, regardless of the URL, as it is // restricted from accessing other origins. - if (origin.unique()) + if (origin.opaque()) return true; // Standard URLs must match the reported origin. @@ -4032,7 +4050,9 @@ // appropriate NetworkContext. bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve( - common_params.url, mojo::MakeRequest(&default_factory_info)); + GetOriginForURLLoaderFactory(common_params.url, + GetSiteInstance()), + mojo::MakeRequest(&default_factory_info)); subresource_loader_factories->set_bypass_redirect_checks( bypass_redirect_checks); } @@ -4079,7 +4099,8 @@ network::mojom::URLLoaderFactoryPtrInfo factory_proxy_info; auto factory_request = mojo::MakeRequest(&factory_proxy_info); GetContentClient()->browser()->WillCreateURLLoaderFactory( - browser_context, this, false /* is_navigation */, common_params.url, + browser_context, this, false /* is_navigation */, + GetOriginForURLLoaderFactory(common_params.url, GetSiteInstance()), &factory_request, nullptr /* bypass_redirect_checks */); // Keep DevTools proxy lasy, i.e. closest to the network. RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( @@ -4208,11 +4229,17 @@ // completing an unload handler. ResetWaitingState(); + // Error page will commit in an opaque origin. + // + // TODO(lukasza): https://crbug.com/888079: Use this origin when committing + // later on. + url::Origin origin = url::Origin(); + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories; if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { network::mojom::URLLoaderFactoryPtrInfo default_factory_info; bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve( - common_params.url, mojo::MakeRequest(&default_factory_info)); + origin, mojo::MakeRequest(&default_factory_info)); subresource_loader_factories = std::make_unique<URLLoaderFactoryBundleInfo>( std::move(default_factory_info), URLLoaderFactoryBundleInfo::SchemeMap(), bypass_redirect_checks); @@ -4753,7 +4780,7 @@ network::mojom::URLLoaderFactoryPtrInfo default_factory_info; bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve( - last_committed_url_, mojo::MakeRequest(&default_factory_info)); + last_committed_origin_, mojo::MakeRequest(&default_factory_info)); std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories = std::make_unique<URLLoaderFactoryBundleInfo>( @@ -4774,10 +4801,10 @@ } bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve( - const GURL& url, + const url::Origin& origin, network::mojom::URLLoaderFactoryRequest default_factory_request) { bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryInternal( - url, std::move(default_factory_request)); + origin, std::move(default_factory_request)); // Add connection error observer when Network Service is running // out-of-process. @@ -4801,7 +4828,7 @@ } bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal( - const GURL& url, + const url::Origin& origin, network::mojom::URLLoaderFactoryRequest default_factory_request) { network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParams::New(); @@ -4816,8 +4843,8 @@ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { GetContentClient()->browser()->WillCreateURLLoaderFactory( - context, this, false /* is_navigation */, url, &default_factory_request, - &bypass_redirect_checks); + context, this, false /* is_navigation */, origin, + &default_factory_request, &bypass_redirect_checks); } // Keep DevTools proxy lasy, i.e. closest to the network. @@ -5430,7 +5457,7 @@ // Error pages must commit in a unique origin. Terminate the renderer // process if this is violated. - if (!validated_params->origin.unique()) { + if (!validated_params->origin.opaque()) { DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin); bad_message::ReceivedBadMessage( process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT); @@ -5448,7 +5475,7 @@ net::ERR_BLOCKED_BY_CLIENT) { // Since this is known to be an error page commit, verify it happened in // a unique origin, terminating the renderer process otherwise. - if (!validated_params->origin.unique()) { + if (!validated_params->origin.opaque()) { DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, validated_params->origin); bad_message::ReceivedBadMessage( process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 3bd1639..1dc020f 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1059,16 +1059,19 @@ // |OnNetworkServiceConnectionError()| if the factory is out-of-process. If // this returns true, any redirect safety checks should be bypassed in // downstream loaders. - // |url| is the URL that the RenderFrame is either committing (in the case of - // navigation) or has last committed (when handling network process crashes). + // + // |origin| is the origin that the RenderFrame is either committing (in the + // case of navigation) or has last committed (when handling network process + // crashes). bool CreateNetworkServiceDefaultFactoryAndObserve( - const GURL& url, + const url::Origin& origin, network::mojom::URLLoaderFactoryRequest default_factory_request); - // |url| is the URL that the RenderFrame is either committing (in the case of - // navigation) or has last committed (when handling network process crashes). + // |origin| is the origin that the RenderFrame is either committing (in the + // case of navigation) or has last committed (when handling network process + // crashes). bool CreateNetworkServiceDefaultFactoryInternal( - const GURL& url, + const url::Origin& origin, network::mojom::URLLoaderFactoryRequest default_factory_request); // Returns true if the ExecuteJavaScript() API can be used on this host.
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index e5c7a51..1281c89 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1594,7 +1594,7 @@ // It is possible that last_successful_url() was a nonstandard scheme (for // example, "about:blank"). If so, examine the replicated origin to determine // the site. - if (!candidate->GetLastCommittedOrigin().unique() && + if (!candidate->GetLastCommittedOrigin().opaque() && SiteInstanceImpl::IsSameWebSite( browser_context, GURL(candidate->GetLastCommittedOrigin().Serialize()), dest_url, @@ -1609,7 +1609,7 @@ // tests rely on that behavior. To accomplish this, compare |dest_url| // against the site URL. if (candidate->last_successful_url().IsAboutBlank() && - candidate->GetLastCommittedOrigin().unique() && + candidate->GetLastCommittedOrigin().opaque() && SiteInstanceImpl::IsSameWebSite( browser_context, candidate->GetSiteInstance()->original_url(), dest_url, should_compare_effective_urls)) { @@ -2573,7 +2573,7 @@ // If dest_url is a unique origin like about:blank, then the need for a swap // is determined by the source_instance or dest_instance. GURL resolved_url = dest_url; - if (url::Origin::Create(resolved_url).unique()) { + if (url::Origin::Create(resolved_url).opaque()) { if (source_instance) { resolved_url = source_instance->GetSiteURL(); } else if (dest_instance) {
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc index fd6639a..b657fa5 100644 --- a/content/browser/frame_host/render_frame_message_filter.cc +++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -466,12 +466,11 @@ const GURL& site_for_cookies, GetCookiesCallback callback, const net::CookieList& cookie_list) { - net::URLRequestContext* context = GetRequestContextForURL(url); // Check the policy for get cookies, and pass cookie_list to the // TabSpecificContentSetting for logging purpose. - if (context && GetContentClient()->browser()->AllowGetCookie( - url, site_for_cookies, cookie_list, resource_context_, - render_process_id_, render_frame_id)) { + if (GetContentClient()->browser()->AllowGetCookie( + url, site_for_cookies, cookie_list, resource_context_, + render_process_id_, render_frame_id)) { std::move(callback).Run(net::CanonicalCookie::BuildCookieLine(cookie_list)); } else { std::move(callback).Run(std::string()); @@ -553,26 +552,32 @@ if (!GetContentClient()->browser()->AllowSetCookie( url, site_for_cookies, *cookie, resource_context_, render_process_id_, - render_frame_id)) - return; - - net::URLRequestContext* context = GetRequestContextForURL(url); - // If the embedder overrides the URLRequestContext then always use it, even if - // the network service is enabled, instead of the CookieManager associated - // this process' StoragePartition. - if (base::FeatureList::IsEnabled(network::features::kNetworkService) && - context == request_context_->GetURLRequestContext()) { - (*GetCookieManager()) - ->SetCanonicalCookie(*cookie, url.SchemeIsCryptographic(), - !options.exclude_httponly(), - net::CookieStore::SetCookiesCallback()); + render_frame_id)) { return; } - // Pass a null callback since we don't care about when the 'set' completes. - context->cookie_store()->SetCanonicalCookieAsync( - std::move(cookie), url.SchemeIsCryptographic(), - !options.exclude_httponly(), net::CookieStore::SetCookiesCallback()); + // If the embedder overrides the cookie store then always use it, even if + // the network service is enabled, instead of the CookieManager associated + // this process' StoragePartition. + net::CookieStore* cookie_store = + GetContentClient()->browser()->OverrideCookieStoreForURL( + url, resource_context_); + if (cookie_store || + !base::FeatureList::IsEnabled(network::features::kNetworkService)) { + if (!cookie_store) + cookie_store = request_context_->GetURLRequestContext()->cookie_store(); + + // Pass a null callback since we don't care about when the 'set' completes. + cookie_store->SetCanonicalCookieAsync( + std::move(cookie), url.SchemeIsCryptographic(), + !options.exclude_httponly(), net::CookieStore::SetCookiesCallback()); + return; + } + + (*GetCookieManager()) + ->SetCanonicalCookie(*cookie, url.SchemeIsCryptographic(), + !options.exclude_httponly(), + net::CookieStore::SetCookiesCallback()); } void RenderFrameMessageFilter::GetCookies(int render_frame_id, @@ -603,33 +608,35 @@ options.set_same_site_cookie_mode( net::CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE); } - - net::URLRequestContext* context = GetRequestContextForURL(url); - // If the embedder overrides the URLRequestContext then always use it, even if + // If the embedder overrides the cookie store then always use it, even if // the network service is enabled, instead of the CookieManager associated // this process' StoragePartition. - if (base::FeatureList::IsEnabled(network::features::kNetworkService) && - context == request_context_->GetURLRequestContext()) { - // TODO(jam): modify GetRequestContextForURL to work with network service. - // Merge this with code path below for non-network service. - (*GetCookieManager()) - ->GetCookieList( - url, options, - base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, - this, render_frame_id, url, site_for_cookies, - std::move(callback))); + net::CookieStore* cookie_store = + GetContentClient()->browser()->OverrideCookieStoreForURL( + url, resource_context_); + if (cookie_store || + !base::FeatureList::IsEnabled(network::features::kNetworkService)) { + if (!cookie_store) + cookie_store = request_context_->GetURLRequestContext()->cookie_store(); + + // If we crash here, figure out what URL the renderer was requesting. + // http://crbug.com/99242 + DEBUG_ALIAS_FOR_GURL(url_buf, url); + + cookie_store->GetCookieListWithOptionsAsync( + url, options, + base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this, + render_frame_id, url, site_for_cookies, + std::move(callback))); return; } - // If we crash here, figure out what URL the renderer was requesting. - // http://crbug.com/99242 - DEBUG_ALIAS_FOR_GURL(url_buf, url); - - context->cookie_store()->GetCookieListWithOptionsAsync( - url, options, - base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this, - render_frame_id, url, site_for_cookies, - std::move(callback))); + (*GetCookieManager()) + ->GetCookieList( + url, options, + base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this, + render_frame_id, url, site_for_cookies, + std::move(callback))); } #if BUILDFLAG(ENABLE_PLUGINS) @@ -720,17 +727,4 @@ #endif // ENABLE_PLUGINS -net::URLRequestContext* RenderFrameMessageFilter::GetRequestContextForURL( - const GURL& url) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - net::URLRequestContext* context = - GetContentClient()->browser()->OverrideRequestContextForURL( - url, resource_context_); - if (!context) - context = request_context_->GetURLRequestContext(); - - return context; -} - } // namespace content
diff --git a/content/browser/frame_host/render_frame_message_filter.h b/content/browser/frame_host/render_frame_message_filter.h index a661ac5..91a7d32 100644 --- a/content/browser/frame_host/render_frame_message_filter.h +++ b/content/browser/frame_host/render_frame_message_filter.h
@@ -35,7 +35,6 @@ } namespace net { -class URLRequestContext; class URLRequestContextGetter; } @@ -171,11 +170,6 @@ bool is_throttled); #endif // ENABLE_PLUGINS - // Returns the correct net::URLRequestContext depending on what type of url is - // given. - // Only call on the IO thread. - net::URLRequestContext* GetRequestContextForURL(const GURL& url); - #if BUILDFLAG(ENABLE_PLUGINS) PluginServiceImpl* plugin_service_; base::FilePath profile_data_directory_;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc index 0c919ba..2172021 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -31,7 +31,7 @@ const char kInvalidOrigin[] = "Origin is invalid"; bool IsValidOrigin(const url::Origin& origin) { - return !origin.unique(); + return !origin.opaque(); } blink::mojom::IDBStatus GetIndexedDBStatus(leveldb::Status status) {
diff --git a/content/browser/isolated_origin_util.cc b/content/browser/isolated_origin_util.cc index fe25348..9086edb 100644 --- a/content/browser/isolated_origin_util.cc +++ b/content/browser/isolated_origin_util.cc
@@ -31,7 +31,7 @@ // static bool IsolatedOriginUtil::IsValidIsolatedOrigin(const url::Origin& origin) { - if (origin.unique()) + if (origin.opaque()) return false; // Isolated origins should have HTTP or HTTPS schemes. Hosts in other
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index a5ea7dd9..90543ca5 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -1562,6 +1562,10 @@ ->RegisterNonNetworkNavigationURLLoaderFactories( frame_tree_node_id, &non_network_url_loader_factories_); + // Navigation requests are not associated with any particular + // |network::ResourceRequest::request_initiator| origin - using an opaque + // origin instead. + url::Origin navigation_request_initiator = url::Origin(); // The embedder may want to proxy all network-bound URLLoaderFactory // requests that it can. If it elects to do so, we'll pass its proxy // endpoints off to the URLLoaderRequestController where wthey will be @@ -1570,8 +1574,8 @@ auto factory_request = mojo::MakeRequest(&factory_info); bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory( partition->browser_context(), frame_tree_node->current_frame_host(), - true /* is_navigation */, new_request->url, &factory_request, - &bypass_redirect_checks); + true /* is_navigation */, navigation_request_initiator, + &factory_request, &bypass_redirect_checks); if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( frame_tree_node->current_frame_host(), true, false, &factory_request)) { @@ -1698,12 +1702,18 @@ DVLOG(1) << "Ignoring request with unknown scheme: " << url.spec(); return; } + + // Navigation requests are not associated with any particular + // |network::ResourceRequest::request_initiator| origin - using an opaque + // origin instead. + url::Origin navigation_request_initiator = url::Origin(); + FrameTreeNode* frame_tree_node = FrameTreeNode::GloballyFindByID(frame_tree_node_id); auto* frame = frame_tree_node->current_frame_host(); GetContentClient()->browser()->WillCreateURLLoaderFactory( frame->GetSiteInstance()->GetBrowserContext(), frame, - true /* is_navigation */, url, &factory, + true /* is_navigation */, navigation_request_initiator, &factory, nullptr /* bypass_redirect_checks */); it->second->Clone(std::move(factory)); }
diff --git a/content/browser/media/cdm_storage_impl.cc b/content/browser/media/cdm_storage_impl.cc index dd19f2bd..fa67789 100644 --- a/content/browser/media/cdm_storage_impl.cc +++ b/content/browser/media/cdm_storage_impl.cc
@@ -36,7 +36,7 @@ const std::string& cdm_file_system_id, media::mojom::CdmStorageRequest request) { DVLOG(3) << __func__; - DCHECK(!render_frame_host->GetLastCommittedOrigin().unique()) + DCHECK(!render_frame_host->GetLastCommittedOrigin().opaque()) << "Invalid origin specified for CdmStorageImpl::Create"; // Take a reference to the FileSystemContext.
diff --git a/content/browser/media/webaudio/OWNERS b/content/browser/media/webaudio/OWNERS new file mode 100644 index 0000000..5f297b8b --- /dev/null +++ b/content/browser/media/webaudio/OWNERS
@@ -0,0 +1,4 @@ +hongchan@chromium.org +rtoy@chromium.org + +# COMPONENT: Blink>WebAudio \ No newline at end of file
diff --git a/content/browser/media/webaudio/audio_context_manager_impl.cc b/content/browser/media/webaudio/audio_context_manager_impl.cc index 6660e4bd..889ccb0 100644 --- a/content/browser/media/webaudio/audio_context_manager_impl.cc +++ b/content/browser/media/webaudio/audio_context_manager_impl.cc
@@ -15,14 +15,18 @@ void AudioContextManagerImpl::Create( RenderFrameHost* render_frame_host, blink::mojom::AudioContextManagerRequest request) { - mojo::MakeStrongBinding( - std::make_unique<AudioContextManagerImpl>(render_frame_host), - std::move(request)); + DCHECK(render_frame_host); + + // The object is bound to the lifetime of |render_frame_host| and the mojo + // connection. See FrameServiceBase for details. + new AudioContextManagerImpl(render_frame_host, std::move(request)); } AudioContextManagerImpl::AudioContextManagerImpl( - RenderFrameHost* render_frame_host) - : render_frame_host_impl_( + RenderFrameHost* render_frame_host, + blink::mojom::AudioContextManagerRequest request) + : FrameServiceBase(render_frame_host, std::move(request)), + render_frame_host_impl_( static_cast<RenderFrameHostImpl*>(render_frame_host)) { DCHECK(render_frame_host); }
diff --git a/content/browser/media/webaudio/audio_context_manager_impl.h b/content/browser/media/webaudio/audio_context_manager_impl.h index cc03296f..06d1c6b4 100644 --- a/content/browser/media/webaudio/audio_context_manager_impl.h +++ b/content/browser/media/webaudio/audio_context_manager_impl.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_MEDIA_WEBAUDIO_AUDIO_CONTEXT_MANAGER_IMPL_H_ #include "content/common/content_export.h" +#include "content/public/browser/frame_service_base.h" #include "mojo/public/cpp/bindings/binding.h" #include "third_party/blink/public/mojom/webaudio/audio_context_manager.mojom.h" @@ -17,10 +18,12 @@ // Implements the mojo interface between WebAudio and the browser so that // WebAudio can report when audible sounds from an AudioContext starts and // stops. -class CONTENT_EXPORT AudioContextManagerImpl - : public blink::mojom::AudioContextManager { +class CONTENT_EXPORT AudioContextManagerImpl final + : public content::FrameServiceBase<blink::mojom::AudioContextManager> { public: - explicit AudioContextManagerImpl(RenderFrameHost* render_frame_host); + explicit AudioContextManagerImpl( + RenderFrameHost* render_frame_host, + blink::mojom::AudioContextManagerRequest request); ~AudioContextManagerImpl() override; static void Create(RenderFrameHost* render_frame_host,
diff --git a/content/browser/notifications/notification_id_generator.cc b/content/browser/notifications/notification_id_generator.cc index 99fa0034..9ab34c9 100644 --- a/content/browser/notifications/notification_id_generator.cc +++ b/content/browser/notifications/notification_id_generator.cc
@@ -64,7 +64,7 @@ std::string NotificationIdGenerator::GenerateForNonPersistentNotification( const url::Origin& origin, const std::string& token) const { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); DCHECK(!token.empty()); return base::StringPrintf( "%c%c%s%c%s", kNonPersistentNotificationPrefix, kNotificationTagSeparator,
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc index 96cda1d..55d9db7e 100644 --- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc +++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
@@ -70,16 +70,6 @@ return window_->GetBounds().size(); } -void PictureInPictureWindowControllerImpl::ClickCustomControl( - const std::string& control_id) { - DCHECK(window_); - - media_player_id_->render_frame_host->Send( - new MediaPlayerDelegateMsg_ClickPictureInPictureControl( - media_player_id_->render_frame_host->GetRoutingID(), - media_player_id_->delegate_id, control_id)); -} - void PictureInPictureWindowControllerImpl::SetPictureInPictureCustomControls( const std::vector<blink::PictureInPictureControlInfo>& controls) { DCHECK(window_); @@ -186,6 +176,16 @@ return true; } +void PictureInPictureWindowControllerImpl::CustomControlPressed( + const std::string& control_id) { + DCHECK(window_); + + media_player_id_->render_frame_host->Send( + new MediaPlayerDelegateMsg_ClickPictureInPictureControl( + media_player_id_->render_frame_host->GetRoutingID(), + media_player_id_->delegate_id, control_id)); +} + void PictureInPictureWindowControllerImpl::SetAlwaysHidePlayPauseButton( bool is_visible) { if (!window_)
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h index 9677135..330fbec 100644 --- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h +++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
@@ -37,8 +37,6 @@ CONTENT_EXPORT gfx::Size Show() override; CONTENT_EXPORT void Close(bool should_pause_video) override; CONTENT_EXPORT void OnWindowDestroyed() override; - CONTENT_EXPORT void ClickCustomControl( - const std::string& control_id) override; CONTENT_EXPORT void SetPictureInPictureCustomControls( const std::vector<blink::PictureInPictureControlInfo>& controls) override; CONTENT_EXPORT void EmbedSurface(const viz::SurfaceId& surface_id, @@ -48,6 +46,8 @@ CONTENT_EXPORT bool IsPlayerActive() override; CONTENT_EXPORT WebContents* GetInitiatorWebContents() override; CONTENT_EXPORT bool TogglePlayPause() override; + CONTENT_EXPORT void CustomControlPressed( + const std::string& control_id) override; CONTENT_EXPORT void UpdatePlaybackState(bool is_playing, bool reached_end_of_stream) override; CONTENT_EXPORT void SetAlwaysHidePlayPauseButton(bool is_visible) override;
diff --git a/content/browser/quota_dispatcher_host.cc b/content/browser/quota_dispatcher_host.cc index c6f72bd8..dee8d4e 100644 --- a/content/browser/quota_dispatcher_host.cc +++ b/content/browser/quota_dispatcher_host.cc
@@ -117,7 +117,7 @@ return; } - if (origin.unique()) { + if (origin.opaque()) { mojo::ReportBadMessage("Unique origins may not request storage quota."); return; }
diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc index d9fa155..3bc520f 100644 --- a/content/browser/renderer_host/code_cache_host_impl.cc +++ b/content/browser/renderer_host/code_cache_host_impl.cc
@@ -49,7 +49,7 @@ // Don't cache the code corresponding to unique origins. The same-origin // checks should always fail for unique origins but the serialized value of // unique origins does not ensure this. - if (origin.unique()) + if (origin.opaque()) return base::nullopt; return origin; @@ -85,6 +85,7 @@ } void CodeCacheHostImpl::DidGenerateCacheableMetadata( + blink::mojom::CodeCacheType cache_type, const GURL& url, base::Time expected_response_time, const std::vector<uint8_t>& data) { @@ -96,13 +97,20 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) { - base::PostTaskWithTraits( - FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI, - render_process_id_, url, expected_response_time, data)); + // Only store Javascript (not WebAssembly) code in the single-keyed cache. + if (cache_type == blink::mojom::CodeCacheType::kJavascript) { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&CodeCacheHostImpl::DidGenerateCacheableMetadataOnUI, + render_process_id_, url, expected_response_time, + data)); + } else { + mojo::ReportBadMessage("Single-keyed code cache is Javascript only."); + return; + } } else { - if (!generated_code_cache_context_ || - !generated_code_cache_context_->generated_code_cache()) + GeneratedCodeCache* code_cache = GetCodeCache(cache_type); + if (!code_cache) return; base::Optional<url::Origin> requesting_origin = @@ -110,15 +118,16 @@ if (!requesting_origin) return; - generated_code_cache_context_->generated_code_cache()->WriteData( - url, *requesting_origin, expected_response_time, data); + code_cache->WriteData(url, *requesting_origin, expected_response_time, + data); } } -void CodeCacheHostImpl::FetchCachedCode(const GURL& url, +void CodeCacheHostImpl::FetchCachedCode(blink::mojom::CodeCacheType cache_type, + const GURL& url, FetchCachedCodeCallback callback) { - if (!generated_code_cache_context_ || - !generated_code_cache_context_->generated_code_cache()) { + GeneratedCodeCache* code_cache = GetCodeCache(cache_type); + if (!code_cache) { std::move(callback).Run(base::Time(), std::vector<uint8_t>()); return; } @@ -133,13 +142,14 @@ auto read_callback = base::BindRepeating( &CodeCacheHostImpl::OnReceiveCachedCode, weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)); - generated_code_cache_context_->generated_code_cache()->FetchEntry( - url, *requesting_origin, read_callback); + code_cache->FetchEntry(url, *requesting_origin, read_callback); } -void CodeCacheHostImpl::ClearCodeCacheEntry(const GURL& url) { - if (!generated_code_cache_context_ || - !generated_code_cache_context_->generated_code_cache()) +void CodeCacheHostImpl::ClearCodeCacheEntry( + blink::mojom::CodeCacheType cache_type, + const GURL& url) { + GeneratedCodeCache* code_cache = GetCodeCache(cache_type); + if (!code_cache) return; base::Optional<url::Origin> requesting_origin = @@ -147,8 +157,7 @@ if (!requesting_origin) return; - generated_code_cache_context_->generated_code_cache()->DeleteEntry( - url, *requesting_origin); + code_cache->DeleteEntry(url, *requesting_origin); } void CodeCacheHostImpl::DidGenerateCacheableMetadataInCacheStorage( @@ -170,6 +179,18 @@ expected_response_time, buf, data.size())); } +GeneratedCodeCache* CodeCacheHostImpl::GetCodeCache( + blink::mojom::CodeCacheType cache_type) { + if (!generated_code_cache_context_) + return nullptr; + + if (cache_type == blink::mojom::CodeCacheType::kJavascript) + return generated_code_cache_context_->generated_js_code_cache(); + + DCHECK_EQ(blink::mojom::CodeCacheType::kWebAssembly, cache_type); + return generated_code_cache_context_->generated_wasm_code_cache(); +} + void CodeCacheHostImpl::OnReceiveCachedCode(FetchCachedCodeCallback callback, const base::Time& response_time, const std::vector<uint8_t>& data) {
diff --git a/content/browser/renderer_host/code_cache_host_impl.h b/content/browser/renderer_host/code_cache_host_impl.h index 18e9b4ba..4e0844ada 100644 --- a/content/browser/renderer_host/code_cache_host_impl.h +++ b/content/browser/renderer_host/code_cache_host_impl.h
@@ -30,6 +30,7 @@ class CacheStorageContextImpl; class CacheStorageCacheHandle; +class GeneratedCodeCache; class GeneratedCodeCacheContext; // The implementation of a CodeCacheHost, which stores and retrieves resource @@ -53,11 +54,15 @@ private: // blink::mojom::CodeCacheHost implementation. - void DidGenerateCacheableMetadata(const GURL& url, + void DidGenerateCacheableMetadata(blink::mojom::CodeCacheType cache_type, + const GURL& url, base::Time expected_response_time, const std::vector<uint8_t>& data) override; - void FetchCachedCode(const GURL& url, FetchCachedCodeCallback) override; - void ClearCodeCacheEntry(const GURL& url) override; + void FetchCachedCode(blink::mojom::CodeCacheType cache_type, + const GURL& url, + FetchCachedCodeCallback) override; + void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type, + const GURL& url) override; void DidGenerateCacheableMetadataInCacheStorage( const GURL& url, base::Time expected_response_time, @@ -66,6 +71,7 @@ const std::string& cache_storage_cache_name) override; // Helpers. + GeneratedCodeCache* GetCodeCache(blink::mojom::CodeCacheType cache_type); void OnReceiveCachedCode(FetchCachedCodeCallback callback, const base::Time& response_time, const std::vector<uint8_t>& data);
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h index 60a7e28..5aa7c74 100644 --- a/content/browser/renderer_host/input/input_router_impl.h +++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -110,9 +110,6 @@ bool OnMessageReceived(const IPC::Message& message) override; void OnHasTouchEventHandlersForTest(bool has_handlers); - int num_of_active_touches_for_test() { - return touch_action_filter_.num_of_active_touches_for_test(); - } private: friend class InputRouterImplTest;
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc index d295be3..a2140d65 100644 --- a/content/browser/renderer_host/input/input_router_impl_unittest.cc +++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -433,11 +433,11 @@ input_router_->TouchEventHandled( TouchEventWithLatencyInfo(touch_event_), InputEventAckSource::BROWSER, ui::LatencyInfo(), state, overscroll, touch_action); - EXPECT_EQ(input_router_->num_of_active_touches_for_test(), 1); + EXPECT_EQ(input_router_->touch_action_filter_.num_of_active_touches_, 1); ReleaseTouchPoint(0); input_router_->OnTouchEventAck(TouchEventWithLatencyInfo(touch_event_), InputEventAckSource::BROWSER, state); - EXPECT_EQ(input_router_->num_of_active_touches_for_test(), 0); + EXPECT_EQ(input_router_->touch_action_filter_.num_of_active_touches_, 0); } void OnTouchEventAckWithAckState(InputEventAckState ack_state) {
diff --git a/content/browser/renderer_host/input/touch_action_filter.h b/content/browser/renderer_host/input/touch_action_filter.h index 0d57857..0def2d9 100644 --- a/content/browser/renderer_host/input/touch_action_filter.h +++ b/content/browser/renderer_host/input/touch_action_filter.h
@@ -68,12 +68,12 @@ void IncreaseActiveTouches(); void DecreaseActiveTouches(); - int num_of_active_touches_for_test() { return num_of_active_touches_; } // Debugging only. void AppendToGestureSequenceForDebugging(const char* str); private: + friend class InputRouterImplTest; friend class MockRenderWidgetHost; friend class TouchActionFilterTest; friend class SitePerProcessBrowserTouchActionTest;
diff --git a/content/browser/renderer_host/web_database_host_impl.cc b/content/browser/renderer_host/web_database_host_impl.cc index 955ad95..65af343 100644 --- a/content/browser/renderer_host/web_database_host_impl.cc +++ b/content/browser/renderer_host/web_database_host_impl.cc
@@ -376,7 +376,7 @@ } bool WebDatabaseHostImpl::ValidateOrigin(const url::Origin& origin) { - if (origin.unique()) { + if (origin.opaque()) { mojo::ReportBadMessage("Invalid origin."); return false; }
diff --git a/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc b/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc index 3ba2c39c..f7baefc5 100644 --- a/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc +++ b/content/browser/service_worker/service_worker_content_settings_proxy_impl.cc
@@ -36,7 +36,7 @@ std::move(callback).Run(false); return; } - if (origin_.unique()) { + if (origin_.opaque()) { std::move(callback).Run(false); return; }
diff --git a/content/browser/service_worker/service_worker_object_host.cc b/content/browser/service_worker/service_worker_object_host.cc index cd4f6ea5..9989c75 100644 --- a/content/browser/service_worker/service_worker_object_host.cc +++ b/content/browser/service_worker/service_worker_object_host.cc
@@ -88,7 +88,7 @@ DCHECK(source_client_info && !source_client_info->client_uuid.empty()); (*event)->source_info_for_client = std::move(source_client_info); // Hide the client url if the client has a unique origin. - if ((*event)->source_origin.unique()) + if ((*event)->source_origin.opaque()) (*event)->source_info_for_client->url = GURL(); // Reset |registration->self_update_delay| iff postMessage is coming from a @@ -130,7 +130,7 @@ (*event)->source_info_for_service_worker = std::move(source_worker_info); // Hide the service worker url if the service worker has a unique origin. - if ((*event)->source_origin.unique()) + if ((*event)->source_origin.opaque()) (*event)->source_info_for_service_worker->url = GURL(); return true; }
diff --git a/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc b/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc index ba7feb6..3626969ae 100644 --- a/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc +++ b/content/browser/shared_worker/shared_worker_content_settings_proxy_impl.cc
@@ -26,7 +26,7 @@ void SharedWorkerContentSettingsProxyImpl::AllowIndexedDB( const base::string16& name, AllowIndexedDBCallback callback) { - if (!origin_.unique()) { + if (!origin_.opaque()) { owner_->AllowIndexedDB(origin_.GetURL(), name, std::move(callback)); } else { std::move(callback).Run(false); @@ -35,7 +35,7 @@ void SharedWorkerContentSettingsProxyImpl::RequestFileSystemAccessSync( RequestFileSystemAccessSyncCallback callback) { - if (!origin_.unique()) { + if (!origin_.opaque()) { owner_->AllowFileSystem(origin_.GetURL(), std::move(callback)); } else { std::move(callback).Run(false);
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index 1d1da537..f09529d 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -491,7 +491,7 @@ // If there is no host but there is a scheme, return the scheme. // This is useful for cases like file URLs. - if (!origin.unique()) { + if (!origin.opaque()) { // Prefer to use the scheme of |origin| rather than |url|, to correctly // cover blob:file: and filesystem:file: URIs (see also // https://crbug.com/697111).
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index a4af347..c5e4d7d 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -8694,9 +8694,9 @@ EXPECT_TRUE(root->child_at(0) ->current_frame_host() ->GetLastCommittedOrigin() - .unique()); + .opaque()); // And verify that the origin in the replication state is also opaque. - EXPECT_TRUE(root->child_at(0)->current_origin().unique()); + EXPECT_TRUE(root->child_at(0)->current_origin().opaque()); // Ask the sandboxed iframe to report the enabled state of the geolocation // feature. If the declared policy was correctly flagged as referring to the @@ -8721,9 +8721,9 @@ EXPECT_TRUE(root->child_at(0) ->current_frame_host() ->GetLastCommittedOrigin() - .unique()); + .opaque()); // And verify that the origin in the replication state is also opaque. - EXPECT_TRUE(root->child_at(0)->current_origin().unique()); + EXPECT_TRUE(root->child_at(0)->current_origin().opaque()); EXPECT_TRUE(ExecuteScriptAndExtractBool( root->child_at(0), @@ -8755,9 +8755,9 @@ EXPECT_TRUE(root->child_at(0) ->current_frame_host() ->GetLastCommittedOrigin() - .unique()); + .opaque()); // And verify that the origin in the replication state is also opaque. - EXPECT_TRUE(root->child_at(0)->current_origin().unique()); + EXPECT_TRUE(root->child_at(0)->current_origin().opaque()); // Verify that geolocation is enabled in the document. bool success = false; @@ -8777,9 +8777,9 @@ EXPECT_FALSE(root->child_at(0) ->current_frame_host() ->GetLastCommittedOrigin() - .unique()); + .opaque()); // Verify that the origin in the replication state is also no longer opaque. - EXPECT_FALSE(root->child_at(0)->current_origin().unique()); + EXPECT_FALSE(root->child_at(0)->current_origin().opaque()); // Verify that the new document does not have geolocation enabled. EXPECT_TRUE(ExecuteScriptAndExtractBool( @@ -9004,7 +9004,7 @@ const blink::ParsedFeaturePolicy initial_effective_policy = root->child_at(2)->effective_frame_policy().container_policy; EXPECT_EQ(1UL, initial_effective_policy[0].origins.size()); - EXPECT_FALSE(initial_effective_policy[0].origins[0].unique()); + EXPECT_FALSE(initial_effective_policy[0].origins[0].opaque()); // Set the "sandbox" attribute; pending policy should update, and should now // be flagged as matching the opaque origin of the frame (without containing @@ -9017,7 +9017,7 @@ const blink::ParsedFeaturePolicy updated_pending_policy = root->child_at(2)->pending_frame_policy().container_policy; EXPECT_EQ(1UL, updated_effective_policy[0].origins.size()); - EXPECT_FALSE(updated_effective_policy[0].origins[0].unique()); + EXPECT_FALSE(updated_effective_policy[0].origins[0].opaque()); EXPECT_TRUE(updated_pending_policy[0].matches_opaque_src); EXPECT_EQ(0UL, updated_pending_policy[0].origins.size());
diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc index 1f909be..e898a43 100644 --- a/content/browser/speech/speech_recognition_dispatcher_host.cc +++ b/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -67,7 +67,7 @@ // Check that the origin specified by the renderer process is one // that it is allowed to access. - if (!params->origin.unique() && + if (!params->origin.opaque() && !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( render_process_id_, params->origin.GetURL())) { LOG(ERROR) << "SRDH::OnStartRequest, disallowed origin: "
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 274dc206..ab06c5eb0 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -1344,7 +1344,7 @@ if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { GetContentClient()->browser()->WillCreateURLLoaderFactory( - browser_context(), nullptr, false /* is_navigation */, GURL(), + browser_context(), nullptr, false /* is_navigation */, url::Origin(), &request, nullptr /* bypass_redirect_checks */); } GetNetworkContext()->CreateURLLoaderFactory(std::move(request),
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index cfecba3..3f2be88 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -289,15 +289,15 @@ entry_exists_ = false; GeneratedCodeCache::ReadDataCallback callback = base::BindRepeating( &RemoveCodeCacheTester::FetchEntryCallback, base::Unretained(this)); - code_cache_context_->generated_code_cache()->FetchEntry(url, origin, - callback); + code_cache_context_->generated_js_code_cache()->FetchEntry(url, origin, + callback); await_completion_.BlockUntilNotified(); return entry_exists_; } void AddEntry(GURL url, url::Origin origin, const std::string& data) { std::vector<uint8_t> data_vector(data.begin(), data.end()); - code_cache_context_->generated_code_cache()->WriteData( + code_cache_context_->generated_js_code_cache()->WriteData( url, origin, base::Time::Now(), data_vector); base::RunLoop().RunUntilIdle(); }
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc index f91723a9..5170b50e 100644 --- a/content/browser/webauth/authenticator_impl.cc +++ b/content/browser/webauth/authenticator_impl.cc
@@ -97,7 +97,7 @@ // Reference https://url.spec.whatwg.org/#valid-domain-string and // https://html.spec.whatwg.org/multipage/origin.html#concept-origin-effective-domain. bool HasValidEffectiveDomain(url::Origin caller_origin) { - return !caller_origin.unique() && + return !caller_origin.opaque() && !url::HostIsIPAddress(caller_origin.host()) && content::IsOriginSecure(caller_origin.GetURL()) && // Additionally, the scheme is required to be HTTP(S). Other schemes
diff --git a/content/child/blink_platform_impl_unittest.cc b/content/child/blink_platform_impl_unittest.cc index 0ac6dac..50e3c86 100644 --- a/content/child/blink_platform_impl_unittest.cc +++ b/content/child/blink_platform_impl_unittest.cc
@@ -117,7 +117,7 @@ EXPECT_TRUE(web_origin.IsUnique()); url::Origin url_origin = web_origin; - EXPECT_TRUE(url_origin.unique()); + EXPECT_TRUE(url_origin.opaque()); web_origin = url::Origin::Create(GURL("")); EXPECT_TRUE(web_origin.IsUnique());
diff --git a/content/child/child_process.cc b/content/child/child_process.cc index 7b55e6f2..4313421 100644 --- a/content/child/child_process.cc +++ b/content/child/child_process.cc
@@ -21,7 +21,7 @@ namespace { base::LazyInstance<base::ThreadLocalPointer<ChildProcess>>::DestructorAtExit - g_lazy_tls = LAZY_INSTANCE_INITIALIZER; + g_lazy_child_process_tls = LAZY_INSTANCE_INITIALIZER; } ChildProcess::ChildProcess( @@ -32,8 +32,8 @@ shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED), io_thread_("Chrome_ChildIOThread") { - DCHECK(!g_lazy_tls.Pointer()->Get()); - g_lazy_tls.Pointer()->Set(this); + DCHECK(!g_lazy_child_process_tls.Pointer()->Get()); + g_lazy_child_process_tls.Pointer()->Set(this); // Initialize TaskScheduler if not already done. A TaskScheduler may already // exist when ChildProcess is instantiated in the browser process or in a @@ -63,7 +63,7 @@ } ChildProcess::~ChildProcess() { - DCHECK(g_lazy_tls.Pointer()->Get() == this); + DCHECK(g_lazy_child_process_tls.Pointer()->Get() == this); // Signal this event before destroying the child process. That way all // background threads can cleanup. @@ -82,7 +82,7 @@ } } - g_lazy_tls.Pointer()->Set(nullptr); + g_lazy_child_process_tls.Pointer()->Set(nullptr); io_thread_.Stop(); if (initialized_task_scheduler_) { @@ -117,7 +117,7 @@ } ChildProcess* ChildProcess::current() { - return g_lazy_tls.Pointer()->Get(); + return g_lazy_child_process_tls.Pointer()->Get(); } base::WaitableEvent* ChildProcess::GetShutDownEvent() {
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index 08c34e44..85a0d8f9 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -84,7 +84,7 @@ const int kConnectionTimeoutS = 15; base::LazyInstance<base::ThreadLocalPointer<ChildThreadImpl>>::DestructorAtExit - g_lazy_tls = LAZY_INSTANCE_INITIALIZER; + g_lazy_child_thread_impl_tls = LAZY_INSTANCE_INITIALIZER; // This isn't needed on Windows because there the sandbox's job object // terminates child processes automatically. For unsandboxed processes (i.e. @@ -402,7 +402,7 @@ void ChildThreadImpl::Init(const Options& options) { TRACE_EVENT0("startup", "ChildThreadImpl::Init"); - g_lazy_tls.Pointer()->Set(this); + g_lazy_child_thread_impl_tls.Pointer()->Set(this); on_channel_error_called_ = false; main_thread_runner_ = base::ThreadTaskRunnerHandle::Get(); #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED) @@ -605,7 +605,7 @@ // automatically. We used to watch the object handle on Windows to do this, // but it wasn't possible to do so on POSIX. channel_->ClearIPCTaskRunner(); - g_lazy_tls.Pointer()->Set(nullptr); + g_lazy_child_thread_impl_tls.Pointer()->Set(nullptr); } void ChildThreadImpl::Shutdown() {} @@ -771,7 +771,7 @@ } ChildThreadImpl* ChildThreadImpl::current() { - return g_lazy_tls.Pointer()->Get(); + return g_lazy_child_thread_impl_tls.Pointer()->Get(); } #if defined(OS_ANDROID)
diff --git a/content/common/content_security_policy/csp_context.cc b/content/common/content_security_policy/csp_context.cc index 94b0a96..5e52b72 100644 --- a/content/common/content_security_policy/csp_context.cc +++ b/content/common/content_security_policy/csp_context.cc
@@ -80,7 +80,7 @@ // When the origin is unique, no URL should match with 'self'. That's why // |self_source_| stays undefined here. - if (origin.unique()) + if (origin.opaque()) return; if (origin.scheme() == url::kFileScheme) {
diff --git a/content/common/origin_util.cc b/content/common/origin_util.cc index 6cac476b..2b15f617 100644 --- a/content/common/origin_util.cc +++ b/content/common/origin_util.cc
@@ -20,7 +20,7 @@ // SecurityOrigin::create might return unique origins for URLs whose schemes are // included in SchemeRegistry::shouldTreatURLSchemeAsNoAccess. bool IsOriginUnique(const url::Origin& origin) { - return origin.unique() || + return origin.opaque() || base::ContainsValue(url::GetNoAccessSchemes(), origin.scheme()); }
diff --git a/content/public/browser/background_fetch_response.h b/content/public/browser/background_fetch_response.h index 0577d963..be3f6c9 100644 --- a/content/public/browser/background_fetch_response.h +++ b/content/public/browser/background_fetch_response.h
@@ -52,8 +52,9 @@ // Used when the download was cancelled by the user. CANCELLED, - // Used when the failure reason is unknown. - UNKNOWN, + // Catch-all error. Used when the failure reason is unknown or not exposed + // to the developer. + FETCH_ERROR, }; // Constructor for failed downloads.
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 76796f9..9380603 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -382,8 +382,9 @@ net::ClientCertIdentityList client_certs, std::unique_ptr<ClientCertificateDelegate> delegate) {} -net::URLRequestContext* ContentBrowserClient::OverrideRequestContextForURL( - const GURL& url, ResourceContext* context) { +net::CookieStore* ContentBrowserClient::OverrideCookieStoreForURL( + const GURL& url, + ResourceContext* context) { return nullptr; } @@ -671,7 +672,7 @@ BrowserContext* browser_context, RenderFrameHost* frame, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request, bool* bypass_redirect_checks) { return false;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 59cfc78..1342f7010 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -110,12 +110,12 @@ class ClientCertIdentity; using ClientCertIdentityList = std::vector<std::unique_ptr<ClientCertIdentity>>; class ClientCertStore; +class CookieStore; class HttpRequestHeaders; class NetLog; class SSLCertRequestInfo; class SSLInfo; class URLRequest; -class URLRequestContext; } // namespace net namespace network { @@ -611,12 +611,11 @@ // "1812:e, 00001800-0000-1000-8000-00805f9b34fb:w, ignored:1, alsoignored." virtual std::string GetWebBluetoothBlocklist(); - // Allow the embedder to override the request context based on the URL for - // certain operations, like cookie access. Returns nullptr to indicate the - // regular request context should be used. + // Allow the embedder to override the cookie store for a particular URL. + // Returns nullptr to indicate the regular cookie store should be used. // This is called on the IO thread. - virtual net::URLRequestContext* OverrideRequestContextForURL( - const GURL& url, ResourceContext* context); + virtual net::CookieStore* OverrideCookieStoreForURL(const GURL& url, + ResourceContext* context); // Allows the embedder to override the LocationProvider implementation. // Return nullptr to indicate the default one for the platform should be @@ -1128,10 +1127,16 @@ // BrowserContext. // // |is_navigation| is true when it's a request used for navigation. - // |url| is set when it's a request for navigations or for a renderer fetching - // subresources. It's not set in the 3rd case (browser-initiated - // non-navigation requests) because in that case the factory is cached and it - // can be used for multiple URLs. + // + // |request_initiator| indicates which origin will be the initiator of + // requests that will use the URLLoaderFactory (see also + // |network::ResourceRequest::requests|). |request_initiator| is set when + // it's a request for a renderer fetching subresources. It's not set when + // creating a factory for navigation requests, because navigation requests are + // made on behalf of the browser, rather than on behalf of any particular + // origin. It's not set in the case of browser-initiated, non-navigation + // requests, because in that case the factory is cached and it can be used for + // multiple URLs. // // |*factory_request| is always valid upon entry and MUST be valid upon // return. The embedder may swap out the value of |*factory_request| for its @@ -1152,7 +1157,7 @@ BrowserContext* browser_context, RenderFrameHost* frame, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request, bool* bypass_redirect_checks);
diff --git a/content/public/browser/picture_in_picture_window_controller.h b/content/public/browser/picture_in_picture_window_controller.h index 7eb691b..63afe6d8 100644 --- a/content/public/browser/picture_in_picture_window_controller.h +++ b/content/public/browser/picture_in_picture_window_controller.h
@@ -51,7 +51,6 @@ // window was requested to be closed and destroyed by the system. virtual void OnWindowDestroyed() = 0; - virtual void ClickCustomControl(const std::string& control_id) = 0; virtual void SetPictureInPictureCustomControls( const std::vector<blink::PictureInPictureControlInfo>&) = 0; virtual void EmbedSurface(const viz::SurfaceId& surface_id, @@ -69,6 +68,9 @@ // call. virtual bool TogglePlayPause() = 0; + // Called when the user interacts with a custom control. + virtual void CustomControlPressed(const std::string& control_id) = 0; + protected: // Use PictureInPictureWindowController::GetOrCreateForWebContents() to // create an instance.
diff --git a/content/public/browser/site_isolation_policy.cc b/content/public/browser/site_isolation_policy.cc index dfa4486..ccadc0cf 100644 --- a/content/public/browser/site_isolation_policy.cc +++ b/content/public/browser/site_isolation_policy.cc
@@ -173,7 +173,7 @@ origins.reserve(origin_strings.size()); for (const base::StringPiece& origin_string : origin_strings) { url::Origin origin = url::Origin::Create(GURL(origin_string)); - if (!origin.unique()) + if (!origin.opaque()) origins.push_back(origin); } return origins;
diff --git a/content/renderer/loader/code_cache_loader_impl.cc b/content/renderer/loader/code_cache_loader_impl.cc index 0fbbeac..edc4e117 100644 --- a/content/renderer/loader/code_cache_loader_impl.cc +++ b/content/renderer/loader/code_cache_loader_impl.cc
@@ -45,10 +45,11 @@ // It is Ok to pass |fetch_code_cache_event| with base::Unretained. Since // this thread is stalled, the fetch_code_cache_event will be kept alive. task_runner->PostTask( - FROM_HERE, - base::BindOnce(&CodeCacheLoaderImpl::FetchFromCodeCacheImpl, - weak_ptr_factory_.GetWeakPtr(), url, std::move(callback), - base::Unretained(&fetch_code_cache_event))); + FROM_HERE, base::BindOnce(&CodeCacheLoaderImpl::FetchFromCodeCacheImpl, + weak_ptr_factory_.GetWeakPtr(), + blink::mojom::CodeCacheType::kJavascript, url, + std::move(callback), + base::Unretained(&fetch_code_cache_event))); // Wait for the fetch from code cache to finish. fetch_code_cache_event.Wait(); @@ -58,12 +59,15 @@ *data_out = data_for_sync_load_; } -void CodeCacheLoaderImpl::FetchFromCodeCache(const GURL& url, - FetchCodeCacheCallback callback) { - FetchFromCodeCacheImpl(url, std::move(callback), nullptr); +void CodeCacheLoaderImpl::FetchFromCodeCache( + blink::mojom::CodeCacheType cache_type, + const GURL& url, + FetchCodeCacheCallback callback) { + FetchFromCodeCacheImpl(cache_type, url, std::move(callback), nullptr); } void CodeCacheLoaderImpl::FetchFromCodeCacheImpl( + blink::mojom::CodeCacheType cache_type, const GURL& gurl, FetchCodeCacheCallback callback, base::WaitableEvent* fetch_event) { @@ -71,9 +75,10 @@ // fetch_event, because the thread is stalled and it will keep the fetch_event // alive. blink::Platform::Current()->FetchCachedCode( - gurl, base::BindOnce(&CodeCacheLoaderImpl::OnReceiveCachedCode, - weak_ptr_factory_.GetWeakPtr(), std::move(callback), - fetch_event)); + cache_type, gurl, + base::BindOnce(&CodeCacheLoaderImpl::OnReceiveCachedCode, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + fetch_event)); } void CodeCacheLoaderImpl::OnReceiveCachedCode(
diff --git a/content/renderer/loader/code_cache_loader_impl.h b/content/renderer/loader/code_cache_loader_impl.h index 99c9d15..fc4084b6 100644 --- a/content/renderer/loader/code_cache_loader_impl.h +++ b/content/renderer/loader/code_cache_loader_impl.h
@@ -22,16 +22,18 @@ // Fetches code cache corresponding to |url| and returns response in // |response_time_out| and |data_out|. |response_time_out| and |data_out| - // cannot be nullptrs. + // cannot be nullptrs. This only fetches from the Javascript cache. void FetchFromCodeCacheSynchronously(const GURL& url, base::Time* response_time_out, std::vector<uint8_t>* data_out) override; - void FetchFromCodeCache(const GURL& url, + void FetchFromCodeCache(blink::mojom::CodeCacheType cache_type, + const GURL& url, FetchCodeCacheCallback callback) override; private: - void FetchFromCodeCacheImpl(const GURL& url, + void FetchFromCodeCacheImpl(blink::mojom::CodeCacheType cache_type, + const GURL& url, FetchCodeCacheCallback callback, base::WaitableEvent* event);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 917eea9..fcafcc9 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -5661,7 +5661,7 @@ // Standard URLs must match the reported origin, when it is not unique. // This check is very similar to RenderFrameHostImpl::CanCommitOrigin, but // adapted to the renderer process side. - if (!params->origin.unique() && params->url.IsStandard() && + if (!params->origin.opaque() && params->url.IsStandard() && render_view_->GetWebkitPreferences().web_security_enabled) { // Exclude file: URLs when settings allow them access any origin. if (params->origin.scheme() != url::kFileScheme ||
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 807e75b..7358f5e 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -451,26 +451,37 @@ return render_thread->GetUserAgent(); } -void RendererBlinkPlatformImpl::CacheMetadata(const blink::WebURL& url, - base::Time response_time, - const char* data, - size_t size) { - // Let the browser know we generated cacheable metadata for this resource. The - // browser may cache it and return it on subsequent responses to speed - // the processing of this resource. - std::vector<uint8_t> copy(data, data + size); - GetCodeCacheHost().DidGenerateCacheableMetadata(url, response_time, copy); +void RendererBlinkPlatformImpl::CacheMetadata( + blink::mojom::CodeCacheType cache_type, + const blink::WebURL& url, + base::Time response_time, + const char* data, + size_t size) { + // Only cache WebAssembly if we have isolated code caches. + // TODO(bbudge) Remove this check when isolated code caches are on by default. + if (cache_type == blink::mojom::CodeCacheType::kJavascript || + base::FeatureList::IsEnabled(features::kIsolatedCodeCache)) { + // Let the browser know we generated cacheable metadata for this resource. + // The browser may cache it and return it on subsequent responses to speed + // the processing of this resource. + std::vector<uint8_t> copy(data, data + size); + GetCodeCacheHost().DidGenerateCacheableMetadata(cache_type, url, + response_time, copy); + } } void RendererBlinkPlatformImpl::FetchCachedCode( + blink::mojom::CodeCacheType cache_type, const GURL& url, base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)> callback) { - GetCodeCacheHost().FetchCachedCode(url, std::move(callback)); + GetCodeCacheHost().FetchCachedCode(cache_type, url, std::move(callback)); } -void RendererBlinkPlatformImpl::ClearCodeCacheEntry(const GURL& url) { - GetCodeCacheHost().ClearCodeCacheEntry(url); +void RendererBlinkPlatformImpl::ClearCodeCacheEntry( + blink::mojom::CodeCacheType cache_type, + const GURL& url) { + GetCodeCacheHost().ClearCodeCacheEntry(cache_type, url); } void RendererBlinkPlatformImpl::CacheMetadataInCacheStorage(
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index b74b59a..81e542c 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -83,15 +83,18 @@ bool IsLinkVisited(unsigned long long linkHash) override; blink::WebPrescientNetworking* PrescientNetworking() override; blink::WebString UserAgent() override; - void CacheMetadata(const blink::WebURL&, + void CacheMetadata(blink::mojom::CodeCacheType cache_type, + const blink::WebURL&, base::Time, const char*, size_t) override; void FetchCachedCode( + blink::mojom::CodeCacheType cache_type, const GURL&, base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>) override; - void ClearCodeCacheEntry(const GURL&) override; + void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type, + const GURL&) override; void CacheMetadataInCacheStorage( const blink::WebURL&, base::Time,
diff --git a/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc b/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc index d7e7c85..3846d18 100644 --- a/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc +++ b/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc
@@ -103,7 +103,8 @@ content::BackgroundFetchResult::FailureReason::TIMEDOUT; break; case download::Client::FailureReason::UNKNOWN: - failure_reason = content::BackgroundFetchResult::FailureReason::UNKNOWN; + failure_reason = + content::BackgroundFetchResult::FailureReason::FETCH_ERROR; break; case download::Client::FailureReason::ABORTED: case download::Client::FailureReason::CANCELLED:
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_chooser_factory.cc b/content/shell/browser/layout_test/layout_test_bluetooth_chooser_factory.cc index dba3161d..b58c7a8 100644 --- a/content/shell/browser/layout_test/layout_test_bluetooth_chooser_factory.cc +++ b/content/shell/browser/layout_test/layout_test_bluetooth_chooser_factory.cc
@@ -100,7 +100,7 @@ RenderFrameHost* frame, const BluetoothChooser::EventHandler& event_handler) { const url::Origin origin = frame->GetLastCommittedOrigin(); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); std::string event = "chooser-opened("; event += origin.Serialize(); event += ")";
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 4f4d95d..ce998bc 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -172,7 +172,7 @@ url::Origin origin = url::Origin::Create(effective_site_url); - if (!origin.unique()) { + if (!origin.opaque()) { // Schemes like blob or filesystem, which have an embedded origin, should // already have been canonicalized to the origin site. CHECK_EQ(origin.scheme(), effective_site_url.scheme())
diff --git a/device/bluetooth/bluez/bluetooth_socket_bluez.cc b/device/bluetooth/bluez/bluetooth_socket_bluez.cc index 3f97c631..75fe8b1d 100644 --- a/device/bluetooth/bluez/bluetooth_socket_bluez.cc +++ b/device/bluetooth/bluez/bluetooth_socket_bluez.cc
@@ -21,7 +21,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/task_runner_util.h" -#include "base/threading/thread_restrictions.h" +#include "base/threading/scoped_blocking_call.h" #include "base/threading/thread_task_runner_handle.h" #include "dbus/bus.h" #include "dbus/object_path.h" @@ -450,7 +450,7 @@ const bluez::BluetoothProfileServiceProvider::Delegate::Options& options, const ConfirmationCallback& callback) { DCHECK(socket_thread()->task_runner()->RunsTasksInCurrentSequence()); - base::AssertBlockingAllowed(); + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); if (!fd.is_valid()) { LOG(WARNING) << uuid_.canonical_value() << " :" << fd.get()
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/extensions/browser/api/declarative_net_request/ruleset_manager.cc index 70881f3..f650956 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_manager.cc +++ b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
@@ -96,7 +96,7 @@ // Returns whether the request to |url| is third party to its |document_origin|. // TODO(crbug.com/696822): Look into caching this. bool IsThirdPartyRequest(const GURL& url, const url::Origin& document_origin) { - if (document_origin.unique()) + if (document_origin.opaque()) return true; return !net::registry_controlled_domains::SameDomainOrHost(
diff --git a/extensions/browser/api/web_request/web_request_event_details.cc b/extensions/browser/api/web_request/web_request_event_details.cc index 54984b47..da0c7b7 100644 --- a/extensions/browser/api/web_request/web_request_event_details.cc +++ b/extensions/browser/api/web_request/web_request_event_details.cc
@@ -165,7 +165,7 @@ if (extension_info_map && initiator_) { int tab_id = -1; dict_.GetInteger(keys::kTabIdKey, &tab_id); - if (initiator_->unique() || + if (initiator_->opaque() || WebRequestPermissions::CanExtensionAccessInitiator( extension_info_map, extension_id, initiator_, tab_id, crosses_incognito)) {
diff --git a/extensions/browser/api/web_request/web_request_permissions.cc b/extensions/browser/api/web_request/web_request_permissions.cc index dfff113..f33db4d 100644 --- a/extensions/browser/api/web_request/web_request_permissions.cc +++ b/extensions/browser/api/web_request/web_request_permissions.cc
@@ -156,7 +156,7 @@ PermissionsData::PageAccess request_access = GetHostAccessForURL(*extension, url, tab_id); PermissionsData::PageAccess initiator_access = - initiator && !initiator->unique() + initiator && !initiator->opaque() ? GetHostAccessForURL(*extension, initiator->GetURL(), tab_id) : PermissionsData::PageAccess::kAllowed; access = GetMinimumAccessType(request_access, initiator_access);
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 2c9921648..2f194bc4 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1343,6 +1343,7 @@ AUTOTESTPRIVATE_LAUNCHAPP = 1280, AUTOTESTPRIVATE_BOOTSTRAPMACHINELEARNINGSERVICE = 1281, AUTOTESTPRIVATE_RUNCROSTINIUNINSTALLER = 1282, + AUTOTESTPRIVATE_TAKESCREENSHOT = 1283, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc index 51759af..65c9e6a 100644 --- a/extensions/browser/extension_web_contents_observer.cc +++ b/extensions/browser/extension_web_contents_observer.cc
@@ -304,11 +304,10 @@ const url::Origin& origin(render_frame_host->GetLastCommittedOrigin()); // Without site isolation, this check is needed to eliminate non-extension // schemes. With site isolation, this is still needed to exclude sandboxed - // extension frames with a unique origin. + // extension frames with an opaque origin. const GURL site_url(render_frame_host->GetSiteInstance()->GetSiteURL()); - if (origin.unique() || - site_url != content::SiteInstance::GetSiteForURL(browser_context, - origin.GetURL())) + if (origin.opaque() || site_url != content::SiteInstance::GetSiteForURL( + browser_context, origin.GetURL())) return nullptr; }
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc index 39df64b..4bf301e 100644 --- a/extensions/shell/browser/shell_content_browser_client.cc +++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -288,7 +288,7 @@ content::BrowserContext* browser_context, content::RenderFrameHost* frame, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request, bool* bypass_redirect_checks) { auto* web_request_api =
diff --git a/extensions/shell/browser/shell_content_browser_client.h b/extensions/shell/browser/shell_content_browser_client.h index 7b419386..8a7b6205 100644 --- a/extensions/shell/browser/shell_content_browser_client.h +++ b/extensions/shell/browser/shell_content_browser_client.h
@@ -77,7 +77,7 @@ content::BrowserContext* browser_context, content::RenderFrameHost* frame_host, bool is_navigation, - const GURL& url, + const url::Origin& request_initiator, network::mojom::URLLoaderFactoryRequest* factory_request, bool* bypass_redirect_checks) override; bool HandleExternalProtocol(
diff --git a/google_apis/gaia/gaia_auth_fetcher.cc b/google_apis/gaia/gaia_auth_fetcher.cc index 1ae2806..8f226bd 100644 --- a/google_apis/gaia/gaia_auth_fetcher.cc +++ b/google_apis/gaia/gaia_auth_fetcher.cc
@@ -227,6 +227,11 @@ fetch_pending_ = false; } +bool GaiaAuthFetcher::IsMultiloginUrl(const GURL& url) { + return base::StartsWith(url.spec(), oauth_multilogin_gurl_.spec(), + base::CompareCase::SENSITIVE); +} + void GaiaAuthFetcher::CreateAndStartGaiaFetcher( const std::string& body, const std::string& headers, @@ -1116,8 +1121,7 @@ OnUberAuthTokenFetch(data, net_error, response_code); } else if (url == oauth_login_gurl_) { OnOAuthLoginFetched(data, net_error, response_code); - } else if (base::StartsWith(url.spec(), oauth_multilogin_gurl_.spec(), - base::CompareCase::SENSITIVE)) { + } else if (IsMultiloginUrl(url)) { OnOAuthMultiloginFetched(data, net_error, response_code); } else if (url == oauth2_revoke_gurl_) { OnOAuth2RevokeTokenFetched(data, net_error, response_code);
diff --git a/google_apis/gaia/gaia_auth_fetcher.h b/google_apis/gaia/gaia_auth_fetcher.h index 723ca2d..cb5662b 100644 --- a/google_apis/gaia/gaia_auth_fetcher.h +++ b/google_apis/gaia/gaia_auth_fetcher.h
@@ -196,6 +196,13 @@ void SetPendingFetch(bool pending_fetch); + // Needed to use XmlHTTPRequest for Multilogin requeston iOS even after + // iOS11 because WKWebView cannot read response body if content-disposition + // header is set. + // TODO(https://crbug.com/889471) Remove this once requests are done using + // NSUrlSession in iOS. + bool IsMultiloginUrl(const GURL& url); + private: // The format of the POST body for IssueAuthToken. static const char kIssueAuthTokenFormat[];
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index 2389884d..2734cfd 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -641,6 +641,13 @@ } builders { + name: "Android FYI 32 dEQP Vk Release (Pixel XL)" + mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" + } + + builders { name: "Android FYI 32 Vk Release (Nexus 5X)" mixins: "android-gpu-fyi-ci" } @@ -653,6 +660,13 @@ } builders { + name: "Android FYI 32 Vk Release (Pixel XL)" + mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" + } + + builders { name: "Android FYI 64 dEQP Vk Release (Nexus 5X)" mixins: "android-gpu-fyi-ci" } @@ -665,6 +679,13 @@ } builders { + name: "Android FYI 64 dEQP Vk Release (Pixel XL)" + mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" + } + + builders { name: "Android FYI 64 Vk Release (Nexus 5X)" mixins: "android-gpu-fyi-ci" } @@ -677,6 +698,13 @@ } builders { + name: "Android FYI 64 Vk Release (Pixel XL)" + mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" + } + + builders { name: "Android FYI dEQP Release (Nexus 5X)" mixins: "android-gpu-fyi-ci" } @@ -2854,6 +2882,22 @@ name: "gpu-manual-try-android-p-pixel-2-64-deqp" } builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-xl-32" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-xl-32-deqp" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-xl-64" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-xl-64-deqp" + } + builders { mixins: "android-try" name: "try-nougat-phone-tester" }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index 749eb4b..68f1c16 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -3633,6 +3633,16 @@ short_name: "N5X" } builders { + name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Pixel XL)" + category: "Android|vk|P32" + short_name: "PXL" + } + builders { + name: "buildbucket/luci.chromium.ci/Android FYI 64 Vk Release (Pixel XL)" + category: "Android|vk|P64" + short_name: "PXL" + } + builders { name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Pixel 2)" category: "Android|vk|P32" short_name: "P2" @@ -3658,6 +3668,16 @@ short_name: "N5X" } builders { + name: "buildbucket/luci.chromium.ci/Android FYI 32 dEQP Vk Release (Pixel XL)" + category: "Android|dqp|vk|P32" + short_name: "PXL" + } + builders { + name: "buildbucket/luci.chromium.ci/Android FYI 64 dEQP Vk Release (Pixel XL)" + category: "Android|dqp|vk|P64" + short_name: "PXL" + } + builders { name: "buildbucket/luci.chromium.ci/Android FYI 32 dEQP Vk Release (Pixel 2)" category: "Android|dqp|vk|P32" short_name: "P2" @@ -4270,6 +4290,18 @@ name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64-deqp" } builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32-deqp" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64-deqp" + } + builders { name: "buildbucket/luci.chromium.try/try-nougat-phone-tester" } builder_view_only: true @@ -4828,6 +4860,18 @@ name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64-deqp" } builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-32-deqp" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-xl-64-deqp" + } + builders { name: "buildbucket/luci.chromium.try/gpu_manual_try_win7_nvidia_rel" } builders {
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index 20e29458..651cbab9 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -75,12 +75,16 @@ triggers: "Android Cronet Builder" triggers: "Android FYI 32 Vk Release (Nexus 5X)" triggers: "Android FYI 32 Vk Release (Pixel 2)" + triggers: "Android FYI 32 Vk Release (Pixel XL)" triggers: "Android FYI 32 dEQP Vk Release (Nexus 5X)" triggers: "Android FYI 32 dEQP Vk Release (Pixel 2)" + triggers: "Android FYI 32 dEQP Vk Release (Pixel XL)" triggers: "Android FYI 64 Vk Release (Nexus 5X)" triggers: "Android FYI 64 Vk Release (Pixel 2)" + triggers: "Android FYI 64 Vk Release (Pixel XL)" triggers: "Android FYI 64 dEQP Vk Release (Nexus 5X)" triggers: "Android FYI 64 dEQP Vk Release (Pixel 2)" + triggers: "Android FYI 64 dEQP Vk Release (Pixel XL)" triggers: "Android FYI Release (NVIDIA Shield TV)" triggers: "Android FYI Release (Nexus 5)" triggers: "Android FYI Release (Nexus 5X)" @@ -415,6 +419,16 @@ } job { + id: "Android FYI 32 dEQP Vk Release (Pixel XL)" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Android FYI 32 dEQP Vk Release (Pixel XL)" + } +} + +job { id: "Android FYI 32 Vk Release (Nexus 5X)" acl_sets: "default" buildbucket: { @@ -435,6 +449,16 @@ } job { + id: "Android FYI 32 Vk Release (Pixel XL)" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Android FYI 32 Vk Release (Pixel XL)" + } +} + +job { id: "Android FYI 64 dEQP Vk Release (Nexus 5X)" acl_sets: "default" buildbucket: { @@ -455,6 +479,16 @@ } job { + id: "Android FYI 64 dEQP Vk Release (Pixel XL)" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Android FYI 64 dEQP Vk Release (Pixel XL)" + } +} + +job { id: "Android FYI 64 Vk Release (Nexus 5X)" acl_sets: "default" buildbucket: { @@ -475,6 +509,16 @@ } job { + id: "Android FYI 64 Vk Release (Pixel XL)" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Android FYI 64 Vk Release (Pixel XL)" + } +} + +job { id: "Android FYI dEQP Release (Nexus 5X)" acl_sets: "default" buildbucket: {
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd index 920aec2..8ad7b9e 100644 --- a/ios/chrome/app/strings/ios_chromium_strings.grd +++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -237,9 +237,6 @@ <message name="IDS_IOS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY" desc="The text of the identity section for iOS."> Chromium verified that <ph name="ISSUER">$1<ex>VeriSign</ex></ph> issued this website's certificate. </message> - <message name="IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT" desc="Info bar message to save a password. [Length: 60em]"> - Do you want Chromium to save your password for this site? - </message> <message name="IDS_IOS_PRODUCT_NAME" desc="The Chrome application name"> Chromium </message>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd index 82cc54d..7480ff25 100644 --- a/ios/chrome/app/strings/ios_google_chrome_strings.grd +++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -237,9 +237,6 @@ <message name="IDS_IOS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY" desc="The text of the identity section for iOS."> Chrome verified that <ph name="ISSUER">$1<ex>VeriSign</ex></ph> issued this website's certificate. </message> - <message name="IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT" desc="Info bar message to save a password. [Length: 60em]"> - Do you want Chrome to save your password for this site? - </message> <message name="IDS_IOS_PRODUCT_NAME" desc="The Chrome application name"> Google Chrome </message>
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 2f0c71b..ae3211e 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1064,20 +1064,20 @@ <message name="IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON" desc="Save button text for password manager [Length: 10em]"> Save </message> - <message name="IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT_SMART_LOCK_BRANDING" desc="Info bar message to save a password, referring to the Google Smart Lock brand. [Length: 70em]"> - Do you want Google Smart Lock to save your password for this site? - </message> - <message name="IDS_IOS_PASSWORD_MANAGER_SMART_LOCK_FOR_PASSWORDS" desc="The more descriptive brand name of the password manager when the user is signed in. Used in various UI elements, can be in link format."> - Google Smart Lock for Passwords + <message name="IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT" desc="Info bar message to save a password. [Length: 60em]"> + Save password? </message> <message name="IDS_IOS_PASSWORD_MANAGER_UPDATE_BUTTON" desc="Label for the 'update' button in the Update Password infobar. This infobar asks if the user wishes to update the saved password for a site to a new password the user has just entered; the button applies the suggested update. [Length: 10em]"> Update </message> <message name="IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD" desc="Infobar message to update a password without associated credential [Length: 70em]."> - Do you want <ph name="PASSWORD_MANAGER_BRAND">$1<ex>Google Chrome</ex></ph> to update your password for this site? + Update password? </message> - <message name="IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD_FOR_ACCOUNT" desc="Infobar message to update a password for named account, referring to PASSWORD_MANAGER_BRAND as the [Length:70em]"> - Do you want <ph name="PASSWORD_MANAGER_BRAND">$1<ex>Google Chrome</ex></ph> to update your password for <ph name="USERNAME">$2<ex>don.john.lemon@example.com</ex></ph> for this site? + <message name="IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD_FOR_ACCOUNT" desc="Infobar message to update a password for named account. [Length:70em]"> + Update password for <ph name="USERNAME">$1<ex>don.john.lemon@example.com</ex></ph>? + </message> + <message name="IDS_SAVE_PASSWORD_FOOTER" desc="The footer text of the infobar that offers user to save/update a password to Chrome."> + Passwords are saved in your Google Account so you can use them on any device. </message> <message name="IDS_IOS_PHOTO_LIBRARY_USAGE_DESCRIPTION" desc="Specifies the reason for accessing the user's photo library while the app is in use [Length: unlimited] [iOS only]."> This lets you save and upload photos. @@ -1187,9 +1187,6 @@ <message name="IDS_IOS_READING_LIST_EMPTY_MESSAGE" desc="Message to explain to the user how to add entries to the reading list" meaning="[Length: unlimited]"> Your reading list is available offline. To add a page to your reading list, tap <ph name="SHARE_OPENING_ICON">SHARE_OPENING_ICON<ex>(menu icon)</ex></ph> then <ph name="READ_LATER_TEXT">READ_LATER_TEXT<ex>Read Later</ex></ph>. </message> - <message name="IDS_IOS_READING_LIST_EMPTY_MESSAGE_LEGACY" desc="Message to explain to the user how to add entries to the reading list" meaning="[Length: unlimited]"> - Your reading list is available offline. To add a page to your reading list, tap <ph name="SHARE_OPENING_ICON">SHARE_OPENING_ICON<ex>Menu > Share > Read Later</ex></ph>. - </message> <message name="IDS_IOS_READING_LIST_JUST_NOW" desc="String indicating that an event (adding item, distillation) happened less than one minute ago. [Length: 25em]"> Just now </message>
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm index 8d2be47..935242b8 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm
@@ -100,7 +100,8 @@ bool AppLauncherTabHelper::IsAppUrl(const GURL& url) { return !(web::UrlHasWebScheme(url) || web::GetWebClient()->IsAppSpecificURL(url) || - url.SchemeIs(url::kFileScheme) || url.SchemeIs(url::kAboutScheme)); + url.SchemeIs(url::kFileScheme) || url.SchemeIs(url::kAboutScheme) || + url.SchemeIs(url::kBlobScheme)); } bool AppLauncherTabHelper::RequestToLaunchApp(const GURL& url,
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm index 6d3404da..1650258 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm
@@ -277,6 +277,9 @@ EXPECT_TRUE(TestShouldAllowRequest(@"data://test", /*target_frame_is_main=*/false, /*has_user_gesture=*/true)); + EXPECT_TRUE(TestShouldAllowRequest(@"blob://test", + /*target_frame_is_main=*/false, + /*has_user_gesture=*/true)); EXPECT_EQ(0U, delegate_.countOfAppsLaunched); }
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h index f8565e8..cd9a6ec 100644 --- a/ios/chrome/browser/experimental_flags.h +++ b/ios/chrome/browser/experimental_flags.h
@@ -58,10 +58,6 @@ // TODO (crbug.com/884719): Remove all use of this flag. bool IsBookmarksUIRebootEnabled(); -// Whether the Reading List UI Reboot is enabled. -// TODO (crbug.com/884720): Remove all use of this flag. -bool IsReadingListUIRebootEnabled(); - // Whether the application group sandbox must be cleared before starting. // Calling this method will reset the flag to false, so the sandbox is cleared // only once.
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm index f9200d9..42b1c0e 100644 --- a/ios/chrome/browser/experimental_flags.mm +++ b/ios/chrome/browser/experimental_flags.mm
@@ -130,8 +130,4 @@ return true; } -bool IsReadingListUIRebootEnabled() { - return true; -} - } // namespace experimental_flags
diff --git a/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm b/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm index 7ea9178a..d13e3d3 100644 --- a/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm +++ b/ios/chrome/browser/feature_engagement/feature_engagement_egtest.mm
@@ -302,15 +302,9 @@ } [chrome_test_util::BrowserCommandDispatcherForMainBVC() showReadingList]; - if (experimental_flags::IsReadingListUIRebootEnabled()) { - [[EarlGrey - selectElementWithMatcher:grey_accessibilityID( - kTableViewNavigationDismissButtonId)] - performAction:grey_tap()]; - } else { - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Done")] - performAction:grey_tap()]; - } + [[EarlGrey selectElementWithMatcher:grey_accessibilityID( + kTableViewNavigationDismissButtonId)] + performAction:grey_tap()]; [ChromeEarlGreyUI openToolsMenu];
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h index 2a72bd2..3931787 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.h
@@ -27,16 +27,14 @@ protected: IOSChromePasswordManagerInfoBarDelegate( - bool is_smart_lock_branding_enabled, + bool is_sync_user, std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager); password_manager::PasswordFormManagerForUI* form_to_save() const { return form_to_save_.get(); } - bool is_smart_lock_branding_enabled() const { - return is_smart_lock_branding_enabled_; - } + bool is_sync_user() const { return is_sync_user_; } void set_infobar_response( password_manager::metrics_util::UIDismissalReason response) { @@ -53,9 +51,7 @@ private: // ConfirmInfoBarDelegate implementation. - base::string16 GetLinkText() const override; int GetIconId() const override; - bool LinkClicked(WindowOpenDisposition disposition) override; // The password_manager::PasswordFormManager managing the form we're asking // the user about, and should save as per their decision. @@ -64,8 +60,8 @@ // Used to track the results we get from the info bar. password_manager::metrics_util::UIDismissalReason infobar_response_; - // Whether to show the password manager branded as Smart Lock. - const bool is_smart_lock_branding_enabled_; + // Whether to show the additional footer. + const bool is_sync_user_; // Dispatcher for calling Application commands. __weak id<ApplicationCommands> dispatcher_ = nil;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm index 379236c..2c39a57 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_infobar_delegate.mm
@@ -8,15 +8,7 @@ #include "base/strings/string16.h" #include "components/password_manager/core/browser/password_form_manager_for_ui.h" -#include "components/password_manager/core/browser/password_manager_constants.h" -#include "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/ui/commands/application_commands.h" -#import "ios/chrome/browser/ui/commands/open_new_tab_command.h" -#include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_theme_resources.h" -#include "ios/web/public/referrer.h" -#include "ui/base/l10n/l10n_util.h" -#include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -27,31 +19,13 @@ IOSChromePasswordManagerInfoBarDelegate:: IOSChromePasswordManagerInfoBarDelegate( - bool is_smart_lock_branding_enabled, + bool is_sync_user, std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save) : form_to_save_(std::move(form_to_save)), infobar_response_(password_manager::metrics_util::NO_DIRECT_INTERACTION), - is_smart_lock_branding_enabled_(is_smart_lock_branding_enabled) {} - -base::string16 IOSChromePasswordManagerInfoBarDelegate::GetLinkText() const { - return is_smart_lock_branding_enabled_ - ? l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK) - : base::string16(); -}; + is_sync_user_(is_sync_user) {} int IOSChromePasswordManagerInfoBarDelegate::GetIconId() const { return IDR_IOS_INFOBAR_SAVE_PASSWORD; }; - -bool IOSChromePasswordManagerInfoBarDelegate::LinkClicked( - WindowOpenDisposition disposition) { - OpenNewTabCommand* command = [[OpenNewTabCommand alloc] - initWithURL:GURL(password_manager::kPasswordManagerHelpCenterSmartLock) - referrer:web::Referrer() - inIncognito:NO - inBackground:NO - appendTo:kCurrentTab]; - [dispatcher_ openURLInNewTab:command]; - return true; -};
diff --git a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h index 796ed42f..dd41983 100644 --- a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h +++ b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
@@ -28,10 +28,9 @@ : public IOSChromePasswordManagerInfoBarDelegate { public: // Creates the infobar for |form_to_save| and adds it to |infobar_manager|. - // |is_smart_lock_enabled| controls the branding string. |dispatcher| is not - // retained. + // |is_sync_user| controls the footer string. |dispatcher| is not retained. static void Create( - bool is_smart_lock_branding_enabled, + bool is_sync_user, infobars::InfoBarManager* infobar_manager, std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save, id<ApplicationCommands> dispatcher); @@ -42,7 +41,7 @@ private: IOSChromeSavePasswordInfoBarDelegate( - bool is_smart_lock_branding_enabled, + bool is_sync_user, std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save); // ConfirmInfoBarDelegate implementation.
diff --git a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm index f659a52..af5e4f0 100644 --- a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm +++ b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm
@@ -25,13 +25,13 @@ // static void IOSChromeSavePasswordInfoBarDelegate::Create( - bool is_smart_lock_branding_enabled, + bool is_sync_user, infobars::InfoBarManager* infobar_manager, std::unique_ptr<PasswordFormManagerForUI> form_to_save, id<ApplicationCommands> dispatcher) { DCHECK(infobar_manager); auto delegate = base::WrapUnique(new IOSChromeSavePasswordInfoBarDelegate( - is_smart_lock_branding_enabled, std::move(form_to_save))); + is_sync_user, std::move(form_to_save))); delegate->set_dispatcher(dispatcher); infobar_manager->AddInfoBar( infobar_manager->CreateConfirmInfoBar(std::move(delegate))); @@ -44,9 +44,9 @@ } IOSChromeSavePasswordInfoBarDelegate::IOSChromeSavePasswordInfoBarDelegate( - bool is_smart_lock_branding_enabled, + bool is_sync_user, std::unique_ptr<PasswordFormManagerForUI> form_manager) - : IOSChromePasswordManagerInfoBarDelegate(is_smart_lock_branding_enabled, + : IOSChromePasswordManagerInfoBarDelegate(is_sync_user, std::move(form_manager)) { form_to_save()->GetMetricsRecorder()->RecordPasswordBubbleShown( form_to_save()->GetCredentialSource(), @@ -59,10 +59,6 @@ } base::string16 IOSChromeSavePasswordInfoBarDelegate::GetMessageText() const { - if (is_smart_lock_branding_enabled()) { - return l10n_util::GetStringUTF16( - IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT_SMART_LOCK_BRANDING); - } return l10n_util::GetStringUTF16( IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT); }
diff --git a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h index 9400fc3c..0ecc20b 100644 --- a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h +++ b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.h
@@ -26,11 +26,11 @@ : public IOSChromePasswordManagerInfoBarDelegate { public: // Creates the infobar for |form_to_save| and adds it to |infobar_manager|. - // |is_smart_lock_enabled| controls the branding string. |baseViewController| - // is the base view controller from which to present UI, and is not retained. + // |is_sync_user| controls the footer text. |baseViewController| is the base + // view controller from which to present UI, and is not retained. // |dispatcher| is not retained. static void Create( - bool is_smart_lock_branding_enabled, + bool is_sync_user, infobars::InfoBarManager* infobar_manager, std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save, UIViewController* baseViewController, @@ -55,13 +55,9 @@ private: IOSChromeUpdatePasswordInfoBarDelegate( - bool is_smart_lock_branding_enabled, + bool is_sync_user, std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save); - // Returns the string with the branded title of the password manager (e.g. - // "Google Smart Lock for Passwords"). - base::string16 GetBranding() const; - // ConfirmInfoBarDelegate implementation. infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; base::string16 GetMessageText() const override;
diff --git a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm index 9894811..65ece545 100644 --- a/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm +++ b/ios/chrome/browser/passwords/ios_chrome_update_password_infobar_delegate.mm
@@ -29,14 +29,14 @@ // static void IOSChromeUpdatePasswordInfoBarDelegate::Create( - bool is_smart_lock_branding_enabled, + bool is_sync_user, infobars::InfoBarManager* infobar_manager, std::unique_ptr<PasswordFormManagerForUI> form_manager, UIViewController* baseViewController, id<ApplicationCommands> dispatcher) { DCHECK(infobar_manager); auto delegate = base::WrapUnique(new IOSChromeUpdatePasswordInfoBarDelegate( - is_smart_lock_branding_enabled, std::move(form_manager))); + is_sync_user, std::move(form_manager))); delegate->set_dispatcher(dispatcher); UpdatePasswordInfoBarController* controller = [[UpdatePasswordInfoBarController alloc] @@ -55,9 +55,9 @@ } IOSChromeUpdatePasswordInfoBarDelegate::IOSChromeUpdatePasswordInfoBarDelegate( - bool is_smart_lock_branding_enabled, + bool is_sync_user, std::unique_ptr<PasswordFormManagerForUI> form_manager) - : IOSChromePasswordManagerInfoBarDelegate(is_smart_lock_branding_enabled, + : IOSChromePasswordManagerInfoBarDelegate(is_sync_user, std::move(form_manager)) { selected_account_ = form_to_save()->GetPreferredMatch()->username_value; form_to_save()->GetMetricsRecorder()->RecordPasswordBubbleShown( @@ -80,13 +80,6 @@ return usernames; } -base::string16 IOSChromeUpdatePasswordInfoBarDelegate::GetBranding() const { - return l10n_util::GetStringUTF16( - is_smart_lock_branding_enabled() - ? IDS_IOS_PASSWORD_MANAGER_SMART_LOCK_FOR_PASSWORDS - : IDS_IOS_SHORT_PRODUCT_NAME); -} - infobars::InfoBarDelegate::InfoBarIdentifier IOSChromeUpdatePasswordInfoBarDelegate::GetIdentifier() const { return UPDATE_PASSWORD_INFOBAR_DELEGATE_MOBILE; @@ -96,9 +89,9 @@ return selected_account_.length() > 0 ? l10n_util::GetStringFUTF16( IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD_FOR_ACCOUNT, - GetBranding(), selected_account_) - : l10n_util::GetStringFUTF16( - IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD, GetBranding()); + selected_account_) + : l10n_util::GetStringUTF16( + IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD); } int IOSChromeUpdatePasswordInfoBarDelegate::GetButtons() const {
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index 457d024..e2beaad 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -621,12 +621,11 @@ if (!_webState) return; - bool isSmartLockBrandingEnabled = false; + bool isSyncUser = false; if (self.browserState) { syncer::SyncService* sync_service = ProfileSyncServiceFactory::GetForBrowserState(self.browserState); - isSmartLockBrandingEnabled = - password_bubble_experiment::IsSmartLockUser(sync_service); + isSyncUser = password_bubble_experiment::IsSmartLockUser(sync_service); } infobars::InfoBarManager* infoBarManager = InfoBarManagerImpl::FromWebState(_webState); @@ -634,14 +633,13 @@ switch (type) { case PasswordInfoBarType::SAVE: IOSChromeSavePasswordInfoBarDelegate::Create( - isSmartLockBrandingEnabled, infoBarManager, std::move(form), - self.dispatcher); + isSyncUser, infoBarManager, std::move(form), self.dispatcher); break; case PasswordInfoBarType::UPDATE: IOSChromeUpdatePasswordInfoBarDelegate::Create( - isSmartLockBrandingEnabled, infoBarManager, std::move(form), - self.baseViewController, self.dispatcher); + isSyncUser, infoBarManager, std::move(form), self.baseViewController, + self.dispatcher); break; } }
diff --git a/ios/chrome/browser/passwords/update_password_infobar_controller.mm b/ios/chrome/browser/passwords/update_password_infobar_controller.mm index 8eec95d..a2d40161 100644 --- a/ios/chrome/browser/passwords/update_password_infobar_controller.mm +++ b/ios/chrome/browser/passwords/update_password_infobar_controller.mm
@@ -75,9 +75,7 @@ } - (void)infobarLinkDidPress:(NSUInteger)tag { - [super infobarLinkDidPress:tag]; - if (tag != kAccountTag) - return; + DCHECK_EQ(kAccountTag, tag); DCHECK(self.baseViewController); self.selectorCoordinator = [[SelectorCoordinator alloc]
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm index d701444..1a081c4 100644 --- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
@@ -113,16 +113,16 @@ // Simulates a POST request on |web_view| using a XMLHttpRequest in // JavaScript. -// This is needed because WKWebView ignores the HTTPBody in a POST request. -// See +// This is needed because WKWebView ignores the HTTPBody in a POST request +// before iOS11 and because WKWebView cannot read response body if +// content-disposition header is set. See // https://bugs.webkit.org/show_bug.cgi?id=145410 -// TODO(crbug.com/740987): Remove this function workaround once iOS 10 is -// dropped. +// TODO(crbug.com/889471) Remove this once requests are done using +// NSUrlSession in iOS. void DoPostRequest(WKWebView* web_view, const std::string& body, const std::string& headers, const GURL& url) { - DCHECK(!base::ios::IsRunningOnIOS11OrLater()); NSMutableString* header_data = [NSMutableString string]; net::HttpRequestHeaders request_headers; request_headers.AddHeadersFromString(headers); @@ -200,15 +200,21 @@ #pragma mark - GaiaAuthFetcherIOSBridge::Request GaiaAuthFetcherIOSBridge::Request::Request() - : pending(false), url(), headers(), body() {} + : pending(false), + url(), + headers(), + body(), + shouldUseXmlHTTPRequest(false) {} GaiaAuthFetcherIOSBridge::Request::Request(const GURL& request_url, const std::string& request_headers, - const std::string& request_body) + const std::string& request_body, + bool shouldUseXmlHTTPRequest) : pending(true), url(request_url), headers(request_headers), - body(request_body) {} + body(request_body), + shouldUseXmlHTTPRequest(shouldUseXmlHTTPRequest) {} #pragma mark - GaiaAuthFetcherIOSBridge @@ -226,8 +232,9 @@ void GaiaAuthFetcherIOSBridge::Fetch(const GURL& url, const std::string& headers, - const std::string& body) { - request_ = Request(url, headers, body); + const std::string& body, + bool shouldUseXmlHTTPRequest) { + request_ = Request(url, headers, body, shouldUseXmlHTTPRequest); FetchPendingRequest(); } @@ -265,7 +272,7 @@ void GaiaAuthFetcherIOSBridge::FetchPendingRequest() { if (!request_.pending) return; - if (!request_.body.empty() && !base::ios::IsRunningOnIOS11OrLater()) { + if (!request_.body.empty() && request_.shouldUseXmlHTTPRequest) { DoPostRequest(GetWKWebView(), request_.body, request_.headers, request_.url); } else { @@ -355,7 +362,9 @@ // a network request with cookies sent and saved is by making it through a // WKWebView. SetPendingFetch(true); - bridge_->Fetch(gaia_gurl, headers, body); + bool shouldUseXmlHTTPRequest = + IsMultiloginUrl(gaia_gurl) || !base::ios::IsRunningOnIOS11OrLater(); + bridge_->Fetch(gaia_gurl, headers, body, shouldUseXmlHTTPRequest); } void GaiaAuthFetcherIOS::CancelRequest() {
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h index 766549c..40e8459e 100644 --- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h
@@ -36,7 +36,8 @@ // will be a POST request. void Fetch(const GURL& url, const std::string& headers, - const std::string& body); + const std::string& body, + bool shouldUseXmlHTTPRequest); // Cancels the current fetch. void Cancel(); @@ -61,7 +62,8 @@ Request(); Request(const GURL& url, const std::string& headers, - const std::string& body); + const std::string& body, + bool shouldUseXmlHTTPRequest); // Whether the request is pending (i.e. awaiting to be processed or // currently being processed). bool pending; @@ -71,6 +73,9 @@ std::string headers; // HTTP body to add to the request. std::string body; + // Whether XmlHTTPRequest should be injected in JS instead of using + // WKWebView directly. + bool shouldUseXmlHTTPRequest; }; // Fetches the pending request if it exists.
diff --git a/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm b/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm index 1e239dd..1c81248b 100644 --- a/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm +++ b/ios/chrome/browser/ui/authentication/authentication_flow_performer.mm
@@ -213,16 +213,16 @@ AuthenticationFlowPerformer* strongSelf = weakSelf; if (!strongSelf) return; + [strongSelf alertControllerDidDisappear:weakAlert]; [[strongSelf delegate] didChooseClearDataPolicy:SHOULD_CLEAR_DATA_CLEAR_DATA]; - [strongSelf alertControllerDidDisappear:weakAlert]; }; ProceduralBlock cancelBlock = ^{ AuthenticationFlowPerformer* strongSelf = weakSelf; if (!strongSelf) return; - [[strongSelf delegate] didChooseCancel]; [strongSelf alertControllerDidDisappear:weakAlert]; + [[strongSelf delegate] didChooseCancel]; }; [_alertCoordinator addItemWithTitle:cancelLabel @@ -337,15 +337,15 @@ AuthenticationFlowPerformer* strongSelf = weakSelf; if (!strongSelf) return; - [[strongSelf delegate] didAcceptManagedConfirmation]; [strongSelf alertControllerDidDisappear:weakAlert]; + [[strongSelf delegate] didAcceptManagedConfirmation]; }; ProceduralBlock cancelBlock = ^{ AuthenticationFlowPerformer* strongSelf = weakSelf; if (!strongSelf) return; - [[strongSelf delegate] didCancelManagedConfirmation]; [strongSelf alertControllerDidDisappear:weakAlert]; + [[strongSelf delegate] didCancelManagedConfirmation]; }; [_alertCoordinator addItemWithTitle:cancelLabel @@ -368,9 +368,9 @@ __weak AuthenticationFlowPerformer* weakSelf = self; __weak AlertCoordinator* weakAlert = _alertCoordinator; ProceduralBlock dismissAction = ^{ + [weakSelf alertControllerDidDisappear:weakAlert]; if (callback) callback(); - [weakSelf alertControllerDidDisappear:weakAlert]; }; NSString* okButtonLabel = l10n_util::GetNSString(IDS_OK);
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 0331322..5b6001b1 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -178,7 +178,6 @@ #import "ios/chrome/browser/ui/print/print_controller.h" #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.h" #import "ios/chrome/browser/ui/qr_scanner/requirements/qr_scanner_presenting.h" -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.h" #import "ios/chrome/browser/ui/reading_list/offline_page_native_content.h" #import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" #import "ios/chrome/browser/ui/reading_list/reading_list_menu_notifier.h" @@ -4511,17 +4510,10 @@ } - (void)showReadingList { - _readingListCoordinator = - experimental_flags::IsReadingListUIRebootEnabled() - ? [[ReadingListCoordinator alloc] - initWithBaseViewController:self - browserState:self.browserState - loader:self] - : [[LegacyReadingListCoordinator alloc] - initWithBaseViewController:self - browserState:self.browserState - loader:self]; - + _readingListCoordinator = [[ReadingListCoordinator alloc] + initWithBaseViewController:self + browserState:self.browserState + loader:self]; [_readingListCoordinator start]; }
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index 743e610..f56c4d5 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -4,12 +4,8 @@ source_set("reading_list") { sources = [ - "legacy_reading_list_coordinator.h", - "legacy_reading_list_coordinator.mm", "offline_page_native_content.h", "offline_page_native_content.mm", - "reading_list_collection_view_item.h", - "reading_list_collection_view_item.mm", "reading_list_coordinator.h", "reading_list_coordinator.mm", "reading_list_list_item.h", @@ -33,6 +29,7 @@ ] deps = [ ":reading_list_ui", + "resources:distillation_fail_new", "//base", "//components/favicon/core", "//components/feature_engagement", @@ -80,18 +77,8 @@ "empty_reading_list_background_view.mm", "empty_reading_list_message_util.h", "empty_reading_list_message_util.mm", - "legacy_reading_list_toolbar.h", - "legacy_reading_list_toolbar.mm", - "legacy_reading_list_toolbar_button.h", - "legacy_reading_list_toolbar_button.mm", - "legacy_reading_list_view_controller.h", - "legacy_reading_list_view_controller.mm", "number_badge_view.h", "number_badge_view.mm", - "reading_list_collection_view_cell.h", - "reading_list_collection_view_cell.mm", - "reading_list_collection_view_controller.h", - "reading_list_collection_view_controller.mm", "reading_list_data_sink.h", "reading_list_data_source.h", "reading_list_list_item_accessibility_delegate.h", @@ -110,13 +97,9 @@ "text_badge_view.mm", ] deps = [ - "resources:distillation_fail", - "resources:distillation_success", "resources:reading_list_empty_state", "resources:reading_list_empty_state_new", - "resources:reading_list_share_icon", "resources:reading_list_side_swipe", - "resources:reading_list_toolbar_icon", "resources:reading_list_tools_icon", "//base", "//base:i18n", @@ -126,8 +109,6 @@ "//ios/chrome/browser", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/alert_coordinator", - "//ios/chrome/browser/ui/collection_view/cells", - "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/list_model", "//ios/chrome/browser/ui/material_components", @@ -137,15 +118,10 @@ "//ios/chrome/browser/ui/util", "//ios/chrome/common", "//ios/chrome/common/favicon", - "//ios/third_party/material_components_ios", - "//ios/third_party/material_roboto_font_loader_ios", "//ui/base", "//ui/strings:ui_strings_grit", "//url", ] - public_deps = [ - "//ios/chrome/browser/ui/collection_view", - ] libs = [ "UIKit.framework" ] } @@ -153,9 +129,7 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ - "legacy_reading_list_coordinator_unittest.mm", "offline_page_native_content_unittest.mm", - "reading_list_collection_view_controller_unittest.mm", "reading_list_list_item_factory_unittest.mm", "reading_list_mediator_unittest.mm", "text_badge_view_unittest.mm",
diff --git a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm b/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm index f562b4d6..51319f1 100644 --- a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm +++ b/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm
@@ -9,8 +9,6 @@ #include "ios/chrome/browser/ui/rtl_geometry.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -21,44 +19,17 @@ // Images name. NSString* const kToolsIcon = @"reading_list_tools_icon"; -NSString* const kToolsIconLegacy = @"reading_list_toolbar_icon"; -NSString* const kShareIconLegacy = @"reading_list_share_icon"; // Tag in string. NSString* const kOpenShareMarker = @"SHARE_OPENING_ICON"; NSString* const kReadLaterTextMarker = @"READ_LATER_TEXT"; // Background view constants. -const CGFloat kFontSize = 16; const CGFloat kLineHeight = 24; -// Enum type describing the icons used by the attributed empty table message. -enum class IconType { TOOLS, SHARE }; -// Returns the UIImage corresponding with |icon_type|. -UIImage* GetIconWithType(IconType icon_type) { - if (experimental_flags::IsReadingListUIRebootEnabled()) { - switch (icon_type) { - case IconType::TOOLS: - return [UIImage imageNamed:kToolsIcon]; - case IconType::SHARE: - NOTREACHED() << "The share icon is not used in the UI refresh."; - return nil; - } - } else { - switch (icon_type) { - case IconType::TOOLS: - return [UIImage imageNamed:kToolsIconLegacy]; - case IconType::SHARE: - return [UIImage imageNamed:kShareIconLegacy]; - } - } -} - // Returns the font to use for the message text. UIFont* GetMessageFont() { - return experimental_flags::IsReadingListUIRebootEnabled() - ? [UIFont preferredFontForTextStyle:UIFontTextStyleBody] - : [[MDCTypography fontLoader] regularFontOfSize:kFontSize]; + return [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; } // Returns the attributes to use for the message text. @@ -66,10 +37,7 @@ NSMutableDictionary* attributes = [NSMutableDictionary dictionary]; UIFont* font = GetMessageFont(); attributes[NSFontAttributeName] = font; - attributes[NSForegroundColorAttributeName] = - experimental_flags::IsReadingListUIRebootEnabled() - ? [UIColor grayColor] - : [[MDCPalette greyPalette] tint700]; + attributes[NSForegroundColorAttributeName] = [UIColor grayColor]; NSMutableParagraphStyle* paragraph_style = [[NSMutableParagraphStyle alloc] init]; paragraph_style.lineBreakMode = NSLineBreakByWordWrapping; @@ -87,9 +55,7 @@ NSMutableDictionary* GetInstructionAttributes() { NSMutableDictionary* attributes = GetMessageAttributes(); attributes[NSFontAttributeName] = - experimental_flags::IsReadingListUIRebootEnabled() - ? [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline] - : [[MDCTypography fontLoader] boldFontOfSize:kFontSize]; + [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; return attributes; } @@ -97,18 +63,15 @@ // correct styling. NSAttributedString* GetReadLaterString() { NSString* read_later_text = - l10n_util::GetNSString(experimental_flags::IsReadingListUIRebootEnabled() - ? IDS_IOS_SHARE_MENU_READING_LIST_ACTION - : IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST); + l10n_util::GetNSString(IDS_IOS_SHARE_MENU_READING_LIST_ACTION); return [[NSAttributedString alloc] initWithString:read_later_text attributes:GetInstructionAttributes()]; } -// Appends the icon with |icon_type| to |text|. Spacer text that is added by -// this function is formatted with |attributes|. -void AppendIcon(IconType icon_type, - NSMutableAttributedString* text, - NSDictionary* attributes) { +// Appends the tools icon to |text|. Spacer text that is added by this function +// is formatted with |attributes|. +void AppendToolsIcon(NSMutableAttributedString* text, + NSDictionary* attributes) { // Add a zero width space to set the attributes for the image. NSAttributedString* spacer = [[NSAttributedString alloc] initWithString:@"\u200B" @@ -117,7 +80,7 @@ // The icon bounds must be offset to be vertically centered with the message // text. - UIImage* icon = GetIconWithType(icon_type); + UIImage* icon = [UIImage imageNamed:kToolsIcon]; CGRect icon_bounds = CGRectZero; icon_bounds.size = icon.size; icon_bounds.origin.y = (GetMessageFont().xHeight - icon.size.height) / 2.0; @@ -132,42 +95,13 @@ [text appendAttributedString:attachment_string]; } -// Appends a carat string and some spacing to |text|. -void AppendCarat(NSMutableAttributedString* text, NSDictionary* attributes) { - // Use a carat facing the appropriate direction for the language. - NSString* carat = [NSString - stringWithFormat:@" %@ ", UseRTLLayout() ? @"\u25C2" : @"\u25B8"]; - [text appendAttributedString:[[NSAttributedString alloc] - initWithString:carat - attributes:attributes]]; -} - // Returns the string to use to describe the buttons needed to access the "Read // Later" option. NSAttributedString* GetInstructionIconString() { NSDictionary* attributes = GetInstructionAttributes(); NSMutableAttributedString* icon_string = [[NSMutableAttributedString alloc] init]; - if (experimental_flags::IsReadingListUIRebootEnabled()) { - // In the UI reboot, only the single tools icon is used. - AppendIcon(IconType::TOOLS, icon_string, attributes); - } else { - if (IsCompactWidth() || !IsIPadIdiom()) { - // TODO(crbug.com/698726): When the share icon is displayed in the toolbar - // for landscape iPhone 6+, remove !IsIPadIdiom(). - // If the device has a compact display the share menu is accessed from the - // toolbar menu. If it is expanded, the share menu is directly accessible. - AppendIcon(IconType::TOOLS, icon_string, attributes); - AppendCarat(icon_string, attributes); - } - AppendIcon(IconType::SHARE, icon_string, attributes); - AppendCarat(icon_string, attributes); - // Append an additional space at the end of the legacy icon string to - // improve the kerning between the carat and the "Read Later" text. - [icon_string appendAttributedString:[[NSAttributedString alloc] - initWithString:@" " - attributes:attributes]]; - } + AppendToolsIcon(icon_string, attributes); return icon_string; } @@ -177,29 +111,12 @@ NSMutableAttributedString* icon_string = [[NSMutableAttributedString alloc] initWithString:@":" attributes:attributes]; - if (experimental_flags::IsReadingListUIRebootEnabled()) { - NSString* tools_text = [NSString - stringWithFormat:@"%@, ", - l10n_util::GetNSString(IDS_IOS_TOOLBAR_SETTINGS)]; - [icon_string appendAttributedString:[[NSAttributedString alloc] - initWithString:tools_text - attributes:attributes]]; - } else { - if ((IsCompactWidth() || !IsIPadIdiom())) { - NSString* tools_text = [NSString - stringWithFormat:@"%@, ", - l10n_util::GetNSString(IDS_IOS_TOOLBAR_SETTINGS)]; - [icon_string appendAttributedString:[[NSAttributedString alloc] - initWithString:tools_text - attributes:attributes]]; - } - NSString* share_text = [NSString - stringWithFormat:@"%@, ", - l10n_util::GetNSString(IDS_IOS_TOOLS_MENU_SHARE)]; - [icon_string appendAttributedString:[[NSAttributedString alloc] - initWithString:share_text - attributes:attributes]]; - } + NSString* tools_text = [NSString + stringWithFormat:@"%@, ", + l10n_util::GetNSString(IDS_IOS_TOOLBAR_SETTINGS)]; + [icon_string appendAttributedString:[[NSAttributedString alloc] + initWithString:tools_text + attributes:attributes]]; return icon_string; } @@ -207,10 +124,8 @@ // icon images are added to the text; otherwise accessible text versions of the // instructions are used. NSAttributedString* GetReadingListEmptyMessage(bool use_icons) { - bool reboot_enabled = experimental_flags::IsReadingListUIRebootEnabled(); - NSString* raw_text = l10n_util::GetNSString( - reboot_enabled ? IDS_IOS_READING_LIST_EMPTY_MESSAGE - : IDS_IOS_READING_LIST_EMPTY_MESSAGE_LEGACY); + NSString* raw_text = + l10n_util::GetNSString(IDS_IOS_READING_LIST_EMPTY_MESSAGE); NSMutableAttributedString* message = [[NSMutableAttributedString alloc] initWithString:raw_text attributes:GetMessageAttributes()]; @@ -218,33 +133,19 @@ use_icons ? GetInstructionIconString() : GetAccessibleInstructionIconString(); NSAttributedString* read_later_string = GetReadLaterString(); - if (reboot_enabled) { - // When the reboot is enabled, two replacements must be made in the text: - // - kOpenShareMarker should be replaced with |instruction_icon_string| - // - kReadLaterTextMarker should be replaced with |read_later_text| - NSRange icon_range = [message.string rangeOfString:kOpenShareMarker]; - DCHECK(icon_range.location != NSNotFound); - [message replaceCharactersInRange:icon_range - withAttributedString:instruction_icon_string]; + // Two replacements must be made in the text: + // - kOpenShareMarker should be replaced with |instruction_icon_string| + // - kReadLaterTextMarker should be replaced with |read_later_text| + NSRange icon_range = [message.string rangeOfString:kOpenShareMarker]; + DCHECK(icon_range.location != NSNotFound); + [message replaceCharactersInRange:icon_range + withAttributedString:instruction_icon_string]; - NSRange read_later_range = - [message.string rangeOfString:kReadLaterTextMarker]; - DCHECK(read_later_range.location != NSNotFound); - [message replaceCharactersInRange:read_later_range - withAttributedString:read_later_string]; - } else { - // In the legacy implementation, kOpenShareMarker is replaced with the - // entire instruction string (i.e. "(tools icon) > (share icon) > Read - // Later". - NSMutableAttributedString* instruction_string = - [[NSMutableAttributedString alloc] init]; - [instruction_string appendAttributedString:instruction_icon_string]; - [instruction_string appendAttributedString:read_later_string]; - NSRange replacement_range = [message.string rangeOfString:kOpenShareMarker]; - DCHECK(replacement_range.location != NSNotFound); - [message replaceCharactersInRange:replacement_range - withAttributedString:instruction_string]; - } + NSRange read_later_range = + [message.string rangeOfString:kReadLaterTextMarker]; + DCHECK(read_later_range.location != NSNotFound); + [message replaceCharactersInRange:read_later_range + withAttributedString:read_later_string]; return message; } } // namespace
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.h b/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.h deleted file mode 100644 index 2474f677..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.h +++ /dev/null
@@ -1,40 +0,0 @@ -// 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 IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_COORDINATOR_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_COORDINATOR_H_ - -#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h" - -namespace ios { -class ChromeBrowserState; -} - -@class ReadingListMediator; -@protocol UrlLoader; - -// Coordinator for Reading List, displaying the Reading List when starting. -@interface LegacyReadingListCoordinator - : ChromeCoordinator<ReadingListListViewControllerDelegate> - -// Mediator used by this coordinator. Reset when |-start| is called. -@property(nonatomic, strong, nullable) ReadingListMediator* mediator; - -- (nullable instancetype) -initWithBaseViewController:(nullable UIViewController*)viewController - browserState:(nonnull ios::ChromeBrowserState*)browserState - loader:(nullable id<UrlLoader>)loader - NS_DESIGNATED_INITIALIZER; - -- (nullable instancetype)initWithBaseViewController: - (nullable UIViewController*)viewController NS_UNAVAILABLE; -- (nullable instancetype) -initWithBaseViewController:(nullable UIViewController*)viewController - browserState:(nullable ios::ChromeBrowserState*)browserState - NS_UNAVAILABLE; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.mm deleted file mode 100644 index 6a45e0e2..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.mm +++ /dev/null
@@ -1,330 +0,0 @@ -// 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. - -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.h" - -#import "base/mac/foundation_util.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.h" -#import "base/strings/sys_string_conversions.h" -#include "components/feature_engagement/public/event_constants.h" -#include "components/feature_engagement/public/tracker.h" -#include "components/reading_list/core/reading_list_model.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#include "ios/chrome/browser/feature_engagement/tracker_factory.h" -#import "ios/chrome/browser/metrics/new_tab_page_uma.h" -#include "ios/chrome/browser/reading_list/offline_url_utils.h" -#include "ios/chrome/browser/reading_list/reading_list_download_service.h" -#include "ios/chrome/browser/reading_list/reading_list_download_service_factory.h" -#include "ios/chrome/browser/reading_list/reading_list_model_factory.h" -#import "ios/chrome/browser/ui/commands/open_new_tab_command.h" -#import "ios/chrome/browser/ui/reading_list/context_menu/reading_list_context_menu_commands.h" -#import "ios/chrome/browser/ui/reading_list/context_menu/reading_list_context_menu_coordinator.h" -#import "ios/chrome/browser/ui/reading_list/context_menu/reading_list_context_menu_params.h" -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h" -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h" -#import "ios/chrome/browser/ui/url_loader.h" -#import "ios/chrome/browser/ui/util/pasteboard_util.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/web/public/navigation_manager.h" -#include "ios/web/public/referrer.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/strings/grit/ui_strings.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface LegacyReadingListCoordinator ()<ReadingListContextMenuCommands> - -@property(nonatomic, assign) ios::ChromeBrowserState* browserState; -// Used to load the Reading List pages. -@property(nonatomic, weak) id<UrlLoader> URLLoader; -// The container view containing both the collection view and the toolbar. -@property(nonatomic, strong) - LegacyReadingListViewController* containerViewController; -// The collection view controller that displays the reading list items (owned by -// |containerViewController|). -@property(nonatomic, weak) - ReadingListCollectionViewController* collectionViewController; -// The context menu displayed for long-presses on reading list items. -@property(nonatomic, strong) - ReadingListContextMenuCoordinator* contextMenuCoordinator; - -@end - -@implementation LegacyReadingListCoordinator - -@synthesize containerViewController = _containerViewController; -@synthesize collectionViewController = _collectionViewController; -@synthesize contextMenuCoordinator = _contextMenuCoordinator; -@synthesize URLLoader = _URLLoader; -@synthesize browserState = _browserState; -@synthesize mediator = _mediator; - -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - browserState: - (ios::ChromeBrowserState*)browserState - loader:(id<UrlLoader>)loader { - self = [super initWithBaseViewController:viewController - browserState:browserState]; - if (self) { - _browserState = browserState; - _URLLoader = loader; - } - return self; -} - -#pragma mark - ChromeCoordinator - -- (void)start { - if (!self.containerViewController) { - ReadingListModel* model = - ReadingListModelFactory::GetInstance()->GetForBrowserState( - self.browserState); - favicon::LargeIconService* largeIconService = - IOSChromeLargeIconServiceFactory::GetForBrowserState(self.browserState); - - ReadingListListItemFactory* itemFactory = - [ReadingListListItemFactory collectionViewItemFactory]; - - self.mediator = [[ReadingListMediator alloc] initWithModel:model - largeIconService:largeIconService - listItemFactory:itemFactory]; - LegacyReadingListToolbar* toolbar = [[LegacyReadingListToolbar alloc] init]; - ReadingListCollectionViewController* collectionViewController = - [[ReadingListCollectionViewController alloc] - initWithDataSource:self.mediator - - toolbar:toolbar]; - collectionViewController.delegate = self; - itemFactory.accessibilityDelegate = collectionViewController; - self.collectionViewController = collectionViewController; - - self.containerViewController = [[LegacyReadingListViewController alloc] - initWithCollectionViewController:collectionViewController - toolbar:toolbar]; - self.containerViewController.delegate = self; - } - - [self.baseViewController presentViewController:self.containerViewController - animated:YES - completion:nil]; - - // Send the "Viewed Reading List" event to the feature_engagement::Tracker - // when the user opens their reading list. - feature_engagement::TrackerFactory::GetForBrowserState(self.browserState) - ->NotifyEvent(feature_engagement::events::kViewedReadingList); -} - -- (void)stop { - [self.containerViewController.presentingViewController - dismissViewControllerAnimated:YES - completion:nil]; - - self.containerViewController = nil; -} - -#pragma mark - ReadingListListViewControllerDelegate - -- (void)dismissReadingListListViewController:(UIViewController*)viewController { - DCHECK_EQ(viewController, self.collectionViewController); - [self.collectionViewController willBeDismissed]; - [self stop]; -} - -- (void)readingListListViewController:(UIViewController*)viewController - displayContextMenuForItem:(ListItem<ReadingListListItem>*)item - atPoint:(CGPoint)menuLocation { - DCHECK_EQ(viewController, self.collectionViewController); - if (!self.containerViewController) { - return; - } - - ListItem<ReadingListListItem>* readingListItem = - base::mac::ObjCCastStrict<ReadingListCollectionViewItem>(item); - - const ReadingListEntry* entry = [self.mediator entryFromItem:readingListItem]; - - if (!entry) { - [self.collectionViewController reloadData]; - return; - } - const GURL entryURL = entry->URL(); - - GURL offlineURL; - if (entry->DistilledState() == ReadingListEntry::PROCESSED) { - offlineURL = reading_list::OfflineURLForPath( - entry->DistilledPath(), entryURL, entry->DistilledURL()); - } - - ReadingListContextMenuParams* params = - [[ReadingListContextMenuParams alloc] init]; - params.title = readingListItem.title; - params.message = base::SysUTF8ToNSString(readingListItem.entryURL.host()); - params.rect = CGRectMake(menuLocation.x, menuLocation.y, 0, 0); - params.view = self.collectionViewController.collectionView; - params.entryURL = entryURL; - params.offlineURL = offlineURL; - - self.contextMenuCoordinator = [[ReadingListContextMenuCoordinator alloc] - initWithBaseViewController:self.containerViewController - params:params]; - self.contextMenuCoordinator.commandHandler = self; - [self.contextMenuCoordinator start]; -} - -- (void)readingListListViewController:(UIViewController*)viewController - openItem:(ListItem<ReadingListListItem>*)item { - const ReadingListEntry* entry = [self.mediator entryFromItem:item]; - if (!entry) { - [self.collectionViewController reloadData]; - return; - } - [self loadEntryURL:entry->URL() - withOfflineURL:GURL::EmptyGURL() - inNewTab:NO - incognito:NO]; -} - -- (void)readingListListViewController:(UIViewController*)viewController - openItemInNewTab:(ListItem<ReadingListListItem>*)item - incognito:(BOOL)incognito { - const ReadingListEntry* entry = [self.mediator entryFromItem:item]; - if (!entry) { - [self.collectionViewController reloadData]; - return; - } - [self loadEntryURL:entry->URL() - withOfflineURL:GURL::EmptyGURL() - inNewTab:YES - incognito:incognito]; -} - -- (void)readingListListViewController:(UIViewController*)viewController - openItemOfflineInNewTab:(id<ReadingListListItem>)item { - const ReadingListEntry* entry = [self.mediator entryFromItem:item]; - if (!entry) - return; - - if (entry->DistilledState() == ReadingListEntry::PROCESSED) { - const GURL entryURL = entry->URL(); - GURL offlineURL = reading_list::OfflineURLForPath( - entry->DistilledPath(), entryURL, entry->DistilledURL()); - [self loadEntryURL:entry->URL() - withOfflineURL:offlineURL - inNewTab:YES - incognito:NO]; - } -} - -#pragma mark - ReadingListContextMenuCommands - -- (void)openURLInNewTabForContextMenuWithParams: - (ReadingListContextMenuParams*)params { - [self loadEntryURL:params.entryURL - withOfflineURL:GURL::EmptyGURL() - inNewTab:YES - incognito:NO]; - [self cleanUpContextMenu]; -} - -- (void)openURLInNewIncognitoTabForContextMenuWithParams: - (ReadingListContextMenuParams*)params { - [self loadEntryURL:params.entryURL - withOfflineURL:GURL::EmptyGURL() - inNewTab:YES - incognito:YES]; - [self cleanUpContextMenu]; -} - -- (void)copyURLForContextMenuWithParams:(ReadingListContextMenuParams*)params { - StoreURLInPasteboard(params.entryURL); - [self cleanUpContextMenu]; -} - -- (void)openOfflineURLInNewTabForContextMenuWithParams: - (ReadingListContextMenuParams*)params { - [self loadEntryURL:params.entryURL - withOfflineURL:params.offlineURL - inNewTab:YES - incognito:NO]; - [self cleanUpContextMenu]; -} - -- (void)cancelReadingListContextMenuWithParams: - (ReadingListContextMenuParams*)params { - [self cleanUpContextMenu]; -} - -#pragma mark - Context Menu Helpers - -// Stops the context menu coordinator and resets the property. -- (void)cleanUpContextMenu { - [self.contextMenuCoordinator stop]; - self.contextMenuCoordinator = nil; -} - -#pragma mark - Private - -// Loads reading list URLs. If |offlineURL| is valid, the item will be loaded -// offline; otherwise |entryURL| is loaded. |newTab| and |incognito| can be -// used to optionally open the URL in a new tab or in incognito. The -// coordinator is also stopped after the load is requested. -- (void)loadEntryURL:(const GURL&)entryURL - withOfflineURL:(const GURL&)offlineURL - inNewTab:(BOOL)newTab - incognito:(BOOL)incognito { - DCHECK(entryURL.is_valid()); - base::RecordAction(base::UserMetricsAction("MobileReadingListOpen")); - new_tab_page_uma::RecordAction( - self.browserState, new_tab_page_uma::ACTION_OPENED_READING_LIST_ENTRY); - - // Load the offline URL if available. - GURL loadURL = entryURL; - if (offlineURL.is_valid()) { - loadURL = offlineURL; - // Offline URLs should always be opened in new tabs. - newTab = YES; - // Record the offline load and update the model. - UMA_HISTOGRAM_BOOLEAN("ReadingList.OfflineVersionDisplayed", true); - const GURL updateURL = entryURL; - [self.mediator markEntryRead:updateURL]; - } - - // Prepare the collection for dismissal. - [self.collectionViewController willBeDismissed]; - - if (newTab) { - // Use a referrer with a specific URL to signal that this entry should not - // be taken into account for the Most Visited tiles. - web::Referrer referrer = web::Referrer(GURL(kReadingListReferrerURL), - web::ReferrerPolicyDefault); - OpenNewTabCommand* command = - [[OpenNewTabCommand alloc] initWithURL:loadURL - referrer:referrer - inIncognito:incognito - inBackground:NO - appendTo:kLastTab]; - [self.URLLoader webPageOrderedOpen:command]; - } else { - web::NavigationManager::WebLoadParams params(loadURL); - params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK; - params.referrer = web::Referrer(GURL(kReadingListReferrerURL), - web::ReferrerPolicyDefault); - [self.URLLoader loadURLWithParams:params]; - } - - [self stop]; -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator_unittest.mm b/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator_unittest.mm deleted file mode 100644 index ef33eec3..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator_unittest.mm +++ /dev/null
@@ -1,202 +0,0 @@ -// 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. - -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_coordinator.h" - -#include <memory> - -#include "base/time/default_clock.h" -#include "components/favicon/core/large_icon_service.h" -#include "components/favicon/core/test/mock_favicon_service.h" -#include "components/feature_engagement/public/event_constants.h" -#include "components/feature_engagement/public/feature_constants.h" -#include "components/feature_engagement/public/tracker.h" -#include "components/feature_engagement/test/mock_tracker.h" -#include "components/reading_list/core/reading_list_entry.h" -#include "components/reading_list/core/reading_list_model_impl.h" -#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#include "ios/chrome/browser/feature_engagement/tracker_factory.h" -#include "ios/chrome/browser/reading_list/offline_url_utils.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_utils.h" -#import "ios/chrome/browser/ui/url_loader.h" -#import "ios/chrome/test/fakes/fake_url_loader.h" -#include "ios/web/public/referrer.h" -#import "ios/web/public/test/web_test_with_web_state.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#import "third_party/ocmock/OCMock/OCMock.h" -#import "third_party/ocmock/gtest_support.h" -#include "ui/base/page_transition_types.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -using favicon::PostReply; -using testing::_; - -#pragma mark - LegacyReadingListCoordinatorTest - -class LegacyReadingListCoordinatorTest : public web::WebTestWithWebState { - public: - LegacyReadingListCoordinatorTest() { - url_loader_ = [[FakeURLLoader alloc] init]; - - TestChromeBrowserState::Builder builder; - builder.AddTestingFactory( - feature_engagement::TrackerFactory::GetInstance(), - base::BindRepeating(&LegacyReadingListCoordinatorTest:: - BuildFeatureEngagementMockTracker)); - browser_state_ = builder.Build(); - - reading_list_model_.reset(new ReadingListModelImpl( - nullptr, nullptr, base::DefaultClock::GetInstance())); - large_icon_service_.reset(new favicon::LargeIconService( - &mock_favicon_service_, /*image_fetcher=*/nullptr)); - mediator_ = [[ReadingListMediator alloc] - initWithModel:reading_list_model_.get() - largeIconService:large_icon_service_.get() - listItemFactory:[ReadingListListItemFactory - collectionViewItemFactory]]; - coordinator_ = [[LegacyReadingListCoordinator alloc] - initWithBaseViewController:nil - browserState:browser_state_.get() - loader:url_loader_]; - coordinator_.mediator = mediator_; - - EXPECT_CALL(mock_favicon_service_, - GetLargestRawFaviconForPageURL(_, _, _, _, _)) - .WillRepeatedly(PostReply<5>(favicon_base::FaviconRawBitmapResult())); - } - - ~LegacyReadingListCoordinatorTest() override {} - - LegacyReadingListCoordinator* GetCoordinator() { return coordinator_; } - - ReadingListModel* GetReadingListModel() { return reading_list_model_.get(); } - FakeURLLoader* GetLoader() { return url_loader_; } - - ios::ChromeBrowserState* GetBrowserState() { return browser_state_.get(); } - - ReadingListCollectionViewController* - GetAReadingListCollectionViewController() { - return [[ReadingListCollectionViewController alloc] - initWithDataSource:mediator_ - toolbar:nil]; - } - - static std::unique_ptr<KeyedService> BuildFeatureEngagementMockTracker( - web::BrowserState*) { - return std::make_unique<feature_engagement::test::MockTracker>(); - } - - private: - LegacyReadingListCoordinator* coordinator_; - ReadingListMediator* mediator_; - std::unique_ptr<ReadingListModelImpl> reading_list_model_; - FakeURLLoader* url_loader_; - testing::StrictMock<favicon::MockFaviconService> mock_favicon_service_; - std::unique_ptr<favicon::LargeIconService> large_icon_service_; - std::unique_ptr<TestChromeBrowserState> browser_state_; -}; - -// Tests that the implementation of LegacyReadingListCoordinator -// openItemAtIndexPath opens the entry. -TEST_F(LegacyReadingListCoordinatorTest, OpenItem) { - // Setup. - GURL url("https://chromium.org"); - std::string title("Chromium"); - ReadingListModel* model = GetReadingListModel(); - model->AddEntry(url, title, reading_list::ADDED_VIA_CURRENT_APP); - - ReadingListCollectionViewItem* item = - [[ReadingListCollectionViewItem alloc] initWithType:0]; - item.entryURL = url; - item.distillationState = ReadingListUIDistillationStatusSuccess; - - // Action. - [GetCoordinator() - readingListListViewController:GetAReadingListCollectionViewController() - openItem:item]; - - // Tests. - FakeURLLoader* loader = GetLoader(); - EXPECT_EQ(url, loader.url); - EXPECT_TRUE(ui::PageTransitionCoreTypeIs(ui::PAGE_TRANSITION_AUTO_BOOKMARK, - loader.transition)); - EXPECT_EQ(NO, loader.rendererInitiated); -} - -TEST_F(LegacyReadingListCoordinatorTest, OpenItemOffline) { - // Setup. - GURL url("https://chromium.org"); - std::string title("Chromium"); - ReadingListModel* model = GetReadingListModel(); - model->AddEntry(url, title, reading_list::ADDED_VIA_CURRENT_APP); - base::FilePath distilled_path("test"); - GURL distilled_url("https://distilled.com"); - model->SetEntryDistilledInfo(url, distilled_path, distilled_url, 123, - base::Time::FromTimeT(10)); - - ReadingListCollectionViewItem* item = - [[ReadingListCollectionViewItem alloc] init]; - item.entryURL = url; - item.distillationState = ReadingListUIDistillationStatusSuccess; - GURL offlineURL = - reading_list::OfflineURLForPath(distilled_path, url, distilled_url); - ASSERT_FALSE(model->GetEntryByURL(url)->IsRead()); - - // Action. - [GetCoordinator() - readingListListViewController:GetAReadingListCollectionViewController() - openItemOfflineInNewTab:item]; - - // Tests. - FakeURLLoader* loader = GetLoader(); - EXPECT_EQ(offlineURL, loader.url); - EXPECT_FALSE(loader.inIncognito); - EXPECT_TRUE(model->GetEntryByURL(url)->IsRead()); -} - -TEST_F(LegacyReadingListCoordinatorTest, OpenItemInNewTab) { - // Setup. - GURL url("https://chromium.org"); - std::string title("Chromium"); - ReadingListModel* model = GetReadingListModel(); - model->AddEntry(url, title, reading_list::ADDED_VIA_CURRENT_APP); - - ReadingListCollectionViewItem* item = - [[ReadingListCollectionViewItem alloc] init]; - item.entryURL = url; - item.distillationState = ReadingListUIDistillationStatusSuccess; - - // Action. - [GetCoordinator() - readingListListViewController:GetAReadingListCollectionViewController() - openItemInNewTab:item - incognito:YES]; - - // Tests. - FakeURLLoader* loader = GetLoader(); - EXPECT_EQ(url, loader.url); - EXPECT_TRUE(loader.inIncognito); -} - -TEST_F(LegacyReadingListCoordinatorTest, SendViewedReadingListEventInStart) { - // Setup. - feature_engagement::test::MockTracker* tracker = - static_cast<feature_engagement::test::MockTracker*>( - feature_engagement::TrackerFactory::GetForBrowserState( - GetBrowserState())); - - // Actions and Tests. - EXPECT_CALL((*tracker), - NotifyEvent(feature_engagement::events::kViewedReadingList)); - [GetCoordinator() start]; -}
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h deleted file mode 100644 index be47c61b..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2016 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 IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_TOOLBAR_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_TOOLBAR_H_ - -#import <UIKit/UIKit.h> - -@class ActionSheetCoordinator; -@class LegacyReadingListToolbar; - -typedef NS_ENUM(NSInteger, LegacyReadingListToolbarState) { - NoneSelected, - OnlyReadSelected, - OnlyUnreadSelected, - MixedItemsSelected -}; - -typedef NS_ENUM(NSInteger, LegacyReadingListToolbarHeight) { - NormalHeight, - ExpandedHeight -}; - -@protocol LegacyReadingListToolbarActions<NSObject> - -// Callback for the toolbar mark button. -- (void)markPressed; -// Callback for the toolbar delete button. -- (void)deletePressed; -// Enters editing mode. Updates the toolbar. -- (void)enterEditingModePressed; -// Exits editing mode. Updates the toolbar. -- (void)exitEditingModePressed; - -@end - -// View at the bottom of the reading list panel that presents options to edit -// the entries. When editing, the interface changes, allowing the user to delete -// them and mark them read/unread. -@interface LegacyReadingListToolbar : UIView - -// The toolbar state. The text of the buttons change to reflect the state. -@property(nonatomic, assign) LegacyReadingListToolbarState state; - -// Informs the toolbar whether there are read items. The "Delete All Read" -// button will be enabled accordingly. -- (void)setHasReadItem:(BOOL)hasRead; -// Sets the editing mode for the toolbar, showing/hiding buttons accordingly. -- (void)setEditing:(BOOL)editing; -// Returns an empty ActionSheetCoordiantor anchored to the mark button with no -// message and no title. -- (ActionSheetCoordinator*)actionSheetForMarkWithBaseViewController: - (UIViewController*)viewController; -// Updates the height of the toolbar. -- (void)updateHeight; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_TOOLBAR_H_
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.mm b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.mm deleted file mode 100644 index 608b147..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.mm +++ /dev/null
@@ -1,293 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h" - -#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button_identifiers.h" -#import "ios/chrome/common/ui_util/constraints_ui_util.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" -#include "ui/base/l10n/l10n_util_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -const CGFloat kToolbarNormalHeight = 48.0f; -// Height of the toolbar when button labels has word-wrap up to 2 lines. -const CGFloat kToolbarTwoLinesHeight = 58.0f; -// Height of the toolbar when button labels has word-wrap up to 3 lines. -const CGFloat kToolbarThreeLinesHeight = 68.0f; -// Shadow opacity. -const CGFloat kShadowOpacity = 0.12f; -// Shadow radius. -const CGFloat kShadowRadius = 12.0f; -// Horizontal margin for the stack view content. -const CGFloat kHorizontalMargin = 16.0f; -// Vertical margin for the stack view content. -const CGFloat kVerticalMargin = 8.0f; -// Horizontal spacing between the buttons of the stack view. This is used for -// calculating the maximum width of buttons but NOT used directly to set -// stackView.spacing. -const CGFloat kHorizontalSpacing = 8.0f; - -} // namespace - -@interface LegacyReadingListToolbar () - -// Button that displays "Edit". -@property(nonatomic, strong) LegacyReadingListToolbarButton* editButton; -// Button that displays "Delete". -@property(nonatomic, strong) LegacyReadingListToolbarButton* deleteButton; -// Button that displays "Delete All Read". -@property(nonatomic, strong) LegacyReadingListToolbarButton* deleteAllButton; -// Button that displays "Cancel". -@property(nonatomic, strong) LegacyReadingListToolbarButton* cancelButton; -// Button that displays the mark options. -@property(nonatomic, strong) LegacyReadingListToolbarButton* markButton; -// Stack view for arranging the buttons. -@property(nonatomic, strong) UIStackView* stackView; -// Height constraint for the stack view containing the buttons. -@property(nonatomic, strong) NSLayoutConstraint* heightConstraint; - -// Set the mark button label to |text|. -- (void)setMarkButtonText:(NSString*)text; -// Updates the button labels to match an empty selection. -- (void)updateButtonsForEmptySelection; -// Updates the button labels to match a selection containing only read items. -- (void)updateButtonsForOnlyReadSelection; -// Updates the button labels to match a selection containing only unread items. -- (void)updateButtonsForOnlyUnreadSelection; -// Updates the button labels to match a selection containing unread and read -// items. -- (void)updateButtonsForOnlyMixedSelection; - -@end - -@implementation LegacyReadingListToolbar - -@synthesize editButton = _editButton; -@synthesize deleteButton = _deleteButton; -@synthesize deleteAllButton = _deleteAllButton; -@synthesize cancelButton = _cancelButton; -@synthesize markButton = _markButton; -@synthesize stackView = _stackView; -@synthesize state = _state; -@synthesize heightConstraint = _heightConstraint; - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _deleteButton = [[LegacyReadingListToolbarButton alloc] - initWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_DELETE_BUTTON) - destructive:YES - position:Leading - identifier:kReadingListToolbarDeleteButtonID]; - - _deleteAllButton = [[LegacyReadingListToolbarButton alloc] - initWithText:l10n_util::GetNSString( - IDS_IOS_READING_LIST_DELETE_ALL_READ_BUTTON) - destructive:YES - position:Leading - identifier:kReadingListToolbarDeleteAllReadButtonID]; - - _markButton = [[LegacyReadingListToolbarButton alloc] - initWithText:l10n_util::GetNSString( - IDS_IOS_READING_LIST_MARK_ALL_BUTTON) - destructive:NO - position:Centered - identifier:kReadingListToolbarMarkButtonID]; - - _cancelButton = [[LegacyReadingListToolbarButton alloc] - initWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_CANCEL_BUTTON) - destructive:NO - position:Trailing - identifier:kReadingListToolbarCancelButtonID]; - - _editButton = [[LegacyReadingListToolbarButton alloc] - initWithText:l10n_util::GetNSString(IDS_IOS_READING_LIST_EDIT_BUTTON) - destructive:NO - position:Trailing - identifier:kReadingListToolbarEditButtonID]; - - [_editButton addTarget:nil - action:@selector(enterEditingModePressed) - forControlEvents:UIControlEventTouchUpInside]; - - [_deleteButton addTarget:nil - action:@selector(deletePressed) - forControlEvents:UIControlEventTouchUpInside]; - - [_deleteAllButton addTarget:nil - action:@selector(deletePressed) - forControlEvents:UIControlEventTouchUpInside]; - - [_markButton addTarget:nil - action:@selector(markPressed) - forControlEvents:UIControlEventTouchUpInside]; - - [_cancelButton addTarget:nil - action:@selector(exitEditingModePressed) - forControlEvents:UIControlEventTouchUpInside]; - - _stackView = [[UIStackView alloc] initWithArrangedSubviews:@[ - _editButton, _deleteButton, _deleteAllButton, _markButton, _cancelButton - ]]; - _stackView.axis = UILayoutConstraintAxisHorizontal; - _stackView.alignment = UIStackViewAlignmentFill; - _stackView.distribution = UIStackViewDistributionFillEqually; - - [self addSubview:_stackView]; - _stackView.translatesAutoresizingMaskIntoConstraints = NO; - - PinToSafeArea(_stackView, self); - _heightConstraint = [_stackView.heightAnchor - constraintEqualToConstant:kToolbarNormalHeight]; - _heightConstraint.active = YES; - - _stackView.layoutMargins = UIEdgeInsetsMake( - kVerticalMargin, kHorizontalMargin, kVerticalMargin, kHorizontalMargin); - _stackView.layoutMarginsRelativeArrangement = YES; - - self.backgroundColor = [UIColor whiteColor]; - [[self layer] setShadowOpacity:kShadowOpacity]; - [[self layer] setShadowRadius:kShadowRadius]; - [self setEditing:NO]; - } - return self; -} - -#pragma mark Public Methods - -- (void)setEditing:(BOOL)editing { - self.editButton.hidden = editing; - self.deleteButton.hidden = YES; - self.deleteAllButton.hidden = !editing; - self.cancelButton.hidden = !editing; - self.markButton.hidden = !editing; - - [self updateHeight]; -} - -- (void)setState:(LegacyReadingListToolbarState)state { - switch (state) { - case NoneSelected: - [self updateButtonsForEmptySelection]; - break; - case OnlyReadSelected: - [self updateButtonsForOnlyReadSelection]; - break; - case OnlyUnreadSelected: - [self updateButtonsForOnlyUnreadSelection]; - break; - case MixedItemsSelected: - [self updateButtonsForOnlyMixedSelection]; - break; - } - _state = state; - - [self updateHeight]; -} - -- (void)setHasReadItem:(BOOL)hasRead { - [self.deleteAllButton setEnabled:hasRead]; -} - -- (ActionSheetCoordinator*)actionSheetForMarkWithBaseViewController: - (UIViewController*)viewController { - return [[ActionSheetCoordinator alloc] - initWithBaseViewController:viewController - title:nil - message:nil - rect:self.markButton.bounds - view:self.markButton]; -} - -#pragma mark Private Methods - -- (void)updateButtonsForEmptySelection { - self.deleteAllButton.hidden = NO; - self.deleteButton.hidden = YES; - [self setMarkButtonText:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_ALL_BUTTON)]; -} - -- (void)updateButtonsForOnlyReadSelection { - self.deleteAllButton.hidden = YES; - self.deleteButton.hidden = NO; - [self setMarkButtonText:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_UNREAD_BUTTON)]; -} - -- (void)updateButtonsForOnlyUnreadSelection { - self.deleteAllButton.hidden = YES; - self.deleteButton.hidden = NO; - [self setMarkButtonText:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_READ_BUTTON)]; -} - -- (void)updateButtonsForOnlyMixedSelection { - self.deleteAllButton.hidden = YES; - self.deleteButton.hidden = NO; - [self setMarkButtonText:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_BUTTON)]; -} - -- (void)setMarkButtonText:(NSString*)text { - [self.markButton setTitle:text]; -} - -- (void)updateHeight { - NSArray* buttons = @[ - _editButton, _deleteButton, _deleteAllButton, _markButton, _cancelButton - ]; - - CGFloat availableWidth = self.frame.size.width - kHorizontalMargin * 2; - NSUInteger visibleCount = 0; - - // Count the number of visible buttons and deduct the button spacings from - // availableWidth. - for (LegacyReadingListToolbarButton* button in buttons) { - if (!button.hidden) { - visibleCount++; - if (visibleCount > 1) { - availableWidth -= kHorizontalSpacing; - } - } - } - - // Set the button width manually here instead of relying on UIStackView's auto - // width distribution which is unpredictable when rounding happens. - CGFloat maxButtonWidth = ceil(availableWidth / visibleCount); - for (LegacyReadingListToolbarButton* button in buttons) { - if (!button.hidden) { - [button setMaxWidth:maxButtonWidth]; - } - } - - CGFloat toolbarHeight = kToolbarNormalHeight; - CGFloat lineHeight = - ceil([LegacyReadingListToolbarButton textFont].lineHeight); - CGSize labelBounds = CGSizeMake(maxButtonWidth, CGFLOAT_MAX); - // Expand toolbar height in case word wrapping happens. - for (LegacyReadingListToolbarButton* button in buttons) { - if (!button.hidden) { - CGFloat labelHeight = - [[button titleLabel] sizeThatFits:labelBounds].height; - if (labelHeight > lineHeight * 2) { - toolbarHeight = kToolbarThreeLinesHeight; - break; - } - if (labelHeight > lineHeight) { - toolbarHeight = kToolbarTwoLinesHeight; - } - } - } - self.heightConstraint.constant = toolbarHeight; -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h deleted file mode 100644 index e8e5f62..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h +++ /dev/null
@@ -1,44 +0,0 @@ -// 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 IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_TOOLBAR_BUTTON_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_TOOLBAR_BUTTON_H_ - -#import <UIKit/UIKit.h> - -typedef NS_ENUM(NSInteger, ButtonPositioning) { Leading, Centered, Trailing }; - -// A button class for the buttons in LegacyReadingListToolbar's stackview. -// Handles the layout alignment of the button and its titleLabel. -@interface LegacyReadingListToolbarButton : UIView - -// Initializer. -- (instancetype)initWithText:(NSString*)labelText - destructive:(BOOL)isDestructive - position:(ButtonPositioning)position - identifier:(NSString*)identifier; - -// Associates a target object and action method with the UIButton. -- (void)addTarget:(id)target - action:(SEL)action - forControlEvents:(UIControlEvents)controlEvents; - -// Sets the title text of the UIButton. -- (void)setTitle:(NSString*)title; - -// Enables or disables the UIButton. -- (void)setEnabled:(BOOL)enabled; - -// Gets the titleLabel of the UIButton. -- (UILabel*)titleLabel; - -// Sets the maximum width contraint of LegacyReadingListToolbarButton. -- (void)setMaxWidth:(CGFloat)maxWidth; - -// The font of the title text. -+ (UIFont*)textFont; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_TOOLBAR_BUTTON_H_
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.mm b/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.mm deleted file mode 100644 index c522cd6..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.mm +++ /dev/null
@@ -1,176 +0,0 @@ -// 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. - -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h" - -#include "base/logging.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#include "ios/chrome/browser/ui/rtl_geometry.h" -#import "ios/chrome/common/ui_util/constraints_ui_util.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface LegacyReadingListToolbarButton () - -// The actual UIButton object inside LegacyReadingListToolbarButton. -@property(nonatomic, strong) UIButton* button; - -// Width constraint for the LegacyReadingListToolbarButton. -@property(nonatomic, strong) NSLayoutConstraint* widthConstraint; - -@end - -@implementation LegacyReadingListToolbarButton - -@synthesize button = _button; -@synthesize widthConstraint = _widthConstraint; - -#pragma mark - Public - -- (instancetype)initWithText:(NSString*)labelText - destructive:(BOOL)isDestructive - position:(ButtonPositioning)position - identifier:(NSString*)identifier { - self = [super init]; - if (!self) { - return self; - } - - _button = [self buttonWithText:labelText - destructive:isDestructive - position:position]; - _button.translatesAutoresizingMaskIntoConstraints = NO; - _button.accessibilityIdentifier = identifier; - [self addSubview:_button]; - - NSDictionary* views = @{@"button" : _button}; - NSArray* constraints = nil; - - switch (position) { - case Leading: { - constraints = @[ @"V:|[button]|", @"H:|[button]" ]; - ApplyVisualConstraints(constraints, views); - [_button.trailingAnchor - constraintLessThanOrEqualToAnchor:self.trailingAnchor] - .active = YES; - break; - } - case Centered: { - constraints = @[ @"V:|[button]|" ]; - ApplyVisualConstraints(constraints, views); - [_button.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] - .active = YES; - [_button.trailingAnchor - constraintLessThanOrEqualToAnchor:self.trailingAnchor] - .active = YES; - [_button.leadingAnchor - constraintGreaterThanOrEqualToAnchor:self.leadingAnchor] - .active = YES; - break; - } - case Trailing: { - constraints = @[ @"V:|[button]|", @"H:[button]|" ]; - ApplyVisualConstraints(constraints, views); - [_button.leadingAnchor - constraintGreaterThanOrEqualToAnchor:self.leadingAnchor] - .active = YES; - break; - } - } - return self; -} - -- (void)addTarget:(id)target - action:(SEL)action - forControlEvents:(UIControlEvents)controlEvents { - [self.button addTarget:target action:action forControlEvents:controlEvents]; -} - -- (void)setTitle:(NSString*)title { - [self.button setTitle:title forState:UIControlStateNormal]; -} - -- (void)setEnabled:(BOOL)enabled { - self.button.enabled = enabled; -} - -- (UILabel*)titleLabel { - return self.button.titleLabel; -} - -- (void)setMaxWidth:(CGFloat)maxWidth { - if (!self.widthConstraint) { - self.widthConstraint = - [self.button.widthAnchor constraintLessThanOrEqualToConstant:maxWidth]; - self.widthConstraint.active = YES; - } - self.widthConstraint.constant = maxWidth; -} - -#pragma mark - Private - -- (UIButton*)buttonWithText:(NSString*)title - destructive:(BOOL)isDestructive - position:(ButtonPositioning)position { - UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; - [button setTitle:title forState:UIControlStateNormal]; - button.titleLabel.numberOfLines = 3; - button.titleLabel.adjustsFontSizeToFitWidth = YES; - - button.backgroundColor = [UIColor whiteColor]; - UIColor* textColor = isDestructive ? [[MDCPalette cr_redPalette] tint500] - : [[MDCPalette cr_bluePalette] tint500]; - [button setTitleColor:textColor forState:UIControlStateNormal]; - [button setTitleColor:[UIColor lightGrayColor] - forState:UIControlStateDisabled]; - [button setTitleColor:[textColor colorWithAlphaComponent:0.3] - forState:UIControlStateHighlighted]; - [[button titleLabel] setFont:[[self class] textFont]]; - - switch (position) { - case Leading: { - button.titleLabel.textAlignment = NSTextAlignmentNatural; - if (UseRTLLayout()) { - button.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentRight; - } else { - button.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeft; - } - break; - } - case Centered: { - button.titleLabel.textAlignment = NSTextAlignmentCenter; - button.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentCenter; - break; - } - case Trailing: { - if (UseRTLLayout()) { - button.titleLabel.textAlignment = NSTextAlignmentLeft; - button.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeft; - } else { - button.titleLabel.textAlignment = NSTextAlignmentRight; - button.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentRight; - } - break; - } - } - - return button; -} - -#pragma mark - Static Properties - -// The font of the title text. -+ (UIFont*)textFont { - return [MDCTypography subheadFont]; -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.h b/ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.h deleted file mode 100644 index 752cf32..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2016 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 IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_VIEW_CONTROLLER_H_ - -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h" - -@class ReadingListCollectionViewController; -@protocol ReadingListListViewControllerDelegate; - -// Container for the ReadingList Collection View Controller and the toolbar. It -// handles the interactions between the two. -@interface LegacyReadingListViewController : UIViewController - -- (instancetype) -initWithCollectionViewController: - (ReadingListCollectionViewController*)collectionViewController - toolbar:(LegacyReadingListToolbar*)toolbar - NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithNibName:(NSString*)nibNameOrNil - bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; -- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; -- (instancetype)init NS_UNAVAILABLE; - -@property(nonatomic, weak) id<ReadingListListViewControllerDelegate> delegate; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_LEGACY_READING_LIST_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.mm b/ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.mm deleted file mode 100644 index acccdc0..0000000 --- a/ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.mm +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_view_controller.h" - -#import <MobileCoreServices/MobileCoreServices.h> - -#import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h" -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h" -#import "ios/chrome/common/ui_util/constraints_ui_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -typedef NS_ENUM(NSInteger, LayoutPriority) { - LayoutPriorityLow = 750, - LayoutPriorityHigh = 751 -}; -} - -@interface LegacyReadingListViewController ()< - LegacyReadingListToolbarActions, - ReadingListListViewControllerAudience> - -@property(nonatomic, strong, readonly) - ReadingListCollectionViewController* readingListCollectionViewController; -@property(nonatomic, strong, readonly) LegacyReadingListToolbar* toolbar; - -@end - -@implementation LegacyReadingListViewController - -@synthesize delegate = _delegate; -@synthesize readingListCollectionViewController = - _readingListCollectionViewController; -@synthesize toolbar = _toolbar; - -- (instancetype) -initWithCollectionViewController: - (ReadingListCollectionViewController*)collectionViewController - toolbar:(LegacyReadingListToolbar*)toolbar { - self = [super initWithNibName:nil bundle:nil]; - if (self) { - _toolbar = toolbar; - _readingListCollectionViewController = collectionViewController; - collectionViewController.audience = self; - - // Configure modal presentation. - [self setModalPresentationStyle:UIModalPresentationFormSheet]; - [self setModalTransitionStyle:UIModalTransitionStyleCoverVertical]; - } - return self; -} - -- (void)viewDidLoad { - [self addChildViewController:self.readingListCollectionViewController]; - [self.view addSubview:self.readingListCollectionViewController.view]; - [self.readingListCollectionViewController didMoveToParentViewController:self]; - - [_toolbar setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self.readingListCollectionViewController.view - setTranslatesAutoresizingMaskIntoConstraints:NO]; - - NSDictionary* views = - @{@"collection" : self.readingListCollectionViewController.view}; - NSArray* constraints = @[ @"V:|[collection]", @"H:|[collection]|" ]; - ApplyVisualConstraints(constraints, views); - - // This constraint has a low priority so it will only take effect when the - // toolbar isn't present, allowing the collection to take the whole page. - NSLayoutConstraint* constraint = - [self.readingListCollectionViewController.view.bottomAnchor - constraintEqualToAnchor:self.view.bottomAnchor]; - constraint.priority = LayoutPriorityLow; - constraint.active = YES; -} - -- (BOOL)prefersStatusBarHidden { - return NO; -} - -#pragma mark UIAccessibilityAction - -- (BOOL)accessibilityPerformEscape { - [self.delegate dismissReadingListListViewController: - self.readingListCollectionViewController]; - return YES; -} - -#pragma mark - LegacyReadingListToolbarActionTarget - -- (void)markPressed { - [self.readingListCollectionViewController markPressed]; -} - -- (void)deletePressed { - [self.readingListCollectionViewController deletePressed]; -} - -- (void)enterEditingModePressed { - // Ignore the button tap if view controller presenting. - if ([self presentedViewController]) { - return; - } - [self.readingListCollectionViewController enterEditingModePressed]; -} - -- (void)exitEditingModePressed { - [self.readingListCollectionViewController exitEditingModePressed]; -} - -#pragma mark - ReadingListListViewControllerAudience - -- (void)readingListHasItems:(BOOL)hasItems { - if (hasItems) { - // If there are items, add the toolbar. - [self.view addSubview:_toolbar]; - NSDictionary* views = @{ - @"toolbar" : _toolbar, - @"collection" : self.readingListCollectionViewController.view - }; - NSArray* constraints = @[ @"V:[collection][toolbar]|", @"H:|[toolbar]|" ]; - ApplyVisualConstraints(constraints, views); - } else { - // If there is no item, remove the toolbar. The constraints will make sure - // the collection takes the whole view. - [_toolbar removeFromSuperview]; - } -} - -#pragma mark - UIResponder - -- (BOOL)canBecomeFirstResponder { - return YES; -} - -- (NSArray*)keyCommands { - __weak LegacyReadingListViewController* weakSelf = self; - return - @[ [UIKeyCommand cr_keyCommandWithInput:UIKeyInputEscape - modifierFlags:Cr_UIKeyModifierNone - title:nil - action:^{ - [weakSelf accessibilityPerformEscape]; - }] ]; -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h deleted file mode 100644 index 61526f1..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h +++ /dev/null
@@ -1,33 +0,0 @@ -// 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 IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_CELL_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_CELL_H_ - -#import "ios/chrome/browser/ui/reading_list/reading_list_ui_distillation_status.h" -#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h" - -@class FaviconViewNew; - -// Cell for ReadingListCollectionViewItem. -@interface ReadingListCell : MDCCollectionViewCell - -// Title label. -@property(nonatomic, readonly, strong) UILabel* titleLabel; -// Subtitle label. -@property(nonatomic, readonly, strong) UILabel* subtitleLabel; -// Timestamp of the distillation in microseconds since Jan 1st 1970. -@property(nonatomic, readonly, strong) UILabel* distillationDateLabel; -// Size of the distilled files. -@property(nonatomic, readonly, strong) UILabel* distillationSizeLabel; -// Whether to show |distillationDateLabel| and |distillationSizeLabel|. -@property(nonatomic, assign) BOOL showDistillationInfo; -// View for displaying the favicon for the reading list entry. -@property(nonatomic, readonly, strong) FaviconViewNew* faviconView; -// Status of the offline version. Updates the visual indicator when updated. -@property(nonatomic, assign) ReadingListUIDistillationStatus distillationState; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_CELL_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.mm deleted file mode 100644 index 5bb51e8..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.mm +++ /dev/null
@@ -1,240 +0,0 @@ -// 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. - -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h" - -#include "base/strings/sys_string_conversions.h" -#include "base/time/time.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#import "ios/chrome/common/favicon/favicon_view.h" -#import "ios/chrome/common/ui_util/constraints_ui_util.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/l10n/time_format.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -NSString* kSuccessImageString = @"distillation_success"; -NSString* kFailureImageString = @"distillation_fail"; - -// Height of the cell. -const CGFloat kCellHeight = 72; - -// Distillation indicator constants. -const CGFloat kDistillationIndicatorSize = 18; - -// Margin for the elements displayed in the cell. -const CGFloat kMargin = 16; - -// Transparency of the distillation size and date. -const CGFloat kInfoTextTransparency = 0.38; -} // namespace - -@implementation ReadingListCell { - UIImageView* _downloadIndicator; - UILayoutGuide* _textGuide; - - // View containing |_distillationSizeLabel| and |_distillationDateLabel|. - UIView* _infoView; -} -@synthesize faviconView = _faviconView; -@synthesize titleLabel = _titleLabel; -@synthesize subtitleLabel = _subtitleLabel; -@synthesize distillationDateLabel = _distillationDateLabel; -@synthesize distillationSizeLabel = _distillationSizeLabel; -@synthesize showDistillationInfo = _showDistillationInfo; -@synthesize distillationState = _distillationState; - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - id<MDCTypographyFontLoading> fontLoader = [MDCTypography fontLoader]; - CGFloat faviconSize = kFaviconPreferredSize; - _titleLabel = [[UILabel alloc] init]; - _titleLabel.font = [fontLoader mediumFontOfSize:16]; - _titleLabel.textColor = [[MDCPalette greyPalette] tint900]; - _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; - _titleLabel.accessibilityIdentifier = @"Reading List Item title"; - - _subtitleLabel = [[UILabel alloc] init]; - _subtitleLabel.font = [fontLoader mediumFontOfSize:14]; - _subtitleLabel.textColor = [[MDCPalette greyPalette] tint500]; - _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; - _subtitleLabel.accessibilityIdentifier = @"Reading List Item subtitle"; - - _distillationDateLabel = [[UILabel alloc] init]; - _distillationDateLabel.font = [fontLoader mediumFontOfSize:12]; - [_distillationDateLabel - setContentHuggingPriority:UILayoutPriorityDefaultHigh - forAxis:UILayoutConstraintAxisHorizontal]; - _distillationDateLabel.textColor = - [UIColor colorWithWhite:0 alpha:kInfoTextTransparency]; - _distillationDateLabel.translatesAutoresizingMaskIntoConstraints = NO; - _distillationDateLabel.accessibilityIdentifier = - @"Reading List Item distillation date"; - - _distillationSizeLabel = [[UILabel alloc] init]; - _distillationSizeLabel.font = [fontLoader mediumFontOfSize:12]; - [_distillationSizeLabel - setContentHuggingPriority:UILayoutPriorityDefaultHigh - forAxis:UILayoutConstraintAxisHorizontal]; - _distillationSizeLabel.textColor = - [UIColor colorWithWhite:0 alpha:kInfoTextTransparency]; - _distillationSizeLabel.translatesAutoresizingMaskIntoConstraints = NO; - _distillationSizeLabel.accessibilityIdentifier = - @"Reading List Item distillation size"; - - _faviconView = [[FaviconViewNew alloc] init]; - CGFloat fontSize = floorf(faviconSize / 2); - [_faviconView setFont:[fontLoader regularFontOfSize:fontSize]]; - _faviconView.translatesAutoresizingMaskIntoConstraints = NO; - - _downloadIndicator = [[UIImageView alloc] init]; - [_downloadIndicator setTranslatesAutoresizingMaskIntoConstraints:NO]; - _downloadIndicator.accessibilityIdentifier = - @"Reading List Item download indicator"; - [_faviconView addSubview:_downloadIndicator]; - - [self.contentView addSubview:_faviconView]; - [self.contentView addSubview:_titleLabel]; - [self.contentView addSubview:_subtitleLabel]; - - _infoView = [[UIView alloc] initWithFrame:CGRectZero]; - [_infoView addSubview:_distillationDateLabel]; - [_infoView addSubview:_distillationSizeLabel]; - _infoView.translatesAutoresizingMaskIntoConstraints = NO; - - _textGuide = [[UILayoutGuide alloc] init]; - [self.contentView addLayoutGuide:_textGuide]; - - ApplyVisualConstraintsWithMetrics( - @[ - @"H:|[date]-(>=margin)-[size]|", - @"V:[title][subtitle]", - @"H:|-(margin)-[favicon]-(margin)-[title]-(>=margin)-|", - @"H:[favicon]-(margin)-[subtitle]-(>=margin)-|", - @"V:|[date]|", - @"V:|[size]|", - ], - @{ - @"favicon" : _faviconView, - @"title" : _titleLabel, - @"subtitle" : _subtitleLabel, - @"date" : _distillationDateLabel, - @"size" : _distillationSizeLabel, - }, - @{ - @"margin" : @(kMargin), - }); - - // Sets the bottom of the text. Lower the priority so we can add the details - // later. - NSLayoutConstraint* bottomTextConstraint = [_textGuide.bottomAnchor - constraintEqualToAnchor:_subtitleLabel.bottomAnchor]; - bottomTextConstraint.priority = UILayoutPriorityDefaultHigh; - NSLayoutConstraint* topTextConstraint = - [_textGuide.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor]; - - [NSLayoutConstraint activateConstraints:@[ - // Height for the cell. - [self.contentView.heightAnchor constraintEqualToConstant:kCellHeight], - - // Text constraints. - topTextConstraint, - bottomTextConstraint, - - // Favicons are always the same size. - [_faviconView.widthAnchor constraintEqualToConstant:faviconSize], - [_faviconView.heightAnchor constraintEqualToConstant:faviconSize], - - // Center the content (favicon and text) vertically. - [_faviconView.centerYAnchor - constraintEqualToAnchor:self.contentView.centerYAnchor], - [_textGuide.centerYAnchor - constraintEqualToAnchor:self.contentView.centerYAnchor], - - // Place the download indicator in the bottom right corner of the favicon. - [[_downloadIndicator centerXAnchor] - constraintEqualToAnchor:_faviconView.trailingAnchor], - [[_downloadIndicator centerYAnchor] - constraintEqualToAnchor:_faviconView.bottomAnchor], - [[_downloadIndicator widthAnchor] - constraintEqualToConstant:kDistillationIndicatorSize], - [[_downloadIndicator heightAnchor] - constraintEqualToConstant:kDistillationIndicatorSize], - ]]; - - self.editingSelectorColor = [[MDCPalette cr_bluePalette] tint500]; - } - return self; -} - -- (void)setDistillationState: - (ReadingListUIDistillationStatus)distillationState { - if (_distillationState == distillationState) - return; - - _distillationState = distillationState; - switch (distillationState) { - case ReadingListUIDistillationStatusFailure: - [_downloadIndicator setImage:[UIImage imageNamed:kFailureImageString]]; - break; - - case ReadingListUIDistillationStatusSuccess: - [_downloadIndicator setImage:[UIImage imageNamed:kSuccessImageString]]; - break; - - case ReadingListUIDistillationStatusPending: - [_downloadIndicator setImage:nil]; - break; - } -} - -- (void)setShowDistillationInfo:(BOOL)showDistillationInfo { - if (_showDistillationInfo == showDistillationInfo) - return; - - _showDistillationInfo = showDistillationInfo; - if (!_showDistillationInfo) { - [_infoView removeFromSuperview]; - return; - } - [self.contentView addSubview:_infoView]; - ApplyVisualConstraintsWithMetrics( - @[ - @"H:|-(margin)-[favicon]-(margin)-[detail]-(margin)-|", - ], - @{ - @"favicon" : _faviconView, - @"detail" : _infoView, - }, - @{ - @"margin" : @(kMargin), - }); - [NSLayoutConstraint activateConstraints:@[ - [_infoView.topAnchor constraintEqualToAnchor:_subtitleLabel.bottomAnchor], - [_infoView.bottomAnchor constraintEqualToAnchor:_textGuide.bottomAnchor], - ]]; -} - -#pragma mark - UICollectionViewCell - -- (void)prepareForReuse { - self.titleLabel.text = nil; - self.subtitleLabel.text = nil; - self.distillationDateLabel.text = nil; - self.distillationSizeLabel.text = nil; - self.showDistillationInfo = NO; - self.distillationState = ReadingListUIDistillationStatusPending; - [self.faviconView configureWithAttributes:nil]; - self.accessibilityCustomActions = nil; - [super prepareForReuse]; -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h deleted file mode 100644 index 22c6bedd..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2016 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 IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_CONTROLLER_H_ - -#import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" - -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h" - -@protocol ReadingListDataSource; -@protocol ReadingListListViewControllerAudience; -@protocol ReadingListListViewControllerDelegate; - -@interface ReadingListCollectionViewController - : CollectionViewController<ReadingListListItemAccessibilityDelegate, - LegacyReadingListToolbarActions> - -- (instancetype)initWithDataSource:(id<ReadingListDataSource>)dataSource - toolbar:(LegacyReadingListToolbar*)toolbar - NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithLayout:(UICollectionViewLayout*)layout - style:(CollectionViewControllerStyle)style - NS_UNAVAILABLE; - -@property(nonatomic, weak) id<ReadingListListViewControllerDelegate> delegate; -@property(nonatomic, weak) id<ReadingListListViewControllerAudience> audience; -@property(nonatomic, weak) id<ReadingListDataSource> dataSource; - -// Prepares this view controller to be dismissed. -- (void)willBeDismissed; - -// Reloads all the data. -- (void)reloadData; - -+ (NSString*)accessibilityIdentifier; - -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm deleted file mode 100644 index ff29e33..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.mm +++ /dev/null
@@ -1,967 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" - -#include "base/logging.h" -#import "base/mac/foundation_util.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.h" -#include "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/list_model/list_item+Controller.h" -#import "ios/chrome/browser/ui/material_components/chrome_app_bar_view_controller.h" -#import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h" -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_data_sink.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_data_source.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_updater.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_audience.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#include "ui/base/l10n/l10n_util_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -// Types of ListItems used by the reading list UI. -typedef NS_ENUM(NSInteger, ItemType) { - ItemTypeHeader = kItemTypeEnumZero, - ItemTypeItem, -}; -// Identifiers for sections in the reading list. -typedef NS_ENUM(NSInteger, SectionIdentifier) { - SectionIdentifierUnread = kSectionIdentifierEnumZero, - SectionIdentifierRead, -}; -} // namespace - -@interface ReadingListCollectionViewController ()< - ReadingListDataSink, - UIGestureRecognizerDelegate> { - // Toolbar with the actions. - LegacyReadingListToolbar* _toolbar; - // Action sheet presenting the subactions of the toolbar. - AlertCoordinator* _actionSheet; - UIView* _emptyCollectionBackground; - - // Whether the data source has pending modifications. - BOOL _dataSourceHasBeenModified; -} - -// Redefine the model to return ReadingListListItems -@property(nonatomic, readonly) - CollectionViewModel<CollectionViewItem<ReadingListListItem>*>* - collectionViewModel; - -// Whether the data source modifications should be taken into account. -@property(nonatomic, assign) BOOL shouldMonitorDataSource; - -// Casts |item| to a CollectionViewItem. -- (CollectionViewItem<ReadingListListItem>*)collectionItemForReadingListItem: - (id<ReadingListListItem>)item; -// Handles "Done" button touches. -- (void)donePressed; -// Loads all the items in all sections. -- (void)loadItems; -// Fills section |sectionIdentifier| with the items from |array|. -- (void)loadItemsFromArray:(NSArray<id<ReadingListListItem>>*)array - toSection:(SectionIdentifier)sectionIdentifier; -// Reloads the data if a change occurred during editing -- (void)applyPendingUpdates; -// Returns whether there are elements in the section identified by -// |sectionIdentifier|. -- (BOOL)hasItemInSection:(SectionIdentifier)sectionIdentifier; -// Adds an empty background if needed. -- (void)collectionIsEmpty; -// Handles a long press. -- (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer; -// Updates the toolbar state according to the selected items. -- (void)updateToolbarState; -// Displays an action sheet to let the user choose to mark all the elements as -// read or as unread. Used when nothing is selected. -- (void)markAllItemsAs; -// Displays an action sheet to let the user choose to mark all the selected -// elements as read or as unread. Used if read and unread elements are selected. -- (void)markMixedItemsAs; -// Marks all items as read. -- (void)markAllRead; -// Marks all items as unread. -- (void)markAllUnread; -// Marks the items at |indexPaths| as read. -- (void)markItemsReadAtIndexPath:(NSArray*)indexPaths; -// Marks the items at |indexPaths| as unread. -- (void)markItemsUnreadAtIndexPath:(NSArray*)indexPaths; -// Deletes all the read items. -- (void)deleteAllReadItems; -// Deletes all the items at |indexPath|. -- (void)deleteItemsAtIndexPaths:(NSArray*)indexPaths; -// Initializes |_actionSheet| with |self| as base view controller, and the -// toolbar's mark button as anchor point. -- (void)initializeActionSheet; -// Exits the editing mode and update the toolbar state with animation. -- (void)exitEditingModeAnimated:(BOOL)animated; -// Applies |updater| to the URL of every cell in the section |identifier|. The -// updates are done in reverse order of the cells in the section to keep the -// order. The monitoring of the data source updates are suspended during this -// time. -- (void)updateItemsInSectionIdentifier:(SectionIdentifier)identifier - usingItemUpdater:(ReadingListListItemUpdater)updater; -// Applies |updater| to the URL of every element in |indexPaths|. The updates -// are done in reverse order |indexPaths| to keep the order. The monitoring of -// the data source updates are suspended during this time. -- (void)updateIndexPaths:(NSArray<NSIndexPath*>*)indexPaths - usingItemUpdater:(ReadingListListItemUpdater)updater; -// Move all the items from |sourceSectionIdentifier| to -// |destinationSectionIdentifier| and removes the empty section from the -// collection. -- (void)moveItemsFromSection:(SectionIdentifier)sourceSectionIdentifier - toSection:(SectionIdentifier)destinationSectionIdentifier; -// Move the currently selected elements to |sectionIdentifier| and removes the -// empty sections. -- (void)moveSelectedItems:(NSArray*)sortedIndexPaths - toSection:(SectionIdentifier)sectionIdentifier; -// Makes sure |sectionIdentifier| exists with the correct header. -// Returns the index of the new section in the collection view; NSIntegerMax if -// no section has been created. -- (NSInteger)initializeSection:(SectionIdentifier)sectionIdentifier; -// Returns the header for the |sectionIdentifier|. -- (CollectionViewTextItem*)headerForSection: - (SectionIdentifier)sectionIdentifier; -// Removes the empty sections from the collection and the model. -- (void)removeEmptySections; - -@end - -@implementation ReadingListCollectionViewController - -@synthesize audience = _audience; -@synthesize delegate = _delegate; -@synthesize dataSource = _dataSource; - -@dynamic collectionViewModel; -@synthesize shouldMonitorDataSource = _shouldMonitorDataSource; - -+ (NSString*)accessibilityIdentifier { - return @"ReadingListCollectionView"; -} - -#pragma mark lifecycle - -- (instancetype)initWithDataSource:(id<ReadingListDataSource>)dataSource - toolbar:(LegacyReadingListToolbar*)toolbar { - UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; - self = - [super initWithLayout:layout style:CollectionViewControllerStyleAppBar]; - if (self) { - _toolbar = toolbar; - - _dataSource = dataSource; - _emptyCollectionBackground = [[EmptyReadingListBackgroundView alloc] init]; - - _shouldMonitorDataSource = YES; - _dataSourceHasBeenModified = NO; - - _dataSource.dataSink = self; - } - return self; -} - -#pragma mark - properties - -- (void)setToolbarState:(LegacyReadingListToolbarState)toolbarState { - [_toolbar setState:toolbarState]; -} - -- (void)setAudience:(id<ReadingListListViewControllerAudience>)audience { - _audience = audience; - if (self.dataSource.ready) { - [audience readingListHasItems:self.dataSource.hasElements]; - } -} - -#pragma mark - UIViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = l10n_util::GetNSString(IDS_IOS_TOOLS_MENU_READING_LIST); - self.collectionView.accessibilityIdentifier = - [ReadingListCollectionViewController accessibilityIdentifier]; - // Add "Done" button. - UIBarButtonItem* doneItem = [[UIBarButtonItem alloc] - initWithTitle:l10n_util::GetNSString(IDS_IOS_READING_LIST_DONE_BUTTON) - style:UIBarButtonItemStylePlain - target:self - action:@selector(donePressed)]; - doneItem.accessibilityIdentifier = @"Done"; - self.navigationItem.rightBarButtonItem = doneItem; - - // Customize collection view settings. - self.styler.cellStyle = MDCCollectionViewCellStyleCard; - self.styler.separatorInset = UIEdgeInsetsMake(0, 16, 0, 16); - - UILongPressGestureRecognizer* longPressRecognizer = - [[UILongPressGestureRecognizer alloc] - initWithTarget:self - action:@selector(handleLongPress:)]; - longPressRecognizer.delegate = self; - [self.collectionView addGestureRecognizer:longPressRecognizer]; -} - -- (void)viewDidLayoutSubviews { - [super viewDidLayoutSubviews]; - [_toolbar updateHeight]; -} - -#pragma mark - UICollectionViewDelegate - -- (void)collectionView:(UICollectionView*)collectionView - didSelectItemAtIndexPath:(NSIndexPath*)indexPath { - [super collectionView:collectionView didSelectItemAtIndexPath:indexPath]; - - if (self.editor.editing) { - [self updateToolbarState]; - } else { - id<ReadingListListItem> item = - [self.collectionViewModel itemAtIndexPath:indexPath]; - [self.delegate readingListListViewController:self openItem:item]; - } -} - -- (void)collectionView:(UICollectionView*)collectionView - didDeselectItemAtIndexPath:(NSIndexPath*)indexPath { - [super collectionView:collectionView didDeselectItemAtIndexPath:indexPath]; - if (self.editor.editing) { - // When deselecting an item, if we are editing, we want to update the - // toolbar based on the selected items. - [self updateToolbarState]; - } -} - -#pragma mark - MDCCollectionViewController - -- (void)updateFooterInfoBarIfNecessary { - // No-op. This prevents the default infobar from showing. - // TODO(crbug.com/653547): Remove this once the MDC adds an option for - // preventing the infobar from showing. -} - -#pragma mark - MDCCollectionViewStylingDelegate - -- (CGFloat)collectionView:(UICollectionView*)collectionView - cellHeightAtIndexPath:(NSIndexPath*)indexPath { - NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - if (type == ItemTypeItem) - return MDCCellDefaultTwoLineHeight; - else - return MDCCellDefaultOneLineHeight; -} - -#pragma mark - MDCCollectionViewEditingDelegate - -- (BOOL)collectionViewAllowsEditing:(nonnull UICollectionView*)collectionView { - return YES; -} - -#pragma mark - ReadingListDataSink - -- (void)dataSourceReady:(id<ReadingListDataSource>)dataSource { - [self loadModel]; - if ([self isViewLoaded]) { - [self.collectionView reloadData]; - } -} - -- (void)dataSourceChanged { - // If we are editing and monitoring the model updates, set a flag to reload - // the data at the end of the editing. - if (self.editor.editing) { - _dataSourceHasBeenModified = YES; - } else { - [self reloadData]; - } -} - -- (NSArray<id<ReadingListListItem>>*)readItems { - return [self readingListItemsForSection:SectionIdentifierRead]; -} - -- (NSArray<id<ReadingListListItem>>*)unreadItems { - return [self readingListItemsForSection:SectionIdentifierUnread]; -} - -- (void)itemHasChangedAfterDelay:(id<ReadingListListItem>)item { - CollectionViewItem<ReadingListListItem>* collectionItem = - [self collectionItemForReadingListItem:item]; - if ([self.collectionViewModel hasItem:collectionItem]) { - [self reconfigureCellsForItems:@[ collectionItem ]]; - } -} - -- (void)itemsHaveChanged:(NSArray<id<ReadingListListItem>>*)items { - [self reconfigureCellsForItems:items]; -} - -#pragma mark - ReadingListDataSink Helpers - -- (NSArray<id<ReadingListListItem>>*)readingListItemsForSection: - (SectionIdentifier)sectionID { - if (![self.collectionViewModel hasSectionForSectionIdentifier:sectionID]) { - return nil; - } - NSMutableArray<id<ReadingListListItem>>* items = [NSMutableArray array]; - NSArray<CollectionViewItem*>* sectionItems = - [self.collectionViewModel itemsInSectionWithIdentifier:sectionID]; - for (id<ReadingListListItem> item in sectionItems) { - [items addObject:item]; - } - return items; -} - -#pragma mark - Public methods - -- (void)reloadData { - [self loadModel]; - if ([self isViewLoaded]) { - [self.collectionView reloadData]; - } -} - -- (void)willBeDismissed { - [self.dataSource dataSinkWillBeDismissed]; - [_actionSheet stop]; -} - -#pragma mark - ReadingListListItemAccessibilityDelegate - -- (BOOL)isItemRead:(id<ReadingListListItem>)item { - return [self.dataSource isItemRead:item]; -} - -- (void)deleteItem:(id<ReadingListListItem>)item { - CollectionViewItem<ReadingListListItem>* collectionItem = - [self collectionItemForReadingListItem:item]; - if ([self.collectionViewModel hasItem:collectionItem]) { - [self deleteItemsAtIndexPaths:@[ [self.collectionViewModel - indexPathForItem:collectionItem] ]]; - } -} - -- (void)openItemInNewTab:(id<ReadingListListItem>)item { - [self.delegate readingListListViewController:self - openItemInNewTab:item - incognito:NO]; -} - -- (void)openItemInNewIncognitoTab:(id<ReadingListListItem>)item { - [self.delegate readingListListViewController:self - openItemInNewTab:item - incognito:YES]; -} - -- (void)openItemOffline:(id<ReadingListListItem>)item { - [self.delegate readingListListViewController:self - openItemOfflineInNewTab:item]; -} - -- (void)markItemRead:(id<ReadingListListItem>)item { - CollectionViewItem<ReadingListListItem>* collectionItem = - [self collectionItemForReadingListItem:item]; - if ([self.collectionViewModel hasItem:collectionItem - inSectionWithIdentifier:SectionIdentifierUnread]) { - [self markItemsReadAtIndexPath:@[ [self.collectionViewModel - indexPathForItem:collectionItem] ]]; - } -} - -- (void)markItemUnread:(id<ReadingListListItem>)item { - CollectionViewItem<ReadingListListItem>* collectionItem = - [self collectionItemForReadingListItem:item]; - if ([self.collectionViewModel hasItem:collectionItem - inSectionWithIdentifier:SectionIdentifierRead]) { - [self markItemsUnreadAtIndexPath:@[ [self.collectionViewModel - indexPathForItem:collectionItem] ]]; - } -} - -#pragma mark - UIGestureRecognizerDelegate - -- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer - shouldReceiveTouch:(UITouch*)touch { - // Prevent the context menu to be displayed if the long press is done on the - // App Bar. - CGPoint location = - [touch locationInView:self.appBarViewController.navigationBar]; - return !CGRectContainsPoint(self.appBarViewController.navigationBar.frame, - location); -} - -#pragma mark - Private methods - -- (void)donePressed { - if ([self.editor isEditing]) { - [self exitEditingModeAnimated:NO]; - } - [self dismiss]; -} - -- (void)dismiss { - [self.delegate dismissReadingListListViewController:self]; -} - -- (void)loadModel { - [super loadModel]; - _dataSourceHasBeenModified = NO; - - if (!self.dataSource.hasElements) { - [self collectionIsEmpty]; - } else { - self.collectionView.alwaysBounceVertical = YES; - [self loadItems]; - self.collectionView.backgroundView = nil; - [self.audience readingListHasItems:YES]; - } -} - -- (void)loadItemsFromArray:(NSArray<id<ReadingListListItem>>*)items - toSection:(SectionIdentifier)sectionIdentifier { - if (items.count == 0) { - return; - } - CollectionViewModel* model = self.collectionViewModel; - [model addSectionWithIdentifier:sectionIdentifier]; - [model setHeader:[self headerForSection:sectionIdentifier] - forSectionWithIdentifier:sectionIdentifier]; - for (CollectionViewItem<ReadingListListItem>* item in items) { - item.type = ItemTypeItem; - [self.dataSource fetchFaviconForItem:item]; - [model addItem:item toSectionWithIdentifier:sectionIdentifier]; - } -} - -- (void)loadItems { - NSMutableArray<id<ReadingListListItem>>* readArray = [NSMutableArray array]; - NSMutableArray<id<ReadingListListItem>>* unreadArray = [NSMutableArray array]; - [self.dataSource fillReadItems:readArray unreadItems:unreadArray]; - [self loadItemsFromArray:unreadArray toSection:SectionIdentifierUnread]; - [self loadItemsFromArray:readArray toSection:SectionIdentifierRead]; - - BOOL hasRead = readArray.count > 0; - [_toolbar setHasReadItem:hasRead]; -} - -- (void)applyPendingUpdates { - if (_dataSourceHasBeenModified) { - [self reloadData]; - } -} - -- (BOOL)hasItemInSection:(SectionIdentifier)sectionIdentifier { - if (![self.collectionViewModel - hasSectionForSectionIdentifier:sectionIdentifier]) { - // No section. - return NO; - } - - NSInteger section = - [self.collectionViewModel sectionForSectionIdentifier:sectionIdentifier]; - NSInteger numberOfItems = - [self.collectionViewModel numberOfItemsInSection:section]; - - return numberOfItems > 0; -} - -- (void)collectionIsEmpty { - if (self.collectionView.backgroundView) { - return; - } - // The collection is empty, add background. - self.collectionView.alwaysBounceVertical = NO; - self.collectionView.backgroundView = _emptyCollectionBackground; - [self.audience readingListHasItems:NO]; -} - -- (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer { - if (self.editor.editing || - gestureRecognizer.state != UIGestureRecognizerStateBegan) { - return; - } - - CGPoint touchLocation = - [gestureRecognizer locationOfTouch:0 inView:self.collectionView]; - NSIndexPath* touchedItemIndexPath = - [self.collectionView indexPathForItemAtPoint:touchLocation]; - if (!touchedItemIndexPath || - ![self.collectionViewModel hasItemAtIndexPath:touchedItemIndexPath]) { - // Make sure there is an item at this position. - return; - } - - CollectionViewItem<ReadingListListItem>* item = - [self.collectionViewModel itemAtIndexPath:touchedItemIndexPath]; - if (item.type != ItemTypeItem) { - // Do not trigger context menu on headers. - return; - } - - [self.delegate readingListListViewController:self - displayContextMenuForItem:item - atPoint:touchLocation]; -} - -#pragma mark - LegacyReadingListToolbarDelegate - -- (void)markPressed { - if (![self.editor isEditing]) { - return; - } - switch ([_toolbar state]) { - case NoneSelected: - [self markAllItemsAs]; - break; - case OnlyUnreadSelected: - [self markItemsReadAtIndexPath:self.collectionView - .indexPathsForSelectedItems]; - break; - case OnlyReadSelected: - [self markItemsUnreadAtIndexPath:self.collectionView - .indexPathsForSelectedItems]; - break; - case MixedItemsSelected: - [self markMixedItemsAs]; - break; - } -} - -- (void)deletePressed { - if (![self.editor isEditing]) { - return; - } - if ([_toolbar state] == NoneSelected) { - [self deleteAllReadItems]; - } else { - [self - deleteItemsAtIndexPaths:self.collectionView.indexPathsForSelectedItems]; - } -} -- (void)enterEditingModePressed { - if ([self.editor isEditing]) { - return; - } - self.toolbarState = NoneSelected; - [self.editor setEditing:YES animated:YES]; - [_toolbar setEditing:YES]; -} - -- (void)exitEditingModePressed { - if (![self.editor isEditing]) { - return; - } - [self exitEditingModeAnimated:YES]; -} - -#pragma mark - Private methods - Toolbar - -- (CollectionViewItem<ReadingListListItem>*)collectionItemForReadingListItem: - (id<ReadingListListItem>)item { - return base::mac::ObjCCastStrict<CollectionViewItem<ReadingListListItem>>( - item); -} - -- (void)updateToolbarState { - BOOL readSelected = NO; - BOOL unreadSelected = NO; - - if ([self.collectionView.indexPathsForSelectedItems count] == 0) { - // No entry selected. - self.toolbarState = NoneSelected; - return; - } - - // Sections for section identifiers. - NSInteger sectionRead = NSNotFound; - NSInteger sectionUnread = NSNotFound; - - if ([self hasItemInSection:SectionIdentifierRead]) { - sectionRead = [self.collectionViewModel - sectionForSectionIdentifier:SectionIdentifierRead]; - } - if ([self hasItemInSection:SectionIdentifierUnread]) { - sectionUnread = [self.collectionViewModel - sectionForSectionIdentifier:SectionIdentifierUnread]; - } - - // Check selected sections. - for (NSIndexPath* index in self.collectionView.indexPathsForSelectedItems) { - if (index.section == sectionRead) { - readSelected = YES; - } else if (index.section == sectionUnread) { - unreadSelected = YES; - } - } - - // Update toolbar state. - if (readSelected) { - if (unreadSelected) { - // Read and Unread selected. - self.toolbarState = MixedItemsSelected; - } else { - // Read selected. - self.toolbarState = OnlyReadSelected; - } - } else if (unreadSelected) { - // Unread selected. - self.toolbarState = OnlyUnreadSelected; - } -} - -- (void)markAllItemsAs { - [self initializeActionSheet]; - __weak ReadingListCollectionViewController* weakSelf = self; - [_actionSheet addItemWithTitle:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_ALL_READ_ACTION) - action:^{ - [weakSelf markAllRead]; - } - style:UIAlertActionStyleDefault]; - [_actionSheet - addItemWithTitle:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_ALL_UNREAD_ACTION) - action:^{ - [weakSelf markAllUnread]; - } - style:UIAlertActionStyleDefault]; - [_actionSheet start]; -} - -- (void)markMixedItemsAs { - [self initializeActionSheet]; - __weak ReadingListCollectionViewController* weakSelf = self; - [_actionSheet - addItemWithTitle:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_READ_BUTTON) - action:^{ - [weakSelf - markItemsReadAtIndexPath:weakSelf.collectionView - .indexPathsForSelectedItems]; - } - style:UIAlertActionStyleDefault]; - [_actionSheet - addItemWithTitle:l10n_util::GetNSStringWithFixup( - IDS_IOS_READING_LIST_MARK_UNREAD_BUTTON) - action:^{ - [weakSelf - markItemsUnreadAtIndexPath: - weakSelf.collectionView.indexPathsForSelectedItems]; - } - style:UIAlertActionStyleDefault]; - [_actionSheet start]; -} - -- (void)initializeActionSheet { - _actionSheet = [_toolbar actionSheetForMarkWithBaseViewController:self]; - - [_actionSheet addItemWithTitle:l10n_util::GetNSStringWithFixup(IDS_CANCEL) - action:nil - style:UIAlertActionStyleCancel]; -} - -- (void)markAllRead { - if (![self.editor isEditing]) { - return; - } - if (![self hasItemInSection:SectionIdentifierUnread]) { - [self exitEditingModeAnimated:YES]; - return; - } - - [self updateItemsInSectionIdentifier:SectionIdentifierUnread - usingItemUpdater:^(id<ReadingListListItem> item) { - [self.dataSource setReadStatus:YES forItem:item]; - }]; - - [self exitEditingModeAnimated:YES]; - [self moveItemsFromSection:SectionIdentifierUnread - toSection:SectionIdentifierRead]; -} - -- (void)markAllUnread { - if (![self hasItemInSection:SectionIdentifierRead]) { - [self exitEditingModeAnimated:YES]; - return; - } - - [self updateItemsInSectionIdentifier:SectionIdentifierRead - usingItemUpdater:^(id<ReadingListListItem> item) { - [self.dataSource setReadStatus:NO forItem:item]; - }]; - - [self exitEditingModeAnimated:YES]; - [self moveItemsFromSection:SectionIdentifierRead - toSection:SectionIdentifierUnread]; -} - -- (void)markItemsReadAtIndexPath:(NSArray*)indexPaths { - base::RecordAction(base::UserMetricsAction("MobileReadingListMarkRead")); - NSArray* sortedIndexPaths = - [indexPaths sortedArrayUsingSelector:@selector(compare:)]; - [self updateIndexPaths:sortedIndexPaths - usingItemUpdater:^(id<ReadingListListItem> item) { - [self.dataSource setReadStatus:YES forItem:item]; - }]; - - [self exitEditingModeAnimated:YES]; - [self moveSelectedItems:sortedIndexPaths toSection:SectionIdentifierRead]; -} - -- (void)markItemsUnreadAtIndexPath:(NSArray*)indexPaths { - base::RecordAction(base::UserMetricsAction("MobileReadingListMarkUnread")); - NSArray* sortedIndexPaths = - [indexPaths sortedArrayUsingSelector:@selector(compare:)]; - [self updateIndexPaths:sortedIndexPaths - usingItemUpdater:^(id<ReadingListListItem> item) { - [self.dataSource setReadStatus:NO forItem:item]; - }]; - - [self exitEditingModeAnimated:YES]; - [self moveSelectedItems:sortedIndexPaths toSection:SectionIdentifierUnread]; -} - -- (void)deleteAllReadItems { - base::RecordAction(base::UserMetricsAction("MobileReadingListDeleteRead")); - if (![self hasItemInSection:SectionIdentifierRead]) { - [self exitEditingModeAnimated:YES]; - return; - } - - [self updateItemsInSectionIdentifier:SectionIdentifierRead - usingItemUpdater:^(id<ReadingListListItem> item) { - [self.dataSource removeEntryFromItem:item]; - }]; - - [self exitEditingModeAnimated:YES]; - [self.collectionView performBatchUpdates:^{ - NSInteger readSection = [self.collectionViewModel - sectionForSectionIdentifier:SectionIdentifierRead]; - [self.collectionView - deleteSections:[NSIndexSet indexSetWithIndex:readSection]]; - [self.collectionViewModel - removeSectionWithIdentifier:SectionIdentifierRead]; - } - completion:^(BOOL) { - // Reload data to take into account possible sync events. - [self applyPendingUpdates]; - }]; - // As we modified the section in the batch update block, remove the section in - // another block. - [self removeEmptySections]; -} - -- (void)deleteItemsAtIndexPaths:(NSArray*)indexPaths { - [self updateIndexPaths:indexPaths - usingItemUpdater:^(id<ReadingListListItem> item) { - [self.dataSource removeEntryFromItem:item]; - }]; - - [self exitEditingModeAnimated:YES]; - - [self.collectionView performBatchUpdates:^{ - [self collectionView:self.collectionView - willDeleteItemsAtIndexPaths:indexPaths]; - - [self.collectionView deleteItemsAtIndexPaths:indexPaths]; - } - completion:^(BOOL) { - // Reload data to take into account possible sync events. - [self applyPendingUpdates]; - }]; - // As we modified the section in the batch update block, remove the section in - // another block. - [self removeEmptySections]; -} - -- (void)updateItemsInSectionIdentifier:(SectionIdentifier)identifier - usingItemUpdater:(ReadingListListItemUpdater)updater { - [self.dataSource beginBatchUpdates]; - NSArray* readItems = - [self.collectionViewModel itemsInSectionWithIdentifier:identifier]; - // Read the objects in reverse order to keep the order (last modified first). - for (id item in [readItems reverseObjectEnumerator]) { - if (updater) - updater(item); - } - [self.dataSource endBatchUpdates]; -} - -- (void)updateIndexPaths:(NSArray<NSIndexPath*>*)indexPaths - usingItemUpdater:(ReadingListListItemUpdater)updater { - [self.dataSource beginBatchUpdates]; - // Read the objects in reverse order to keep the order (last modified first). - for (NSIndexPath* index in [indexPaths reverseObjectEnumerator]) { - id<ReadingListListItem> item = - [self.collectionViewModel itemAtIndexPath:index]; - if (updater) - updater(item); - } - [self.dataSource endBatchUpdates]; -} - -- (void)moveItemsFromSection:(SectionIdentifier)sourceSectionIdentifier - toSection:(SectionIdentifier)destinationSectionIdentifier { - NSInteger sourceSection = [self.collectionViewModel - sectionForSectionIdentifier:sourceSectionIdentifier]; - NSInteger numberOfSourceItems = - [self.collectionViewModel numberOfItemsInSection:sourceSection]; - - NSMutableArray* sortedIndexPaths = [NSMutableArray array]; - - for (int index = 0; index < numberOfSourceItems; index++) { - NSIndexPath* itemIndex = - [NSIndexPath indexPathForItem:index inSection:sourceSection]; - [sortedIndexPaths addObject:itemIndex]; - } - - [self moveSelectedItems:sortedIndexPaths - toSection:destinationSectionIdentifier]; -} - -- (void)moveSelectedItems:(NSArray*)sortedIndexPaths - toSection:(SectionIdentifier)sectionIdentifier { - // Reconfigure cells, allowing the custom actions to be updated. - [self reconfigureCellsAtIndexPaths:sortedIndexPaths]; - - NSInteger sectionCreatedIndex = [self initializeSection:sectionIdentifier]; - - [self.collectionView performBatchUpdates:^{ - NSInteger section = [self.collectionViewModel - sectionForSectionIdentifier:sectionIdentifier]; - - NSInteger newItemIndex = 0; - for (NSIndexPath* index in sortedIndexPaths) { - // The |sortedIndexPaths| is a copy of the index paths before the - // destination section has been added if necessary. The section part of - // the index potentially needs to be updated. - NSInteger updatedSection = index.section; - if (updatedSection >= sectionCreatedIndex) - updatedSection++; - if (updatedSection == section) { - // The item is already in the targeted section, there is no need to move - // it. - continue; - } - - NSIndexPath* updatedIndex = - [NSIndexPath indexPathForItem:index.item inSection:updatedSection]; - NSIndexPath* indexForModel = - [NSIndexPath indexPathForItem:index.item - newItemIndex - inSection:updatedSection]; - - // Index of the item in the new section. The newItemIndex is the index of - // this item in the targeted section. - NSIndexPath* newIndexPath = - [NSIndexPath indexPathForItem:newItemIndex++ inSection:section]; - - [self collectionView:self.collectionView - willMoveItemAtIndexPath:indexForModel - toIndexPath:newIndexPath]; - [self.collectionView moveItemAtIndexPath:updatedIndex - toIndexPath:newIndexPath]; - } - } - completion:^(BOOL) { - // Reload data to take into account possible sync events. - [self applyPendingUpdates]; - }]; - // As we modified the section in the batch update block, remove the section in - // another block. - [self removeEmptySections]; -} - -- (NSInteger)initializeSection:(SectionIdentifier)sectionIdentifier { - if (![self.collectionViewModel - hasSectionForSectionIdentifier:sectionIdentifier]) { - // The new section IndexPath will be 1 if it is the read section with - // items in the unread section, 0 otherwise. - BOOL hasNonEmptySectionAbove = - sectionIdentifier == SectionIdentifierRead && - [self hasItemInSection:SectionIdentifierUnread]; - NSInteger sectionIndex = hasNonEmptySectionAbove ? 1 : 0; - - [self.collectionView performBatchUpdates:^{ - [self.collectionViewModel insertSectionWithIdentifier:sectionIdentifier - atIndex:sectionIndex]; - - [self.collectionViewModel - setHeader:[self headerForSection:sectionIdentifier] - forSectionWithIdentifier:sectionIdentifier]; - - [self.collectionView - insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]]; - } - completion:nil]; - - return sectionIndex; - } - return NSIntegerMax; -} - -- (CollectionViewTextItem*)headerForSection: - (SectionIdentifier)sectionIdentifier { - CollectionViewTextItem* header = - [[CollectionViewTextItem alloc] initWithType:ItemTypeHeader]; - - switch (sectionIdentifier) { - case SectionIdentifierRead: - header.text = l10n_util::GetNSString(IDS_IOS_READING_LIST_READ_HEADER); - break; - case SectionIdentifierUnread: - header.text = l10n_util::GetNSString(IDS_IOS_READING_LIST_UNREAD_HEADER); - break; - } - header.textColor = [[MDCPalette greyPalette] tint500]; - return header; -} - -- (void)removeEmptySections { - [self.collectionView performBatchUpdates:^{ - - SectionIdentifier a[] = {SectionIdentifierRead, SectionIdentifierUnread}; - for (size_t i = 0; i < arraysize(a); i++) { - SectionIdentifier sectionIdentifier = a[i]; - - if ([self.collectionViewModel - hasSectionForSectionIdentifier:sectionIdentifier] && - ![self hasItemInSection:sectionIdentifier]) { - NSInteger section = [self.collectionViewModel - sectionForSectionIdentifier:sectionIdentifier]; - - [self.collectionView - deleteSections:[NSIndexSet indexSetWithIndex:section]]; - [self.collectionViewModel - removeSectionWithIdentifier:sectionIdentifier]; - } - } - } - completion:nil]; - if (!self.dataSource.hasElements) { - [self collectionIsEmpty]; - } else { - [_toolbar setHasReadItem:self.dataSource.hasReadElements]; - } -} - -- (void)exitEditingModeAnimated:(BOOL)animated { - [_actionSheet stop]; - [self.editor setEditing:NO animated:animated]; - [_toolbar setEditing:NO]; -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller_unittest.mm deleted file mode 100644 index 508917e..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller_unittest.mm +++ /dev/null
@@ -1,215 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" - -#include <memory> -#include <unordered_set> - -#import "base/mac/foundation_util.h" -#include "base/strings/sys_string_conversions.h" -#include "base/time/default_clock.h" -#include "components/favicon/core/large_icon_service.h" -#include "components/favicon/core/test/mock_favicon_service.h" -#include "components/reading_list/core/reading_list_model.h" -#include "components/reading_list/core/reading_list_model_impl.h" -#include "components/reading_list/core/reading_list_model_storage.h" -#include "components/url_formatter/url_formatter.h" -#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#import "ios/chrome/browser/favicon/favicon_loader.h" -#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_view_controller_delegate.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h" -#include "ios/web/public/test/test_web_thread_bundle.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" -#import "third_party/ocmock/OCMock/OCMock.h" -#import "third_party/ocmock/gtest_support.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -using favicon::PostReply; -using testing::_; - -#pragma mark - ReadingListCollectionViewControllerTest - -class ReadingListCollectionViewControllerTest : public PlatformTest { - public: - ReadingListCollectionViewControllerTest() {} - ~ReadingListCollectionViewControllerTest() override {} - - testing::StrictMock<favicon::MockFaviconService> mock_favicon_service_; - std::unique_ptr<ReadingListModelImpl> reading_list_model_; - ReadingListMediator* mediator_; - std::unique_ptr<favicon::LargeIconService> large_icon_service_; - std::unique_ptr<FaviconLoader> favicon_loader; - - ReadingListCollectionViewController* reading_list_view_controller_; - id mock_delegate_; - - void SetUp() override { - PlatformTest::SetUp(); - - EXPECT_CALL(mock_favicon_service_, - GetLargestRawFaviconForPageURL(_, _, _, _, _)) - .WillRepeatedly(PostReply<5>(favicon_base::FaviconRawBitmapResult())); - - reading_list_model_.reset(new ReadingListModelImpl( - nullptr, nullptr, base::DefaultClock::GetInstance())); - favicon_loader.reset(new FaviconLoader(new favicon::LargeIconService( - &mock_favicon_service_, /*image_fetcher=*/nullptr))); - mediator_ = [[ReadingListMediator alloc] - initWithModel:reading_list_model_.get() - faviconLoader:favicon_loader.get() - listItemFactory:[ReadingListListItemFactory collectionViewItemFactory]]; - reading_list_view_controller_ = [[ReadingListCollectionViewController alloc] - initWithDataSource:mediator_ - toolbar:nil]; - - mock_delegate_ = [OCMockObject - niceMockForProtocol:@protocol(ReadingListListViewControllerDelegate)]; - [reading_list_view_controller_ setDelegate:mock_delegate_]; - } - - private: - web::TestWebThreadBundle thread_bundle_; - DISALLOW_COPY_AND_ASSIGN(ReadingListCollectionViewControllerTest); -}; - -// Tests that reading list items are displayed. -TEST_F(ReadingListCollectionViewControllerTest, DisplaysItems) { - // Prefill some items. - reading_list_model_->AddEntry(GURL("https://chromium.org"), "news", - reading_list::ADDED_VIA_CURRENT_APP); - reading_list_model_->AddEntry(GURL("https://mail.chromium.org"), "mail", - reading_list::ADDED_VIA_CURRENT_APP); - reading_list_model_->AddEntry(GURL("https://foo.bar"), "Foo", - reading_list::ADDED_VIA_CURRENT_APP); - reading_list_model_->SetReadStatus(GURL("https://foo.bar"), true); - - // Load view. - [reading_list_view_controller_ view]; - - // There are two sections: Read and Unread. - DCHECK([reading_list_view_controller_.collectionView numberOfSections] == 2); - // There are two unread articles. - DCHECK([reading_list_view_controller_.collectionView - numberOfItemsInSection:0] == 2); - // There is one read article. - DCHECK([reading_list_view_controller_.collectionView - numberOfItemsInSection:1] == 1); -} - -// Tests that the view controller is dismissed when Done button is pressed. -TEST_F(ReadingListCollectionViewControllerTest, GetsDismissed) { - // Load view. - [reading_list_view_controller_ view]; - - [[mock_delegate_ expect] - dismissReadingListListViewController:reading_list_view_controller_]; - - // Simulate tap on "Done" button. - UIBarButtonItem* done = - reading_list_view_controller_.navigationItem.rightBarButtonItem; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - // Since @selector stored in done.action is a method returning void, there is - // no potential for memory leak. It is OK to ignore this warning here. - [done.target performSelector:done.action]; -#pragma clang diagnostic pop - - EXPECT_OCMOCK_VERIFY(mock_delegate_); -} - -// Tests that when an item is selected, the article is opened with UrlLoader and -// the view controller is dismissed. -TEST_F(ReadingListCollectionViewControllerTest, OpensItems) { - NSIndexPath* indexPath = [NSIndexPath indexPathForItem:1 inSection:0]; - - GURL url("https://chromium.org"); - GURL url2("https://chromium.org/2"); - reading_list_model_->AddEntry(url, "chromium", - reading_list::ADDED_VIA_CURRENT_APP); - reading_list_model_->AddEntry(url2, "chromium - 2", - reading_list::ADDED_VIA_CURRENT_APP); - - ReadingListCollectionViewItem* readingListItem = - base::mac::ObjCCastStrict<ReadingListCollectionViewItem>( - [[reading_list_view_controller_ collectionViewModel] - itemAtIndexPath:indexPath]); - - [[mock_delegate_ expect] - readingListListViewController:reading_list_view_controller_ - openItem:readingListItem]; - - // Simulate touch on second cell. - [reading_list_view_controller_ - collectionView:reading_list_view_controller_.collectionView - didSelectItemAtIndexPath:indexPath]; - - EXPECT_OCMOCK_VERIFY(mock_delegate_); -} - -// Tests that the ReadingListCollectionView is creating -// ReadingListCollectionViewItem with the correct informations. -TEST_F(ReadingListCollectionViewControllerTest, - TestItemInitializationUndistilled) { - // Setup. - GURL url("https://chromium.org"); - std::string title("Chromium"); - reading_list_model_->AddEntry(url, title, - reading_list::ADDED_VIA_CURRENT_APP); - // Load view. - [reading_list_view_controller_ view]; - DCHECK([reading_list_view_controller_.collectionView - numberOfItemsInSection:0] == 1); - NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; - ReadingListCollectionViewItem* readingListItem = - base::mac::ObjCCastStrict<ReadingListCollectionViewItem>( - [[reading_list_view_controller_ collectionViewModel] - itemAtIndexPath:indexPath]); - EXPECT_EQ(base::SysNSStringToUTF8([readingListItem title]), title); - EXPECT_EQ([readingListItem entryURL], url); - EXPECT_EQ([readingListItem faviconPageURL], url); - EXPECT_EQ([readingListItem distillationState], - ReadingListUIDistillationStatusPending); -} - -// Tests that the ReadingListCollectionView is creating -// ReadingListCollectionViewItem with the correct informations for distilled -// items. -TEST_F(ReadingListCollectionViewControllerTest, - TestItemInitializationDistilled) { - // Setup. - GURL url("https://chromium.org"); - std::string title("Chromium"); - GURL distilled_url("https://chromium.org/distilled"); - base::FilePath distilled_path("/distilled/path"); - reading_list_model_->AddEntry(url, title, - reading_list::ADDED_VIA_CURRENT_APP); - int64_t size = 50; - reading_list_model_->SetEntryDistilledInfo(url, distilled_path, distilled_url, - size, base::Time::FromTimeT(100)); - // Load view. - [reading_list_view_controller_ view]; - DCHECK([reading_list_view_controller_.collectionView - numberOfItemsInSection:0] == 1); - NSIndexPath* indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; - ReadingListCollectionViewItem* readingListItem = - base::mac::ObjCCastStrict<ReadingListCollectionViewItem>( - [[reading_list_view_controller_ collectionViewModel] - itemAtIndexPath:indexPath]); - EXPECT_EQ(base::SysNSStringToUTF8([readingListItem title]), title); - EXPECT_EQ([readingListItem entryURL], url); - EXPECT_EQ([readingListItem faviconPageURL], distilled_url); - EXPECT_EQ([readingListItem distillationState], - ReadingListUIDistillationStatusSuccess); -}
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h deleted file mode 100644 index d2933b7..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2016 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 IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_ITEM_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_ITEM_H_ - -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h" - -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item.h" - -// Collection view item for representing a ReadingListEntry. -@interface ReadingListCollectionViewItem - : CollectionViewItem<ReadingListListItem> -@end - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_COLLECTION_VIEW_ITEM_H_
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.mm b/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.mm deleted file mode 100644 index 0f8a9949..0000000 --- a/ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.mm +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" - -#include "base/strings/sys_string_conversions.h" -#include "components/url_formatter/url_formatter.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h" -#import "ios/chrome/browser/ui/util/pasteboard_util.h" -#import "ios/chrome/common/favicon/favicon_view.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ui/base/l10n/l10n_util.h" -#import "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -#pragma mark - ReadingListCollectionViewItem - -@implementation ReadingListCollectionViewItem -@synthesize title = _title; -@synthesize entryURL = _entryURL; -@synthesize faviconPageURL = _faviconPageURL; -@synthesize distillationState = _distillationState; -@synthesize distillationSizeText = _distillationSizeText; -@synthesize distillationDateText = _distillationDateText; -@synthesize customActionFactory = _customActionFactory; -@synthesize attributes = _attributes; - -#pragma mark - ListItem - -- (Class)cellClass { - return [ReadingListCell class]; -} - -#pragma mark - CollectionViewTextItem - -- (void)configureCell:(ReadingListCell*)cell { - [super configureCell:cell]; - [cell.faviconView configureWithAttributes:self.attributes]; - cell.titleLabel.text = self.title; - NSString* subtitle = base::SysUTF16ToNSString( - url_formatter::FormatUrl(self.entryURL.GetOrigin())); - cell.subtitleLabel.text = subtitle; - cell.distillationSizeLabel.text = self.distillationSizeText; - cell.distillationDateLabel.text = self.distillationDateText; - cell.showDistillationInfo = self.distillationSizeText.length > 0 && - self.distillationDateText.length > 0; - cell.distillationState = _distillationState; - cell.isAccessibilityElement = YES; - cell.accessibilityLabel = GetReadingListCellAccessibilityLabel( - self.title, subtitle, self.distillationState); - cell.accessibilityCustomActions = - [self.customActionFactory customActionsForItem:self]; -} - -#pragma mark - NSObject - -- (NSString*)description { - return [NSString stringWithFormat:@"Reading List item \"%@\" for url %s", - self.title, self.entryURL.spec().c_str()]; -} - -- (BOOL)isEqual:(id)other { - return AreReadingListListItemsEqual(self, other); -} - -@end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm index 891b641..b9d17c3 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -107,7 +107,7 @@ ReadingListModelFactory::GetInstance()->GetForBrowserState( self.browserState); ReadingListListItemFactory* itemFactory = - [ReadingListListItemFactory tableViewItemFactory]; + [[ReadingListListItemFactory alloc] init]; FaviconLoader* faviconLoader = IOSChromeFaviconLoaderFactory::GetForBrowserState(self.browserState); self.mediator = [[ReadingListMediator alloc] initWithModel:model
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm index 63bb324..8654318 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -18,16 +18,11 @@ #import "ios/chrome/browser/ui/commands/reading_list_add_command.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h" #import "ios/chrome/browser/ui/reading_list/empty_reading_list_background_view.h" -#import "ios/chrome/browser/ui/reading_list/legacy_reading_list_toolbar_button.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.h" #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button_identifiers.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_url_cell_favicon_badge_view.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h" #import "ios/chrome/browser/ui/table_view/table_view_empty_view.h" -#include "ios/chrome/browser/ui/ui_util.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_theme_resources.h" #import "ios/chrome/test/app/chrome_test_util.h" @@ -116,33 +111,12 @@ return model; } -// The ancestor class of toolbar buttons. -Class ToolbarButtonAncestorClass() { - return experimental_flags::IsReadingListUIRebootEnabled() - ? [UIToolbar class] - : [LegacyReadingListToolbarButton class]; -} - -// The class displaying the reading list cells. -Class ReadingListCellClass() { - return experimental_flags::IsReadingListUIRebootEnabled() - ? [TableViewURLCell class] - : [ReadingListCell class]; -} - -// The class displaying the reading list. -Class ReadingListViewControllerClass() { - return experimental_flags::IsReadingListUIRebootEnabled() - ? [ReadingListTableViewController class] - : [ReadingListCollectionViewController class]; -} - // Scroll to the top of the Reading List. void ScrollToTop() { NSError* error = nil; - [[EarlGrey selectElementWithMatcher:grey_accessibilityID( - [ReadingListViewControllerClass() - accessibilityIdentifier])] + [[EarlGrey selectElementWithMatcher:grey_accessibilityID([ + [ReadingListTableViewController class] + accessibilityIdentifier])] performAction:grey_scrollToContentEdgeWithStartPoint(kGREYContentEdgeTop, 0.5, 0.5) error:&error]; @@ -156,7 +130,7 @@ selectElementWithMatcher: grey_allOf( grey_accessibilityID(kReadingListToolbarMarkButtonID), - grey_ancestor(grey_kindOfClass(ToolbarButtonAncestorClass())), + grey_ancestor(grey_kindOfClass([UIToolbar class])), chrome_test_util::ButtonWithAccessibilityLabelId(a11y_label_id), nil)] assertWithMatcher:grey_sufficientlyVisible()]; } @@ -166,7 +140,7 @@ [[EarlGrey selectElementWithMatcher:grey_allOf(grey_accessibilityID(button_id), grey_ancestor(grey_kindOfClass( - ToolbarButtonAncestorClass())), + [UIToolbar class])), nil)] assertWithMatcher:grey_notVisible()]; } @@ -176,7 +150,7 @@ [[EarlGrey selectElementWithMatcher:grey_allOf(grey_accessibilityID(button_id), grey_ancestor(grey_kindOfClass( - ToolbarButtonAncestorClass())), + [UIToolbar class])), nil)] assertWithMatcher:grey_sufficientlyVisible()]; } @@ -202,12 +176,12 @@ id<GREYMatcher> matcher = grey_allOf(chrome_test_util::StaticTextWithAccessibilityLabel( base::SysUTF8ToNSString(entryTitle)), - grey_ancestor(grey_kindOfClass(ReadingListCellClass())), + grey_ancestor(grey_kindOfClass([TableViewURLCell class])), grey_sufficientlyVisible(), nil); [[[EarlGrey selectElementWithMatcher:matcher] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100) onElementWithMatcher:grey_accessibilityID( - ReadingListViewControllerClass())] + [ReadingListTableViewController class])] performAction:action]; } @@ -229,11 +203,11 @@ selectElementWithMatcher: grey_allOf(chrome_test_util::StaticTextWithAccessibilityLabel( base::SysUTF8ToNSString(entryTitle)), - grey_ancestor(grey_kindOfClass(ReadingListCellClass())), + grey_ancestor(grey_kindOfClass([TableViewURLCell class])), grey_sufficientlyVisible(), nil)] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100) onElementWithMatcher:grey_accessibilityID( - [ReadingListViewControllerClass() + [[ReadingListTableViewController class] accessibilityIdentifier])] assertWithMatcher:grey_notNil()]; } @@ -262,11 +236,11 @@ selectElementWithMatcher: grey_allOf(chrome_test_util::StaticTextWithAccessibilityLabel( base::SysUTF8ToNSString(title)), - grey_ancestor(grey_kindOfClass(ReadingListCellClass())), + grey_ancestor(grey_kindOfClass([TableViewURLCell class])), grey_sufficientlyVisible(), nil)] usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100) onElementWithMatcher:grey_accessibilityID( - [ReadingListViewControllerClass() + [[ReadingListTableViewController class] accessibilityIdentifier])] assertWithMatcher:grey_notNil() error:&error]; @@ -320,38 +294,17 @@ // Returns a match for the Reading List Empty Collection Background. id<GREYMatcher> EmptyBackground() { - Class empty_background_class = - experimental_flags::IsReadingListUIRebootEnabled() - ? [TableViewEmptyView class] - : [EmptyReadingListBackgroundView class]; - return grey_accessibilityID([empty_background_class accessibilityIdentifier]); + return grey_accessibilityID( + [[TableViewEmptyView class] accessibilityIdentifier]); } // Adds the current page to the Reading List. void AddCurrentPageToReadingList() { // Add the page to the reading list. - if (IsUIRefreshPhase1Enabled()) { - [ChromeEarlGreyUI openToolsMenu]; - [ChromeEarlGreyUI - tapToolsMenuButton:chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_SHARE_MENU_READING_LIST_ACTION)]; - } else if (base::ios::IsRunningOnIOS11OrLater()) { - // On iOS 11, it is not possible to interact with the share menu in EG. - // Send directly the command instead. This is the closest behavior we can - // have from the normal behavior. - web::WebState* web_state = chrome_test_util::GetCurrentWebState(); - ReadingListAddCommand* command = [[ReadingListAddCommand alloc] - initWithURL:web_state->GetVisibleURL() - title:base::SysUTF16ToNSString(web_state->GetTitle())]; - [chrome_test_util::DispatcherForActiveBrowserViewController() - addToReadingList:command]; - } else { - [ChromeEarlGreyUI openShareMenu]; - [[EarlGrey selectElementWithMatcher: - chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_SHARE_MENU_READING_LIST_ACTION)] - performAction:grey_tap()]; - } + [ChromeEarlGreyUI openToolsMenu]; + [ChromeEarlGreyUI + tapToolsMenuButton:chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_SHARE_MENU_READING_LIST_ACTION)]; // Wait for the snackbar to appear. id<GREYMatcher> snackbar_matcher = @@ -388,9 +341,7 @@ // Wait until one element is distilled. void WaitForDistillation() { NSString* a11y_id = - experimental_flags::IsReadingListUIRebootEnabled() - ? [TableViewURLCellFaviconBadgeView accessibilityIdentifier] - : @"Reading List Item distillation date"; + [TableViewURLCellFaviconBadgeView accessibilityIdentifier]; ConditionBlock wait_for_distillation_date = ^{ NSError* error = nil; [[EarlGrey selectElementWithMatcher:grey_accessibilityID(a11y_id)] @@ -429,17 +380,11 @@ // Opens the page security info bubble. void OpenPageSecurityInfoBubble() { - if (IsUIRefreshPhase1Enabled()) { - // In UI Refresh, the security info is accessed through the tools menu. - [ChromeEarlGreyUI openToolsMenu]; - // Tap on the Page Info button. - [ChromeEarlGreyUI - tapToolsMenuButton:grey_accessibilityID(kToolsMenuSiteInformation)]; - } else { - [[EarlGrey - selectElementWithMatcher:chrome_test_util::PageSecurityInfoIndicator()] - performAction:grey_tap()]; - } + // In UI Refresh, the security info is accessed through the tools menu. + [ChromeEarlGreyUI openToolsMenu]; + // Tap on the Page Info button. + [ChromeEarlGreyUI + tapToolsMenuButton:grey_accessibilityID(kToolsMenuSiteInformation)]; } // Tests that the correct version of kDistillableURL is displayed. @@ -479,22 +424,12 @@ } // Test the presence of the omnibox offline chip. - if (IsRefreshLocationBarEnabled()) { - [[EarlGrey selectElementWithMatcher: - grey_allOf(chrome_test_util::PageSecurityInfoIndicator(), - chrome_test_util::ImageViewWithImageNamed( - @"location_bar_offline"), - nil)] - assertWithMatcher:online ? grey_nil() : grey_notNil()]; - } else { - [[EarlGrey - selectElementWithMatcher:grey_allOf( - chrome_test_util::PageSecurityInfoButton(), - chrome_test_util::ButtonWithImage( - IDR_IOS_OMNIBOX_OFFLINE), - nil)] - assertWithMatcher:online ? grey_nil() : grey_notNil()]; - } + [[EarlGrey selectElementWithMatcher: + grey_allOf(chrome_test_util::PageSecurityInfoIndicator(), + chrome_test_util::ImageViewWithImageNamed( + @"location_bar_offline"), + nil)] + assertWithMatcher:online ? grey_nil() : grey_notNil()]; } } // namespace
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h index ab76c21..60886f3 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h +++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h
@@ -15,15 +15,6 @@ // Factory object that produces ListItems for Reading List. @interface ReadingListListItemFactory : NSObject -// A factory that produces ReadingListTableViewItems. -+ (instancetype)tableViewItemFactory; - -// A factory that produces ReadingListCollectionViewItems. -+ (instancetype)collectionViewItemFactory; - -// Use either |+tableViewItemFactory| or |+collectionViewItemFactory|. -- (instancetype)init NS_UNAVAILABLE; - // The accessibility delegate to use for the created items. @property(nonatomic, weak) id<ReadingListListItemAccessibilityDelegate> accessibilityDelegate;
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.mm b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.mm index 5ca6401..4ed4051 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.mm
@@ -9,7 +9,6 @@ #include "base/strings/sys_string_conversions.h" #include "components/reading_list/core/reading_list_entry.h" #include "components/url_formatter/url_formatter.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_util.h" #import "ios/chrome/browser/ui/reading_list/reading_list_table_view_item.h" @@ -19,32 +18,19 @@ #error "This file requires ARC support." #endif -namespace { -// The different types of items to be vended by the factory. -enum class ItemFactoryType { TABLE, COLLECTION }; -} // namespace - @interface ReadingListListItemFactory () -// The factory type. -@property(nonatomic, assign) ItemFactoryType factoryType; // The factory supplying custom accessibility actions to the items. @property(nonatomic, readonly, strong) ReadingListListItemCustomActionFactory* customActionFactory; -// Initializer for a factory of |factoryType|. -- (instancetype)initWithFactoryType:(ItemFactoryType)factoryType - NS_DESIGNATED_INITIALIZER; - @end @implementation ReadingListListItemFactory -@synthesize factoryType = _factoryType; @synthesize customActionFactory = _customActionFactory; -- (instancetype)initWithFactoryType:(ItemFactoryType)factoryType { +- (instancetype)init { if (self = [super init]) { - _factoryType = factoryType; _customActionFactory = [[ReadingListListItemCustomActionFactory alloc] init]; } @@ -64,22 +50,10 @@ #pragma mark Public -+ (instancetype)tableViewItemFactory { - return [[ReadingListListItemFactory alloc] - initWithFactoryType:ItemFactoryType::TABLE]; -} - -+ (instancetype)collectionViewItemFactory { - return [[ReadingListListItemFactory alloc] - initWithFactoryType:ItemFactoryType::COLLECTION]; -} - - (ListItem<ReadingListListItem>*)cellItemForReadingListEntry: (const ReadingListEntry*)entry { ListItem<ReadingListListItem>* item = - self.factoryType == ItemFactoryType::TABLE - ? [[ReadingListTableViewItem alloc] initWithType:0] - : [[ReadingListCollectionViewItem alloc] initWithType:0]; + [[ReadingListTableViewItem alloc] initWithType:0]; item.title = base::SysUTF8ToNSString(entry->Title()); const GURL& URL = entry->URL(); item.entryURL = URL;
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory_unittest.mm index 08845a42..bc32f67 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory_unittest.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_factory_unittest.mm
@@ -6,7 +6,6 @@ #include "base/time/time.h" #include "components/reading_list/core/reading_list_entry.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h" @@ -39,25 +38,8 @@ id<ReadingListListItemAccessibilityDelegate> mockDelegate = OCMProtocolMock(@protocol(ReadingListListItemAccessibilityDelegate)); ReadingListListItemFactory* factory = - [ReadingListListItemFactory tableViewItemFactory]; + [[ReadingListListItemFactory alloc] init]; factory.accessibilityDelegate = mockDelegate; id<ReadingListListItem> item = [factory cellItemForReadingListEntry:&entry_]; EXPECT_EQ(item.customActionFactory.accessibilityDelegate, mockDelegate); } - -// Tests that |+tableViewItemFactory| returns ReadingListTableViewItems. -TEST_F(ReadingListListItemFactoryTest, TableViewItem) { - ReadingListListItemFactory* factory = - [ReadingListListItemFactory tableViewItemFactory]; - id<ReadingListListItem> item = [factory cellItemForReadingListEntry:&entry_]; - EXPECT_TRUE([item isKindOfClass:[ReadingListTableViewItem class]]); -} - -// Tests that |+collectionViewItemFactory| returns -// ReadingListCollectionViewItems. -TEST_F(ReadingListListItemFactoryTest, CollectionViewItem) { - ReadingListListItemFactory* factory = - [ReadingListListItemFactory collectionViewItemFactory]; - id<ReadingListListItem> item = [factory cellItemForReadingListEntry:&entry_]; - EXPECT_TRUE([item isKindOfClass:[ReadingListCollectionViewItem class]]); -}
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm index 0bbc81d..ab607f1 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_mediator.mm
@@ -16,7 +16,6 @@ #import "ios/chrome/browser/favicon/favicon_loader.h" #include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" #import "ios/chrome/browser/ui/favicon/favicon_attributes_provider.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_data_sink.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h"
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm index bb2d103..b3100f9 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_mediator_unittest.mm
@@ -14,10 +14,10 @@ #include "components/url_formatter/url_formatter.h" #import "ios/chrome/browser/favicon/favicon_loader.h" #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_custom_action_factory.h" #import "ios/chrome/browser/ui/reading_list/reading_list_list_item_factory.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_table_view_item.h" #include "ios/web/public/test/test_web_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -75,14 +75,12 @@ mediator_ = [[ReadingListMediator alloc] initWithModel:model_.get() faviconLoader:favicon_loader.get() - listItemFactory:[ReadingListListItemFactory - collectionViewItemFactory]]; + listItemFactory:[[ReadingListListItemFactory alloc] init]]; } else { mediator_ = [[ReadingListMediator alloc] initWithModel:model_.get() largeIconService:large_icon_service_.get() - listItemFactory:[ReadingListListItemFactory - collectionViewItemFactory]]; + listItemFactory:[[ReadingListListItemFactory alloc] init]]; } } @@ -111,8 +109,8 @@ // Tests. EXPECT_EQ(3U, [unreadArray count]); EXPECT_EQ(2U, [readArray count]); - NSArray<ReadingListCollectionViewItem*>* rlReadArray = [readArray copy]; - NSArray<ReadingListCollectionViewItem*>* rlUneadArray = [unreadArray copy]; + NSArray<ReadingListTableViewItem*>* rlReadArray = [readArray copy]; + NSArray<ReadingListTableViewItem*>* rlUneadArray = [unreadArray copy]; EXPECT_TRUE([rlUneadArray[0].title isEqualToString:@""]); EXPECT_TRUE([rlReadArray[0].title isEqualToString:@"read2"]); EXPECT_TRUE([rlReadArray[1].title isEqualToString:@"read1"]);
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_utils.h b/ios/chrome/browser/ui/reading_list/reading_list_utils.h index 08ebdb6..471e9e5 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_utils.h +++ b/ios/chrome/browser/ui/reading_list/reading_list_utils.h
@@ -6,7 +6,7 @@ #define IOS_CHROME_BROWSER_UI_READING_LIST_READING_LIST_UTILS_H_ #include "components/reading_list/core/reading_list_entry.h" -#import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_cell.h" +#import "ios/chrome/browser/ui/reading_list/reading_list_ui_distillation_status.h" namespace reading_list {
diff --git a/ios/chrome/browser/ui/reading_list/resources/BUILD.gn b/ios/chrome/browser/ui/reading_list/resources/BUILD.gn index f21f50bd..ade93f74 100644 --- a/ios/chrome/browser/ui/reading_list/resources/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/resources/BUILD.gn
@@ -4,15 +4,6 @@ import("//build/config/ios/asset_catalog.gni") -imageset("distillation_fail") { - sources = [ - "distillation_fail.imageset/Contents.json", - "distillation_fail.imageset/distillation_fail.png", - "distillation_fail.imageset/distillation_fail@2x.png", - "distillation_fail.imageset/distillation_fail@3x.png", - ] -} - imageset("distillation_fail_new") { sources = [ "distillation_fail_new.imageset/Contents.json", @@ -22,15 +13,6 @@ ] } -imageset("distillation_success") { - sources = [ - "distillation_success.imageset/Contents.json", - "distillation_success.imageset/distillation_success.png", - "distillation_success.imageset/distillation_success@2x.png", - "distillation_success.imageset/distillation_success@3x.png", - ] -} - imageset("reading_list_empty_state") { sources = [ "reading_list_empty_state.imageset/Contents.json", @@ -49,15 +31,6 @@ ] } -imageset("reading_list_share_icon") { - sources = [ - "reading_list_share_icon.imageset/Contents.json", - "reading_list_share_icon.imageset/reading_list_share_icon.png", - "reading_list_share_icon.imageset/reading_list_share_icon@2x.png", - "reading_list_share_icon.imageset/reading_list_share_icon@3x.png", - ] -} - imageset("reading_list_side_swipe") { sources = [ "reading_list_side_swipe.imageset/Contents.json", @@ -67,15 +40,6 @@ ] } -imageset("reading_list_toolbar_icon") { - sources = [ - "reading_list_toolbar_icon.imageset/Contents.json", - "reading_list_toolbar_icon.imageset/reading_list_toolbar_icon.png", - "reading_list_toolbar_icon.imageset/reading_list_toolbar_icon@2x.png", - "reading_list_toolbar_icon.imageset/reading_list_toolbar_icon@3x.png", - ] -} - imageset("reading_list_tools_icon") { sources = [ "reading_list_tools_icon.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/Contents.json b/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/Contents.json deleted file mode 100644 index 03a4054f..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "distillation_fail.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "distillation_fail@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "distillation_fail@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail.png b/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail.png deleted file mode 100644 index dc403ea..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail@2x.png b/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail@2x.png deleted file mode 100644 index 804ed571..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail@3x.png b/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail@3x.png deleted file mode 100644 index e48983a..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_fail.imageset/distillation_fail@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/Contents.json b/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/Contents.json deleted file mode 100644 index e608ccb..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "distillation_success.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "distillation_success@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "distillation_success@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success.png b/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success.png deleted file mode 100644 index 368452e..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success@2x.png b/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success@2x.png deleted file mode 100644 index 719d6576d..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success@3x.png b/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success@3x.png deleted file mode 100644 index df30dbe0..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/distillation_success.imageset/distillation_success@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_share_icon.imageset/Contents.json b/ios/chrome/browser/ui/reading_list/resources/reading_list_share_icon.imageset/Contents.json deleted file mode 100644 index 259992d..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_share_icon.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "reading_list_share_icon.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "reading_list_share_icon@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "reading_list_share_icon@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_toolbar_icon.imageset/Contents.json b/ios/chrome/browser/ui/reading_list/resources/reading_list_toolbar_icon.imageset/Contents.json deleted file mode 100644 index f1f5ab81..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_toolbar_icon.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "reading_list_toolbar_icon.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "reading_list_toolbar_icon@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "reading_list_toolbar_icon@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/reading_list/text_badge_view.mm b/ios/chrome/browser/ui/reading_list/text_badge_view.mm index 095b706..aa9e933 100644 --- a/ios/chrome/browser/ui/reading_list/text_badge_view.mm +++ b/ios/chrome/browser/ui/reading_list/text_badge_view.mm
@@ -5,9 +5,7 @@ #import "ios/chrome/browser/ui/reading_list/text_badge_view.h" #include "base/logging.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #include "ios/chrome/browser/ui/ui_util.h" -#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -15,7 +13,6 @@ namespace { const CGFloat kFontSize = 11.0f; -const CGFloat kLegacyFontSize = 10.0f; // The margin between the top and bottom of the label and the badge. const CGFloat kLabelVerticalMargin = 2.5f; // The default value for the margin between the sides of the label and the @@ -63,14 +60,10 @@ [self addSubview:self.label]; self.didAddSubviews = YES; [self activateConstraints]; - if (IsUIRefreshPhase1Enabled()) { - [self setBackgroundColor:[UIColor colorWithRed:0.101 - green:0.45 - blue:0.909 - alpha:0.1]]; - } else { - [self setBackgroundColor:[[MDCPalette cr_bluePalette] tint500]]; - } + [self setBackgroundColor:[UIColor colorWithRed:0.101 + green:0.45 + blue:0.909 + alpha:0.1]]; [self setAccessibilityLabel:self.label.text]; } [super willMoveToSuperview:newSuperview]; @@ -99,17 +92,10 @@ // Return a label that displays text in white with center alignment. + (UILabel*)labelWithText:(NSString*)text { UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; - if (IsUIRefreshPhase1Enabled()) { - [label setFont:[UIFont systemFontOfSize:kFontSize - weight:UIFontWeightSemibold]]; - [label setTextColor:[UIColor colorWithRed:0.101 - green:0.45 - blue:0.909 - alpha:1]]; - } else { - [label setFont:[[MDCTypography fontLoader] boldFontOfSize:kLegacyFontSize]]; - [label setTextColor:[UIColor whiteColor]]; - } + [label + setFont:[UIFont systemFontOfSize:kFontSize weight:UIFontWeightSemibold]]; + [label + setTextColor:[UIColor colorWithRed:0.101 green:0.45 blue:0.909 alpha:1]]; [label setTranslatesAutoresizingMaskIntoConstraints:NO]; [label setText:text]; [label setTextAlignment:NSTextAlignmentCenter];
diff --git a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm index 36ca586..7642ae6 100644 --- a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm
@@ -121,7 +121,7 @@ _passwordForm = passwordForm; if (!_passwordForm.blacklisted_by_user) { _username = base::SysUTF16ToNSString(_passwordForm.username_value); - if (_passwordForm.federation_origin.unique()) { + if (_passwordForm.federation_origin.opaque()) { _password = base::SysUTF16ToNSString(_passwordForm.password_value); } else { _federation = @@ -198,7 +198,7 @@ [model addItem:[self usernameCopyButtonItem] toSectionWithIdentifier:SectionIdentifierUsername]; - if (_passwordForm.federation_origin.unique()) { + if (_passwordForm.federation_origin.opaque()) { [model addSectionWithIdentifier:SectionIdentifierPassword]; SettingsTextItem* passwordHeader = [[SettingsTextItem alloc] initWithType:ItemTypeHeader];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index 974c3d5c..9a7340ad 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -304,21 +304,42 @@ // scrolling. self.topToolbar.pageControl.userInteractionEnabled = NO; self.pageChangeInteraction = PageChangeInteractionScrollDrag; - [self updatePageViewAccessibilityVisibility]; } - (void)scrollViewDidEndDragging:(UIScrollView*)scrollView willDecelerate:(BOOL)decelerate { // Re-enable the page control since the user isn't dragging anymore. self.topToolbar.pageControl.userInteractionEnabled = YES; - [self updatePageViewAccessibilityVisibility]; } - (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView { // Mark the interaction as ended, so that scrolls that don't change page don't // cause other interactions to be mislabeled. self.pageChangeInteraction = PageChangeInteractionNone; - [self updatePageViewAccessibilityVisibility]; + + // Update _currentPage if scroll view has moved to a new page. Especially + // important here for 3-finger accessibility swipes since it's not registered + // as dragging in scrollViewDidScroll: + TabGridPage page = GetPageFromScrollView(scrollView); + if (page != _currentPage) { + // Original current page is about to not be visible. Disable it from being + // focused by VoiceOver. + self.currentPageViewController.view.accessibilityElementsHidden = YES; + _currentPage = page; + // Allow VoiceOver to focus on the new current page's elements. + self.currentPageViewController.view.accessibilityElementsHidden = NO; + [self broadcastIncognitoContentVisibility]; + [self configureButtonsForActiveAndCurrentPage]; + + // TODO(crbug.com/872303) : This is a workaround because TabRestoreService + // does not notify observers when entries are removed. When close all tabs + // removes entries, the remote tabs page in the tab grid are not updated. + // This ensures that the table is updated whenever scrolling to it. + if (_currentPage == TabGridPageRemoteTabs) { + [self.remoteTabsViewController loadModel]; + [self.remoteTabsViewController.tableView reloadData]; + } + } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView*)scrollView { @@ -531,9 +552,15 @@ // the ivar may have been set before the scroll view could be updated. Calling // this method should always update the scroll view's offset if possible. + // Original current page is about to not be visible. Disable it from being + // focused by VoiceOver. + self.currentPageViewController.view.accessibilityElementsHidden = YES; + // If the view isn't loaded yet, just do bookkeeping on _currentPage. if (!self.viewLoaded) { _currentPage = currentPage; + // Allow VoiceOver to focus on the new current page's elements. + self.currentPageViewController.view.accessibilityElementsHidden = NO; return; } CGFloat pageWidth = self.scrollView.frame.size.width; @@ -556,6 +583,9 @@ _currentPage = currentPage; } } + // Allow VoiceOver to focus on the new current page's elements. + self.currentPageViewController.view.accessibilityElementsHidden = NO; + // TODO(crbug.com/872303) : This is a workaround because TabRestoreService // does not notify observers when entries are removed. When close all tabs // removes entries, the remote tabs page in the tab grid are not updated. This @@ -582,7 +612,6 @@ if (_scrollViewAnimatingContentOffset == scrollViewAnimatingContentOffset) return; _scrollViewAnimatingContentOffset = scrollViewAnimatingContentOffset; - [self updatePageViewAccessibilityVisibility]; } // Adds the scroll view and sets constraints. @@ -908,19 +937,6 @@ kTabGridCloseAllButtonIdentifier; } -// Updates the visibility of the pages' accessibility elements. When -// |scrollView| is scrolling, all pages should be visible. When stationary, -// however, the accessibility elements of off-screen pages should be hidden. -- (void)updatePageViewAccessibilityVisibility { - BOOL scrolling = self.scrollView.dragging || self.scrollView.decelerating || - self.scrollViewAnimatingContentOffset; - UIViewController* currentPageViewController = self.currentPageViewController; - for (UIViewController* pageViewController in self.pageViewControllers) { - pageViewController.view.accessibilityElementsHidden = - !scrolling && pageViewController != currentPageViewController; - } -} - // Shows the two toolbars and the floating button. Suitable for use in // animations. - (void)showToolbars {
diff --git a/ios/third_party/material_sprited_animation_view_ios/README.chromium b/ios/third_party/material_sprited_animation_view_ios/README.chromium index a1f29d9..451f5399 100644 --- a/ios/third_party/material_sprited_animation_view_ios/README.chromium +++ b/ios/third_party/material_sprited_animation_view_ios/README.chromium
@@ -1,7 +1,7 @@ Name: Material Sprited Animation View URL: https://github.com/material-foundation/material-sprited-animation-view-ios Version: 0 -Revision: c6e16d06bdafd95540c62b3402d9414692fbca81 +Revision: 8af9adaa182044cf2920dfb620b863669e1aeb7c License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/ios/web/web_state/web_frame_util_unittest.mm b/ios/web/web_state/web_frame_util_unittest.mm index 404b7f31..dfa93dd1 100644 --- a/ios/web/web_state/web_frame_util_unittest.mm +++ b/ios/web/web_state/web_frame_util_unittest.mm
@@ -103,6 +103,9 @@ EXPECT_EQ(nullptr, GetWebFrameWithId(&test_web_state, "iframe")); EXPECT_EQ(nullptr, GetWebFrameWithId(&test_web_state, "main_frame")); EXPECT_EQ(nullptr, GetWebFrameWithId(&test_web_state, "unused")); + + // Test that GetWebFrameWithId returns nullptr for the empty string. + EXPECT_EQ(nullptr, GetWebFrameWithId(&test_web_state, "")); } // Tests the GetWebFrameId GetWebFrameId function.
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index 591d5ee..33b6fd5 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -384,6 +384,7 @@ "internal/cwv_preview_element_info_unittest.mm", "internal/cwv_scroll_view_unittest.mm", "internal/signin/cwv_identity_unittest.mm", + "internal/sync/cwv_sync_controller_unittest.mm", "internal/translate/cwv_translation_controller_unittest.mm", "internal/translate/cwv_translation_language_unittest.mm", "internal/translate/cwv_translation_policy_unittest.mm", @@ -399,7 +400,10 @@ "//components/autofill/core/browser:test_support", "//components/autofill/ios/browser:test_support", "//components/autofill/ios/form_util:test_support", + "//components/browser_sync:test_support", "//components/prefs:test_support", + "//components/signin/core/browser:test_support", + "//components/sync:test_support_driver", "//ios/web/public/test", "//ios/web/public/test/fakes", "//testing/gtest",
diff --git a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm new file mode 100644 index 0000000..7b248e30 --- /dev/null +++ b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
@@ -0,0 +1,117 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web_view/internal/sync/cwv_sync_controller_internal.h" + +#include <memory> +#include <set> + +#include "base/callback.h" +#include "base/files/file_path.h" +#include "components/browser_sync/profile_sync_service_mock.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/device_id_helper.h" +#include "components/signin/core/browser/fake_gaia_cookie_manager_service.h" +#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" +#include "components/signin/core/browser/fake_signin_manager.h" +#include "components/signin/core/browser/test_signin_client.h" +#include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h" +#include "components/signin/ios/browser/profile_oauth2_token_service_ios_provider.h" +#include "components/sync/driver/fake_sync_client.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#include "ios/web_view/internal/web_view_browser_state.h" +#import "ios/web_view/public/cwv_identity.h" +#import "ios/web_view/public/cwv_sync_controller_data_source.h" +#import "ios/web_view/public/cwv_sync_controller_delegate.h" +#include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace ios_web_view { + +class CWVSyncControllerTest : public PlatformTest { + protected: + CWVSyncControllerTest() + : browser_state_(/*off_the_record=*/false), + signin_client_(browser_state_.GetPrefs()), + token_service_(browser_state_.GetPrefs()), + gaia_cookie_manager_service_(&token_service_, + "cookie-source", + &signin_client_), + signin_manager_(&signin_client_, + &token_service_, + &account_tracker_service_, + &gaia_cookie_manager_service_) { + web_state_.SetBrowserState(&browser_state_); + + browser_sync::ProfileSyncService::InitParams init_params; + init_params.start_behavior = browser_sync::ProfileSyncService::MANUAL_START; + init_params.sync_client = std::make_unique<syncer::FakeSyncClient>(); + init_params.url_loader_factory = browser_state_.GetSharedURLLoaderFactory(); + init_params.network_time_update_callback = base::DoNothing(); + init_params.signin_scoped_device_id_callback = base::BindRepeating( + &signin::GetSigninScopedDeviceId, browser_state_.GetPrefs()); + profile_sync_service_ = + std::make_unique<browser_sync::ProfileSyncServiceMock>(&init_params); + + account_tracker_service_.Initialize(browser_state_.GetPrefs(), + base::FilePath()); + + sync_controller_ = [[CWVSyncController alloc] + initWithProfileSyncService:profile_sync_service_.get() + accountTrackerService:&account_tracker_service_ + signinManager:&signin_manager_ + tokenService:&token_service_]; + }; + + web::TestWebThreadBundle web_thread_bundle_; + ios_web_view::WebViewBrowserState browser_state_; + web::TestWebState web_state_; + std::unique_ptr<browser_sync::ProfileSyncServiceMock> profile_sync_service_; + AccountTrackerService account_tracker_service_; + TestSigninClient signin_client_; + FakeProfileOAuth2TokenService token_service_; + FakeGaiaCookieManagerService gaia_cookie_manager_service_; + FakeSigninManager signin_manager_; + CWVSyncController* sync_controller_; +}; + +// Verifies CWVSyncControllerDataSource methods are invoked with the correct +// parameters. +TEST_F(CWVSyncControllerTest, DataSourceCallbacks) { + // [delegate expect] returns an autoreleased object, but it must be destroyed + // before this test exits to avoid holding on to |sync_controller_|. + @autoreleasepool { + id data_source = OCMProtocolMock(@protocol(CWVSyncControllerDataSource)); + + [[data_source expect] + syncController:sync_controller_ + getAccessTokenForScopes:[OCMArg checkWithBlock:^BOOL(NSArray* scopes) { + return [scopes containsObject:@"scope1.chromium.org"] && + [scopes containsObject:@"scope2.chromium.org"]; + }] + completionHandler:[OCMArg any]]; + + CWVIdentity* identity = + [[CWVIdentity alloc] initWithEmail:@"johndoe@chromium.org" + fullName:@"John Doe" + gaiaID:@"1337"]; + [sync_controller_ startSyncWithIdentity:identity dataSource:data_source]; + + std::set<std::string> scopes = {"scope1.chromium.org", + "scope2.chromium.org"}; + ProfileOAuth2TokenServiceIOSProvider::AccessTokenCallback callback; + [sync_controller_ fetchAccessTokenForScopes:scopes callback:callback]; + + [data_source verify]; + } +} + +} // namespace ios_web_view
diff --git a/media/base/android/android_cdm_factory.cc b/media/base/android/android_cdm_factory.cc index 2da000b..87f1755c 100644 --- a/media/base/android/android_cdm_factory.cc +++ b/media/base/android/android_cdm_factory.cc
@@ -55,7 +55,7 @@ // Bound |cdm_created_cb| so we always fire it asynchronously. CdmCreatedCB bound_cdm_created_cb = BindToCurrentLoop(cdm_created_cb); - if (security_origin.unique()) { + if (security_origin.opaque()) { bound_cdm_created_cb.Run(nullptr, "Invalid origin."); return; }
diff --git a/media/base/android/media_drm_bridge_factory.cc b/media/base/android/media_drm_bridge_factory.cc index 90ac867..024449d30 100644 --- a/media/base/android/media_drm_bridge_factory.cc +++ b/media/base/android/media_drm_bridge_factory.cc
@@ -39,7 +39,7 @@ const CdmCreatedCB& cdm_created_cb) { DCHECK(MediaDrmBridge::IsKeySystemSupported(key_system)); DCHECK(MediaDrmBridge::IsAvailable()); - DCHECK(!security_origin.unique()); + DCHECK(!security_origin.opaque()); DCHECK(scheme_uuid_.empty()) << "This factory can only be used once."; scheme_uuid_ = MediaDrmBridge::GetUUID(key_system);
diff --git a/media/cdm/cdm_adapter_factory.cc b/media/cdm/cdm_adapter_factory.cc index 997dd987..1118ce8f 100644 --- a/media/cdm/cdm_adapter_factory.cc +++ b/media/cdm/cdm_adapter_factory.cc
@@ -31,7 +31,7 @@ const CdmCreatedCB& cdm_created_cb) { DVLOG(1) << __func__ << ": key_system=" << key_system; - if (security_origin.unique()) { + if (security_origin.opaque()) { LOG(ERROR) << "Invalid Origin: " << security_origin; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(cdm_created_cb, nullptr, "Invalid origin."));
diff --git a/media/cdm/default_cdm_factory.cc b/media/cdm/default_cdm_factory.cc index da698c3..8d818cf 100644 --- a/media/cdm/default_cdm_factory.cc +++ b/media/cdm/default_cdm_factory.cc
@@ -41,7 +41,7 @@ const SessionKeysChangeCB& session_keys_change_cb, const SessionExpirationUpdateCB& session_expiration_update_cb, const CdmCreatedCB& cdm_created_cb) { - if (security_origin.unique()) { + if (security_origin.opaque()) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(cdm_created_cb, nullptr, "Invalid origin.")); return;
diff --git a/media/formats/mp4/avc.cc b/media/formats/mp4/avc.cc index 235795f7..99a0b4e2 100644 --- a/media/formats/mp4/avc.cc +++ b/media/formats/mp4/avc.cc
@@ -331,10 +331,11 @@ AVCBitstreamConverter::~AVCBitstreamConverter() = default; -bool AVCBitstreamConverter::ConvertFrame( +bool AVCBitstreamConverter::ConvertAndAnalyzeFrame( std::vector<uint8_t>* frame_buf, bool is_keyframe, - std::vector<SubsampleEntry>* subsamples) const { + std::vector<SubsampleEntry>* subsamples, + AnalysisResult* analysis_result) const { // Convert the AVC NALU length fields to Annex B headers, as expected by // decoding libraries. Since this may enlarge the size of the buffer, we also // update the clear byte count for each subsample if encryption is used to @@ -343,7 +344,13 @@ RCHECK(AVC::ConvertFrameToAnnexB(avc_config_->length_size, frame_buf, subsamples)); - if (is_keyframe) { + // |is_keyframe| may be incorrect. Analyze the frame to see if it is a + // keyframe. |is_keyframe| will be used if the analysis is inconclusive. + // Also, provide the analysis result to the caller via out parameter + // |analysis_result|. + *analysis_result = Analyze(frame_buf, subsamples); + + if (analysis_result->is_keyframe.value_or(is_keyframe)) { // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of // a frame. If subsample info is present, we also update the clear byte // count for that first subsample.
diff --git a/media/formats/mp4/avc.h b/media/formats/mp4/avc.h index 444d219..e83f561 100644 --- a/media/formats/mp4/avc.h +++ b/media/formats/mp4/avc.h
@@ -80,16 +80,16 @@ #endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) // BitstreamConverter interface - bool ConvertFrame(std::vector<uint8_t>* frame_buf, - bool is_keyframe, - std::vector<SubsampleEntry>* subsamples) const override; - - AnalysisResult Analyze( - std::vector<uint8_t>* frame_buf, - std::vector<SubsampleEntry>* subsamples) const override; + bool ConvertAndAnalyzeFrame(std::vector<uint8_t>* frame_buf, + bool is_keyframe, + std::vector<SubsampleEntry>* subsamples, + AnalysisResult* analysis_result) const override; private: ~AVCBitstreamConverter() override; + AnalysisResult Analyze( + std::vector<uint8_t>* frame_buf, + std::vector<SubsampleEntry>* subsamples) const override; std::unique_ptr<AVCDecoderConfigurationRecord> avc_config_; #if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING)
diff --git a/media/formats/mp4/bitstream_converter.h b/media/formats/mp4/bitstream_converter.h index 5d3c360..b6ad4a47 100644 --- a/media/formats/mp4/bitstream_converter.h +++ b/media/formats/mp4/bitstream_converter.h
@@ -47,9 +47,17 @@ // of input frame are encrypted and should update |subsamples| if necessary, // to make sure it correctly describes the converted output frame. See // SubsampleEntry definition in media/base/decrypt_config.h for more info. - virtual bool ConvertFrame(std::vector<uint8_t>* frame_buf, - bool is_keyframe, - std::vector<SubsampleEntry>* subsamples) const = 0; + // |analysis_result| is an output parameter that contains the AnalysisResult + // found during conversion. + virtual bool ConvertAndAnalyzeFrame( + std::vector<uint8_t>* frame_buf, + bool is_keyframe, + std::vector<SubsampleEntry>* subsamples, + AnalysisResult* analysis_result) const = 0; + + protected: + friend class base::RefCountedThreadSafe<BitstreamConverter>; + virtual ~BitstreamConverter(); // Inspects an already converted frame for conformance. If conformant, // inspects further to see if the converted frame appears to be a keyframe. @@ -57,10 +65,6 @@ virtual AnalysisResult Analyze( std::vector<uint8_t>* frame_buf, std::vector<SubsampleEntry>* subsamples) const = 0; - - protected: - friend class base::RefCountedThreadSafe<BitstreamConverter>; - virtual ~BitstreamConverter(); }; } // namespace mp4
diff --git a/media/formats/mp4/hevc.cc b/media/formats/mp4/hevc.cc index 8e8c8ea..b2f606db 100644 --- a/media/formats/mp4/hevc.cc +++ b/media/formats/mp4/hevc.cc
@@ -236,14 +236,20 @@ HEVCBitstreamConverter::~HEVCBitstreamConverter() { } -bool HEVCBitstreamConverter::ConvertFrame( +bool HEVCBitstreamConverter::ConvertAndAnalyzeFrame( std::vector<uint8_t>* frame_buf, bool is_keyframe, - std::vector<SubsampleEntry>* subsamples) const { + std::vector<SubsampleEntry>* subsamples, + AnalysisResult* analysis_result) const { RCHECK(AVC::ConvertFrameToAnnexB(hevc_config_->lengthSizeMinusOne + 1, frame_buf, subsamples)); + // |is_keyframe| may be incorrect. Analyze the frame to see if it is a + // keyframe. |is_keyframe| will be used if the analysis is inconclusive. + // Also, provide the analysis result to the caller via out parameter + // |analysis_result|. + *analysis_result = Analyze(frame_buf, subsamples); - if (is_keyframe) { + if (analysis_result->is_keyframe.value_or(is_keyframe)) { // If this is a keyframe, we (re-)inject HEVC params headers at the start of // a frame. If subsample info is present, we also update the clear byte // count for that first subsample.
diff --git a/media/formats/mp4/hevc.h b/media/formats/mp4/hevc.h index 87ec4ff..7ec661a 100644 --- a/media/formats/mp4/hevc.h +++ b/media/formats/mp4/hevc.h
@@ -95,16 +95,16 @@ std::unique_ptr<HEVCDecoderConfigurationRecord> hevc_config); // BitstreamConverter interface - bool ConvertFrame(std::vector<uint8_t>* frame_buf, - bool is_keyframe, - std::vector<SubsampleEntry>* subsamples) const override; - - AnalysisResult Analyze( - std::vector<uint8_t>* frame_buf, - std::vector<SubsampleEntry>* subsamples) const override; + bool ConvertAndAnalyzeFrame(std::vector<uint8_t>* frame_buf, + bool is_keyframe, + std::vector<SubsampleEntry>* subsamples, + AnalysisResult* analysis_result) const override; private: ~HEVCBitstreamConverter() override; + AnalysisResult Analyze( + std::vector<uint8_t>* frame_buf, + std::vector<SubsampleEntry>* subsamples) const override; std::unique_ptr<HEVCDecoderConfigurationRecord> hevc_config_; };
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index 14c437af..5337c1ff 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -809,15 +809,15 @@ runs_->video_description().video_codec == kCodecHEVC || runs_->video_description().video_codec == kCodecDolbyVision) { DCHECK(runs_->video_description().frame_bitstream_converter); - if (!runs_->video_description().frame_bitstream_converter->ConvertFrame( - &frame_buf, is_keyframe, &subsamples)) { + BitstreamConverter::AnalysisResult analysis; + if (!runs_->video_description() + .frame_bitstream_converter->ConvertAndAnalyzeFrame( + &frame_buf, is_keyframe, &subsamples, &analysis)) { MEDIA_LOG(ERROR, media_log_) << "Failed to prepare video sample for decode"; return ParseResult::kError; } - BitstreamConverter::AnalysisResult analysis = - runs_->video_description().frame_bitstream_converter->Analyze( - &frame_buf, &subsamples); + // If conformance analysis was not actually performed, assume the frame is // conformant. If it was performed and found to be non-conformant, log // it.
diff --git a/media/mojo/clients/mojo_cdm_factory.cc b/media/mojo/clients/mojo_cdm_factory.cc index 63564aa..4250576 100644 --- a/media/mojo/clients/mojo_cdm_factory.cc +++ b/media/mojo/clients/mojo_cdm_factory.cc
@@ -38,7 +38,7 @@ const CdmCreatedCB& cdm_created_cb) { DVLOG(2) << __func__ << ": " << key_system; - if (security_origin.unique()) { + if (security_origin.opaque()) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(cdm_created_cb, nullptr, "Invalid origin.")); return;
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc index 92fce88..b5a587e 100644 --- a/net/url_request/url_fetcher_core.cc +++ b/net/url_request/url_fetcher_core.cc
@@ -574,7 +574,7 @@ request_->SetReferrer(referrer_); request_->set_referrer_policy(referrer_policy_); request_->set_site_for_cookies(initiator_.has_value() && - !initiator_.value().unique() + !initiator_.value().opaque() ? initiator_.value().GetURL() : original_url_); request_->set_initiator(initiator_);
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 3b3a7e2..825a96b3 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -479,7 +479,7 @@ void URLRequest::set_initiator(const base::Optional<url::Origin>& initiator) { DCHECK(!is_pending_); - DCHECK(!initiator.has_value() || initiator.value().unique() || + DCHECK(!initiator.has_value() || initiator.value().opaque() || initiator.value().GetURL().is_valid()); initiator_ = initiator; }
diff --git a/pdf/pdfium/pdfium_print.cc b/pdf/pdfium/pdfium_print.cc index 8645c558..b440ed2 100644 --- a/pdf/pdfium/pdfium_print.cc +++ b/pdf/pdfium/pdfium_print.cc
@@ -174,31 +174,27 @@ // Performs N-up PDF generation for |doc| based on |pages_per_sheet| and // the parameters in |print_settings|. // On success, returns the N-up version of |doc|. On failure, returns nullptr. -ScopedFPDFDocument NupPdfToPdf(FPDF_DOCUMENT doc, +ScopedFPDFDocument NupPdfToPdf(ScopedFPDFDocument doc, uint32_t pages_per_sheet, const PP_PrintSettings_Dev& print_settings) { DCHECK(doc); DCHECK(ShouldDoNup(pages_per_sheet)); - PP_Size page_size = print_settings.paper_size; - printing::NupParameters nup_params; - bool is_landscape = PDFiumPrint::IsSourcePdfLandscape(doc); + bool is_landscape = PDFiumPrint::IsSourcePdfLandscape(doc.get()); nup_params.SetParameters(pages_per_sheet, is_landscape); - // Import n pages to one. + PP_Size page_size = print_settings.paper_size; bool paper_is_landscape = page_size.width > page_size.height; if (nup_params.landscape() != paper_is_landscape) std::swap(page_size.width, page_size.height); - ScopedFPDFDocument output_doc_nup(FPDF_ImportNPagesToOne( - doc, page_size.width, page_size.height, nup_params.num_pages_on_x_axis(), - nup_params.num_pages_on_y_axis())); - if (output_doc_nup) { - FitContentsToPrintableAreaIfRequired(output_doc_nup.get(), 1.0f, - print_settings); - } - return output_doc_nup; + ScopedFPDFDocument nup_doc(FPDF_ImportNPagesToOne( + doc.get(), page_size.width, page_size.height, + nup_params.num_pages_on_x_axis(), nup_params.num_pages_on_y_axis())); + if (nup_doc) + FitContentsToPrintableAreaIfRequired(nup_doc.get(), 1.0f, print_settings); + return nup_doc; } int GetBlockForJpeg(void* param, @@ -311,19 +307,17 @@ return nullptr; } - uint32_t pages_per_sheet = pdf_print_settings.pages_per_sheet; - if (ShouldDoNup(pages_per_sheet)) { - if (!FlattenPrintData(output_doc.get())) - return nullptr; - return NupPdfToPdf(output_doc.get(), pages_per_sheet, print_settings); - } - double scale_factor = pdf_print_settings.scale_factor / 100.0; FitContentsToPrintableAreaIfRequired(output_doc.get(), scale_factor, print_settings); if (!FlattenPrintData(output_doc.get())) return nullptr; - return output_doc; + + uint32_t pages_per_sheet = pdf_print_settings.pages_per_sheet; + if (!ShouldDoNup(pages_per_sheet)) + return output_doc; + + return NupPdfToPdf(std::move(output_doc), pages_per_sheet, print_settings); } ScopedFPDFDocument PDFiumPrint::CreateRasterPdf(
diff --git a/printing/backend/printing_restrictions.cc b/printing/backend/printing_restrictions.cc index a9b41e4..b284818a 100644 --- a/printing/backend/printing_restrictions.cc +++ b/printing/backend/printing_restrictions.cc
@@ -7,6 +7,7 @@ namespace printing { const char kAllowedColorModes[] = "allowedColorModes"; +const char kAllowedDuplexModes[] = "allowedDuplexModes"; const char kPageWidthUm[] = "WidthUm"; const char kPageHeightUm[] = "HeightUm"; @@ -52,6 +53,9 @@ if (mode_name == "any") return DuplexModeRestriction::kNone; + if (mode_name == "simplex") + return DuplexModeRestriction::kSimplex; + if (mode_name == "duplex") return DuplexModeRestriction::kDuplex;
diff --git a/printing/backend/printing_restrictions.h b/printing/backend/printing_restrictions.h index fd818ad..d9ef7fef 100644 --- a/printing/backend/printing_restrictions.h +++ b/printing/backend/printing_restrictions.h
@@ -49,6 +49,7 @@ // Must coincide with the name of field in |print_preview.Policies| in // chrome/browser/resources/print_preview/native_layer.js PRINTING_EXPORT extern const char kAllowedColorModes[]; +PRINTING_EXPORT extern const char kAllowedDuplexModes[]; // Dictionary keys to be used with |kPrintingAllowedPageSizes| and // |kPrintingSizeDefault| policies.
diff --git a/printing/page_setup.cc b/printing/page_setup.cc index fb342d5..3a856545 100644 --- a/printing/page_setup.cc +++ b/printing/page_setup.cc
@@ -10,6 +10,29 @@ namespace printing { +namespace { + +// Checks whether |printable_area| can be used to form a valid symmetrical +// printable area, so that margin_left equals margin_right, and margin_top +// equals margin_bottom. For example if +// printable_area.x() * 2 >= page_size.width(), then the +// content_width = page_size.width() - 2 * printable_area.x() would be zero or +// negative, which is invalid. +// |page_size| is the physical page size that includes margins. +bool IsValidPrintableArea(const gfx::Size& page_size, + const gfx::Rect& printable_area) { + return !printable_area.IsEmpty() && printable_area.x() >= 0 && + printable_area.y() >= 0 && + printable_area.right() <= page_size.width() && + printable_area.bottom() <= page_size.height() && + printable_area.x() * 2 < page_size.width() && + printable_area.y() * 2 < page_size.height() && + printable_area.right() * 2 > page_size.width() && + printable_area.bottom() * 2 > page_size.height(); +} + +} // namespace + PageMargins::PageMargins() : header(0), footer(0), @@ -45,6 +68,26 @@ PageSetup::~PageSetup() = default; +// static +gfx::Rect PageSetup::GetSymmetricalPrintableArea( + const gfx::Size& page_size, + const gfx::Rect& printable_area) { + if (!IsValidPrintableArea(page_size, printable_area)) + return gfx::Rect(); + + int left_right_margin = + std::max(printable_area.x(), page_size.width() - printable_area.right()); + int top_bottom_margin = std::max( + printable_area.y(), page_size.height() - printable_area.bottom()); + int width = page_size.width() - 2 * left_right_margin; + int height = page_size.height() - 2 * top_bottom_margin; + + gfx::Rect symmetrical_printable_area = gfx::Rect(page_size); + symmetrical_printable_area.ClampToCenteredSize(gfx::Size(width, height)); + + return symmetrical_printable_area; +} + void PageSetup::Clear() { physical_size_.SetSize(0, 0); printable_area_.SetRect(0, 0, 0, 0);
diff --git a/printing/page_setup.h b/printing/page_setup.h index 4126bea..f02ee056 100644 --- a/printing/page_setup.h +++ b/printing/page_setup.h
@@ -39,6 +39,10 @@ PageSetup(const PageSetup& other); ~PageSetup(); + // Gets a symmetrical printable area. + static gfx::Rect GetSymmetricalPrintableArea(const gfx::Size& page_size, + const gfx::Rect& printable_area); + void Clear(); // Equality operator.
diff --git a/printing/page_setup_unittest.cc b/printing/page_setup_unittest.cc index 50aa639f..83b1d83 100644 --- a/printing/page_setup_unittest.cc +++ b/printing/page_setup_unittest.cc
@@ -11,13 +11,15 @@ #include "testing/gtest/include/gtest/gtest.h" +namespace printing { + TEST(PageSetupTest, Random) { time_t seed = time(NULL); int kMax = 10; srand(static_cast<unsigned>(seed)); // Margins. - printing::PageMargins margins; + PageMargins margins; margins.header = rand() % kMax; margins.footer = rand() % kMax; margins.left = rand() % kMax; @@ -35,12 +37,12 @@ printable_area.y()); // Make the calculations. - printing::PageSetup setup; + PageSetup setup; setup.SetRequestedMargins(margins); setup.Init(page_size, printable_area, kTextHeight); // Calculate the effective margins. - printing::PageMargins effective_margins; + PageMargins effective_margins; effective_margins.header = std::max(margins.header, printable_area.y()); effective_margins.left = std::max(margins.left, printable_area.x()); effective_margins.top = std::max(margins.top, @@ -101,7 +103,7 @@ TEST(PageSetupTest, HardCoded) { // Margins. - printing::PageMargins margins; + PageMargins margins; margins.header = 2; margins.footer = 2; margins.left = 4; @@ -115,12 +117,12 @@ gfx::Rect printable_area(3, 3, 94, 94); // Make the calculations. - printing::PageSetup setup; + PageSetup setup; setup.SetRequestedMargins(margins); setup.Init(page_size, printable_area, kTextHeight); // Calculate the effective margins. - printing::PageMargins effective_margins; + PageMargins effective_margins; effective_margins.header = 3; effective_margins.left = 4; effective_margins.top = 6; @@ -165,7 +167,7 @@ } TEST(PageSetupTest, OutOfRangeMargins) { - printing::PageMargins margins; + PageMargins margins; margins.header = 0; margins.footer = 0; margins.left = -10; @@ -177,7 +179,7 @@ gfx::Rect printable_area(1, 2, 96, 94); // Make the calculations. - printing::PageSetup setup; + PageSetup setup; setup.SetRequestedMargins(margins); setup.Init(page_size, printable_area, 0); @@ -195,7 +197,7 @@ TEST(PageSetupTest, FlipOrientation) { // Margins. - printing::PageMargins margins; + PageMargins margins; margins.header = 2; margins.footer = 3; margins.left = 4; @@ -209,7 +211,7 @@ gfx::Rect printable_area(8, 9, 92, 50); // Make the calculations. - printing::PageSetup setup; + PageSetup setup; setup.SetRequestedMargins(margins); setup.Init(page_size, printable_area, kTextHeight); @@ -274,3 +276,34 @@ EXPECT_EQ(setup.effective_margins().right, 6); EXPECT_EQ(setup.effective_margins().bottom, 7); } + +TEST(PageSetupTest, GetSymmetricalPrintableArea) { + gfx::Rect printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(0, 0, 560, 750)); + EXPECT_EQ(gfx::Rect(52, 42, 508, 708), printable_area); + + printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(50, 60, 550, 700)); + EXPECT_EQ(gfx::Rect(50, 60, 512, 672), printable_area); + + printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(-1, 60, 520, 700)); + EXPECT_EQ(gfx::Rect(), printable_area); + printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(50, -1, 520, 700)); + EXPECT_EQ(gfx::Rect(), printable_area); + printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(100, 60, 520, 700)); + EXPECT_EQ(gfx::Rect(), printable_area); + printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(50, 100, 520, 700)); + EXPECT_EQ(gfx::Rect(), printable_area); + printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(400, 60, 212, 700)); + EXPECT_EQ(gfx::Rect(), printable_area); + printable_area = PageSetup::GetSymmetricalPrintableArea( + gfx::Size(612, 792), gfx::Rect(40, 600, 212, 192)); + EXPECT_EQ(gfx::Rect(), printable_area); +} + +} // namespace printing
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index 754fe5a..b00a88cf 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn
@@ -417,7 +417,6 @@ source_set("sandbox_services_headers") { sources = [ "system_headers/arm64_linux_syscalls.h", - "system_headers/arm64_linux_ucontext.h", "system_headers/arm_linux_syscalls.h", "system_headers/arm_linux_ucontext.h", "system_headers/i386_linux_ucontext.h", @@ -429,12 +428,9 @@ "system_headers/linux_time.h", "system_headers/linux_ucontext.h", "system_headers/mips64_linux_syscalls.h", - "system_headers/mips64_linux_ucontext.h", "system_headers/mips_linux_syscalls.h", - "system_headers/mips_linux_ucontext.h", "system_headers/x86_32_linux_syscalls.h", "system_headers/x86_64_linux_syscalls.h", - "system_headers/x86_64_linux_ucontext.h", ] }
diff --git a/sandbox/linux/system_headers/arm64_linux_ucontext.h b/sandbox/linux/system_headers/arm64_linux_ucontext.h deleted file mode 100644 index 48303ba..0000000 --- a/sandbox/linux/system_headers/arm64_linux_ucontext.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_ - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> -#include <signal.h> -#include <stdint.h> -// We also need greg_t for the sandbox, include it in this header as well. -typedef uint64_t greg_t; - -struct ucontext_t { - unsigned long uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - sigset_t uc_sigmask; - /* glibc uses a 1024-bit sigset_t */ - uint8_t unused[1024 / 8 - sizeof(sigset_t)]; - /* last for future expansion */ - struct sigcontext uc_mcontext; -}; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/arm_linux_ucontext.h b/sandbox/linux/system_headers/arm_linux_ucontext.h index 35208fa..2b2090e 100644 --- a/sandbox/linux/system_headers/arm_linux_ucontext.h +++ b/sandbox/linux/system_headers/arm_linux_ucontext.h
@@ -7,10 +7,6 @@ #include <stddef.h> -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#if !defined(__native_client_nonsfi__) -#include <asm/sigcontext.h> -#else // In PNaCl toolchain, sigcontext and stack_t is not defined. So here declare // them. struct sigcontext { @@ -43,7 +39,6 @@ size_t ss_size; } stack_t; -#endif // We also need greg_t for the sandbox, include it in this header as well. typedef unsigned long greg_t; @@ -62,8 +57,4 @@ unsigned long uc_regspace[128] __attribute__((__aligned__(8))); } ucontext_t; -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - #endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/i386_linux_ucontext.h b/sandbox/linux/system_headers/i386_linux_ucontext.h index f438033..1a7b975 100644 --- a/sandbox/linux/system_headers/i386_linux_ucontext.h +++ b/sandbox/linux/system_headers/i386_linux_ucontext.h
@@ -8,22 +8,15 @@ #include <stddef.h> #include <stdint.h> -// We do something compatible with glibc. Hopefully, at some point Android will -// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. // This is mostly copied from breakpad (common/android/include/sys/ucontext.h), // except we do use sigset_t for uc_sigmask instead of a custom type. -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#if !defined(__native_client_nonsfi__) -#include <asm/sigcontext.h> -#else // In PNaCl toolchain, sigcontext is not defined. So here declare it. typedef struct sigaltstack { void* ss_sp; int ss_flags; size_t ss_size; } stack_t; -#endif /* 80-bit floating-point register */ struct _libc_fpreg { @@ -89,8 +82,4 @@ struct _libc_fpstate __fpregs_mem; } ucontext_t; -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - #endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/linux_signal.h b/sandbox/linux/system_headers/linux_signal.h index 5ac4fdb..e4fd3461 100644 --- a/sandbox/linux/system_headers/linux_signal.h +++ b/sandbox/linux/system_headers/linux_signal.h
@@ -108,11 +108,6 @@ typedef siginfo_t LinuxSigInfo; -#if defined(__ANDROID__) -// Android's signal.h doesn't define ucontext etc. -#include "sandbox/linux/system_headers/linux_ucontext.h" -#endif // defined(__ANDROID__) - #endif // !defined(__native_client_nonsfi__) // struct sigset_t is different size in PNaCl from the Linux's.
diff --git a/sandbox/linux/system_headers/linux_ucontext.h b/sandbox/linux/system_headers/linux_ucontext.h index e97d727..22ce780 100644 --- a/sandbox/linux/system_headers/linux_ucontext.h +++ b/sandbox/linux/system_headers/linux_ucontext.h
@@ -5,26 +5,18 @@ #ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ #define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ -#if defined(__ANDROID__) || defined(__native_client_nonsfi__) +#if defined(__native_client_nonsfi__) #if defined(__arm__) #include "sandbox/linux/system_headers/arm_linux_ucontext.h" #elif defined(__i386__) #include "sandbox/linux/system_headers/i386_linux_ucontext.h" -#elif defined(__x86_64__) -#include "sandbox/linux/system_headers/x86_64_linux_ucontext.h" -#elif defined(__mips32__) -#include "sandbox/linux/system_headers/mips_linux_ucontext.h" -#elif defined(__mips64__) -#include "sandbox/linux/system_headers/mips64_linux_ucontext.h" -#elif defined(__aarch64__) -#include "sandbox/linux/system_headers/arm64_linux_ucontext.h" #else -#error "No support for your architecture in Android or PNaCl header" +#error "No support for your architecture in PNaCl header" #endif -#else // defined(__ANDROID__) || defined(__native_client_nonsfi__) -#error "The header file included on non Android and non PNaCl." -#endif // defined(__ANDROID__) || defined(__native_client_nonsfi__) +#else // defined(__native_client_nonsfi__) +#error "The header file included on non PNaCl." +#endif // defined(__native_client_nonsfi__) #endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/mips64_linux_ucontext.h b/sandbox/linux/system_headers/mips64_linux_ucontext.h deleted file mode 100644 index 3d10479..0000000 --- a/sandbox/linux/system_headers/mips64_linux_ucontext.h +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_UCONTEXT_H_ - -#include <stdint.h> - -// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), -// except we do use sigset_t for uc_sigmask instead of a custom type. -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -// Ensure that 'stack_t' is defined. -#include <asm/signal.h> - -// We also need greg_t for the sandbox, include it in this header as well. -typedef unsigned long greg_t; - -typedef struct { - uint64_t gregs[32]; - uint64_t fpregs[32]; - uint64_t mdhi; - uint64_t hi1; - uint64_t hi2; - uint64_t hi3; - uint64_t mdlo; - uint64_t lo1; - uint64_t lo2; - uint64_t lo3; - uint64_t pc; - uint32_t fpc_csr; - uint32_t used_math; - uint32_t dsp; - uint32_t reserved; -} mcontext_t; - -typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - // Other fields are not used by Google Breakpad. Don't define them. -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/mips_linux_ucontext.h b/sandbox/linux/system_headers/mips_linux_ucontext.h deleted file mode 100644 index 774bf312..0000000 --- a/sandbox/linux/system_headers/mips_linux_ucontext.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_ - -#include <stdint.h> - -// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), -// except we do use sigset_t for uc_sigmask instead of a custom type. -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -// Ensure that 'stack_t' is defined. -#include <asm/signal.h> - -// We also need greg_t for the sandbox, include it in this header as well. -typedef unsigned long greg_t; - -typedef struct { - uint32_t regmask; - uint32_t status; - uint64_t pc; - uint64_t gregs[32]; - uint64_t fpregs[32]; - uint32_t acx; - uint32_t fpc_csr; - uint32_t fpc_eir; - uint32_t used_math; - uint32_t dsp; - uint64_t mdhi; - uint64_t mdlo; - uint32_t hi1; - uint32_t lo1; - uint32_t hi2; - uint32_t lo2; - uint32_t hi3; - uint32_t lo3; -} mcontext_t; - -typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - // Other fields are not used by Google Breakpad. Don't define them. -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/x86_64_linux_ucontext.h b/sandbox/linux/system_headers/x86_64_linux_ucontext.h deleted file mode 100644 index 1f1abe6..0000000 --- a/sandbox/linux/system_headers/x86_64_linux_ucontext.h +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ - -#include <stdint.h> - -// We do something compatible with glibc. Hopefully, at some point Android will -// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. -// Spec: -// http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/libc-ddefs.html#AEN5668 - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> - -struct _libc_fpxreg { - unsigned short significand[4]; - unsigned short exponent; - unsigned short padding[3]; -}; - -struct _libc_xmmreg { - uint32_t element[4]; -}; - -struct _libc_fpstate { - uint16_t cwd; - uint16_t swd; - uint16_t twd; - uint16_t fop; - uint64_t rip; - uint64_t rdp; - uint32_t mxcsr; - uint32_t mxcsr_mask; - struct _libc_fpxreg _st[8]; - struct _libc_xmmreg _xmm[16]; - uint32_t padding[24]; -}; - -typedef uint64_t greg_t; - -typedef struct { - greg_t gregs[23]; - struct _libc_fpstate* fpregs; - unsigned long __reserved1[8]; -} mcontext_t; - -enum { - REG_R8 = 0, - REG_R9, - REG_R10, - REG_R11, - REG_R12, - REG_R13, - REG_R14, - REG_R15, - REG_RDI, - REG_RSI, - REG_RBP, - REG_RBX, - REG_RDX, - REG_RAX, - REG_RCX, - REG_RSP, - REG_RIP, - REG_EFL, - REG_CSGSFS, - REG_ERR, - REG_TRAPNO, - REG_OLDMASK, - REG_CR2, - NGREG, -}; - -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - struct _libc_fpstate __fpregs_mem; -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc index a89ac86..920a6fd 100644 --- a/services/network/cors/cors_url_loader.cc +++ b/services/network/cors/cors_url_loader.cc
@@ -463,8 +463,8 @@ // In the future blob URLs will not come here because there will be a // separate URLLoaderFactory for blobs. // TODO(yhirano): Remove this logic at the time. - if (request_.url.SchemeIsBlob() && request_.request_initiator->unique() && - url::Origin::Create(request_.url).unique()) { + if (request_.url.SchemeIsBlob() && request_.request_initiator->opaque() && + url::Origin::Create(request_.url).opaque()) { return; }
diff --git a/services/network/public/cpp/cors/origin_access_list.cc b/services/network/public/cpp/cors/origin_access_list.cc index 96420a3..36b4e4a 100644 --- a/services/network/public/cpp/cors/origin_access_list.cc +++ b/services/network/public/cpp/cors/origin_access_list.cc
@@ -49,7 +49,7 @@ bool OriginAccessList::IsAllowed(const url::Origin& source_origin, const GURL& destination) const { - if (source_origin.unique()) + if (source_origin.opaque()) return false; std::string source = source_origin.Serialize(); url::Origin destination_origin = url::Origin::Create(destination); @@ -63,7 +63,7 @@ const std::vector<mojom::CorsOriginPatternPtr>& patterns, PatternMap* map) { DCHECK(map); - DCHECK(!source_origin.unique()); + DCHECK(!source_origin.opaque()); std::string source = source_origin.Serialize(); map->erase(source); @@ -86,7 +86,7 @@ bool allow_subdomains, PatternMap* map) { DCHECK(map); - DCHECK(!source_origin.unique()); + DCHECK(!source_origin.opaque()); std::string source = source_origin.Serialize(); (*map)[source].push_back(OriginAccessEntry(
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index e0b94df..2b14077 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -171,6 +171,8 @@ #define SK_SUPPORT_LEGACY_AAA_CHOICE #endif +#define SK_LEGACY_COLORSPACE_XFORM_STEPS_IMPL + ///////////////////////// Imported from BUILD.gn and skia_common.gypi /* In some places Skia can use static initializers for global initialization,
diff --git a/storage/browser/fileapi/quota/quota_backend_impl.cc b/storage/browser/fileapi/quota/quota_backend_impl.cc index 0b71123..19236d1 100644 --- a/storage/browser/fileapi/quota/quota_backend_impl.cc +++ b/storage/browser/fileapi/quota/quota_backend_impl.cc
@@ -40,7 +40,7 @@ int64_t delta, const ReserveQuotaCallback& callback) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); if (!delta) { callback.Run(base::File::FILE_OK, 0); return; @@ -57,7 +57,7 @@ FileSystemType type, int64_t size) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); DCHECK_LE(0, size); if (!size) return; @@ -68,7 +68,7 @@ FileSystemType type, int64_t delta) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); if (!delta) return; ReserveQuotaInternal(QuotaReservationInfo(origin, type, delta)); @@ -82,7 +82,7 @@ void QuotaBackendImpl::IncrementDirtyCount(const url::Origin& origin, FileSystemType type) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); base::FilePath path; if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) return; @@ -93,7 +93,7 @@ void QuotaBackendImpl::DecrementDirtyCount(const url::Origin& origin, FileSystemType type) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); base::FilePath path; if (GetUsageCachePath(origin, type, &path) != base::File::FILE_OK) return; @@ -108,7 +108,7 @@ int64_t usage, int64_t quota) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!info.origin.unique()); + DCHECK(!info.origin.opaque()); DCHECK_LE(0, usage); DCHECK_LE(0, quota); if (status != blink::mojom::QuotaStatusCode::kOk) { @@ -138,7 +138,7 @@ void QuotaBackendImpl::ReserveQuotaInternal(const QuotaReservationInfo& info) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!info.origin.unique()); + DCHECK(!info.origin.opaque()); DCHECK(quota_manager_proxy_.get()); quota_manager_proxy_->NotifyStorageModified( storage::QuotaClient::kFileSystem, info.origin, @@ -150,7 +150,7 @@ FileSystemType type, base::FilePath* usage_file_path) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); DCHECK(usage_file_path); base::File::Error error = base::File::FILE_OK; *usage_file_path =
diff --git a/storage/browser/fileapi/quota/quota_reservation_buffer.cc b/storage/browser/fileapi/quota/quota_reservation_buffer.cc index 9aa294e0..802f054 100644 --- a/storage/browser/fileapi/quota/quota_reservation_buffer.cc +++ b/storage/browser/fileapi/quota/quota_reservation_buffer.cc
@@ -25,7 +25,7 @@ origin_(origin), type_(type), reserved_quota_(0) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); DCHECK(sequence_checker_.CalledOnValidSequence()); reservation_manager_->IncrementDirtyCount(origin, type); } @@ -101,7 +101,7 @@ FileSystemType type, base::File::Error error, int64_t delta_unused) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); if (error == base::File::FILE_OK && reservation_manager) { reservation_manager->DecrementDirtyCount(origin, type); return true;
diff --git a/storage/browser/fileapi/quota/quota_reservation_manager.cc b/storage/browser/fileapi/quota/quota_reservation_manager.cc index c00bdc9e..d8702ca 100644 --- a/storage/browser/fileapi/quota/quota_reservation_manager.cc +++ b/storage/browser/fileapi/quota/quota_reservation_manager.cc
@@ -29,33 +29,33 @@ FileSystemType type, int64_t size, const ReserveQuotaCallback& callback) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); backend_->ReserveQuota(origin, type, size, callback); } void QuotaReservationManager::ReleaseReservedQuota(const url::Origin& origin, FileSystemType type, int64_t size) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); backend_->ReleaseReservedQuota(origin, type, size); } void QuotaReservationManager::CommitQuotaUsage(const url::Origin& origin, FileSystemType type, int64_t delta) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); backend_->CommitQuotaUsage(origin, type, delta); } void QuotaReservationManager::IncrementDirtyCount(const url::Origin& origin, FileSystemType type) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); backend_->IncrementDirtyCount(origin, type); } void QuotaReservationManager::DecrementDirtyCount(const url::Origin& origin, FileSystemType type) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); backend_->DecrementDirtyCount(origin, type); } @@ -63,7 +63,7 @@ QuotaReservationManager::GetReservationBuffer(const url::Origin& origin, FileSystemType type) { DCHECK(sequence_checker_.CalledOnValidSequence()); - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); QuotaReservationBuffer** buffer = &reservation_buffers_[std::make_pair(origin, type)]; if (!*buffer) { @@ -85,7 +85,7 @@ scoped_refptr<QuotaReservation> QuotaReservationManager::CreateReservation( const url::Origin& origin, FileSystemType type) { - DCHECK(!origin.unique()); + DCHECK(!origin.opaque()); return GetReservationBuffer(origin, type)->CreateReservation(); }
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index cfc72399..8c05148 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -3087,6 +3087,21 @@ "test": "base_unittests" }, { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "os": "Ubuntu-14.04", + "pool": "Chrome-CrOS-VM" + } + ], + "hard_timeout": 3600, + "io_timeout": 3600 + }, + "test": "chrome_login_tast_tests" + }, + { "args": [ "--dbus-stub", "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.chromeos_unittests.filter"
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 96cdbf66..642a9683 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -193,6 +193,102 @@ } ] }, + "Android FYI 32 Vk Release (Pixel XL)": { + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "angle_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "-v", + "--one-frame-only" + ], + "isolate_name": "angle_perftests", + "name": "angle_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ] + } + } + ] + }, "Android FYI 32 dEQP Vk Release (Nexus 5X)": { "gtest_tests": [ { @@ -281,6 +377,50 @@ } ] }, + "Android FYI 32 dEQP Vk Release (Pixel XL)": { + "gtest_tests": [ + { + "args": [ + "--deqp-egl-display-type=angle-vulkan", + "--enable-xml-result-parsing", + "--shard-timeout=500", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "name": "angle_deqp_gles2_vulkan_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 4 + }, + "test": "angle_deqp_gles2_tests" + } + ] + }, "Android FYI 64 Vk Release (Nexus 5X)": { "gtest_tests": [ { @@ -473,6 +613,102 @@ } ] }, + "Android FYI 64 Vk Release (Pixel XL)": { + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "angle_unittests" + } + ], + "isolated_scripts": [ + { + "args": [ + "-v", + "--one-frame-only" + ], + "isolate_name": "angle_perftests", + "name": "angle_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ] + } + } + ] + }, "Android FYI 64 dEQP Vk Release (Nexus 5X)": { "gtest_tests": [ { @@ -561,6 +797,50 @@ } ] }, + "Android FYI 64 dEQP Vk Release (Pixel XL)": { + "gtest_tests": [ + { + "args": [ + "--deqp-egl-display-type=angle-vulkan", + "--enable-xml-result-parsing", + "--shard-timeout=500", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "name": "angle_deqp_gles2_vulkan_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "P", + "device_type": "marlin", + "os": "Android", + "pool": "Chrome-GPU" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 4 + }, + "test": "angle_deqp_gles2_tests" + } + ] + }, "Android FYI Release (NVIDIA Shield TV)": { "gtest_tests": [ {
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter index 07a57dfb..e76edb77 100644 --- a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter +++ b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
@@ -173,7 +173,7 @@ # Default extension tests. -DefaultProfileExtensionBrowserTest.NoExtensionHosts -# Encrypted media tests are flaky due to race condition. crbug.com/880584 +# Encrypted media tests are failing on Asan/Lsan bot due to memory leak. crbug.com/889993 -ECKEncryptedMediaTest.* -EncryptedMediaTest.* -CDM_9/ECKEncryptedMediaTest.* @@ -205,12 +205,6 @@ -ManagedWithoutPermission/ManagedWithoutPermissionPlatformKeysTest.* -ManagedWithPermission/ManagedWithPermissionPlatformKeysTest.* -# Needs video surface layer support. Should be fixed when renderers don't use -# the window service for embedding. -# https://crbug.com/884589 https://crbug.com/881574 --MediaEngagementBrowserTest.* --MediaEngagementAutoplayBrowserTest.* - # Flaky https://crbug.com/887175 -PrerenderBrowserTest.PrerenderHTML5VideoJs
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 72c6974..fa59232 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -299,6 +299,10 @@ "label": "//chrome/android:chrome_junit_tests", "type": "junit_test", }, + "chrome_login_tast_tests": { + "label": "//chromeos:chrome_login_tast_tests", + "type": "raw", + }, "chrome_official_builder": { "label": "//:chrome_official_builder", "type": "additional_compile_target",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index e215548c..3452e14c 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -430,6 +430,7 @@ 'chromeos_gtests_experimental': { 'base_unittests': {}, + 'chrome_login_tast_tests': {}, 'chromeos_unittests': { 'args': [ # TODO(crbug.com/865693): Don't stub out dbus clients.
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 5c357eab..e805d246 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1764,6 +1764,24 @@ 'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts', }, }, + 'Android FYI 32 Vk Release (Pixel XL)': { + 'os_type': 'android', + 'skip_merge_script': True, + 'swarming': { + 'dimension_sets': [ + { + 'device_type': 'marlin', + 'device_os': 'P', + 'os': 'Android', + 'pool': 'Chrome-GPU', + }, + ], + }, + 'test_suites': { + 'gtest_tests': 'gpu_angle_gtests', + 'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts', + }, + }, 'Android FYI 32 dEQP Vk Release (Nexus 5X)': { 'os_type': 'android', 'skip_merge_script': True, @@ -1798,6 +1816,23 @@ 'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests', }, }, + 'Android FYI 32 dEQP Vk Release (Pixel XL)': { + 'os_type': 'android', + 'skip_merge_script': True, + 'swarming': { + 'dimension_sets': [ + { + 'device_type': 'marlin', + 'device_os': 'P', + 'os': 'Android', + 'pool': 'Chrome-GPU', + }, + ], + }, + 'test_suites': { + 'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests', + }, + }, 'Android FYI 64 Vk Release (Nexus 5X)': { 'os_type': 'android', 'skip_merge_script': True, @@ -1834,6 +1869,24 @@ 'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts', }, }, + 'Android FYI 64 Vk Release (Pixel XL)': { + 'os_type': 'android', + 'skip_merge_script': True, + 'swarming': { + 'dimension_sets': [ + { + 'device_type': 'marlin', + 'device_os': 'P', + 'os': 'Android', + 'pool': 'Chrome-GPU', + }, + ], + }, + 'test_suites': { + 'gtest_tests': 'gpu_angle_gtests', + 'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts', + }, + }, 'Android FYI 64 dEQP Vk Release (Nexus 5X)': { 'os_type': 'android', 'skip_merge_script': True, @@ -1868,6 +1921,23 @@ 'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests', }, }, + 'Android FYI 64 dEQP Vk Release (Pixel XL)': { + 'os_type': 'android', + 'skip_merge_script': True, + 'swarming': { + 'dimension_sets': [ + { + 'device_type': 'marlin', + 'device_os': 'P', + 'os': 'Android', + 'pool': 'Chrome-GPU', + }, + ], + }, + 'test_suites': { + 'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests', + }, + }, 'Android FYI Release (NVIDIA Shield TV)': { 'browser_config': 'android-chromium', 'os_type': 'android',
diff --git a/testing/libfuzzer/gen_fuzzer_owners.py b/testing/libfuzzer/gen_fuzzer_owners.py index af0f04f..c9590a3d 100755 --- a/testing/libfuzzer/gen_fuzzer_owners.py +++ b/testing/libfuzzer/gen_fuzzer_owners.py
@@ -59,10 +59,11 @@ return for source in sources: - if not os.path.exists(source): + full_source_path = os.path.join(CHROMIUM_SRC_DIR, source) + if not os.path.exists(full_source_path): continue - with open(source, 'r') as source_file_handle: + with open(full_source_path, 'r') as source_file_handle: source_content = source_file_handle.read() if SubStringExistsIn( @@ -72,10 +73,11 @@ git_dir = os.path.join(CHROMIUM_SRC_DIR, '.git') is_git_file = bool(subprocess.check_output( - ['git', '--git-dir', git_dir, 'ls-files', source])) + ['git', '--git-dir', git_dir, 'ls-files', source], + cwd=CHROMIUM_SRC_DIR)) if not is_git_file: # File is not in working tree. Return owners for third_party. - return GetOwnersIfThirdParty(source) + return GetOwnersIfThirdParty(full_source_path) # git log --follow and --reverse don't work together and using just # --follow is too slow. Make a best estimate with an assumption that @@ -83,7 +85,8 @@ # copyright line and does not change even with file rename / move. blame_output = subprocess.check_output( ['git', '--git-dir', git_dir, - 'blame', '--porcelain', '-L1,1', source]) + 'blame', '--porcelain', '-L1,1', source], + cwd=CHROMIUM_SRC_DIR) return GetAuthorFromGitBlame(blame_output) return None
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index ce496d42..3873cd8 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -623,6 +623,33 @@ ] } ], + "AutofillPreviewStyleExperiment": [ + { + "platforms": [], + "experiments": [ + { + "name": "Enabled_BlackOnGoogleBlue050_V2", + "params": { + "bg_color": "#E8F0FE", + "color": "#000000" + }, + "enable_features": [ + "AutofillPreviewStyleExperiment" + ] + }, + { + "name": "Enabled_BlackOnGoogleYellow050_V2", + "params": { + "bg_color": "#E6F4EA", + "color": "#000000" + }, + "enable_features": [ + "AutofillPreviewStyleExperiment" + ] + } + ] + } + ], "AutofillResetFullServerCardsOnAuthError": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 50e48e24..f02b50b3 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -359,7 +359,6 @@ crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ] crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ] crbug.com/591099 fast/forms/placeholder-position.html [ Failure ] -crbug.com/890135 fast/forms/select/menulist-appearance-rtl.html [ Failure ] crbug.com/591099 fast/frames/crash-frameset-CSS-content-property.html [ Crash Pass ] crbug.com/835484 fast/inline/continuation-outlines-with-layers.html [ Failure ] crbug.com/835484 fast/inline/continuation-outlines.html [ Failure ] @@ -393,7 +392,6 @@ crbug.com/591099 fast/writing-mode/fieldsets.html [ Failure ] crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ] crbug.com/591099 fast/writing-mode/table-percent-width-quirk.html [ Pass ] -crbug.com/890135 fragmentation/transformed-clip-before-second-column.html [ Failure ] crbug.com/591099 hittesting/inline-with-clip-path.html [ Failure ] crbug.com/855039 html/details_summary/details-writing-mode-align-center.html [ Failure ] crbug.com/855039 html/details_summary/details-writing-mode-align-left.html [ Failure ] @@ -415,8 +413,6 @@ crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Pass ] crbug.com/591099 images/color-profile-image-filter-all.html [ Failure ] -crbug.com/890135 images/rendering-broken-block-flow-images.html [ Failure ] -crbug.com/890135 images/rendering-broken-images.html [ Failure ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-pseudo-element.js [ Failure ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Failure ] crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ] @@ -491,8 +487,6 @@ crbug.com/591099 virtual/exotic-color-space/ [ Skip ] crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ] crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure ] -crbug.com/890135 virtual/gpu-rasterization/images/rendering-broken-block-flow-images.html [ Failure ] -crbug.com/890135 virtual/gpu-rasterization/images/rendering-broken-images.html [ Failure ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-arc-circumference.html [ Failure Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-gradient-over-pattern.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index f58124e..d98c073 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -332,6 +332,7 @@ crbug.com/863454 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-multicol-002.html [ Failure ] crbug.com/863454 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-multicol-003.html [ Failure ] crbug.com/882333 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-inline-block-001.html [ Failure ] +crbug.com/882333 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-inline-flex-001.html [ Failure ] # [css-align] @@ -411,7 +412,6 @@ # Tests for LayoutNG to pass, but not planned to fix for pre-LayoutNG. crbug.com/774229 editing/pasteboard/copy-paste-white-space.html [ Failure ] crbug.com/855279 fast/css/text-overflow-ellipsis-vertical-hittest.html [ Failure ] -crbug.com/591099 fast/dom/inner-text-first-letter.html [ Failure ] crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure ] crbug.com/796943 fast/text/international/shape-across-elements-simple.html [ Failure ] crbug.com/877946 external/wpt/css/CSS2/linebox/anonymous-inline-inherit-001.html [ Failure ] @@ -787,7 +787,7 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-floats.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with-margin-top-and-line-after-break-2.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with-margin-top-and-line-after-break-3.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with-margin-top-and-line-after-break.html [ Failure ] +crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with-margin-top-and-line-after-break.html [ Crash Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with-margin-top-and-line-before-break.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-line-overflow.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-line-underflow-2.html [ Failure ] @@ -822,6 +822,7 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/composited-with-child-layer-in-next-column.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/composited-with-overflow-in-next-column.html [ Failure ] crbug.com/714962 virtual/layout_ng_experimental/fast/multicol/content-change-same-height.html [ Failure ] +crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/cssom-view.html [ Crash ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/doubly-nested-with-top-padding-crossing-row-boundaries.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/abspos-becomes-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/abspos-multicol-with-spanner-becomes-spanner.html [ Failure ] @@ -850,7 +851,7 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spanner-pseudo-before.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/invalid-spanner-container-becomes-valid.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/relpos-becomes-static-has-abspos.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-abspos-next-to-spanner.html [ Failure ] +crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-abspos-next-to-spanner.html [ Crash Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-after-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-before-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-between-spanners.html [ Failure ] @@ -876,6 +877,7 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flexbox.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flexbox-starts-at-column-boundary.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flexbox-starts-at-column-boundary-with-block.html [ Failure ] +crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flexbox-with-overflow-auto-child-crash.html [ Crash ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flipped-blocks-border-after.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/flipped-blocks-hit-test.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/float-after-break-after.html [ Failure ] @@ -2789,6 +2791,11 @@ crbug.com/800898 external/wpt/FileAPI/url/url-in-tags-revoke.window.html [ Timeout ] crbug.com/800898 external/wpt/workers/worker-from-blob-url.window.html [ Timeout ] +crbug.com/854474 external/wpt/console/console-label-conversion.any.html [ Skip ] +crbug.com/854474 external/wpt/console/console-label-conversion.any.worker.html [ Skip ] +crbug.com/854474 external/wpt/console/idlharness.any.html [ Skip ] +crbug.com/854474 external/wpt/console/idlharness.any.worker.html [ Skip ] + crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass Timeout ] crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.html [ Pass Timeout ] crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.worker.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json index ff307897..558b5ad 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -36119,6 +36119,18 @@ {} ] ], + "css/css-contain/contain-layout-button-001.html": [ + [ + "/css/css-contain/contain-layout-button-001.html", + [ + [ + "/css/css-contain/reference/contain-layout-button-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-contain/contain-layout-cell-001.html": [ [ "/css/css-contain/contain-layout-cell-001.html", @@ -36143,6 +36155,30 @@ {} ] ], + "css/css-contain/contain-layout-flexbox-001.html": [ + [ + "/css/css-contain/contain-layout-flexbox-001.html", + [ + [ + "/css/css-contain/reference/contain-layout-flexbox-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-contain/contain-layout-grid-001.html": [ + [ + "/css/css-contain/contain-layout-grid-001.html", + [ + [ + "/css/css-contain/reference/contain-layout-grid-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-contain/contain-layout-ifc-022.html": [ [ "/css/css-contain/contain-layout-ifc-022.html", @@ -45631,6 +45667,18 @@ {} ] ], + "css/css-grid/alignment/grid-gutters-013.html": [ + [ + "/css/css-grid/alignment/grid-gutters-013.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "css/css-grid/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-001.html": [ [ "/css/css-grid/alignment/self-baseline/grid-self-baseline-changes-grid-area-size-001.html", @@ -54607,18 +54655,6 @@ {} ] ], - "css/css-scoping/host-specificity-003.html": [ - [ - "/css/css-scoping/host-specificity-003.html", - [ - [ - "/css/css-scoping/reference/green-box.html", - "==" - ] - ], - {} - ] - ], "css/css-scoping/host-specificity.html": [ [ "/css/css-scoping/host-specificity.html", @@ -91427,6 +91463,18 @@ {} ] ], + "css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001.html": [ + [ + "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001.html", + [ + [ + "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html": [ [ "/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001a.html", @@ -119734,11 +119782,26 @@ {} ] ], + "css/css-contain/reference/contain-layout-button-001-ref.html": [ + [ + {} + ] + ], "css/css-contain/reference/contain-layout-cell-001-ref.html": [ [ {} ] ], + "css/css-contain/reference/contain-layout-flexbox-001-ref.html": [ + [ + {} + ] + ], + "css/css-contain/reference/contain-layout-grid-001-ref.html": [ + [ + {} + ] + ], "css/css-contain/reference/contain-layout-ifc-022-ref.html": [ [ {} @@ -145364,6 +145427,11 @@ {} ] ], + "css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001-ref.html": [ + [ + {} + ] + ], "css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001-ref.html": [ [ {} @@ -177054,16 +177122,6 @@ {} ] ], - "webaudio/the-audio-api/the-analysernode-interface/ctor-analyser-expected.txt": [ - [ - {} - ] - ], - "webaudio/the-audio-api/the-analysernode-interface/test-analysernode-expected.txt": [ - [ - {} - ] - ], "webaudio/the-audio-api/the-audiobuffer-interface/.gitkeep": [ [ {} @@ -196928,12 +196986,6 @@ {} ] ], - "css/css-flexbox/flex-minimum-height-flex-items-009.html": [ - [ - "/css/css-flexbox/flex-minimum-height-flex-items-009.html", - {} - ] - ], "css/css-flexbox/flexbox_first-letter.html": [ [ "/css/css-flexbox/flexbox_first-letter.html", @@ -286816,7 +286868,7 @@ "support" ], "README.md": [ - "684f4617f689d0611b18ce1b338bfdeb8d5886b7", + "6f9436bc3e4261e2f6813253e1709cbb60763ca2", "support" ], "WebCryptoAPI/META.yml": [ @@ -288516,11 +288568,11 @@ "testharness" ], "background-fetch/fetch.https.window-expected.txt": [ - "500f09d50ac7ca9b190618313cc5550b37cbefa9", + "8066dd23d555ca290cf54306cfd9e4c261812686", "support" ], "background-fetch/fetch.https.window.js": [ - "98ecdfa3933c40b909793100b4b9f9cccb35cb86", + "b8b1ff0983cdce1c799d03c7f1856548fa649b17", "testharness" ], "background-fetch/get-ids.https.window.js": [ @@ -288552,7 +288604,7 @@ "support" ], "background-fetch/mixed-content-and-allowed-schemes.https.window.js": [ - "9f24f13581819ef444a89cb7549de900f5b98ef6", + "05b32501228fbb765a5c782102660ebd476f0168", "testharness" ], "background-fetch/port-blocking.https.window.js": [ @@ -288576,7 +288628,7 @@ "support" ], "background-fetch/service_workers/sw.js": [ - "43d778c08914da6c8ff75acb819676895adbc180", + "af4655dbad4ef6ad6b17d79bb2645aee98ce1102", "support" ], "background-fetch/update-ui.https.window.js": [ @@ -290120,7 +290172,7 @@ "testharness" ], "console/console-label-conversion.any-expected.txt": [ - "b12067a3f50dbb1faf9359770de01b994a2be564", + "1fde3cad9bdf9b8817ae1af6c7b823edb00f0dc5", "support" ], "console/console-label-conversion.any.js": [ @@ -290128,7 +290180,7 @@ "testharness" ], "console/console-label-conversion.any.worker-expected.txt": [ - "b12067a3f50dbb1faf9359770de01b994a2be564", + "1fde3cad9bdf9b8817ae1af6c7b823edb00f0dc5", "support" ], "console/console-number-format-specifiers-symbol-manual.html": [ @@ -290148,7 +290200,7 @@ "manual" ], "console/idlharness.any-expected.txt": [ - "1c02b8e703c6a55fca9425254f5d92a1064c894c", + "3b3bae18dfea489adf03e139283fce6ae117edf2", "support" ], "console/idlharness.any.js": [ @@ -290156,7 +290208,7 @@ "testharness" ], "console/idlharness.any.worker-expected.txt": [ - "1c02b8e703c6a55fca9425254f5d92a1064c894c", + "3b3bae18dfea489adf03e139283fce6ae117edf2", "support" ], "content-security-policy/META.yml": [ @@ -314991,6 +315043,10 @@ "fadb3c41c5363742eb88bdf803eac7cdbf5e7a8f", "reftest" ], + "css/css-contain/contain-layout-button-001.html": [ + "e8beef7c0edfa20258b9600376d3ab245ca63f32", + "reftest" + ], "css/css-contain/contain-layout-cell-001.html": [ "fa1af0eee6848a34c61f47861c22d9efb56ab059", "reftest" @@ -314999,6 +315055,14 @@ "331a0e6519b0af23ba91355584f0c37dfcf6a88e", "reftest" ], + "css/css-contain/contain-layout-flexbox-001.html": [ + "2b206edb57f46f3baa9dcfbcc24591b852cf8697", + "reftest" + ], + "css/css-contain/contain-layout-grid-001.html": [ + "a6bcc4dbc2adda58602281eac5c2c0b2c0a9de61", + "reftest" + ], "css/css-contain/contain-layout-ifc-022.html": [ "3e4f3dafbf213c18a09cfd2a7512dd485c13f839", "reftest" @@ -315332,7 +315396,7 @@ "reftest" ], "css/css-contain/contain-size-button-001.html": [ - "1e4965e9daf380aec19cf43902c409ad6b457370", + "4b2ecd7b76e421ea5dfffce6654d722142b5823c", "reftest" ], "css/css-contain/contain-size-fieldset-001.html": [ @@ -315340,11 +315404,11 @@ "reftest" ], "css/css-contain/contain-size-flexbox-001.html": [ - "31e82f5d24c4aa673291a2ce25c660cf10977e28", + "16ba62eda041abe11424f63c65d6dfd46aa82570", "reftest" ], "css/css-contain/contain-size-grid-001.html": [ - "f67f0e118e00b3426986b39226310c59b14a3755", + "4510c1e55368aeea38a79ba66059acd4d7660ddb", "reftest" ], "css/css-contain/contain-size-grid-002.html": [ @@ -315459,10 +315523,22 @@ "c68bee1d0aa4f9201fb6e48cc25199f373128ca8", "support" ], + "css/css-contain/reference/contain-layout-button-001-ref.html": [ + "11a784b213cbc05d10cdcc199a11055fe0c0fdfa", + "support" + ], "css/css-contain/reference/contain-layout-cell-001-ref.html": [ "9ff7f45e39ca741b4b334c1c9b3d1d5ee6759b73", "support" ], + "css/css-contain/reference/contain-layout-flexbox-001-ref.html": [ + "832e4c72c2cef426f2d759e77435290fff2f0d55", + "support" + ], + "css/css-contain/reference/contain-layout-grid-001-ref.html": [ + "b5ff8e0e0dad0cd586e7b899d8a7905b26063233", + "support" + ], "css/css-contain/reference/contain-layout-ifc-022-ref.html": [ "682af7d4f44b22f987c069dbbee370520612bc10", "support" @@ -315580,7 +315656,7 @@ "support" ], "css/css-contain/reference/contain-size-button-001-ref.html": [ - "1cbaaccd1a0751c5dadf913e1fc31d130ff95259", + "eff64aa8e2ef0c7fbce03858e90ef0d9e2a7ee6b", "support" ], "css/css-contain/reference/contain-size-fieldset-001-ref.html": [ @@ -315588,11 +315664,11 @@ "support" ], "css/css-contain/reference/contain-size-flexbox-001-ref.html": [ - "85628b59c48f7931e7d3e5a498da60cc264dc363", + "70f408643007d8338f401ef947f7bb24f1eaedc9", "support" ], "css/css-contain/reference/contain-size-grid-001-ref.html": [ - "d71636bd5f4a344352249b50563eb03d249484c6", + "cf4f8076650928dfd0cefc18665ef1e8ab52d7b6", "support" ], "css/css-contain/reference/contain-size-monolithic-001-ref.html": [ @@ -316815,10 +316891,6 @@ "ead7a424b374fddb247046d2a36a37a11669baae", "reftest" ], - "css/css-flexbox/flex-minimum-height-flex-items-009.html": [ - "718386af02069fa1a3fff0ee5aaa10415ef4b23a", - "testharness" - ], "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [ "b8e2866edaa46af46900c287238894cd8ddef24c", "reftest" @@ -327915,6 +327987,10 @@ "1e56e708dfb45f1dd1e48d7779818d244eb25f3d", "reftest" ], + "css/css-grid/alignment/grid-gutters-013.html": [ + "e72814725d2cb90fba6f3bd4d1e8370f37382fbb", + "reftest" + ], "css/css-grid/alignment/grid-row-axis-alignment-positioned-items-001.html": [ "e350f972357cfdc9559c5a86116e538d87c9ce61", "testharness" @@ -333983,10 +334059,6 @@ "3132d3a3455241347d6fe421f3434c361e424493", "reftest" ], - "css/css-scoping/host-specificity-003.html": [ - "54a22599d8f83f612d7fc9ff91abfe650114c6e2", - "reftest" - ], "css/css-scoping/host-specificity.html": [ "3ef61d4135fe7dbf846feb82540ca1a213ce7987", "reftest" @@ -363831,6 +363903,14 @@ "cf54aabe9936b3963e7343d566d957633fc26c69", "reftest" ], + "css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001-ref.html": [ + "5e5561cadf2ddbd6dfd2c7b4819f146f61be006b", + "support" + ], + "css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001.html": [ + "d64c4bdf28ecb783af4f342d515dcf63134602c6", + "reftest" + ], "css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001-ref.html": [ "b5377110201d1de21a966c8a7f1a7d60dfff4126", "support" @@ -395264,7 +395344,7 @@ "support" ], "interfaces/screen-capture.idl": [ - "668f4588ba2a24a909dc7f44b24628c56631296d", + "b79d09d19dced9e3b77e791e2d543fc9f44742ee", "support" ], "interfaces/screen-orientation.idl": [ @@ -426831,10 +426911,6 @@ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", "support" ], - "webaudio/the-audio-api/the-analysernode-interface/ctor-analyser-expected.txt": [ - "b335e1bde0cf91dfa3f541b48b2927cf58f52083", - "support" - ], "webaudio/the-audio-api/the-analysernode-interface/ctor-analyser.html": [ "a9aa4831516c6a5cefa7c8b4f67f3ef246d24777", "testharness" @@ -426867,10 +426943,6 @@ "04fe48096459dd0bbf4b3b0fd206c90c0bcae0f0", "testharness" ], - "webaudio/the-audio-api/the-analysernode-interface/test-analysernode-expected.txt": [ - "09df255c35c3d4b156167684aee019c0a318b572", - "support" - ], "webaudio/the-audio-api/the-analysernode-interface/test-analysernode.html": [ "a8b5a7154e94479460c1085c6b5cb584e9b6976c", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/README.md b/third_party/WebKit/LayoutTests/external/wpt/README.md index 684f461..6f9436b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/README.md +++ b/third_party/WebKit/LayoutTests/external/wpt/README.md
@@ -432,11 +432,11 @@ Search filters to find things to review: -* [Open PRs (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22) -* [Reviewed but still open PRs (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+-label%3Amozilla%3Agecko-sync+-label%3Achromium-export+-label%3Awebkit-export+-label%3Aservo-export+review%3Aapproved+-label%3A%22do+not+merge+yet%22+-label%3A%22status%3Aneeds-spec-decision%22) (Merge? Something left to fix? Ping other reviewer?) +* [Open PRs (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22+-label%3Avendor-imports) +* [Reviewed but still open PRs (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+-label%3Amozilla%3Agecko-sync+-label%3Achromium-export+-label%3Awebkit-export+-label%3Aservo-export+-label%3Avendor-imports+review%3Aapproved+-label%3A%22do+not+merge+yet%22+-label%3A%22status%3Aneeds-spec-decision%22) (Merge? Something left to fix? Ping other reviewer?) * [Open PRs without reviewers](https://github.com/web-platform-tests/wpt/pulls?q=is%3Apr+is%3Aopen+label%3Astatus%3Aneeds-reviewers) -* [Open PRs with label `infra` (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3Ainfra+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22) -* [Open PRs with label `docs` (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3Adocs+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22) +* [Open PRs with label `infra` (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3Ainfra+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22+-label%3Avendor-imports) +* [Open PRs with label `docs` (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3Adocs+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22+-label%3Avendor-imports) Getting Involved ================
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt index 500f09d..8066dd2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window-expected.txt
@@ -2,11 +2,13 @@ PASS Background Fetch requires an activated Service Worker PASS Argument verification is done for BackgroundFetchManager.fetch() PASS IDs must be unique among active Background Fetch registrations +PASS Empty URL is OK. PASS Using Background Fetch to successfully fetch a single resource PASS Background Fetch that exceeds the quota throws a QuotaExceededError FAIL Fetches can have requests with duplicate URLs promise_test: Unhandled rejection with value: object "TypeError: Fetches with duplicate requests are not yet supported. Consider adding query params to make the requests unique. For updates check http://crbug.com/871174" FAIL Fetches can have requests with a body promise_test: Unhandled rejection with value: object "TypeError: Requests with a body are not yet supported. For updates check http://crbug.com/774054" PASS recordsAvailable is false after onbackgroundfetchsuccess finishes execution. PASS Using Background Fetch to fetch a non-existent resource should fail. +PASS Fetches with mixed content should fail. Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js index 98ecdfa3..b8b1ff09 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/fetch.https.window.js
@@ -70,6 +70,21 @@ backgroundFetchTest(async (test, backgroundFetch) => { const registrationId = uniqueId(); const registration = + await backgroundFetch.fetch(registrationId, ''); + + assert_equals(registration.id, registrationId); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + + assert_equals('backgroundfetchsuccess', type); + assert_equals(eventRegistration.result, 'success'); + assert_equals(eventRegistration.failureReason, ''); + +}, 'Empty URL is OK.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = await backgroundFetch.fetch(registrationId, 'resources/feature-name.txt'); assert_equals(registration.id, registrationId); @@ -190,4 +205,20 @@ assert_equals(eventRegistration.result, 'failure'); assert_equals(eventRegistration.failureReason, 'bad-status'); -}, 'Using Background Fetch to fetch a non-existent resource should fail.'); \ No newline at end of file +}, 'Using Background Fetch to fetch a non-existent resource should fail.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registration = await backgroundFetch.fetch( + 'my-id', + ['https://example.com', 'http://example.com']); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + + assert_equals('backgroundfetchfail', type); + assert_equals(eventRegistration.failureReason, 'fetch-error'); + + assert_equals(results.length, 2); + assert_true(results[0].url.includes('https://example.com')); + assert_equals(results[1].url, ''); + +}, 'Fetches with mixed content should fail.');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/mixed-content-and-allowed-schemes.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/mixed-content-and-allowed-schemes.https.window.js index 9f24f13..05b3250 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/mixed-content-and-allowed-schemes.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/mixed-content-and-allowed-schemes.https.window.js
@@ -32,34 +32,6 @@ backgroundFetchTest((t, bgFetch) => { return promise_rejects(t, new TypeError(), - bgFetch.fetch(uniqueId(), 'http://example.com')); -}, 'non-loopback http: fetch should reject'); - -backgroundFetchTest((t, bgFetch) => { - return promise_rejects(t, new TypeError(), - bgFetch.fetch(uniqueId(), 'http://192.0.2.0')); -}, 'non-loopback IPv4 http: fetch should reject'); - -backgroundFetchTest((t, bgFetch) => { - return promise_rejects(t, new TypeError(), - bgFetch.fetch(uniqueId(), 'http://[2001:db8::1]')); -}, 'non-loopback IPv6 http: fetch should reject'); - -backgroundFetchTest((t, bgFetch) => { - return promise_rejects(t, new TypeError(), - bgFetch.fetch(uniqueId(), ['https://example.com', - 'http://example.com'])); -}, 'https: and non-loopback http: fetch should reject'); - -backgroundFetchTest((t, bgFetch) => { - return promise_rejects(t, new TypeError(), - bgFetch.fetch(uniqueId(), ['http://example.com', - 'https://example.com'])); -}, 'non-loopback http: and https: fetch should reject'); - - -backgroundFetchTest((t, bgFetch) => { - return promise_rejects(t, new TypeError(), bgFetch.fetch(uniqueId(), 'wss:127.0.0.1')); }, 'wss: fetch should reject');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/service_workers/sw.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/service_workers/sw.js index 43d778c0..af4655d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/service_workers/sw.js +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/service_workers/sw.js
@@ -27,5 +27,3 @@ self.addEventListener('backgroundfetchsuccess', handleBackgroundFetchUpdateEvent); self.addEventListener('backgroundfetchfail', handleBackgroundFetchUpdateEvent); - -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any-expected.txt index b12067a..1fde3cad 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any-expected.txt
@@ -23,14 +23,14 @@ } }); }" did not throw -FAIL console.timeLog()'s label gets converted to string via label.toString() when label is an object console[method] is not a function +FAIL console.timeLog()'s label gets converted to string via label.toString() when label is an object assert_true: timeLog() must call toString() on label when label is an object expected true got false FAIL console.timeLog() throws exceptions generated by erroneous label.toString() conversion assert_throws: timeLog must re-throw any exceptions thrown by label.toString() conversion function "() => { console[method]({ toString() { throw new Error('conversion error'); } }); - }" threw object "TypeError: console[method] is not a function" ("TypeError") expected object "[object Object]" ("Error") + }" did not throw FAIL console.timeEnd()'s label gets converted to string via label.toString() when label is an object assert_true: timeEnd() must call toString() on label when label is an object expected true got false FAIL console.timeEnd() throws exceptions generated by erroneous label.toString() conversion assert_throws: timeEnd must re-throw any exceptions thrown by label.toString() conversion function "() => { console[method]({
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any.worker-expected.txt index b12067a..1fde3cad 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any.worker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/console/console-label-conversion.any.worker-expected.txt
@@ -23,14 +23,14 @@ } }); }" did not throw -FAIL console.timeLog()'s label gets converted to string via label.toString() when label is an object console[method] is not a function +FAIL console.timeLog()'s label gets converted to string via label.toString() when label is an object assert_true: timeLog() must call toString() on label when label is an object expected true got false FAIL console.timeLog() throws exceptions generated by erroneous label.toString() conversion assert_throws: timeLog must re-throw any exceptions thrown by label.toString() conversion function "() => { console[method]({ toString() { throw new Error('conversion error'); } }); - }" threw object "TypeError: console[method] is not a function" ("TypeError") expected object "[object Object]" ("Error") + }" did not throw FAIL console.timeEnd()'s label gets converted to string via label.toString() when label is an object assert_true: timeEnd() must call toString() on label when label is an object expected true got false FAIL console.timeEnd() throws exceptions generated by erroneous label.toString() conversion assert_throws: timeEnd must re-throw any exceptions thrown by label.toString() conversion function "() => { console[method]({
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any-expected.txt index 1c02b8e70..3b3bae1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any-expected.txt
@@ -17,7 +17,7 @@ FAIL console namespace: operation groupCollapsed(any...) assert_equals: operation has wrong .length expected 0 but got 1 FAIL console namespace: operation groupEnd() assert_equals: operation has wrong .length expected 0 but got 1 FAIL console namespace: operation time(DOMString) assert_equals: operation has wrong .length expected 0 but got 1 -FAIL console namespace: operation timeLog(DOMString, any...) assert_own_property: namespace object missing operation "timeLog" expected property "timeLog" missing +FAIL console namespace: operation timeLog(DOMString, any...) assert_equals: operation has wrong .length expected 0 but got 1 FAIL console namespace: operation timeEnd(DOMString) assert_equals: operation has wrong .length expected 0 but got 1 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any.worker-expected.txt index 1c02b8e70..3b3bae1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any.worker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/console/idlharness.any.worker-expected.txt
@@ -17,7 +17,7 @@ FAIL console namespace: operation groupCollapsed(any...) assert_equals: operation has wrong .length expected 0 but got 1 FAIL console namespace: operation groupEnd() assert_equals: operation has wrong .length expected 0 but got 1 FAIL console namespace: operation time(DOMString) assert_equals: operation has wrong .length expected 0 but got 1 -FAIL console namespace: operation timeLog(DOMString, any...) assert_own_property: namespace object missing operation "timeLog" expected property "timeLog" missing +FAIL console namespace: operation timeLog(DOMString, any...) assert_equals: operation has wrong .length expected 0 but got 1 FAIL console namespace: operation timeEnd(DOMString) assert_equals: operation has wrong .length expected 0 but got 1 Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-button-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-button-001.html new file mode 100644 index 0000000..e8beef7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-button-001.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Layout containment on button</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-layout"> +<link rel="match" href="reference/contain-layout-button-001-ref.html"> +<meta name=assert content="Layout containment does apply to buttons, thus their baseline is the same than if they don't have contents."> +<style> +button { + border: 5px solid green; + padding: 0; + contain: layout; + color: transparent; + width: 0; + height: 0; +} +</style> + +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the bottom, and then the word "after".</p> +before<button>b</button>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-flexbox-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-flexbox-001.html new file mode 100644 index 0000000..2b206ed --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-flexbox-001.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Layout containment on flexbox container</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-layout"> +<link rel="match" href="reference/contain-layout-flexbox-001-ref.html"> +<meta name=assert content="Layout containment does apply to flexbox containers, thus their baseline is the same than if they don't have contents."> +<style> +div { + display: inline-flex; + border: 5px solid green; + contain: layout; + color: transparent; + width: 0; + height: 0; +} +</style> + +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the bottom, and then the word "after".</p> +before<div>f</div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-grid-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-grid-001.html new file mode 100644 index 0000000..a6bcc4d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-grid-001.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Layout containment on grid container</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-layout"> +<link rel="match" href="reference/contain-layout-grid-001-ref.html"> +<meta name=assert content="Layout containment does apply to grid containers, thus their baseline is the same than if they don't have contents."> +<style> +div { + display: inline-grid; + border: 5px solid green; + contain: layout; + color: transparent; + width: 0; + height: 0; +} +</style> + +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the bottom, and then the word "after".</p> +before<div>g</div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-button-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-button-001.html index 1e4965e..4b2ecd7b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-button-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-button-001.html
@@ -4,15 +4,16 @@ <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> <link rel="match" href="reference/contain-size-button-001-ref.html"> -<meta name=assert content="Size containment does apply to buttons, thus their size and baseline is the same than if they don't have contents."> +<meta name=assert content="Size containment does apply to buttons, thus their size is the same than if they don't have contents."> <style> button { border: 5px solid green; padding: 0; contain: size; color: transparent; + font-size: 2em; } </style> -<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square, and then the word "after".</p> +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the top, and then the word "after".</p> before<button>flex</button>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-flexbox-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-flexbox-001.html index 31e82f5..16ba62e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-flexbox-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-flexbox-001.html
@@ -4,15 +4,16 @@ <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> <link rel="match" href="reference/contain-size-flexbox-001-ref.html"> -<meta name=assert content="Size containment does apply to flexbox containers, thus their size and baseline is the same than if they don't have contents."> +<meta name=assert content="Size containment does apply to flexbox containers, thus their size is the same than if they don't have contents."> <style> div { display: inline-flex; border: 5px solid green; contain: size; color: transparent; + font-size: 2em; } </style> -<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square, and then the word "after".</p> +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the top, and then the word "after".</p> before<div>flex</div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-grid-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-grid-001.html index f67f0e11..4510c1e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-grid-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-grid-001.html
@@ -4,15 +4,16 @@ <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> <link rel="match" href="reference/contain-size-grid-001-ref.html"> -<meta name=assert content="Size containment does apply to grid containers, thus their size and baseline is the same than if they don't have contents."> +<meta name=assert content="Size containment does apply to grid containers, thus their size is the same than if they don't have contents."> <style> div { display: inline-grid; border: 5px solid green; contain: size; color: transparent; + font-size: 2em; } </style> -<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square, and then the word "after".</p> +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the top, and then the word "after".</p> before<div>grid</div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-button-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-button-001-ref.html new file mode 100644 index 0000000..11a784b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-button-001-ref.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Reference file</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<style> +button { + border: 5px solid green; + padding: 0; + color: transparent; + width: 0; + height: 0px; + /* Layout containment creates a stacking context, the following lines simuluate the same in the reference file. */ + position: relative; + z-index: 1; +} +</style> + +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the bottom, and then the word "after".</p> +before<button></button>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-flexbox-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-flexbox-001-ref.html new file mode 100644 index 0000000..832e4c7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-flexbox-001-ref.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Reference file</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<style> +div { + display: inline-flex; + border: 5px solid green; + /* Layout containment creates a stacking context, the following lines simuluate the same in the reference file. */ + position: relative; + z-index: 1; +} +</style> + +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the bottom, and then the word "after".</p> +before<div></div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-grid-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-grid-001-ref.html new file mode 100644 index 0000000..b5ff8e0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-grid-001-ref.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Reference file</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<style> +div { + display: inline-grid; + border: 5px solid green; + /* Layout containment creates a stacking context, the following lines simuluate the same in the reference file. */ + position: relative; + z-index: 1; +} +</style> + +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the bottom, and then the word "after".</p> +before<div></div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-button-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-button-001-ref.html index 1cbaaccd..eff64aa 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-button-001-ref.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-button-001-ref.html
@@ -6,8 +6,12 @@ button { border: 5px solid green; padding: 0; + color: transparent; + width: 0; + height: 0; + font-size: 2em; } </style> -<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square, and then the word "after".</p> -before<button></button>after +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the top, and then the word "after".</p> +before<button>b</button>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-flexbox-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-flexbox-001-ref.html index 85628b5..70f4086 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-flexbox-001-ref.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-flexbox-001-ref.html
@@ -6,8 +6,12 @@ div { display: inline-flex; border: 5px solid green; + color: transparent; + width: 0; + height: 0; + font-size: 2em; } </style> -<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square, and then the word "after".</p> -before<div></div>after +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the top, and then the word "after".</p> +before<div>f</div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-grid-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-grid-001-ref.html index d71636b..cf4f8076 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-grid-001-ref.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-grid-001-ref.html
@@ -6,8 +6,12 @@ div { display: inline-grid; border: 5px solid green; + color: transparent; + width: 0; + height: 0; + font-size: 2em; } </style> -<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square, and then the word "after".</p> -before<div></div>after +<p>This test passes if it has the same output as the reference. You see the word "before", a 10px green square at the top, and then the word "after".</p> +before<div>g</div>after
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001-ref.html new file mode 100644 index 0000000..5e5561c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001-ref.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html> +<head> + <meta charset="utf-8"> + <title> + CSS Reftest Reference + </title> + <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com"> + <style> + .container { + width: 100px; + display: flex; + border: 1px solid purple; + margin-bottom: 15px; + } + .item { + margin: 2px; + background: lightblue; + } + .inline-box { + display: inline-block; + height: 10px; + width: 10px; + background: lightgray; + border: 1px solid black; + } + #change-width { + /* Using hardcoded CSS as reference for testcase's tweak: */ + width: 300px; + } + #change-flex { + /* Using hardcoded CSS as reference for testcase's tweak: */ + flex: 0 0 75px; + } + </style> +</head> +<body> + <div class="container"> + <div class="item" id="change-width"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + <div class="item"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + </div> + + <div class="container"> + <div class="item" id="change-flex"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + <div class="item"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + </div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001.html new file mode 100644 index 0000000..d64c4bdf --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-dyn-resize-001.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html> +<head> + <meta charset="utf-8"> + <title> + CSS Test: Testing how a sizing change to one flex item impacts its sibling + </title> + <link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#layout-algorithm"> + <link rel="match" href="flexbox-dyn-resize-001-ref.html"> + <style> + .container { + width: 100px; + display: flex; + border: 1px solid purple; + margin-bottom: 15px; + } + .item { + margin: 2px; + background: lightblue; + } + .inline-box { + display: inline-block; + height: 10px; + width: 10px; + background: lightgray; + border: 1px solid black; + } + </style> + <script> + function go() { + // Make this item steal all the spare width (forcing its sibling to shrink) + // by giving it a huge 'width' and therefore huge flex-basis: + document.getElementById("change-width").style.width = "300px"; + + // Make this item steal all the spare width (forcing its sibling to shrink) + // by giving it a pretty big flex-basis and no shrinkability: + document.getElementById("change-flex").style.flex = "0 0 75px" + } + </script> +</head> +<body onload="go()"> + <div class="container"> + <div class="item" id="change-width"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + <div class="item"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + </div> + + <div class="container"> + <div class="item" id="change-flex"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + <div class="item"> + <div class="inline-box"></div><div class="inline-box"></div> + </div> + </div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl index 668f4588..b79d09d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl
@@ -7,12 +7,24 @@ Promise<MediaStream> getDisplayMedia(optional MediaStreamConstraints constraints); }; +partial dictionary MediaTrackSupportedConstraints { + boolean displaySurface = true; + boolean logicalSurface = true; + boolean cursor = true; +}; + partial dictionary MediaTrackConstraintSet { ConstrainDOMString displaySurface; ConstrainBoolean logicalSurface; ConstrainDOMString cursor; }; +partial dictionary MediaTrackSettings { + DOMString displaySurface; + boolean logicalSurface; + DOMString cursor; +}; + enum DisplayCaptureSurfaceType { "monitor", "window",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl index 8e998df..0b5c866 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/speech-api.idl
@@ -137,7 +137,8 @@ attribute EventHandler onboundary; }; -[Exposed=Window] +[Exposed=Window, + Constructor(DOMString type, SpeechSynthesisEventInit eventInitDict)] interface SpeechSynthesisEvent : Event { readonly attribute SpeechSynthesisUtterance utterance; readonly attribute unsigned long charIndex; @@ -145,6 +146,13 @@ readonly attribute DOMString name; }; +dictionary SpeechSynthesisEventInit : EventInit { + required SpeechSynthesisUtterance utterance; + unsigned long charIndex = 0; + float elapsedTime = 0; + DOMString name = ""; +}; + enum SpeechSynthesisErrorCode { "canceled", "interrupted", @@ -160,11 +168,16 @@ "not-allowed", }; -[Exposed=Window] +[Exposed=Window, + Constructor(DOMString type, SpeechSynthesisErrorEventInit eventInitDict)] interface SpeechSynthesisErrorEvent : SpeechSynthesisEvent { readonly attribute SpeechSynthesisErrorCode error; }; +dictionary SpeechSynthesisErrorEventInit : SpeechSynthesisEventInit { + required SpeechSynthesisErrorCode error; +}; + [Exposed=Window] interface SpeechSynthesisVoice { readonly attribute DOMString voiceURI;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html index acf0d7d..1b86552 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html +++ b/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html
@@ -8,7 +8,7 @@ async_test(t => { const utter = new SpeechSynthesisUtterance('1'); utter.onerror = t.step_func_done((e) => { - assert_equals(e.name, "not-allowed"); + assert_equals(e.error, "not-allowed"); }); utter.onend = t.step_func_done(() => assert_unreached()); speechSynthesis.speak(utter);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesisErrorEvent-constructor.html b/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesisErrorEvent-constructor.html new file mode 100644 index 0000000..61e179c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesisErrorEvent-constructor.html
@@ -0,0 +1,88 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +/* +[Exposed=Window, + Constructor(DOMString type, SpeechSynthesisErrorEventInit eventInitDict)] +interface SpeechSynthesisErrorEvent : SpeechSynthesisErrorEvent { + readonly attribute SpeechSynthesisErrorCode error; +}; +*/ +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisErrorEvent(); + }); +}, "SpeechSynthesisErrorEvent with no arguments throws TypeError"); + +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisErrorEvent("type"); + }); +}, "SpeechSynthesisErrorEvent with no eventInitDict throws TypeError"); + +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisErrorEvent("type", {}); + }); +}, `SpeechSynthesisErrorEvent with empty eventInitDict throws TypeError (requires + utterance and error)`); + +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisErrorEvent("type", {error:"not-allowed"}); + }); +}, `SpeechSynthesisErrorEvent with eventInitDict without utterance throws + TypeError`); + +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisErrorEvent("type", {utterance: new SpeechSynthesisUtterance()}); + }); +}, `SpeechSynthesisErrorEvent with eventInitDict without error throws + TypeError`); + +test(() => { + const utterance = new SpeechSynthesisUtterance("foo"); + const event = new SpeechSynthesisErrorEvent("type", {utterance: utterance, error:"not-allowed"}); + assert_equals(event.utterance, utterance); + assert_equals(event.error, "not-allowed"); + assert_equals(event.charIndex, 0); + assert_equals(event.elapsedTime, 0); + assert_equals(event.name, ""); +}, "SpeechSynthesisErrorEvent with eventInitDict having utterance and error"); + +test(() => { + const utterance = new SpeechSynthesisUtterance("foo"); + const event = new SpeechSynthesisErrorEvent("type", { + utterance: utterance, + charIndex: 5, + elapsedTime: 100, + name: "foo", + error: "synthesis-failed" + }); + assert_equals(event.bubbles, false); + assert_equals(event.cancelable, false); + assert_equals(event.type, "type"); + assert_equals(event.utterance, utterance); + assert_equals(event.charIndex, 5); + assert_equals(event.elapsedTime, 100); + assert_equals(event.name, "foo"); + assert_equals(event.error, "synthesis-failed"); +}, "SpeechSynthesisErrorEvent with custom eventInitDict"); + +test(() => { + function createEventFunc(error) { + return () => { + new SpeechSynthesisErrorEvent("type", { + utterance: new SpeechSynthesisUtterance(), + error: error + }); + }; + }; + assert_throws(new TypeError(), createEventFunc("")); + assert_throws(new TypeError(), createEventFunc("foo")); + assert_throws(new TypeError(), createEventFunc("bar")); +}, "SpeechSynthesisErrorEvent with wrong error enum"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesisEvent-constructor.html b/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesisEvent-constructor.html new file mode 100644 index 0000000..47a37d25 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/speech-api/SpeechSynthesisEvent-constructor.html
@@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +/* +[Exposed=Window, + Constructor(DOMString type, SpeechSynthesisEventInit eventInitDict)] +interface SpeechSynthesisEvent : Event { + readonly attribute SpeechSynthesisUtterance utterance; + readonly attribute unsigned long charIndex; + readonly attribute float elapsedTime; + readonly attribute DOMString name; +}; +*/ +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisEvent(); + }); +}, "SpeechSynthesisEvent with no arguments throws TypeError"); + +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisEvent("type"); + }); +}, "SpeechSynthesisEvent with no eventInitDict throws TypeError"); + +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisEvent("type", {}); + }); +}, `SpeechSynthesisEvent with empty eventInitDict throws TypeError (requires + utterance)`); + +test(() => { + assert_throws(new TypeError(), () => { + new SpeechSynthesisEvent("type", {charIndex: 10, elapsedTime: 50, name:"foo"}); + }); +}, `SpeechSynthesisEvent with eventInitDict not having utterance throws + TypeError`); + +test(() => { + const utterance = new SpeechSynthesisUtterance("foo"); + const event = new SpeechSynthesisEvent("type", {utterance: utterance}); + assert_equals(event.utterance, utterance); + assert_equals(event.charIndex, 0); + assert_equals(event.elapsedTime, 0); + assert_equals(event.name, ""); +}, "SpeechSynthesisEvent with eventInitDict having an utterance"); + +test(() => { + const utterance = new SpeechSynthesisUtterance("foo"); + const event = new SpeechSynthesisEvent("type", { + utterance: utterance, + charIndex: 5, + elapsedTime: 100, + name: "foo" + }); + assert_equals(event.bubbles, false); + assert_equals(event.cancelable, false); + assert_equals(event.type, "type"); + assert_equals(event.utterance, utterance); + assert_equals(event.charIndex, 5); + assert_equals(event.elapsedTime, 100); + assert_equals(event.name, "foo"); +}, "SpeechSynthesisEvent with custom eventInitDict"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt index 12eedaf..e913d754 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/speech-api/idlharness.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 216 tests; 60 PASS, 156 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 216 tests; 67 PASS, 149 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Window: original interface defined FAIL SpeechRecognition interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechRecognition" expected property "SpeechRecognition" missing @@ -195,13 +195,13 @@ PASS SpeechSynthesisEvent interface: attribute charIndex PASS SpeechSynthesisEvent interface: attribute elapsedTime PASS SpeechSynthesisEvent interface: attribute name -FAIL SpeechSynthesisErrorEvent interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesisErrorEvent" expected property "SpeechSynthesisErrorEvent" missing -FAIL SpeechSynthesisErrorEvent interface object length assert_own_property: self does not have own property "SpeechSynthesisErrorEvent" expected property "SpeechSynthesisErrorEvent" missing -FAIL SpeechSynthesisErrorEvent interface object name assert_own_property: self does not have own property "SpeechSynthesisErrorEvent" expected property "SpeechSynthesisErrorEvent" missing -FAIL SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "SpeechSynthesisErrorEvent" expected property "SpeechSynthesisErrorEvent" missing -FAIL SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "SpeechSynthesisErrorEvent" expected property "SpeechSynthesisErrorEvent" missing -FAIL SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "SpeechSynthesisErrorEvent" expected property "SpeechSynthesisErrorEvent" missing -FAIL SpeechSynthesisErrorEvent interface: attribute error assert_own_property: self does not have own property "SpeechSynthesisErrorEvent" expected property "SpeechSynthesisErrorEvent" missing +PASS SpeechSynthesisErrorEvent interface: existence and properties of interface object +PASS SpeechSynthesisErrorEvent interface object length +PASS SpeechSynthesisErrorEvent interface object name +PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object +PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's "constructor" property +PASS SpeechSynthesisErrorEvent interface: existence and properties of interface prototype object's @@unscopables property +PASS SpeechSynthesisErrorEvent interface: attribute error FAIL SpeechSynthesisVoice interface: existence and properties of interface object assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing FAIL SpeechSynthesisVoice interface object length assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing FAIL SpeechSynthesisVoice interface object name assert_own_property: self does not have own property "SpeechSynthesisVoice" expected property "SpeechSynthesisVoice" missing
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt index d8d65a9..361d4f6 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -14,7 +14,7 @@ LayoutNGBlockFlow {DD} at (40,20) size 744x40 LayoutNGBlockFlow (anonymous) at (0,0) size 744x20 LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 98x18 + LayoutBlockFlow (anonymous) at (1,1) size 98x18 LayoutText (anonymous) at (26,1) size 68x16 text run at (26,1) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}" text run at (73,1) width 21: "abc" @@ -29,7 +29,7 @@ LayoutNGBlockFlow {DD} at (40,80) size 744x40 LayoutNGBlockFlow (anonymous) at (0,0) size 744x20 LayoutMenuList {SELECT} at (0,0) size 200x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 198x18 + LayoutBlockFlow (anonymous) at (1,1) size 198x18 LayoutText (anonymous) at (4,1) size 68x16 text run at (4,1) width 21: "abc" text run at (25,1) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}" @@ -44,7 +44,7 @@ LayoutNGBlockFlow {DD} at (40,140) size 744x40 LayoutNGBlockFlow (anonymous) at (0,0) size 744x20 LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 98x18 + LayoutBlockFlow (anonymous) at (1,1) size 98x18 LayoutText (anonymous) at (4,1) size 68x16 text run at (4,1) width 21: "abc" text run at (25,1) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}" @@ -62,7 +62,7 @@ text run at (0,0) width 139: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}" LayoutNGBlockFlow (anonymous) at (0,39) size 784x20 LayoutMenuList {SELECT} at (0,0) size 137x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 135x18 + LayoutBlockFlow (anonymous) at (1,1) size 135x18 LayoutText (anonymous) at (4,1) size 115x16 text run at (4,1) width 115 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}" LayoutText {#text} at (0,0) size 0x0 @@ -76,11 +76,11 @@ layer at (8,399) size 784x160 LayoutBlockFlow {DIV} at (0,383) size 784x160 LayoutMultiColumnSet (anonymous) at (0,0) size 784x160 -layer at (8,399) size 384x320 backgroundClip at (0,0) size 400x559 clip at (0,0) size 400x559 +layer at (8,399) size 384x320 backgroundClip at (0,0) size 800x559 clip at (0,0) size 800x559 LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x320 LayoutBlockFlow {DIV} at (0,0) size 384x160 LayoutMenuList {SELECT} at (0,0) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (4,1) size 179x18 text run at (4,1) width 35: "First " text run at (39,1) width 56 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}" @@ -95,7 +95,7 @@ text run at (82,1) width 30 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} (" text run at (112,1) width 26: " fifth" LayoutMenuList {SELECT} at (0,40) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (4,1) size 179x18 text run at (4,1) width 25: "fifth" text run at (29,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} " @@ -110,14 +110,14 @@ text run at (81,1) width 33 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} (" text run at (114,1) width 24: "First" LayoutMenuList {SELECT} at (0,80) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (4,1) size 179x18 text run at (4,1) width 179 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth" LayoutBlockFlow {DIV} at (0,102) size 352x18 LayoutText {#text} at (1,1) size 137x15 text run at (1,1) width 137 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth" LayoutMenuList {SELECT} at (0,120) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (4,1) size 179x18 text run at (4,1) width 179 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth" LayoutBlockFlow {DIV} at (0,142) size 352x18 @@ -125,7 +125,7 @@ text run at (1,1) width 137 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth" LayoutBlockFlow {DIV} at (0,160) size 384x160 LayoutMenuList {SELECT} at (0,0) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (165,1) size 179x18 text run at (165,1) width 35: "First " text run at (200,1) width 56 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}" @@ -140,7 +140,7 @@ text run at (295,1) width 30 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} (" text run at (325,1) width 26: " fifth" LayoutMenuList {SELECT} at (0,40) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (165,1) size 179x18 text run at (165,1) width 25: "fifth" text run at (190,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} " @@ -155,14 +155,14 @@ text run at (294,1) width 33 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} (" text run at (327,1) width 24: "First" LayoutMenuList {SELECT} at (0,80) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (165,1) size 179x18 text run at (165,1) width 179 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth" LayoutBlockFlow {DIV} at (0,102) size 352x18 LayoutText {#text} at (214,1) size 137x15 text run at (214,1) width 137 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth" LayoutMenuList {SELECT} at (0,120) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] - LayoutNGBlockFlow (anonymous) at (1,1) size 348x21 + LayoutBlockFlow (anonymous) at (1,1) size 348x21 LayoutText (anonymous) at (165,1) size 179x18 text run at (165,1) width 179 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth" LayoutBlockFlow {DIV} at (0,142) size 352x18
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/transformed-clip-before-second-column-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/transformed-clip-before-second-column-expected.txt deleted file mode 100644 index de54a1fd..0000000 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/transformed-clip-before-second-column-expected.txt +++ /dev/null
@@ -1,22 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x86 - LayoutNGBlockFlow {HTML} at (0,0) size 800x86 - LayoutNGBlockFlow {BODY} at (8,8) size 784x70 -layer at (8,8) size 784x70 - LayoutBlockFlow {DIV} at (0,0) size 784x70 - LayoutMultiColumnSet (anonymous) at (0,0) size 784x70 -layer at (8,8) size 384x140 backgroundClip at (0,0) size 400x78 clip at (0,0) size 400x78 - LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x140 - LayoutBlockFlow {DIV} at (0,0) size 384x100 -layer at (408,38) size 384x40 scrollHeight 41 - LayoutBlockFlow {DIV} at (0,100) size 384x40 - LayoutBlockFlow (anonymous) at (0,0) size 384x20 - LayoutText {#text} at (0,0) size 312x19 - text run at (0,0) width 312: "There should be a black rectangle below this text." -layer at (408,58) size 384x20 - LayoutBlockFlow {DIV} at (0,20) size 384x20 - LayoutInline {<pseudo:before>} at (0,0) size 10x19 - LayoutTextFragment (anonymous) at (0,0) size 10x19 - text run at (0,0) width 10: "\x{E8A7}" - LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/rendering-broken-block-flow-images-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/rendering-broken-block-flow-images-expected.txt deleted file mode 100644 index 097bcaf..0000000 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/rendering-broken-block-flow-images-expected.txt +++ /dev/null
@@ -1,363 +0,0 @@ -layer at (0,0) size 800x600 clip at (0,0) size 785x585 scrollWidth 973 scrollHeight 860 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 785x860 backgroundClip at (0,0) size 785x585 clip at (0,0) size 785x585 - LayoutNGBlockFlow {HTML} at (0,0) size 785x860 - LayoutNGBlockFlow {BODY} at (8,16) size 769x836 - LayoutNGBlockFlow {P} at (0,0) size 769x20 - LayoutText {#text} at (0,0) size 315x19 - text run at (0,0) width 315: "crbug.com/644802: Render alt text per html5 spec" -layer at (8,52) size 769x800 backgroundClip at (0,0) size 785x585 clip at (0,0) size 785x585 - LayoutBlockFlow {DIV} at (0,36) size 769x800 - LayoutMultiColumnSet (anonymous) at (0,0) size 769x800 -layer at (8,52) size 180x3621 backgroundClip at (0,0) size 196x585 clip at (0,0) size 196x585 - LayoutMultiColumnFlowThread (anonymous) at (0,0) size 180.25x3621 - LayoutBlockFlow {DIV} at (0,16) size 180.25x401 - LayoutBlockFlow {P} at (0,0) size 180.25x20 - LayoutText {#text} at (0,0) size 132x19 - text run at (0,0) width 132: "Different dimensions" - LayoutNGBlockFlow (anonymous) at (0,36) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,56) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,81) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,121) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,171) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,211) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,251) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,291) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,341) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,381) size 180.25x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutBlockFlow {DIV} at (0,433) size 180.25x361 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,231) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,271) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,321) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,361) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,6) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,800) size 180.25x381 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (16,0) size 172x39 - text run at (16,0) width 156: "Different dimensions, no" - text run at (0,20) width 50: "alt text, " - text run at (50,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,231) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,271) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,321) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,361) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 - LayoutBlockFlow {DIV} at (0,1197) size 180.25x361 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutImage {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutImage {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutImage {IMG} at (0,231) size 50x0 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,231) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutImage {IMG} at (0,271) size 0x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,321) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutImage {IMG} at (0,361) size 0x0 - LayoutBlockFlow {DIV} at (0,1600) size 180.25x421 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,271) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,311) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,401) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,401) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 - LayoutBlockFlow {DIV} at (0,2400) size 180.25x441 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,271) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,311) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,401) size 180.25x20 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,421) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 - LayoutBlockFlow {DIV} at (0,3200) size 180.25x421 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 31: "src =" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,271) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,311) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,401) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,401) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 -layer at (8,561) size 25x25 backgroundClip at (8,561) size 25x24 clip at (9,562) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (8,626) size 50x50 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (204,128) size 25x25 clip at (205,129) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (204,193) size 50x50 clip at (205,194) size 48x48 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/rendering-broken-images-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/rendering-broken-images-expected.txt deleted file mode 100644 index 6fa9db3..0000000 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/rendering-broken-images-expected.txt +++ /dev/null
@@ -1,364 +0,0 @@ -layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 860 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 785x860 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutNGBlockFlow {HTML} at (0,0) size 785x860 - LayoutNGBlockFlow {BODY} at (8,16) size 769x836 - LayoutNGBlockFlow {P} at (0,0) size 769x20 - LayoutText {#text} at (0,0) size 315x19 - text run at (0,0) width 315: "crbug.com/644802: Render alt text per html5 spec" -layer at (8,52) size 769x800 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow {DIV} at (0,36) size 769x800 - LayoutMultiColumnSet (anonymous) at (0,0) size 769x408 -layer at (8,52) size 180x1552 backgroundClip at (0,0) size 196x460 clip at (0,0) size 196x460 - LayoutMultiColumnFlowThread (anonymous) at (0,0) size 180.25x1552 - LayoutBlockFlow {DIV} at (0,16) size 180.25x136 - LayoutBlockFlow {P} at (0,0) size 180.25x20 - LayoutText {#text} at (0,0) size 132x19 - text run at (0,0) width 132: "Different dimensions" - LayoutNGBlockFlow (anonymous) at (0,36) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutBR {BR} at (70,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutBR {BR} at (70,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,80) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,168) size 180.25x204 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x148 - LayoutText {#text} at (0,10) size 12x19 - text run at (0,10) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 25x25 [bgcolor=#008000] - LayoutBR {BR} at (37,10) size 0x19 - LayoutText {#text} at (0,65) size 12x19 - text run at (0,65) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,30) size 50x50 [bgcolor=#008000] - LayoutBR {BR} at (62,65) size 0x19 - LayoutText {#text} at (0,86) size 12x19 - text run at (0,86) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,85) size 16x16 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (28,86) size 0x19 - LayoutText {#text} at (0,107) size 12x19 - text run at (0,107) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,106) size 16x16 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (28,107) size 0x19 - LayoutText {#text} at (0,128) size 12x19 - text run at (0,128) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,127) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutText {#text} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,408) size 180.25x201 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x145 - LayoutText {#text} at (0,10) size 12x19 - text run at (0,10) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 25x25 [bgcolor=#008000] - LayoutBR {BR} at (37,10) size 0x19 - LayoutText {#text} at (0,65) size 12x19 - text run at (0,65) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,30) size 50x50 [bgcolor=#008000] - LayoutBR {BR} at (62,65) size 0x19 - LayoutText {#text} at (0,85) size 12x19 - text run at (0,85) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,100) size 0x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (12,85) size 0x19 - LayoutText {#text} at (0,105) size 12x19 - text run at (0,105) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,120) size 0x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (12,105) size 0x19 - LayoutText {#text} at (0,125) size 12x19 - text run at (0,125) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,140) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (12,125) size 0x19 - LayoutBlockFlow {DIV} at (0,816) size 180.25x236 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x180 - LayoutText {#text} at (0,10) size 12x19 - text run at (0,10) width 12: "1." - LayoutImage {IMG} at (12,0) size 25x25 [bgcolor=#008000] - LayoutText {#text} at (37,10) size 4x19 - text run at (37,10) width 4: " " - LayoutBR {BR} at (41,10) size 0x19 - LayoutText {#text} at (0,65) size 12x19 - text run at (0,65) width 12: "2." - LayoutImage {IMG} at (12,30) size 50x50 [bgcolor=#008000] - LayoutText {#text} at (62,65) size 4x19 - text run at (62,65) width 4: " " - LayoutBR {BR} at (66,65) size 0x19 - LayoutText {#text} at (0,85) size 12x19 - text run at (0,85) width 12: "3." - LayoutImage {IMG} at (12,100) size 50x0 [bgcolor=#008000] - LayoutText {#text} at (62,85) size 4x19 - text run at (62,85) width 4: " " - LayoutBR {BR} at (66,85) size 0x19 - LayoutText {#text} at (0,140) size 12x19 - text run at (0,140) width 12: "4." - LayoutImage {IMG} at (12,105) size 0x50 [bgcolor=#008000] - LayoutText {#text} at (12,140) size 4x19 - text run at (12,140) width 4: " " - LayoutBR {BR} at (16,140) size 0x19 - LayoutText {#text} at (0,160) size 12x19 - text run at (0,160) width 12: "5." - LayoutImage {IMG} at (12,175) size 0x0 - LayoutText {#text} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,1068) size 180.25x156 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,40) size 4x19 - text run at (70,40) width 4: " " - LayoutBR {BR} at (74,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,60) size 4x19 - text run at (70,60) width 4: " " - LayoutBR {BR} at (74,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,95) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutText {#text} at (12,80) size 4x19 - text run at (12,80) width 4: " " - LayoutBR {BR} at (16,80) size 0x19 - LayoutBlockFlow {DIV} at (0,1224) size 180.25x156 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,40) size 4x19 - text run at (70,40) width 4: " " - LayoutBR {BR} at (74,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,60) size 4x19 - text run at (70,60) width 4: " " - LayoutBR {BR} at (74,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,80) size 58x20 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,80) size 4x19 - text run at (70,80) width 4: " " - LayoutBR {BR} at (74,80) size 0x19 - LayoutBlockFlow {DIV} at (0,1396) size 180.25x156 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 31: "src =" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,40) size 4x19 - text run at (70,40) width 4: " " - LayoutBR {BR} at (74,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,60) size 4x19 - text run at (70,60) width 4: " " - LayoutBR {BR} at (74,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,95) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutText {#text} at (12,80) size 4x19 - text run at (12,80) width 4: " " - LayoutBR {BR} at (16,80) size 0x19 -layer at (20,276) size 25x25 clip at (21,277) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (20,306) size 50x50 clip at (21,307) size 48x48 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (216,108) size 25x25 clip at (217,109) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (216,138) size 50x50 clip at (217,139) size 48x48 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/rendering-broken-block-flow-images-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/rendering-broken-block-flow-images-expected.txt deleted file mode 100644 index 097bcaf..0000000 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/rendering-broken-block-flow-images-expected.txt +++ /dev/null
@@ -1,363 +0,0 @@ -layer at (0,0) size 800x600 clip at (0,0) size 785x585 scrollWidth 973 scrollHeight 860 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 785x860 backgroundClip at (0,0) size 785x585 clip at (0,0) size 785x585 - LayoutNGBlockFlow {HTML} at (0,0) size 785x860 - LayoutNGBlockFlow {BODY} at (8,16) size 769x836 - LayoutNGBlockFlow {P} at (0,0) size 769x20 - LayoutText {#text} at (0,0) size 315x19 - text run at (0,0) width 315: "crbug.com/644802: Render alt text per html5 spec" -layer at (8,52) size 769x800 backgroundClip at (0,0) size 785x585 clip at (0,0) size 785x585 - LayoutBlockFlow {DIV} at (0,36) size 769x800 - LayoutMultiColumnSet (anonymous) at (0,0) size 769x800 -layer at (8,52) size 180x3621 backgroundClip at (0,0) size 196x585 clip at (0,0) size 196x585 - LayoutMultiColumnFlowThread (anonymous) at (0,0) size 180.25x3621 - LayoutBlockFlow {DIV} at (0,16) size 180.25x401 - LayoutBlockFlow {P} at (0,0) size 180.25x20 - LayoutText {#text} at (0,0) size 132x19 - text run at (0,0) width 132: "Different dimensions" - LayoutNGBlockFlow (anonymous) at (0,36) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,56) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,81) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,121) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,171) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,211) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,251) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,291) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,341) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,381) size 180.25x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutBlockFlow {DIV} at (0,433) size 180.25x361 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,231) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,271) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,321) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,361) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,6) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,800) size 180.25x381 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (16,0) size 172x39 - text run at (16,0) width 156: "Different dimensions, no" - text run at (0,20) width 50: "alt text, " - text run at (50,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,231) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,271) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,321) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,361) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 - LayoutBlockFlow {DIV} at (0,1197) size 180.25x361 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutImage {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutImage {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutImage {IMG} at (0,231) size 50x0 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,231) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutImage {IMG} at (0,271) size 0x50 [bgcolor=#008000] - LayoutNGBlockFlow (anonymous) at (0,321) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutImage {IMG} at (0,361) size 0x0 - LayoutBlockFlow {DIV} at (0,1600) size 180.25x421 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,271) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,311) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,401) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,401) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 - LayoutBlockFlow {DIV} at (0,2400) size 180.25x441 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,271) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,311) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,401) size 180.25x20 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,421) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 - LayoutBlockFlow {DIV} at (0,3200) size 180.25x421 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 31: "src =" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x20 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (0,76) size 25x25 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 23x39 - LayoutText {#text} at (0,16) size 23x39 - text run at (0,16) width 15: "alt" - text run at (0,36) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,101) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (0,141) size 50x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,191) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "3." - LayoutNGBlockFlow {IMG} at (0,231) size 50x40 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 31x39 - LayoutText {#text} at (16,0) size 31x39 - text run at (16,0) width 15: "alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,271) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "4." - LayoutNGBlockFlow {IMG} at (0,311) size 180.25x50 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutNGBlockFlow (anonymous) at (0,361) size 180.25x40 - LayoutBR {BR} at (0,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "5." - LayoutNGBlockFlow {IMG} at (0,401) size 180.25x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutNGBlockFlow (anonymous) at (0,401) size 180.25x20 - LayoutBR {BR} at (0,0) size 0x19 -layer at (8,561) size 25x25 backgroundClip at (8,561) size 25x24 clip at (9,562) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (8,626) size 50x50 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (204,128) size 25x25 clip at (205,129) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (204,193) size 50x50 clip at (205,194) size 48x48 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/rendering-broken-images-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/rendering-broken-images-expected.txt deleted file mode 100644 index 6fa9db3..0000000 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/rendering-broken-images-expected.txt +++ /dev/null
@@ -1,364 +0,0 @@ -layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 860 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 785x860 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutNGBlockFlow {HTML} at (0,0) size 785x860 - LayoutNGBlockFlow {BODY} at (8,16) size 769x836 - LayoutNGBlockFlow {P} at (0,0) size 769x20 - LayoutText {#text} at (0,0) size 315x19 - text run at (0,0) width 315: "crbug.com/644802: Render alt text per html5 spec" -layer at (8,52) size 769x800 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow {DIV} at (0,36) size 769x800 - LayoutMultiColumnSet (anonymous) at (0,0) size 769x408 -layer at (8,52) size 180x1552 backgroundClip at (0,0) size 196x460 clip at (0,0) size 196x460 - LayoutMultiColumnFlowThread (anonymous) at (0,0) size 180.25x1552 - LayoutBlockFlow {DIV} at (0,16) size 180.25x136 - LayoutBlockFlow {P} at (0,0) size 180.25x20 - LayoutText {#text} at (0,0) size 132x19 - text run at (0,0) width 132: "Different dimensions" - LayoutNGBlockFlow (anonymous) at (0,36) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutBR {BR} at (70,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutBR {BR} at (70,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,80) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,168) size 180.25x204 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 23: "text" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x148 - LayoutText {#text} at (0,10) size 12x19 - text run at (0,10) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 25x25 [bgcolor=#008000] - LayoutBR {BR} at (37,10) size 0x19 - LayoutText {#text} at (0,65) size 12x19 - text run at (0,65) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,30) size 50x50 [bgcolor=#008000] - LayoutBR {BR} at (62,65) size 0x19 - LayoutText {#text} at (0,86) size 12x19 - text run at (0,86) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,85) size 16x16 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (28,86) size 0x19 - LayoutText {#text} at (0,107) size 12x19 - text run at (0,107) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,106) size 16x16 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (28,107) size 0x19 - LayoutText {#text} at (0,128) size 12x19 - text run at (0,128) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,127) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutText {#text} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,408) size 180.25x201 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x145 - LayoutText {#text} at (0,10) size 12x19 - text run at (0,10) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 25x25 [bgcolor=#008000] - LayoutBR {BR} at (37,10) size 0x19 - LayoutText {#text} at (0,65) size 12x19 - text run at (0,65) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,30) size 50x50 [bgcolor=#008000] - LayoutBR {BR} at (62,65) size 0x19 - LayoutText {#text} at (0,85) size 12x19 - text run at (0,85) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,100) size 0x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (12,85) size 0x19 - LayoutText {#text} at (0,105) size 12x19 - text run at (0,105) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,120) size 0x0 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (12,105) size 0x19 - LayoutText {#text} at (0,125) size 12x19 - text run at (0,125) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,140) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutBR {BR} at (12,125) size 0x19 - LayoutBlockFlow {DIV} at (0,816) size 180.25x236 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 175x39 - text run at (0,0) width 175: "Different dimensions, no alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x180 - LayoutText {#text} at (0,10) size 12x19 - text run at (0,10) width 12: "1." - LayoutImage {IMG} at (12,0) size 25x25 [bgcolor=#008000] - LayoutText {#text} at (37,10) size 4x19 - text run at (37,10) width 4: " " - LayoutBR {BR} at (41,10) size 0x19 - LayoutText {#text} at (0,65) size 12x19 - text run at (0,65) width 12: "2." - LayoutImage {IMG} at (12,30) size 50x50 [bgcolor=#008000] - LayoutText {#text} at (62,65) size 4x19 - text run at (62,65) width 4: " " - LayoutBR {BR} at (66,65) size 0x19 - LayoutText {#text} at (0,85) size 12x19 - text run at (0,85) width 12: "3." - LayoutImage {IMG} at (12,100) size 50x0 [bgcolor=#008000] - LayoutText {#text} at (62,85) size 4x19 - text run at (62,85) width 4: " " - LayoutBR {BR} at (66,85) size 0x19 - LayoutText {#text} at (0,140) size 12x19 - text run at (0,140) width 12: "4." - LayoutImage {IMG} at (12,105) size 0x50 [bgcolor=#008000] - LayoutText {#text} at (12,140) size 4x19 - text run at (12,140) width 4: " " - LayoutBR {BR} at (16,140) size 0x19 - LayoutText {#text} at (0,160) size 12x19 - text run at (0,160) width 12: "5." - LayoutImage {IMG} at (12,175) size 0x0 - LayoutText {#text} at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (0,1068) size 180.25x156 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 49: "src = \"\"" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,40) size 4x19 - text run at (70,40) width 4: " " - LayoutBR {BR} at (74,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,60) size 4x19 - text run at (70,60) width 4: " " - LayoutBR {BR} at (74,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,95) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutText {#text} at (12,80) size 4x19 - text run at (12,80) width 4: " " - LayoutBR {BR} at (16,80) size 0x19 - LayoutBlockFlow {DIV} at (0,1224) size 180.25x156 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 69: "text, no src" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,40) size 4x19 - text run at (70,40) width 4: " " - LayoutBR {BR} at (74,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,60) size 4x19 - text run at (70,60) width 4: " " - LayoutBR {BR} at (74,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,80) size 58x20 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,80) size 4x19 - text run at (70,80) width 4: " " - LayoutBR {BR} at (74,80) size 0x19 - LayoutBlockFlow {DIV} at (0,1396) size 180.25x156 - LayoutBlockFlow {P} at (0,0) size 180.25x40 - LayoutText {#text} at (0,0) size 155x39 - text run at (0,0) width 155: "Different dimensions, alt" - text run at (0,20) width 31: "text, " - text run at (31,20) width 31: "src =" - LayoutNGBlockFlow (anonymous) at (0,56) size 180.25x100 - LayoutText {#text} at (0,0) size 12x19 - text run at (0,0) width 12: "1." - LayoutNGBlockFlow {IMG} at (12,0) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,0) size 4x19 - text run at (70,0) width 4: " " - LayoutBR {BR} at (74,0) size 0x19 - LayoutText {#text} at (0,20) size 12x19 - text run at (0,20) width 12: "2." - LayoutNGBlockFlow {IMG} at (12,20) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,20) size 4x19 - text run at (70,20) width 4: " " - LayoutBR {BR} at (74,20) size 0x19 - LayoutText {#text} at (0,40) size 12x19 - text run at (0,40) width 12: "3." - LayoutNGBlockFlow {IMG} at (12,40) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,40) size 4x19 - text run at (70,40) width 4: " " - LayoutBR {BR} at (74,40) size 0x19 - LayoutText {#text} at (0,60) size 12x19 - text run at (0,60) width 12: "4." - LayoutNGBlockFlow {IMG} at (12,60) size 58x20 [bgcolor=#008000] - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutImage (floating) {IMG} at (0,0) size 16x16 - LayoutInline {SPAN} at (0,0) size 42x19 - LayoutText {#text} at (16,0) size 42x19 - text run at (16,0) width 42: "alt text" - LayoutText {#text} at (70,60) size 4x19 - text run at (70,60) width 4: " " - LayoutBR {BR} at (74,60) size 0x19 - LayoutText {#text} at (0,80) size 12x19 - text run at (0,80) width 12: "5." - LayoutNGBlockFlow {IMG} at (12,95) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 0x0 - LayoutText {#text} at (12,80) size 4x19 - text run at (12,80) width 4: " " - LayoutBR {BR} at (16,80) size 0x19 -layer at (20,276) size 25x25 clip at (21,277) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (20,306) size 50x50 clip at (21,307) size 48x48 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (216,108) size 25x25 clip at (217,109) size 23x23 - LayoutBlockFlow {SPAN} at (0,0) size 25x25 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0 -layer at (216,138) size 50x50 clip at (217,139) size 48x48 - LayoutBlockFlow {SPAN} at (0,0) size 50x50 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 - LayoutInline {SPAN} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-svg-attribute-ns-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-svg-attribute-ns-expected.txt new file mode 100644 index 0000000..5d4c4a02 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-svg-attribute-ns-expected.txt
@@ -0,0 +1,6 @@ +Test that namespaced attributes can be modified. +Original attribute: +xlink:href=fake_original_image.png +Modified attribute: +xlink:href=fake_modified_image.png +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-svg-attribute-ns.js b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-svg-attribute-ns.js new file mode 100644 index 0000000..d92f1e0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-svg-attribute-ns.js
@@ -0,0 +1,22 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startHTML(` + <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"> + <image id='main' xlink:href="fake_original_image.png"/> + </svg> + `, 'Test that namespaced attributes can be modified.'); + + var response = await dp.DOM.getDocument(); + var rootNodeId = response.result.root.nodeId; + + response = await dp.DOM.querySelector({nodeId: rootNodeId, selector: '#main'}) + var nodeId = response.result.nodeId; + testRunner.log('Original attribute:'); + response = await dp.DOM.getAttributes({nodeId}); + testRunner.log(response.result.attributes[2] + '=' + response.result.attributes[3]); + + dp.DOM.setAttributesAsText({nodeId, name: 'xlink:href', text: 'xlink:href="fake_modified_image.png"'}); + response = await dp.DOM.onceAttributeModified(); + testRunner.log('Modified attribute:'); + testRunner.log(response.params.name + '=' + response.params.value); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt index 9e80ac5..43dbaff5 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -6335,6 +6335,10 @@ method constructor setter onaddsourcebuffer setter onremovesourcebuffer +interface SpeechSynthesisErrorEvent : SpeechSynthesisEvent + attribute @@toStringTag + getter error + method constructor interface SpeechSynthesisEvent : Event attribute @@toStringTag getter charIndex
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 8defe0ac..13266312 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -7070,6 +7070,10 @@ method constructor setter onaddsourcebuffer setter onremovesourcebuffer +interface SpeechSynthesisErrorEvent : SpeechSynthesisEvent + attribute @@toStringTag + getter error + method constructor interface SpeechSynthesisEvent : Event attribute @@toStringTag getter charIndex
diff --git a/third_party/blink/common/feature_policy/feature_policy.cc b/third_party/blink/common/feature_policy/feature_policy.cc index 1ac1240..164578ba 100644 --- a/third_party/blink/common/feature_policy/feature_policy.cc +++ b/third_party/blink/common/feature_policy/feature_policy.cc
@@ -83,7 +83,7 @@ if (matches_all_origins_) return true; for (const auto& targetOrigin : origins_) { - if (!origin.unique() && targetOrigin.IsSameOriginWith(origin)) + if (!origin.opaque() && targetOrigin.IsSameOriginWith(origin)) return true; } return false; @@ -168,7 +168,7 @@ FeaturePolicy::FeaturePolicy(url::Origin origin, const FeatureList& feature_list) : origin_(std::move(origin)), feature_list_(feature_list) { - if (origin_.unique()) { + if (origin_.opaque()) { // FeaturePolicy was written expecting opaque Origins to be indistinct, but // this has changed. Split out a new opaque origin here, to defend against // origin-equality. @@ -223,7 +223,7 @@ // must not. inherited_policy = false; if (parent_policy->IsFeatureEnabled(feature)) { - if (parsed_declaration.matches_opaque_src && origin_.unique()) { + if (parsed_declaration.matches_opaque_src && origin_.opaque()) { // If the child frame has an opaque origin, and the declared container // policy indicates that the feature should be enabled, enable it for // the child frame.
diff --git a/third_party/blink/common/origin_trials/trial_token.cc b/third_party/blink/common/origin_trials/trial_token.cc index 1f17fcb..44be9a6a 100644 --- a/third_party/blink/common/origin_trials/trial_token.cc +++ b/third_party/blink/common/origin_trials/trial_token.cc
@@ -181,9 +181,9 @@ datadict->GetString("feature", &feature_name); datadict->GetInteger("expiry", &expiry_timestamp); - // Ensure that the origin is a valid (non-unique) origin URL. + // Ensure that the origin is a valid (non-opaque) origin URL. url::Origin origin = url::Origin::Create(GURL(origin_string)); - if (origin.unique()) { + if (origin.opaque()) { return nullptr; }
diff --git a/third_party/blink/public/mojom/loader/code_cache.mojom b/third_party/blink/public/mojom/loader/code_cache.mojom index 7bd7041..d08a2f3 100644 --- a/third_party/blink/public/mojom/loader/code_cache.mojom +++ b/third_party/blink/public/mojom/loader/code_cache.mojom
@@ -8,22 +8,29 @@ import "url/mojom/origin.mojom"; import "url/mojom/url.mojom"; +// Enumeration of distinct code cache types. +enum CodeCacheType { + kJavascript, // Javascript bytecode. + kWebAssembly, // WebAssembly compiled module code. +}; + // Interface to the code cache in the browser process. Renderer processes // can use this interface to persistently store and retrieve executable code // generated for a URL. interface CodeCacheHost { // Requests that the browser cache |data| associated with |url| and // |expected_response_time|. - DidGenerateCacheableMetadata(url.mojom.Url url, + DidGenerateCacheableMetadata(CodeCacheType cache_type, + url.mojom.Url url, mojo_base.mojom.Time expected_response_time, array<uint8> data); // TODO(crbug.com/867848) Pass the data as mojo data_pipe instead of // array<unit8>. - FetchCachedCode(url.mojom.Url url) => (mojo_base.mojom.Time response_time, - array<uint8> data); + FetchCachedCode(CodeCacheType cache_type, url.mojom.Url url) => + (mojo_base.mojom.Time response_time, array<uint8> data); - ClearCodeCacheEntry(url.mojom.Url url); + ClearCodeCacheEntry(CodeCacheType cache_type, url.mojom.Url url); // Requests that the browser cache |data| for the specified CacheStorage entry. // TODO(https://crbug.com/779444): Verify or remove |cache_storage_origin|.
diff --git a/third_party/blink/public/platform/code_cache_loader.h b/third_party/blink/public/platform/code_cache_loader.h index 2d5741e..85509ef 100644 --- a/third_party/blink/public/platform/code_cache_loader.h +++ b/third_party/blink/public/platform/code_cache_loader.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_CODE_CACHE_LOADER_H_ #include "base/callback.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom-shared.h" #include "url/gurl.h" namespace blink { @@ -25,7 +26,9 @@ const GURL& url, base::Time* response_time_out, std::vector<uint8_t>* data_out) = 0; - virtual void FetchFromCodeCache(const GURL& url, FetchCodeCacheCallback) = 0; + virtual void FetchFromCodeCache(blink::mojom::CodeCacheType cache_type, + const GURL& url, + FetchCodeCacheCallback) = 0; }; } // namespace blink
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index 8dfa718..5a98eaf6 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -47,6 +47,7 @@ #include "mojo/public/cpp/system/message_pipe.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "third_party/blink/public/common/feature_policy/feature_policy.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom-shared.h" #include "third_party/blink/public/platform/blame_context.h" #include "third_party/blink/public/platform/code_cache_loader.h" #include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h" @@ -385,16 +386,19 @@ virtual WebString UserAgent() { return WebString(); } // A suggestion to cache this metadata in association with this URL. - virtual void CacheMetadata(const WebURL&, + virtual void CacheMetadata(blink::mojom::CodeCacheType cache_type, + const WebURL&, base::Time response_time, const char* data, size_t data_size) {} // A request to fetch contents associated with this URL from metadata cache. virtual void FetchCachedCode( + blink::mojom::CodeCacheType cache_type, const GURL&, base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>) {} - virtual void ClearCodeCacheEntry(const GURL&) {} + virtual void ClearCodeCacheEntry(blink::mojom::CodeCacheType cache_type, + const GURL&) {} // A suggestion to cache this metadata in association with this URL which // resource is in CacheStorage.
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index 9ca5760a..9d9007f5 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -1999,6 +1999,12 @@ kSerialRequestPort = 2546, kSerialPortOpen = 2547, kSerialPortClose = 2548, + kBackgroundFetchManagerFetch = 2549, + kBackgroundFetchManagerGet = 2550, + kBackgroundFetchManagerGetIds = 2551, + kBackgroundFetchRegistrationAbort = 2552, + kBackgroundFetchRegistrationMatch = 2553, + kBackgroundFetchRegistrationMatchAll = 2554, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/modules/BUILD.gn b/third_party/blink/renderer/bindings/modules/BUILD.gn index a8b704c..b242546 100644 --- a/third_party/blink/renderer/bindings/modules/BUILD.gn +++ b/third_party/blink/renderer/bindings/modules/BUILD.gn
@@ -52,6 +52,7 @@ "//third_party/blink/renderer/modules/service_worker/install_event.idl", "//third_party/blink/renderer/modules/speech/speech_recognition_error.idl", "//third_party/blink/renderer/modules/speech/speech_recognition_event.idl", + "//third_party/blink/renderer/modules/speech/speech_synthesis_error_event.idl", "//third_party/blink/renderer/modules/speech/speech_synthesis_event.idl", "//third_party/blink/renderer/modules/storage/storage_event.idl", "//third_party/blink/renderer/modules/vr/vr_display_event.idl",
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 92e43fd..084832bb 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -2043,6 +2043,7 @@ "layout/shapes/box_shape_test.cc", "layout/svg/layout_svg_foreign_object_test.cc", "layout/svg/layout_svg_root_test.cc", + "layout/svg/layout_svg_text_test.cc", "layout/text_autosizer_test.cc", "layout/visual_rect_mapping_test.cc", "loader/allowed_by_nosniff_test.cc",
diff --git a/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.cc b/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.cc index 4d9db874..4459b43 100644 --- a/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.cc +++ b/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.cc
@@ -5,6 +5,9 @@ #include "third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.h" #include "third_party/blink/renderer/core/fetch/response.h" +#include "third_party/blink/renderer/core/workers/worker_global_scope.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" +#include "third_party/blink/renderer/platform/testing/url_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -21,4 +24,20 @@ return url_list; } +int WorkerInternalsFetch::getResourcePriority( + WorkerInternals& internals, + const String& url, + WorkerGlobalScope* worker_global) { + if (!worker_global) + return static_cast<int>(ResourceLoadPriority::kUnresolved); + + Resource* resource = worker_global->Fetcher()->AllResources().at( + URLTestHelpers::ToKURL(url.Utf8().data())); + + if (!resource) + return static_cast<int>(ResourceLoadPriority::kUnresolved); + + return static_cast<int>(resource->GetResourceRequest().Priority()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.h b/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.h index c61d826..424de4f 100644 --- a/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.h +++ b/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.h
@@ -11,6 +11,7 @@ namespace blink { +class WorkerGlobalScope; class WorkerInternals; class Response; @@ -19,6 +20,9 @@ public: static Vector<String> getInternalResponseURLList(WorkerInternals&, Response*); + static int getResourcePriority(WorkerInternals&, + const String& url, + WorkerGlobalScope*); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.idl b/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.idl index 9115908..db8f48b 100644 --- a/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.idl +++ b/third_party/blink/renderer/core/fetch/testing/worker_internals_fetch.idl
@@ -6,4 +6,5 @@ ImplementedAs=WorkerInternalsFetch ] partial interface WorkerInternals { sequence<USVString> getInternalResponseURLList(Response response); + unsigned long getResourcePriority(DOMString url, WorkerGlobalScope worker_global); };
diff --git a/third_party/blink/renderer/core/html/html_iframe_element_test.cc b/third_party/blink/renderer/core/html/html_iframe_element_test.cc index 3ca5e96a..8b33cdd 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element_test.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element_test.cc
@@ -269,7 +269,7 @@ EXPECT_FALSE(container_policy[0].matches_all_origins); EXPECT_FALSE(container_policy[0].matches_opaque_src); EXPECT_EQ(1UL, container_policy[0].origins.size()); - EXPECT_FALSE(container_policy[0].origins[0].unique()); + EXPECT_FALSE(container_policy[0].origins[0].opaque()); EXPECT_EQ("http://example.net", container_policy[0].origins[0].Serialize()); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc index 92fe32db..bc124ce6 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -77,6 +77,7 @@ #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/page/frame_tree.h" #include "third_party/blink/renderer/core/page/page.h" +#include "third_party/blink/renderer/core/svg/svg_svg_element.h" #include "third_party/blink/renderer/core/xml/document_xpath_evaluator.h" #include "third_party/blink/renderer/core/xml/xpath_result.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -752,11 +753,15 @@ element->GetDocument().IsHTMLDocument() && element->IsHTMLElement(); // Not all elements can represent the context (i.e. IFRAME), hence using // document.body. - if (should_ignore_case && element->GetDocument().body()) + if (should_ignore_case && element->GetDocument().body()) { fragment->ParseHTML(markup, element->GetDocument().body(), kAllowScriptingContent); - else - fragment->ParseXML(markup, nullptr, kAllowScriptingContent); + } else { + Element* contextElement = nullptr; + if (element->IsSVGElement()) + contextElement = ToSVGElement(element)->ownerSVGElement(); + fragment->ParseXML(markup, contextElement, kAllowScriptingContent); + } Element* parsed_element = fragment->firstChild() && fragment->firstChild()->IsElementNode()
diff --git a/third_party/blink/renderer/core/layout/hit_test_location.cc b/third_party/blink/renderer/core/layout/hit_test_location.cc index 8d795de..37b7080 100644 --- a/third_party/blink/renderer/core/layout/hit_test_location.cc +++ b/third_party/blink/renderer/core/layout/hit_test_location.cc
@@ -121,13 +121,23 @@ } bool HitTestLocation::Intersects(const FloatRect& rect) const { - return IntersectsRect(rect, FloatRect(bounding_box_)); + if (is_rect_based_) + return transformed_rect_.IntersectsRect(rect); + return rect.Contains(transformed_point_); } bool HitTestLocation::Intersects(const FloatRoundedRect& rect) const { return rect.IntersectsQuad(transformed_rect_); } +bool HitTestLocation::Intersects(const FloatQuad& quad) const { + // TODO(chrishtr): if the quads are not rectilinear, calling Intersects + // has false positives. + if (is_rect_based_) + return Intersects(quad.BoundingBox()); + return quad.ContainsPoint(FloatPoint(point_)); +} + bool HitTestLocation::ContainsPoint(const FloatPoint& point) const { return transformed_rect_.ContainsPoint(point); }
diff --git a/third_party/blink/renderer/core/layout/hit_test_location.h b/third_party/blink/renderer/core/layout/hit_test_location.h index 26704ce..3bd5f17 100644 --- a/third_party/blink/renderer/core/layout/hit_test_location.h +++ b/third_party/blink/renderer/core/layout/hit_test_location.h
@@ -70,8 +70,11 @@ } bool Intersects(const LayoutRect&) const; + // Uses floating-point intersection, which uses inclusive intersection + // (see LayoutRect::InclusiveIntersect for a definition) bool Intersects(const FloatRect&) const; bool Intersects(const FloatRoundedRect&) const; + bool Intersects(const FloatQuad&) const; bool ContainsPoint(const FloatPoint&) const; const FloatPoint& TransformedPoint() const { return transformed_point_; }
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index f1415c0..0c7748b 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -179,7 +179,7 @@ LayoutUnit LayoutFlexibleBox::FirstLineBoxBaseline() const { if (IsWritingModeRoot() || number_of_in_flow_children_on_first_line_ <= 0 || - ShouldApplySizeContainment()) + ShouldApplyLayoutContainment()) return LayoutUnit(-1); LayoutBox* baseline_child = nullptr; int child_number = 0;
diff --git a/third_party/blink/renderer/core/layout/layout_grid.cc b/third_party/blink/renderer/core/layout/layout_grid.cc index f4abe07c..34066a6 100644 --- a/third_party/blink/renderer/core/layout/layout_grid.cc +++ b/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -1633,7 +1633,7 @@ LayoutUnit LayoutGrid::FirstLineBoxBaseline() const { if (IsWritingModeRoot() || !grid_->HasGridItems() || - ShouldApplySizeContainment()) + ShouldApplyLayoutContainment()) return LayoutUnit(-1); const LayoutBox* baseline_child = nullptr; const LayoutBox* first_child = nullptr;
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 8ac913c9..0e68b248 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -3818,13 +3818,6 @@ return AffineTransform(); } -bool LayoutObject::NodeAtFloatPoint(HitTestResult&, - const FloatPoint&, - HitTestAction) { - NOTREACHED(); - return false; -} - bool LayoutObject::IsRelayoutBoundaryForInspector() const { return ObjectIsRelayoutBoundary(this); }
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 74f68cb..e99bb88 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -794,13 +794,6 @@ return LocalSVGTransform(); } - // SVG uses FloatPoint precise hit testing, and passes the point in parent - // coordinates instead of in paint invalidation container coordinates. - // Eventually the rest of the layout tree will move to a similar model. - virtual bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction); - // End of SVG-specific methods. bool IsAnonymous() const { return bitfields_.IsAnonymous(); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc index 0e73358c..daf08f2 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -321,6 +321,7 @@ space_builder.SetPercentageResolutionSize(column_size); space_builder.SetIsNewFormattingContext(true); space_builder.SetIsAnonymous(true); + space_builder.SetIsIntermediateLayout(true); return space_builder.ToConstraintSpace(Style().GetWritingMode()); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc index ee9bba3..f025dab 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/layout/hit_test_result.h" #include "third_party/blink/renderer/core/layout/layout_analyzer.h" +#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h" #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h" @@ -173,37 +174,49 @@ GetElement()->SetNeedsResizeObserverUpdate(); } -bool LayoutSVGContainer::NodeAtFloatPoint(HitTestResult& result, - const FloatPoint& point_in_parent, - HitTestAction hit_test_action) { - FloatPoint local_point; +bool LayoutSVGContainer::NodeAtPoint( + HitTestResult& result, + const HitTestLocation& location_in_container, + const LayoutPoint& accumulated_offset, + HitTestAction hit_test_action) { + DCHECK_EQ(accumulated_offset, LayoutPoint()); + HitTestLocation local_location; if (!SVGLayoutSupport::TransformToUserSpaceAndCheckClipping( - *this, LocalToSVGParentTransform(), point_in_parent, local_point)) + *this, LocalToSVGParentTransform(), location_in_container, + local_location)) return false; for (LayoutObject* child = LastChild(); child; child = child->PreviousSibling()) { - if (child->NodeAtFloatPoint(result, local_point, hit_test_action)) { - const LayoutPoint& local_layout_point = LayoutPoint(local_point); + bool found = false; + if (child->IsSVGForeignObject()) { + found = ToLayoutSVGForeignObject(child)->NodeAtPointFromSVG( + result, local_location, accumulated_offset, hit_test_action); + } else { + found = child->NodeAtPoint(result, local_location, accumulated_offset, + hit_test_action); + } + if (found) { + const LayoutPoint& local_layout_point = + LayoutPoint(local_location.TransformedPoint()); UpdateHitTestResult(result, local_layout_point); - HitTestLocation location(local_layout_point); - if (result.AddNodeToListBasedTestResult(child->GetNode(), location) == - kStopHitTesting) + if (result.AddNodeToListBasedTestResult( + child->GetNode(), local_location) == kStopHitTesting) { return true; + } } } - // pointer-events: bounding-box makes it possible for containers to be direct // targets. if (StyleRef().PointerEvents() == EPointerEvents::kBoundingBox) { // Check for a valid bounding box because it will be invalid for empty // containers. if (IsObjectBoundingBoxValid() && - ObjectBoundingBox().Contains(local_point)) { - const LayoutPoint& local_layout_point = LayoutPoint(local_point); + local_location.Intersects(ObjectBoundingBox())) { + const LayoutPoint& local_layout_point = + LayoutPoint(local_location.TransformedPoint()); UpdateHitTestResult(result, local_layout_point); - HitTestLocation location(local_layout_point); - if (result.AddNodeToListBasedTestResult(GetElement(), location) == + if (result.AddNodeToListBasedTestResult(GetElement(), local_location) == kStopHitTesting) return true; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_container.h index 76b501fd..a12b7cf 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.h
@@ -82,9 +82,10 @@ FloatRect StrokeBoundingBox() const final { return stroke_bounding_box_; } - bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction) override; + bool NodeAtPoint(HitTestResult&, + const HitTestLocation& location_in_container, + const LayoutPoint& accumulated_offset, + HitTestAction) override; // Called during layout to update the local transform. virtual SVGTransformChange CalculateLocalTransform();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc index 007629c..4ef7808b 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
@@ -124,21 +124,33 @@ SVGResourcesCache::ClientLayoutChanged(*this); } -bool LayoutSVGForeignObject::NodeAtFloatPoint(HitTestResult& result, - const FloatPoint& point_in_parent, - HitTestAction hit_test_action) { +bool LayoutSVGForeignObject::NodeAtPointFromSVG( + HitTestResult& result, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, + HitTestAction) { + DCHECK_EQ(accumulated_offset, LayoutPoint()); AffineTransform local_transform = LocalSVGTransform(); if (!local_transform.IsInvertible()) return false; - FloatPoint local_point = local_transform.Inverse().MapPoint(point_in_parent); - LayoutPoint point_in_foreign_object(local_point); + AffineTransform inverse = local_transform.Inverse(); + base::Optional<HitTestLocation> local_location; + if (location_in_parent.IsRectBasedTest()) { + local_location.emplace( + inverse.MapPoint(location_in_parent.TransformedPoint()), + inverse.MapQuad(location_in_parent.TransformedRect())); + } else { + local_location.emplace( + (inverse.MapPoint(location_in_parent.TransformedPoint()))); + } + // |local_point| already includes the offset of the <foreignObject> element, // but PaintLayer::HitTestLayer assumes it has not been. - point_in_foreign_object.MoveBy(-Layer()->LayoutBoxLocation()); - HitTestLocation location(point_in_foreign_object); - HitTestResult layer_result(result.GetHitTestRequest(), location); - bool retval = Layer()->HitTest(location, layer_result, + HitTestLocation local_without_offset( + *local_location, -ToLayoutSize(Layer()->LayoutBoxLocation())); + HitTestResult layer_result(result.GetHitTestRequest(), local_without_offset); + bool retval = Layer()->HitTest(local_without_offset, layer_result, LayoutRect(LayoutRect::InfiniteIntRect())); // Preserve the "point in inner node frame" from the original request,
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h index 084e043..c302e8f 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h
@@ -65,9 +65,15 @@ const LayoutPoint&, HitTestAction) override; - bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction) override; + // A method to call when recursively hit testing from an SVG parent. + // Since LayoutSVGRoot has a PaintLayer always, this will cause a + // trampoline through PaintLayer::HitTest and back to a call to NodeAtPoint + // on this object. This is why there are two methods. + bool NodeAtPointFromSVG(HitTestResult&, + const HitTestLocation&, + const LayoutPoint&, + HitTestAction); + bool IsOfType(LayoutObjectType type) const override { return type == kLayoutObjectSVGForeignObject || LayoutSVGBlock::IsOfType(type);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc index fe6dd083..8ba8bf6b 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc
@@ -68,6 +68,17 @@ EXPECT_EQ(div.GetNode(), HitTest(349, 249)); EXPECT_EQ(foreign, HitTest(350, 250)); EXPECT_EQ(svg, HitTest(450, 350)); + + // Rect based hit testing + auto results = RectBasedHitTest(LayoutRect(0, 0, 300, 300)); + int count = 0; + EXPECT_EQ(3u, results.size()); + for (auto result : results) { + Node* node = result.Get(); + if (node == svg || node == div.GetNode() || node == foreign) + count++; + } + EXPECT_EQ(3, count); } TEST_F(LayoutSVGForeignObjectTest, IframeInForeignObject) { @@ -75,7 +86,7 @@ <style>body { margin: 0 }</style> <svg id='svg' style='width: 500px; height: 450px'> <foreignObject id='foreign' x='100' y='100' width='300' height='250'> - <iframe style='border: none; margin: 30px; + <iframe id=iframe style='border: none; margin: 30px; width: 240px; height: 190px'></iframe> </foreignObject> </svg> @@ -92,6 +103,7 @@ const auto& svg = *GetDocument().getElementById("svg"); const auto& foreign = *GetDocument().getElementById("foreign"); const auto& foreign_object = *GetLayoutObjectByElementId("foreign"); + const auto& iframe = *GetDocument().getElementById("iframe"); const auto& div = *ChildDocument().getElementById("div")->GetLayoutObject(); EXPECT_EQ(FloatRect(100, 100, 300, 250), foreign_object.ObjectBoundingBox()); @@ -136,6 +148,18 @@ EXPECT_EQ(ChildDocument().documentElement(), HitTest(369, 319)); EXPECT_EQ(foreign, HitTest(370, 320)); EXPECT_EQ(svg, HitTest(450, 400)); + + // Rect based hit testing + auto results = RectBasedHitTest(LayoutRect(0, 0, 300, 300)); + int count = 0; + EXPECT_EQ(7u, results.size()); + for (auto result : results) { + Node* node = result.Get(); + if (node == svg || node == div.GetNode() || node == foreign || + node == iframe) + count++; + } + EXPECT_EQ(4, count); } TEST_F(LayoutSVGForeignObjectTest, HitTestZoomedForeignObject) { @@ -184,6 +208,17 @@ EXPECT_EQ(svg, HitTest(20, 20)); EXPECT_EQ(foreign, HitTest(280, 280)); EXPECT_EQ(div, HitTest(290, 290)); + + // Rect based hit testing + auto results = RectBasedHitTest(LayoutRect(0, 0, 300, 300)); + int count = 0; + EXPECT_EQ(3u, results.size()); + for (auto result : results) { + Node* node = result.Get(); + if (node == svg || node == &div || node == foreign) + count++; + } + EXPECT_EQ(3, count); } TEST_F(LayoutSVGForeignObjectTest, HitTestViewBoxForeignObject) {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc index 45e5419..40afa1ffd 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc
@@ -43,9 +43,10 @@ ClearNeedsLayout(); } -bool LayoutSVGHiddenContainer::NodeAtFloatPoint(HitTestResult&, - const FloatPoint&, - HitTestAction) { +bool LayoutSVGHiddenContainer::NodeAtPoint(HitTestResult&, + const HitTestLocation&, + const LayoutPoint&, + HitTestAction) { return false; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h index 961dc03..52d9d9f 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h
@@ -55,9 +55,10 @@ void AbsoluteQuads(Vector<FloatQuad>&, MapCoordinatesFlags mode = 0) const final {} - bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction) final; + bool NodeAtPoint(HitTestResult&, + const HitTestLocation& location_in_container, + const LayoutPoint& accumulated_offset, + HitTestAction) final; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc index 0bd47f43..2c52cf4 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
@@ -166,9 +166,11 @@ SVGImagePainter(*this).Paint(paint_info); } -bool LayoutSVGImage::NodeAtFloatPoint(HitTestResult& result, - const FloatPoint& point_in_parent, - HitTestAction hit_test_action) { +bool LayoutSVGImage::NodeAtPoint(HitTestResult& result, + const HitTestLocation& location_in_container, + const LayoutPoint& accumulated_offset, + HitTestAction hit_test_action) { + DCHECK(accumulated_offset == LayoutPoint()); // We only draw in the forground phase, so we only hit-test then. if (hit_test_action != kHitTestForeground) return false; @@ -180,17 +182,18 @@ if (hit_rules.require_visible && style.Visibility() != EVisibility::kVisible) return false; - FloatPoint local_point; + HitTestLocation local_location; if (!SVGLayoutSupport::TransformToUserSpaceAndCheckClipping( - *this, LocalToSVGParentTransform(), point_in_parent, local_point)) + *this, LocalToSVGParentTransform(), location_in_container, + local_location)) return false; if (hit_rules.can_hit_fill || hit_rules.can_hit_bounding_box) { - if (object_bounding_box_.Contains(local_point)) { - const LayoutPoint& local_layout_point = LayoutPoint(local_point); - HitTestLocation location(local_layout_point); + if (local_location.Intersects(object_bounding_box_)) { + const LayoutPoint& local_layout_point = + LayoutPoint(local_location.TransformedPoint()); UpdateHitTestResult(result, local_layout_point); - if (result.AddNodeToListBasedTestResult(GetElement(), location) == + if (result.AddNodeToListBasedTestResult(GetElement(), local_location) == kStopHitTesting) return true; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_image.h b/third_party/blink/renderer/core/layout/svg/layout_svg_image.h index 15ed057..e6b4ed3 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_image.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
@@ -67,9 +67,10 @@ bool UpdateBoundingBox(); - bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction) override; + bool NodeAtPoint(HitTestResult&, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, + HitTestAction) override; AffineTransform LocalSVGTransform() const override { return local_transform_;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc index a0e790fc..f988fbf 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -158,12 +158,4 @@ SVGResourcesCache::ClientStyleChanged(*this, diff, StyleRef()); } -bool LayoutSVGModelObject::NodeAtPoint(HitTestResult&, - const HitTestLocation&, - const LayoutPoint&, - HitTestAction) { - NOTREACHED(); - return false; -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h index bd663b8..b28f725 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
@@ -95,11 +95,6 @@ // LayoutSVGModelObject subclasses should use GetElement() instead. void GetNode() const = delete; - // This method should never be called, SVG uses a different nodeAtPoint method - bool NodeAtPoint(HitTestResult&, - const HitTestLocation& location_in_container, - const LayoutPoint& accumulated_offset, - HitTestAction) final; void AddOutlineRects(Vector<LayoutRect>&, const LayoutPoint& additional_offset, NGOutlineType) const final;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc index 4353b24..0cc835c0 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc
@@ -252,14 +252,15 @@ Traversal<SVGElement>::ChildrenOf(*GetElement())) { if (!ContributesToClip(child_element)) continue; - HitTestLocation location((LayoutPoint())); + HitTestLocation location(point); HitTestResult result(HitTestRequest::kSVGClipContent, location); LayoutObject* layout_object = child_element.GetLayoutObject(); DCHECK(!layout_object->IsBoxModelObject() || !ToLayoutBoxModelObject(layout_object)->HasSelfPaintingLayer()); - if (layout_object->NodeAtFloatPoint(result, point, kHitTestForeground)) + if (layout_object->NodeAtPoint(result, location, LayoutPoint(), + kHitTestForeground)) return true; } return false;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc index 49519a4..504e451 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/layout/layout_analyzer.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" #include "third_party/blink/renderer/core/layout/layout_view.h" +#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_text.h" #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" @@ -509,9 +510,10 @@ const HitTestLocation& location_in_container, const LayoutPoint& accumulated_offset, HitTestAction hit_test_action) { - LayoutPoint point_in_parent = - location_in_container.Point() - ToLayoutSize(accumulated_offset); - LayoutPoint point_in_border_box = point_in_parent - ToLayoutSize(Location()); + LayoutPoint adjusted_location = accumulated_offset + Location(); + + HitTestLocation local_border_box_location(location_in_container, + ToLayoutSize(-adjusted_location)); // Only test SVG content if the point is in our content box, or in case we // don't clip to the viewport, the visual overflow rect. @@ -519,23 +521,44 @@ // supported by nodeAtFloatPoint. bool skip_children = (result.GetHitTestRequest().GetStopNode() == this); if (!skip_children && - (PhysicalContentBoxRect().Contains(point_in_border_box) || + (local_border_box_location.Intersects(PhysicalContentBoxRect()) || (!ShouldApplyViewportClip() && - VisualOverflowRect().Contains(point_in_border_box)))) { - const AffineTransform& local_to_parent_transform = - LocalToSVGParentTransform(); - if (local_to_parent_transform.IsInvertible()) { - FloatPoint local_point = local_to_parent_transform.Inverse().MapPoint( - FloatPoint(point_in_parent)); + local_border_box_location.Intersects(VisualOverflowRect())))) { + const AffineTransform& local_to_border_box_transform = + LocalToBorderBoxTransform(); + if (local_to_border_box_transform.IsInvertible()) { + FloatPoint local_point = local_to_border_box_transform.Inverse().MapPoint( + local_border_box_location.TransformedPoint()); + + base::Optional<HitTestLocation> local_location; + if (location_in_container.IsRectBasedTest()) { + FloatQuad quad_in_container = + local_border_box_location.TransformedRect(); + + local_location.emplace( + local_point, + local_to_border_box_transform.Inverse().MapQuad(quad_in_container)); + } else { + local_location.emplace(local_point); + } for (LayoutObject* child = LastChild(); child; child = child->PreviousSibling()) { - // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet. - if (child->NodeAtFloatPoint(result, local_point, hit_test_action)) { - UpdateHitTestResult(result, point_in_border_box); + bool found = false; + if (child->IsSVGForeignObject()) { + found = ToLayoutSVGForeignObject(child)->NodeAtPointFromSVG( + result, *local_location, LayoutPoint(), hit_test_action); + } else { + found = child->NodeAtPoint(result, *local_location, LayoutPoint(), + hit_test_action); + } + + if (found) { + UpdateHitTestResult(result, local_border_box_location.Point()); if (result.AddNodeToListBasedTestResult( - child->GetNode(), location_in_container) == kStopHitTesting) + child->GetNode(), location_in_container) == kStopHitTesting) { return true; + } } } } @@ -556,7 +579,7 @@ // detect these hits anymore. LayoutRect bounds_rect(accumulated_offset + Location(), Size()); if (location_in_container.Intersects(bounds_rect)) { - UpdateHitTestResult(result, point_in_border_box); + UpdateHitTestResult(result, local_border_box_location.Point()); if (result.AddNodeToListBasedTestResult(GetNode(), location_in_container, bounds_rect) == kStopHitTesting) return true;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc index c336a13..e310f9c 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root_test.cc
@@ -132,4 +132,33 @@ EXPECT_FALSE(root.PaintedOutputOfObjectHasNoEffectRegardlessOfSize()); } +TEST_F(LayoutSVGRootTest, RectBasedHitTestPartialOverlap) { + SetBodyInnerHTML(R"HTML( + <style>body { margin: 0 }</style> + <svg id='svg' style='width: 300px; height: 300px; position: relative; + top: 200px; left: 200px;'> + </svg> + )HTML"); + + const auto& svg = *GetDocument().getElementById("svg"); + const auto& body = *GetDocument().body(); + + // This is the center of the rect-based hit test below. + EXPECT_EQ(body, *HitTest(150, 150)); + + EXPECT_EQ(svg, *HitTest(200, 200)); + + // The center of this rect does not overlap the SVG element, but the + // rect itself does. + auto results = RectBasedHitTest(LayoutRect(0, 0, 300, 300)); + int count = 0; + EXPECT_EQ(2u, results.size()); + for (auto result : results) { + Node* node = result.Get(); + if (node == svg || node == body) + count++; + } + EXPECT_EQ(2, count); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc index 931ccd8..ec54c4a9 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -347,27 +347,29 @@ SVGShapePainter(*this).Paint(paint_info); } -bool LayoutSVGShape::NodeAtFloatPoint(HitTestResult& result, - const FloatPoint& point_in_parent, - HitTestAction hit_test_action) { +bool LayoutSVGShape::NodeAtPoint(HitTestResult& result, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, + HitTestAction hit_test_action) { + DCHECK_EQ(accumulated_offset, LayoutPoint()); // We only draw in the foreground phase, so we only hit-test then. if (hit_test_action != kHitTestForeground) return false; - FloatPoint local_point; + HitTestLocation local_location; if (!SVGLayoutSupport::TransformToUserSpaceAndCheckClipping( - *this, LocalToSVGParentTransform(), point_in_parent, local_point)) + *this, LocalToSVGParentTransform(), location_in_parent, + local_location)) return false; PointerEventsHitRules hit_rules( PointerEventsHitRules::SVG_GEOMETRY_HITTESTING, result.GetHitTestRequest(), StyleRef().PointerEvents()); - if (NodeAtFloatPointInternal(result.GetHitTestRequest(), local_point, - hit_rules)) { - const LayoutPoint& local_layout_point = LayoutPoint(local_point); + if (NodeAtPointInternal(result.GetHitTestRequest(), local_location, + hit_rules)) { + const LayoutPoint local_layout_point(local_location.TransformedPoint()); UpdateHitTestResult(result, local_layout_point); - HitTestLocation location(local_layout_point); - if (result.AddNodeToListBasedTestResult(GetElement(), location) == + if (result.AddNodeToListBasedTestResult(GetElement(), local_location) == kStopHitTesting) return true; } @@ -375,26 +377,30 @@ return false; } -bool LayoutSVGShape::NodeAtFloatPointInternal(const HitTestRequest& request, - const FloatPoint& local_point, - PointerEventsHitRules hit_rules) { +bool LayoutSVGShape::NodeAtPointInternal(const HitTestRequest& request, + const HitTestLocation& local_location, + PointerEventsHitRules hit_rules) { const ComputedStyle& style = StyleRef(); if (hit_rules.require_visible && style.Visibility() != EVisibility::kVisible) return false; if (hit_rules.can_hit_bounding_box && - ObjectBoundingBox().Contains(local_point)) + local_location.Intersects(ObjectBoundingBox())) return true; + + // TODO(chrishtr): support rect-based intersections in the cases below. const SVGComputedStyle& svg_style = style.SvgStyle(); if (hit_rules.can_hit_stroke && (svg_style.HasStroke() || !hit_rules.require_stroke) && - StrokeContains(local_point, hit_rules.require_stroke)) + StrokeContains(local_location.TransformedPoint(), + hit_rules.require_stroke)) return true; WindRule fill_rule = svg_style.FillRule(); if (request.SvgClipContent()) fill_rule = svg_style.ClipRule(); if (hit_rules.can_hit_fill && (svg_style.HasFill() || !hit_rules.require_fill) && - FillContains(local_point, hit_rules.require_fill, fill_rule)) + FillContains(local_location.TransformedPoint(), hit_rules.require_fill, + fill_rule)) return true; return false; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h index c291ae4..098fe31 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
@@ -65,9 +65,9 @@ void SetNeedsBoundariesUpdate() final { needs_boundaries_update_ = true; } void SetNeedsTransformUpdate() final { needs_transform_update_ = true; } - bool NodeAtFloatPointInternal(const HitTestRequest&, - const FloatPoint&, - PointerEventsHitRules); + bool NodeAtPointInternal(const HitTestRequest&, + const HitTestLocation&, + PointerEventsHitRules); Path& GetPath() const { DCHECK(path_); @@ -157,9 +157,10 @@ void UpdateLayout() final; void Paint(const PaintInfo&) const final; - bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction) final; + bool NodeAtPoint(HitTestResult&, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, + HitTestAction) override; FloatRect StrokeBoundingBox() const final { return stroke_bounding_box_; } FloatRect CalculateObjectBoundingBox() const;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc index dbff4629..891b4651 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
@@ -305,31 +305,33 @@ return box; } -bool LayoutSVGText::NodeAtFloatPoint(HitTestResult& result, - const FloatPoint& point_in_parent, - HitTestAction hit_test_action) { +bool LayoutSVGText::NodeAtPoint(HitTestResult& result, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, + HitTestAction hit_test_action) { + DCHECK_EQ(accumulated_offset, LayoutPoint()); // We only draw in the foreground phase, so we only hit-test then. if (hit_test_action != kHitTestForeground) return false; - FloatPoint local_point; + HitTestLocation local_location; if (!SVGLayoutSupport::TransformToUserSpaceAndCheckClipping( - *this, LocalToSVGParentTransform(), point_in_parent, local_point)) + *this, LocalToSVGParentTransform(), location_in_parent, + local_location)) return false; - HitTestLocation hit_test_location(local_point); - if (LayoutBlock::NodeAtPoint(result, hit_test_location, LayoutPoint(), + if (LayoutBlock::NodeAtPoint(result, local_location, accumulated_offset, hit_test_action)) return true; // Consider the bounding box if requested. if (StyleRef().PointerEvents() == EPointerEvents::kBoundingBox) { if (IsObjectBoundingBoxValid() && - ObjectBoundingBox().Contains(local_point)) { - const LayoutPoint& local_layout_point = LayoutPoint(local_point); + local_location.Intersects(ObjectBoundingBox())) { + const LayoutPoint& local_layout_point = + LayoutPoint(local_location.TransformedPoint()); UpdateHitTestResult(result, local_layout_point); - HitTestLocation location(local_layout_point); - if (result.AddNodeToListBasedTestResult(GetElement(), location) == + if (result.AddNodeToListBasedTestResult(GetElement(), local_location) == kStopHitTesting) return true; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text.h b/third_party/blink/renderer/core/layout/svg/layout_svg_text.h index 86d88bbe..ce40fa6 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_text.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
@@ -72,9 +72,10 @@ } void Paint(const PaintInfo&) const override; - bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction) override; + bool NodeAtPoint(HitTestResult&, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, + HitTestAction) override; PositionWithAffinity PositionForPoint(const LayoutPoint&) const override; void UpdateLayout() override;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text_test.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text_test.cc new file mode 100644 index 0000000..150e6ff --- /dev/null +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text_test.cc
@@ -0,0 +1,41 @@ +// Copyright 2018 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 "third_party/blink/renderer/core/layout/layout_geometry_map.h" +#include "third_party/blink/renderer/core/paint/paint_layer.h" +#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" + +namespace blink { + +class LayoutSVGTextTest : public RenderingTest { + public: + LayoutSVGTextTest() : RenderingTest(SingleChildLocalFrameClient::Create()) {} +}; + +TEST_F(LayoutSVGTextTest, RectBasedHitTest) { + SetBodyInnerHTML(R"HTML( + <style>body { margin: 0 }</style> + <svg id=svg width="300" height="300"> + <a id="link"> + <text id="text" y="20">text</text> + </a> + </svg> + )HTML"); + + const auto& svg = *GetDocument().getElementById("svg"); + const auto& text = *GetDocument().getElementById("text")->firstChild(); + + // Rect based hit testing + auto results = RectBasedHitTest(LayoutRect(0, 0, 300, 300)); + int count = 0; + EXPECT_EQ(2u, results.size()); + for (auto result : results) { + Node* node = result.Get(); + if (node == svg || node == text) + count++; + } + EXPECT_EQ(2, count); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc index e03a672e..99fd0f0 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
@@ -75,16 +75,18 @@ return change_detector.ComputeChange(local_to_parent_transform_); } -bool LayoutSVGViewportContainer::NodeAtFloatPoint( +bool LayoutSVGViewportContainer::NodeAtPoint( HitTestResult& result, - const FloatPoint& point_in_parent, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, HitTestAction action) { // Respect the viewport clip which is in parent coordinates. if (SVGLayoutSupport::IsOverflowHidden(*this)) { - if (!viewport_.Contains(point_in_parent)) + if (!location_in_parent.Intersects(viewport_)) return false; } - return LayoutSVGContainer::NodeAtFloatPoint(result, point_in_parent, action); + return LayoutSVGContainer::NodeAtPoint(result, location_in_parent, + accumulated_offset, action); } void LayoutSVGViewportContainer::StyleDidChange(
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h index 8a78177..40bc375 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h
@@ -56,9 +56,10 @@ SVGTransformChange CalculateLocalTransform() override; - bool NodeAtFloatPoint(HitTestResult&, - const FloatPoint& point_in_parent, - HitTestAction) override; + bool NodeAtPoint(HitTestResult&, + const HitTestLocation& location_in_parent, + const LayoutPoint& accumulated_offset, + HitTestAction) final; void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
diff --git a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc index 6965c06..0c9e8cf 100644 --- a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc +++ b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
@@ -308,10 +308,9 @@ DCHECK(line_layout_item.ScalingFactor()); float baseline = font_data->GetFontMetrics().FloatAscent() / line_layout_item.ScalingFactor(); - FloatPoint float_location = FloatPoint(location_in_container.Point()); for (const SVGTextFragment& fragment : text_fragments_) { FloatQuad fragment_quad = fragment.BoundingQuad(baseline); - if (fragment_quad.ContainsPoint(float_location)) { + if (location_in_container.Intersects(fragment_quad)) { line_layout_item.UpdateHitTestResult( result, location_in_container.Point() - ToLayoutSize(accumulated_offset));
diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc b/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc index 02b022f..3b27c60 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc +++ b/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc
@@ -432,12 +432,21 @@ bool SVGLayoutSupport::TransformToUserSpaceAndCheckClipping( const LayoutObject& object, const AffineTransform& local_transform, - const FloatPoint& point_in_parent, - FloatPoint& local_point) { + const HitTestLocation& location_in_parent, + HitTestLocation& local_location) { if (!local_transform.IsInvertible()) return false; - local_point = local_transform.Inverse().MapPoint(point_in_parent); - return PointInClippingArea(object, local_point); + const AffineTransform inverse = local_transform.Inverse(); + if (location_in_parent.IsRectBasedTest()) { + local_location = + HitTestLocation(inverse.MapPoint(location_in_parent.TransformedPoint()), + inverse.MapQuad(location_in_parent.TransformedRect())); + } else { + local_location = HitTestLocation( + inverse.MapPoint(location_in_parent.TransformedPoint())); + } + + return PointInClippingArea(object, local_location.TransformedPoint()); } DashArray SVGLayoutSupport::ResolveSVGDashArray(
diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_support.h b/third_party/blink/renderer/core/layout/svg/svg_layout_support.h index 98abb7c..d4f11ef1 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_layout_support.h +++ b/third_party/blink/renderer/core/layout/svg/svg_layout_support.h
@@ -82,8 +82,8 @@ static bool TransformToUserSpaceAndCheckClipping( const LayoutObject&, const AffineTransform& local_transform, - const FloatPoint& point_in_parent, - FloatPoint& local_point); + const HitTestLocation& location_in_parent, + HitTestLocation& local_location); static void ComputeContainerBoundingBoxes(const LayoutObject* container, FloatRect& object_bounding_box,
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc index c2a44df0..8f8ce7a 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc
@@ -429,6 +429,7 @@ DetachScrollbarLayer(scrollbar_graphics_layer); return; } + scrollbar_layer_group->scrollbar_layer->SetScrollElementId( scrolling_layer->element_id()); scrollbar_graphics_layer->SetContentsToCcLayer( @@ -475,6 +476,7 @@ DetachScrollbarLayer(scrollbar_graphics_layer); scrollbar_graphics_layer->CcLayer()->AddMainThreadScrollingReasons( MainThreadScrollingReason::kCustomScrollbarScrolling); + scrollbar_graphics_layer->CcLayer()->SetIsScrollbar(true); return; }
diff --git a/third_party/blink/renderer/core/svg/svg_geometry_element.cc b/third_party/blink/renderer/core/svg/svg_geometry_element.cc index 78b2eabe..d5f452f 100644 --- a/third_party/blink/renderer/core/svg/svg_geometry_element.cc +++ b/third_party/blink/renderer/core/svg/svg_geometry_element.cc
@@ -97,8 +97,9 @@ PointerEventsHitRules::SVG_GEOMETRY_HITTESTING, request, GetLayoutObject()->StyleRef().PointerEvents()); hit_rules.can_hit_stroke = false; + HitTestLocation location(point->Target()->Value()); return ToLayoutSVGShape(GetLayoutObject()) - ->NodeAtFloatPointInternal(request, point->Target()->Value(), hit_rules); + ->NodeAtPointInternal(request, location, hit_rules); } bool SVGGeometryElement::isPointInStroke(SVGPointTearOff* point) const { @@ -114,8 +115,9 @@ PointerEventsHitRules::SVG_GEOMETRY_HITTESTING, request, GetLayoutObject()->StyleRef().PointerEvents()); hit_rules.can_hit_fill = false; + HitTestLocation location(point->Target()->Value()); return ToLayoutSVGShape(GetLayoutObject()) - ->NodeAtFloatPointInternal(request, point->Target()->Value(), hit_rules); + ->NodeAtPointInternal(request, location, hit_rules); } Path SVGGeometryElement::ToClipPath() const {
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.cc b/third_party/blink/renderer/core/testing/core_unit_test_helper.cc index 19983aa6..b85216b 100644 --- a/third_party/blink/renderer/core/testing/core_unit_test_helper.cc +++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.cc
@@ -52,6 +52,17 @@ return result.InnerNode(); } +HitTestResult::NodeSet RenderingTest::RectBasedHitTest(LayoutRect rect) { + HitTestLocation location(rect); + HitTestResult result( + HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive | + HitTestRequest::kAllowChildFrameContent | + HitTestRequest::kListBased), + location); + GetLayoutView().HitTest(location, result); + return result.ListBasedTestResult(); +} + void RenderingTest::SetUp() { Page::PageClients page_clients; FillWithEmptyClients(page_clients);
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.h b/third_party/blink/renderer/core/testing/core_unit_test_helper.h index 1708ced4..2f2c44d 100644 --- a/third_party/blink/renderer/core/testing/core_unit_test_helper.h +++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
@@ -79,6 +79,7 @@ explicit RenderingTest(LocalFrameClient* = nullptr); const Node* HitTest(int x, int y); + HitTestResult::NodeSet RectBasedHitTest(LayoutRect rect); protected: void SetUp() override;
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc index 0bf6695a..500e8a6 100644 --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
@@ -14,7 +14,6 @@ #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/frame/use_counter.h" -#include "third_party/blink/renderer/core/loader/mixed_content_checker.h" #include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h" #include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h" #include "third_party/blink/renderer/modules/background_fetch/background_fetch_options.h" @@ -84,14 +83,6 @@ !request_url.ProtocolIs(WTF::g_https_atom); } -bool ShouldBlockMixedContent(ExecutionContext* execution_context, - const KURL& request_url) { - // TODO(crbug.com/757441): Using MixedContentChecker::ShouldBlockFetch would - // log better metrics. - return MixedContentChecker::IsMixedContent( - execution_context->GetSecurityOrigin(), request_url); -} - bool ShouldBlockDanglingMarkup(const KURL& request_url) { // "If request's url's potentially-dangling-markup flag is set, and request's // url's scheme is an HTTP(S) scheme, then set response to a network error." @@ -201,14 +192,6 @@ // the Download Service in the browser process can use it without having to // spin up a renderer process. for (const WebServiceWorkerRequest& web_request : web_requests) { - // TODO(crbug.com/757441): Decide whether to support upgrading requests to - // potentially secure URLs (https://w3c.github.io/webappsec-upgrade- - // insecure-requests/) and/or HSTS rewriting. Since this is a new API only - // exposed on Secure Contexts, and the Mixed Content check below will block - // any requests to insecure contexts, it'd be cleanest not to support it. - // Depends how closely compatible with Fetch we want to be. If support is - // added, make sure to report CSP violations before upgrading the URL. - KURL request_url(web_request.Url()); if (!request_url.IsValid()) { @@ -225,7 +208,7 @@ } // Check this before mixed content, so that if mixed content is blocked by - // CSP they get a CSP warning rather than a mixed content warning. + // CSP they get a CSP warning rather than a mixed content failure. if (ShouldBlockDueToCSP(execution_context, request_url)) { return RejectWithTypeError(script_state, request_url, "it violates the Content Security Policy"); @@ -247,13 +230,6 @@ "for loopback IPs"); } - // Blocking fetches due to mixed content is done after Content Security - // Policy to prioritize warnings caused by the latter. - if (ShouldBlockMixedContent(execution_context, request_url)) { - return RejectWithTypeError(script_state, request_url, - "it is insecure; use https instead"); - } - if (ShouldBlockDanglingMarkup(request_url)) { return RejectWithTypeError(script_state, request_url, "it contains dangling markup");
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.idl b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.idl index 12e59cc..d62ceda 100644 --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.idl +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.idl
@@ -8,7 +8,7 @@ Exposed=(Window,Worker), RuntimeEnabled=BackgroundFetch ] interface BackgroundFetchManager { - [CallWith=ScriptState, RaisesException] Promise<BackgroundFetchRegistration> fetch(DOMString id, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options); - [CallWith=ScriptState] Promise<BackgroundFetchRegistration?> get(DOMString id); - [CallWith=ScriptState] Promise<FrozenArray<DOMString>> getIds(); + [CallWith=ScriptState, RaisesException, MeasureAs=BackgroundFetchManagerFetch] Promise<BackgroundFetchRegistration> fetch(DOMString id, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options); + [CallWith=ScriptState, MeasureAs=BackgroundFetchManagerGet] Promise<BackgroundFetchRegistration?> get(DOMString id); + [CallWith=ScriptState, MeasureAs=BackgroundFetchManagerGetIds] Promise<FrozenArray<DOMString>> getIds(); };
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.idl b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.idl index 2e389e8a..e277b8e 100644 --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.idl +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.idl
@@ -35,10 +35,10 @@ attribute EventHandler onprogress; - [CallWith=ScriptState] Promise<boolean> abort(); + [CallWith=ScriptState, MeasureAs=BackgroundFetchRegistrationAbort] Promise<boolean> abort(); // TODO(crbug.com/875201): Change to (Window,Worker) once we support // match() and matchAll() for active fetches. - [CallWith=ScriptState, Exposed=ServiceWorker, RaisesException] Promise<BackgroundFetchRecord> match(RequestInfo request, optional CacheQueryOptions options); - [CallWith=ScriptState, Exposed=ServiceWorker, RaisesException] Promise<sequence<BackgroundFetchRecord>> matchAll(optional RequestInfo request, optional CacheQueryOptions options); + [CallWith=ScriptState, Exposed=ServiceWorker, RaisesException, MeasureAs=BackgroundFetchRegistrationMatch] Promise<BackgroundFetchRecord> match(RequestInfo request, optional CacheQueryOptions options); + [CallWith=ScriptState, Exposed=ServiceWorker, RaisesException, MeasureAs=BackgroundFetchRegistrationMatchAll] Promise<sequence<BackgroundFetchRecord>> matchAll(optional RequestInfo request, optional CacheQueryOptions options); };
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index 928eb865..c598bc8 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -302,6 +302,7 @@ "speech/speech_recognition_result_list.idl", "speech/speech_synthesis.idl", "speech/speech_synthesis_event.idl", + "speech/speech_synthesis_error_event.idl", "speech/speech_synthesis_utterance.idl", "speech/speech_synthesis_voice.idl", "storage/storage.idl", @@ -477,6 +478,8 @@ "app_banner/before_install_prompt_event_init.idl", "background_fetch/background_fetch_event_init.idl", "background_fetch/background_fetch_options.idl", + "speech/speech_synthesis_error_event_init.idl", + "speech/speech_synthesis_event_init.idl", "background_fetch/background_fetch_ui_options.idl", "background_sync/sync_event_init.idl", "bluetooth/bluetooth_le_scan_filter_init.idl",
diff --git a/third_party/blink/renderer/modules/speech/BUILD.gn b/third_party/blink/renderer/modules/speech/BUILD.gn index df1bbde..5597ba5fa 100644 --- a/third_party/blink/renderer/modules/speech/BUILD.gn +++ b/third_party/blink/renderer/modules/speech/BUILD.gn
@@ -30,6 +30,8 @@ "speech_recognition_result_list.h", "speech_synthesis.cc", "speech_synthesis.h", + "speech_synthesis_error_event.cc", + "speech_synthesis_error_event.h", "speech_synthesis_event.cc", "speech_synthesis_event.h", "speech_synthesis_utterance.cc",
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.cc b/third_party/blink/renderer/modules/speech/speech_synthesis.cc index b873d8e..d07e54d5 100644 --- a/third_party/blink/renderer/modules/speech/speech_synthesis.cc +++ b/third_party/blink/renderer/modules/speech/speech_synthesis.cc
@@ -32,7 +32,10 @@ #include "third_party/blink/renderer/core/html/media/autoplay_policy.h" #include "third_party/blink/renderer/core/timing/dom_window_performance.h" #include "third_party/blink/renderer/core/timing/performance.h" +#include "third_party/blink/renderer/modules/speech/speech_synthesis_error_event.h" +#include "third_party/blink/renderer/modules/speech/speech_synthesis_error_event_init.h" #include "third_party/blink/renderer/modules/speech/speech_synthesis_event.h" +#include "third_party/blink/renderer/modules/speech/speech_synthesis_event_init.h" #include "third_party/blink/renderer/platform/speech/platform_speech_synthesis_voice.h" namespace blink { @@ -158,9 +161,28 @@ if (!GetElapsedTimeMillis(&millis)) return; - double elapsed_time_millis = millis - utterance->StartTime() * 1000.0; - utterance->DispatchEvent(*SpeechSynthesisEvent::Create( - type, utterance, char_index, elapsed_time_millis, name)); + SpeechSynthesisEventInit init; + init.setUtterance(utterance); + init.setCharIndex(char_index); + init.setElapsedTime(millis - (utterance->StartTime() * 1000.0)); + init.setName(name); + utterance->DispatchEvent(*SpeechSynthesisEvent::Create(type, init)); +} + +void SpeechSynthesis::FireErrorEvent(SpeechSynthesisUtterance* utterance, + unsigned long char_index, + const String& error) { + double millis; + if (!GetElapsedTimeMillis(&millis)) + return; + + SpeechSynthesisErrorEventInit init; + init.setUtterance(utterance); + init.setCharIndex(char_index); + init.setElapsedTime(millis - (utterance->StartTime() * 1000.0)); + init.setError(error); + utterance->DispatchEvent( + *SpeechSynthesisErrorEvent::Create(EventTypeNames::error, init)); } void SpeechSynthesis::HandleSpeakingCompleted( @@ -180,8 +202,13 @@ // sent an event on an utterance before it got the message that we // canceled it, and we should always report to the user what actually // happened. - FireEvent(error_occurred ? EventTypeNames::error : EventTypeNames::end, - utterance, 0, String()); + if (error_occurred) { + // TODO(csharrison): Actually pass the correct message. For now just use a + // generic error. + FireErrorEvent(utterance, 0, "synthesis-failed"); + } else { + FireEvent(EventTypeNames::end, utterance, 0, String()); + } // Start the next utterance if we just finished one and one was pending. if (should_start_speaking && !utterance_queue_.IsEmpty())
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.h b/third_party/blink/renderer/modules/speech/speech_synthesis.h index 4b87c237..ff767def 100644 --- a/third_party/blink/renderer/modules/speech/speech_synthesis.h +++ b/third_party/blink/renderer/modules/speech/speech_synthesis.h
@@ -92,6 +92,10 @@ unsigned long char_index, const String& name); + void FireErrorEvent(SpeechSynthesisUtterance*, + unsigned long char_index, + const String& error); + // Returns the utterance at the front of the queue. SpeechSynthesisUtterance* CurrentSpeechUtterance() const;
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.cc b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.cc new file mode 100644 index 0000000..4080142 --- /dev/null +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.cc
@@ -0,0 +1,26 @@ +// Copyright 2018 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 "third_party/blink/renderer/modules/speech/speech_synthesis_error_event.h" + +namespace blink { + +// static +SpeechSynthesisErrorEvent* SpeechSynthesisErrorEvent::Create( + const AtomicString& type, + const SpeechSynthesisErrorEventInit& init) { + return new SpeechSynthesisErrorEvent(type, init); +} + +SpeechSynthesisErrorEvent::SpeechSynthesisErrorEvent( + const AtomicString& type, + const SpeechSynthesisErrorEventInit& init) + : SpeechSynthesisEvent(type, + init.utterance(), + init.charIndex(), + init.elapsedTime(), + init.name()), + error_(init.error()) {} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.h b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.h new file mode 100644 index 0000000..24be960 --- /dev/null +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.h
@@ -0,0 +1,33 @@ +// Copyright 2018 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 THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_SYNTHESIS_ERROR_EVENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_SYNTHESIS_ERROR_EVENT_H_ + +#include "third_party/blink/renderer/modules/event_modules.h" +#include "third_party/blink/renderer/modules/speech/speech_synthesis_error_event_init.h" +#include "third_party/blink/renderer/modules/speech/speech_synthesis_event.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +class SpeechSynthesisErrorEvent : public SpeechSynthesisEvent { + DEFINE_WRAPPERTYPEINFO(); + + public: + static SpeechSynthesisErrorEvent* Create( + const AtomicString& type, + const SpeechSynthesisErrorEventInit& init); + + const String error() const { return error_; } + + private: + SpeechSynthesisErrorEvent(const AtomicString& type, + const SpeechSynthesisErrorEventInit& init); + const String error_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_SYNTHESIS_ERROR_EVENT_H_
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.idl b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.idl new file mode 100644 index 0000000..03ba7d7 --- /dev/null +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event.idl
@@ -0,0 +1,28 @@ +// Copyright 2018 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. + +// https://w3c.github.io/speech-api/#enumdef-speechsynthesiserrorcode +enum SpeechSynthesisErrorCode { + "canceled", + "interrupted", + "audio-busy", + "audio-hardware", + "network", + "synthesis-unavailable", + "synthesis-failed", + "language-unavailable", + "voice-unavailable", + "text-too-long", + "invalid-argument", + "not-allowed", +}; + +// https://w3c.github.io/speech-api/#enumdef-speechsynthesiserrorcode +[ + Exposed=Window, + Constructor(DOMString type, SpeechSynthesisErrorEventInit eventInitDict), + RuntimeEnabled=ScriptedSpeech +] interface SpeechSynthesisErrorEvent : SpeechSynthesisEvent { + readonly attribute SpeechSynthesisErrorCode error; +};
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_error_event_init.idl b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event_init.idl new file mode 100644 index 0000000..bb22c8c7 --- /dev/null +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_error_event_init.idl
@@ -0,0 +1,7 @@ +// Copyright 2018 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. + +dictionary SpeechSynthesisErrorEventInit : SpeechSynthesisEventInit { + required SpeechSynthesisErrorCode error; +};
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc b/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc index d8e51cd..6e0ab68 100644 --- a/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event.cc
@@ -27,22 +27,13 @@ namespace blink { -SpeechSynthesisEvent* SpeechSynthesisEvent::Create() { - return new SpeechSynthesisEvent; -} - SpeechSynthesisEvent* SpeechSynthesisEvent::Create( const AtomicString& type, - SpeechSynthesisUtterance* utterance, - unsigned char_index, - float elapsed_time, - const String& name) { - return new SpeechSynthesisEvent(type, utterance, char_index, elapsed_time, - name); + const SpeechSynthesisEventInit& init) { + return new SpeechSynthesisEvent(type, init.utterance(), init.charIndex(), + init.elapsedTime(), init.name()); } -SpeechSynthesisEvent::SpeechSynthesisEvent() = default; - SpeechSynthesisEvent::SpeechSynthesisEvent(const AtomicString& type, SpeechSynthesisUtterance* utterance, unsigned char_index,
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event.h b/third_party/blink/renderer/modules/speech/speech_synthesis_event.h index 2a55b6f..71fbf3e3 100644 --- a/third_party/blink/renderer/modules/speech/speech_synthesis_event.h +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event.h
@@ -27,20 +27,17 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_SYNTHESIS_EVENT_H_ #include "third_party/blink/renderer/modules/event_modules.h" +#include "third_party/blink/renderer/modules/speech/speech_synthesis_event_init.h" #include "third_party/blink/renderer/modules/speech/speech_synthesis_utterance.h" namespace blink { -class SpeechSynthesisEvent final : public Event { +class SpeechSynthesisEvent : public Event { DEFINE_WRAPPERTYPEINFO(); public: - static SpeechSynthesisEvent* Create(); static SpeechSynthesisEvent* Create(const AtomicString& type, - SpeechSynthesisUtterance*, - unsigned char_index, - float elapsed_time, - const String& name); + const SpeechSynthesisEventInit& init); SpeechSynthesisUtterance* utterance() const { return utterance_; } unsigned charIndex() const { return char_index_; } @@ -53,14 +50,14 @@ void Trace(blink::Visitor*) override; - private: - SpeechSynthesisEvent(); + protected: SpeechSynthesisEvent(const AtomicString& type, SpeechSynthesisUtterance*, unsigned char_index, float elapsed_time, const String& name); + private: Member<SpeechSynthesisUtterance> utterance_; unsigned char_index_; float elapsed_time_;
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl b/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl index 4c35b5d..0f9e01be 100644 --- a/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event.idl
@@ -23,10 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// https://dvcs.w3.org/hg/speech-api/raw-file/tip/webspeechapi.html#tts-section - +// https://w3c.github.io/speech-api/#speechsynthesisevent [ - RuntimeEnabled=ScriptedSpeech + RuntimeEnabled=ScriptedSpeech, + Constructor(DOMString type, SpeechSynthesisEventInit eventInitDict) ] interface SpeechSynthesisEvent : Event { readonly attribute SpeechSynthesisUtterance utterance; readonly attribute unsigned long charIndex;
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis_event_init.idl b/third_party/blink/renderer/modules/speech/speech_synthesis_event_init.idl new file mode 100644 index 0000000..741c408c --- /dev/null +++ b/third_party/blink/renderer/modules/speech/speech_synthesis_event_init.idl
@@ -0,0 +1,10 @@ +// Copyright 2018 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. + +dictionary SpeechSynthesisEventInit : EventInit { + required SpeechSynthesisUtterance utterance; + unsigned long charIndex = 0; + float elapsedTime = 0; + DOMString name = ""; +};
diff --git a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc index 97fc9a2..c5cc628 100644 --- a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc +++ b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
@@ -131,7 +131,7 @@ } else { url::Origin target_origin = url::Origin::Create( GURL(StringUTF8Adaptor(tokens[i]).AsStringPiece())); - if (!target_origin.unique()) + if (!target_origin.opaque()) origins.push_back(target_origin); else if (messages) messages->push_back("Unrecognized origin: '" + tokens[i] + "'.");
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc index 39713be..9ac50f8 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -125,16 +125,20 @@ private: const KURL response_url_; const Time response_time_; + const ResourceType resource_type_; }; CachedMetadataSenderImpl::CachedMetadataSenderImpl(const Resource* resource) : response_url_(resource->GetResponse().Url()), - response_time_(resource->GetResponse().ResponseTime()) { + response_time_(resource->GetResponse().ResponseTime()), + resource_type_(resource->GetType()) { DCHECK(resource->GetResponse().CacheStorageCacheName().IsNull()); } void CachedMetadataSenderImpl::Send(const char* data, size_t size) { - Platform::Current()->CacheMetadata(response_url_, response_time_, data, size); + Platform::Current()->CacheMetadata( + Resource::ResourceTypeToCodeCacheType(resource_type_), response_url_, + response_time_, data, size); } // This is a CachedMetadataSender implementation that does nothing. @@ -1232,6 +1236,20 @@ return InitiatorTypeNameToString(fetch_initiator_name); } +// static +blink::mojom::CodeCacheType Resource::ResourceTypeToCodeCacheType( + ResourceType resource_type) { + // Cacheable WebAssembly modules are fetched, so raw resource type. + if (resource_type == ResourceType::kRaw) + return blink::mojom::CodeCacheType::kWebAssembly; + // Cacheable Javascript is a script or a document resource. Also accept mock + // resources for testing. + DCHECK(resource_type == ResourceType::kScript || + resource_type == ResourceType::kMainResource || + resource_type == ResourceType::kMock); + return blink::mojom::CodeCacheType::kJavascript; +} + bool Resource::ShouldBlockLoadEvent() const { return !link_preload_ && IsLoadEventBlockingResourceType(); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.h b/third_party/blink/renderer/platform/loader/fetch/resource.h index 308592a..ddececf 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -28,6 +28,7 @@ #include "base/auto_reset.h" #include "base/optional.h" #include "base/single_thread_task_runner.h" +#include "third_party/blink/public/mojom/loader/code_cache.mojom-shared.h" #include "third_party/blink/public/platform/web_data_consumer_handle.h" #include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h" @@ -405,6 +406,8 @@ ResourceType, const AtomicString& fetch_initiator_name); + static blink::mojom::CodeCacheType ResourceTypeToCodeCacheType(ResourceType); + class ProhibitAddRemoveClientInScope : public base::AutoReset<bool> { public: ProhibitAddRemoveClientInScope(Resource* resource)
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc index 7215f00b..8b6f57c 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -166,7 +166,8 @@ CodeCacheLoader::FetchCodeCacheCallback callback = base::BindOnce(&ResourceLoader::CodeCacheRequest::DidReceiveCachedCode, weak_ptr_factory_.GetWeakPtr(), resource_loader); - code_cache_loader_->FetchFromCodeCache(gurl_, std::move(callback)); + code_cache_loader_->FetchFromCodeCache( + blink::mojom::CodeCacheType::kJavascript, gurl_, std::move(callback)); return true; } @@ -247,7 +248,7 @@ } if (resource_response_time_ != cached_code_response_time_) { - Platform::Current()->ClearCodeCacheEntry(gurl_); + resource_loader->ClearCachedCode(); return; } @@ -695,6 +696,12 @@ resource_->SetSerializedCachedMetadata(data, length); } +void ResourceLoader::ClearCachedCode() { + Platform::Current()->ClearCodeCacheEntry( + Resource::ResourceTypeToCodeCacheType(resource_->GetType()), + resource_->Url()); +} + void ResourceLoader::DidSendData(unsigned long long bytes_sent, unsigned long long total_bytes_to_be_sent) { resource_->DidSendData(bytes_sent, total_bytes_to_be_sent);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h index 67f891a..bed1aacf 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -131,6 +131,7 @@ int64_t decoded_body_length) override; void SendCachedCodeToResource(const char* data, int size); + void ClearCachedCode(); void HandleError(const ResourceError&);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_test.cc index b70b58b..34e50e9 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
@@ -27,7 +27,11 @@ ~MockPlatform() override = default; // From blink::Platform: - void CacheMetadata(const WebURL& url, Time, const char*, size_t) override { + void CacheMetadata(blink::mojom::CodeCacheType cache_type, + const WebURL& url, + Time, + const char*, + size_t) override { cached_urls_.push_back(url); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc b/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc index c67276f2..2746de6 100644 --- a/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler_test.cc
@@ -88,7 +88,8 @@ WebCrypto* Crypto() override { return &mock_web_crypto_; } - void CacheMetadata(const WebURL& url, + void CacheMetadata(blink::mojom::CodeCacheType cache_type, + const WebURL& url, base::Time response_time, const char* data, size_t data_size) override { @@ -125,7 +126,8 @@ MockCachedMetadataSender(KURL response_url) : response_url_(response_url) {} void Send(const char* data, size_t size) override { - Platform::Current()->CacheMetadata(response_url_, response_time_, data, + Platform::Current()->CacheMetadata(blink::mojom::CodeCacheType::kJavascript, + response_url_, response_time_, data, size); }
diff --git a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc index a4e9fb3..d57078d 100644 --- a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc +++ b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc
@@ -15,6 +15,7 @@ } void CodeCacheLoaderMock::FetchFromCodeCache( + blink::mojom::CodeCacheType cache_type, const GURL& kurl, CodeCacheLoader::FetchCodeCacheCallback callback) { std::move(callback).Run(base::Time(), std::vector<uint8_t>());
diff --git a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h index 0459e8e..3fc9db1 100644 --- a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h +++ b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h
@@ -22,6 +22,7 @@ base::Time* response_time_out, std::vector<uint8_t>* data_out) override; void FetchFromCodeCache( + blink::mojom::CodeCacheType cache_type, const GURL& url, CodeCacheLoader::FetchCodeCacheCallback callback) override;
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.cc b/third_party/blink/renderer/platform/weborigin/security_origin.cc index f51f1bb1..6a91910 100644 --- a/third_party/blink/renderer/platform/weborigin/security_origin.cc +++ b/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -201,7 +201,7 @@ scoped_refptr<SecurityOrigin> SecurityOrigin::CreateFromUrlOrigin( const url::Origin& origin) { - if (origin.unique()) + if (origin.opaque()) return CreateUniqueOpaque(); DCHECK(String::FromUTF8(origin.scheme().c_str()).ContainsOnlyASCII());
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc index 3b31fc5..65471a6 100644 --- a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc +++ b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
@@ -580,8 +580,8 @@ url::Origin origin_roundtrip_via_gurl = security_origin_via_gurl->ToUrlOrigin(); - EXPECT_EQ(test_case.opaque, origin_roundtrip_via_kurl.unique()); - EXPECT_EQ(test_case.opaque, origin_roundtrip_via_gurl.unique()); + EXPECT_EQ(test_case.opaque, origin_roundtrip_via_kurl.opaque()); + EXPECT_EQ(test_case.opaque, origin_roundtrip_via_gurl.opaque()); if (!test_case.opaque) { EXPECT_EQ(origin_via_gurl, origin_roundtrip_via_kurl); EXPECT_EQ(origin_roundtrip_via_kurl, origin_roundtrip_via_gurl);
diff --git a/third_party/blink/tools/blinkpy/third_party/README.chromium b/third_party/blink/tools/blinkpy/third_party/README.chromium index fda8e7ea..9ac6c94a 100644 --- a/third_party/blink/tools/blinkpy/third_party/README.chromium +++ b/third_party/blink/tools/blinkpy/third_party/README.chromium
@@ -32,7 +32,7 @@ Name: web-platform-tests - Test Suites for Web Platform specifications Short Name: wpt URL: https://github.com/web-platform-tests/wpt/ -Version: ab64b78a8f6777a1d95d8d1d4bba9ccdbecf94ea +Version: c757432db546a30c1e6ef833df0b597df2dad6bd License: LICENSES FOR W3C TEST SUITES (http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html) License File: wpt/wpt/LICENSE.md Security Critical: no
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh b/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh index 360eaad5..f605cbf 100755 --- a/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh +++ b/third_party/blink/tools/blinkpy/third_party/wpt/checkout.sh
@@ -9,7 +9,7 @@ TARGET_DIR=$DIR/wpt REMOTE_REPO="https://chromium.googlesource.com/external/github.com/web-platform-tests/wpt.git" -WPT_HEAD=ab64b78a8f6777a1d95d8d1d4bba9ccdbecf94ea +WPT_HEAD=c757432db546a30c1e6ef833df0b597df2dad6bd function clone { # Remove existing repo if already exists.
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py index b2e4bce41..59e2d93 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/lint/lint.py
@@ -216,7 +216,8 @@ elif source_file.name_is_reference: ref_files[source_file.name].add(path) else: - test_files[source_file.name].add(path) + name = source_file.name.replace('-manual', '') + test_files[name].add(path) errors = []
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py index 61919fc..ddf046a 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/item.py
@@ -234,7 +234,7 @@ item_type = "stub" -class WebdriverSpecTest(URLManifestItem): +class WebDriverSpecTest(URLManifestItem): item_type = "wdspec" def __init__(self, source_file, url, url_base="/", timeout=None, manifest=None):
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py index 42a8e1ce..9b2f0a1 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/manifest.py
@@ -4,7 +4,7 @@ from collections import defaultdict from six import iteritems, itervalues, viewkeys, string_types -from .item import ManualTest, WebdriverSpecTest, Stub, RefTestNode, RefTest, TestharnessTest, SupportFile, ConformanceCheckerTest, VisualTest +from .item import ManualTest, WebDriverSpecTest, Stub, RefTestNode, RefTest, TestharnessTest, SupportFile, ConformanceCheckerTest, VisualTest from .log import get_logger from .utils import from_os_path, to_os_path @@ -193,7 +193,7 @@ "reftest_node": RefTestNode, "manual": ManualTest, "stub": Stub, - "wdspec": WebdriverSpecTest, + "wdspec": WebDriverSpecTest, "conformancechecker": ConformanceCheckerTest, "visual": VisualTest, "support": SupportFile}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py index 133f8b5..1f08088eb 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/sourcefile.py
@@ -12,7 +12,7 @@ import html5lib from . import XMLParser -from .item import Stub, ManualTest, WebdriverSpecTest, RefTestNode, TestharnessTest, SupportFile, ConformanceCheckerTest, VisualTest +from .item import Stub, ManualTest, WebDriverSpecTest, RefTestNode, TestharnessTest, SupportFile, ConformanceCheckerTest, VisualTest from .utils import rel_path_to_url, ContextManagerBytesIO, cached_property wd_pattern = "*.py" @@ -267,6 +267,7 @@ self.name_prefix("MANIFEST") or self.filename == "META.yml" or self.filename.startswith(".") or + self.filename.endswith(".headers") or self.type_flag == "support" or self.in_non_test_dir()) @@ -645,7 +646,7 @@ rv = TestharnessTest.item_type, tests elif self.name_is_webdriver: - rv = WebdriverSpecTest.item_type, [WebdriverSpecTest(self, self.url, + rv = WebDriverSpecTest.item_type, [WebDriverSpecTest(self, self.url, timeout=self.timeout)] elif self.content_is_css_manual and not self.name_is_reference:
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py index 42e98637..675eb017 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/manifest/vcs.py
@@ -1,5 +1,6 @@ import os import subprocess +import platform from .sourcefile import SourceFile @@ -16,9 +17,12 @@ full_cmd = ["git", cmd] + list(args) try: return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT) - except WindowsError: - full_cmd[0] = "git.bat" - return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT) + except Exception as e: + if platform.uname()[0] == "Windows" and isinstance(e, WindowsError): + full_cmd[0] = "git.bat" + return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT) + else: + raise return git @classmethod
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py index 97a5063c..c4afc69 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/serve/serve.py
@@ -100,9 +100,12 @@ :param request: The Request being processed. """ path = self._get_path(filesystem_path(self.base_path, request, self.url_base), False) - with open(path, "rb") as f: - for key, value in read_script_metadata(f, js_meta_re): - yield key, value + try: + with open(path, "rb") as f: + for key, value in read_script_metadata(f, js_meta_re): + yield key, value + except IOError: + raise HTTPException(404) def _get_meta(self, request): """Get an iterator over strings to inject into the wrapper document @@ -378,15 +381,17 @@ class ServerProc(object): - def __init__(self): + def __init__(self, scheme=None): self.proc = None self.daemon = None self.stop = Event() + self.scheme = scheme def start(self, init_func, host, port, paths, routes, bind_address, config, **kwargs): self.proc = Process(target=self.create_daemon, args=(init_func, host, port, paths, routes, bind_address, config), + name='%s on port %s' % (self.scheme, port), kwargs=kwargs) self.proc.daemon = True self.proc.start() @@ -507,7 +512,7 @@ "ws":start_ws_server, "wss":start_wss_server}[scheme] - server_proc = ServerProc() + server_proc = ServerProc(scheme=scheme) server_proc.start(init_func, host, port, paths, routes, bind_address, config, **kwargs) servers[scheme].append((port, server_proc)) @@ -624,10 +629,22 @@ self.server = None +def release_mozlog_lock(): + try: + from mozlog.structuredlog import StructuredLogger + try: + StructuredLogger._lock.release() + except threading.ThreadError: + pass + except ImportError: + pass + + def start_ws_server(host, port, paths, routes, bind_address, config, **kwargs): - # Ensure that when we start this in a new process we don't inherit the - # global lock in the logging module + # Ensure that when we start this in a new process we have the global lock + # in the logging module unlocked reload_module(logging) + release_mozlog_lock() return WebSocketDaemon(host, str(port), repo_root, @@ -638,9 +655,10 @@ def start_wss_server(host, port, paths, routes, bind_address, config, **kwargs): - # Ensure that when we start this in a new process we don't inherit the - # global lock in the logging module + # Ensure that when we start this in a new process we have the global lock + # in the logging module unlocked reload_module(logging) + release_mozlog_lock() return WebSocketDaemon(host, str(port), repo_root, @@ -828,9 +846,16 @@ servers = start(config, build_routes(config["aliases"]), **kwargs) try: - while any(item.is_alive() for item in iter_procs(servers)): + while all(item.is_alive() for item in iter_procs(servers)): for item in iter_procs(servers): item.join(1) + exited = [item for item in iter_procs(servers) if not item.is_alive()] + subject = "subprocess" if len(exited) == 1 else "subprocesses" + + logger.info("%s %s exited:" % (len(exited), subject)) + + for item in iter_procs(servers): + logger.info("Status of %s:\t%s" % (item.name, "running" if item.is_alive() else "not running")) except KeyboardInterrupt: logger.info("Shutting down")
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py index 9834e5d..052ec66 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/browser.py
@@ -26,12 +26,12 @@ return NotImplemented @abstractmethod - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): """Install the WebDriver implementation for this browser.""" return NotImplemented @abstractmethod - def find_binary(self): + def find_binary(self, venv_path=None, channel=None): """Find the binary of the browser. If the WebDriver for the browser is able to find the binary itself, this @@ -84,9 +84,32 @@ return "%s%s" % (platform, bits) - def install(self, dest=None): + def install(self, dest=None, channel="nightly"): """Install Firefox.""" + branch = { + "nightly": "mozilla-central", + "beta": "mozilla-beta", + "stable": "mozilla-stable" + } + scraper = { + "nightly": "daily", + "beta": "release", + "stable": "release" + } + version = { + "stable": "latest", + "beta": "latest-beta", + "nightly": "latest" + } + application_name = { + "stable": "Firefox.app", + "beta": "Firefox.app", + "nightly": "Firefox Nightly.app" + } + if channel not in branch: + raise ValueError("Unrecognised release channel: %s" % channel) + from mozdownload import FactoryScraper import mozinstall @@ -103,17 +126,20 @@ # os.getcwd() doesn't include the venv path dest = os.path.join(os.getcwd(), "_venv") - dest = os.path.join(dest, "browsers") + dest = os.path.join(dest, "browsers", channel) - filename = FactoryScraper("daily", branch="mozilla-central", destination=dest).download() + filename = FactoryScraper(scraper[channel], + branch=branch[channel], + version=version[channel], + destination=dest).download() try: mozinstall.install(filename, dest) except mozinstall.mozinstall.InstallError: - if platform == "mac" and os.path.exists(os.path.join(dest, "Firefox Nightly.app")): + if platform == "mac" and os.path.exists(os.path.join(dest, application_name[channel])): # mozinstall will fail if nightly is already installed in the venv because # mac installation uses shutil.copy_tree - mozinstall.uninstall(os.path.join(dest, "Firefox Nightly.app")) + mozinstall.uninstall(os.path.join(dest, application_name[channel])) mozinstall.install(filename, dest) else: raise @@ -121,7 +147,7 @@ os.remove(filename) return self.find_binary_path(dest) - def find_binary_path(self, path=None): + def find_binary_path(self,path=None, channel="nightly"): """Looks for the firefox binary in the virtual environment""" platform = { @@ -130,9 +156,15 @@ "Darwin": "mac" }.get(uname[0]) + application_name = { + "stable": "Firefox.app", + "beta": "Firefox.app", + "nightly": "Firefox Nightly.app" + }.get(channel) + if path is None: #os.getcwd() doesn't include the venv path - path = os.path.join(os.getcwd(), "_venv", "browsers") + path = os.path.join(os.getcwd(), "_venv", "browsers", channel) binary = None @@ -142,19 +174,24 @@ import mozinstall binary = mozinstall.get_binary(path, "firefox") elif platform == "mac": - binary = find_executable("firefox", os.path.join(path, "Firefox Nightly.app", "Contents", "MacOS")) + binary = find_executable("firefox", os.path.join(path, application_name, + "Contents", "MacOS")) return binary - def find_binary(self, venv_path=None): + def find_binary(self, venv_path=None, channel=None): if venv_path is None: venv_path = os.path.join(os.getcwd(), "_venv") - binary = self.find_binary_path(os.path.join(venv_path, "browsers")) + if channel is None: + channel = "nightly" + + path = os.path.join(venv_path, "browsers", channel) + binary = self.find_binary_path(path, channel) if not binary and uname[0] == "Darwin": - macpaths = ["/Applications/FirefoxNightly.app/Contents/MacOS", - os.path.expanduser("~/Applications/FirefoxNightly.app/Contents/MacOS"), + macpaths = ["/Applications/Firefox Nightly.app/Contents/MacOS", + os.path.expanduser("~/Applications/Firefox Nightly.app/Contents/MacOS"), "/Applications/Firefox Developer Edition.app/Contents/MacOS", os.path.expanduser("~/Applications/Firefox Developer Edition.app/Contents/MacOS"), "/Applications/Firefox.app/Contents/MacOS", @@ -190,6 +227,18 @@ if channel == "stable": repo = "https://hg.mozilla.org/releases/mozilla-release" tag = "FIREFOX_%s_RELEASE" % version.replace(".", "_") + elif channel == "beta": + repo = "https://hg.mozilla.org/releases/mozilla-beta" + major_version = version.split(".", 1)[0] + # For beta we have a different format for betas that are now in stable releases + # vs those that are not + tags = get("https://hg.mozilla.org/releases/mozilla-beta/json-tags").json()["tags"] + tags = {item["tag"] for item in tags} + end_tag = "FIREFOX_BETA_%s_END" % major_version + if end_tag in tags: + tag = end_tag + else: + tag = "tip" else: repo = "https://hg.mozilla.org/mozilla-central" if channel == "beta": @@ -202,8 +251,14 @@ return "%s/archive/%s.zip/testing/profiles/" % (repo, tag) - def install_prefs(self, binary, dest=None): - version, channel = self.get_version_and_channel(binary) + def install_prefs(self, binary, dest=None, channel=None): + version, channel_ = self.get_version_and_channel(binary) + if channel is not None and channel != channel_: + # Beta doesn't always seem to have the b in the version string, so allow the + # manually supplied value to override the one from the binary + logger.warning("Supplied channel doesn't match binary, using supplied channel") + elif channel is None: + channel = channel_ if dest is None: dest = os.pwd @@ -257,11 +312,18 @@ assert latest_release != 0 return "v%s.%s.%s" % tuple(str(item) for item in latest_release) - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): """Install latest Geckodriver.""" if dest is None: dest = os.getcwd() + if channel == "nightly": + path = self.install_geckodriver_nightly(dest) + if path is not None: + return path + else: + logger.warning("Nightly webdriver not found; falling back to release") + version = self._latest_geckodriver_version() format = "zip" if uname[0] == "Windows" else "tar.gz" logger.debug("Latest geckodriver release %s" % version) @@ -273,9 +335,39 @@ untar(get(url).raw, dest=dest) return find_executable(os.path.join(dest, "geckodriver")) - def version(self, binary=None): + def install_geckodriver_nightly(self, dest): + import tarfile + import mozdownload + logger.info("Attempting to install webdriver from nightly") + try: + s = mozdownload.DailyScraper(branch="mozilla-central", + extension="common.tests.tar.gz", + destination=dest) + package_path = s.download() + except mozdownload.errors.NotFoundError: + return + + try: + exe_suffix = ".exe" if uname[0] == "Windows" else "" + with tarfile.open(package_path, "r") as f: + try: + member = f.getmember("bin%sgeckodriver%s" % (os.path.sep, + exe_suffix)) + except KeyError: + return + # Remove bin/ from the path. + member.name = os.path.basename(member.name) + f.extractall(members=[member], path=dest) + path = os.path.join(dest, member.name) + logger.info("Extracted geckodriver to %s" % path) + finally: + os.unlink(package_path) + + return path + + def version(self, binary=None, channel=None): """Retrieve the release version of the installed browser.""" - binary = binary or self.find_binary() + binary = binary or self.find_binary(channel) version_string = call(binary, "--version").strip() m = re.match(r"Mozilla Firefox (.*)", version_string) if not m: @@ -289,16 +381,16 @@ product = "fennec" requirements = "requirements_firefox.txt" - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError - def find_binary(self, venv_path=None): + def find_binary(self, venv_path=None, channel=None): raise NotImplementedError def find_webdriver(self): raise NotImplementedError - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): raise NotImplementedError def version(self, binary=None): @@ -324,7 +416,7 @@ logger.warn("Unable to find the browser binary.") return None - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError def platform_string(self): @@ -346,13 +438,13 @@ return "%s%s" % (platform, bits) - def find_binary(self): + def find_binary(self, venv_path=None, channel=None): raise NotImplementedError def find_webdriver(self): return find_executable("chromedriver") - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): if dest is None: dest = os.pwd latest = get("http://chromedriver.storage.googleapis.com/LATEST_RELEASE").text.strip() @@ -391,22 +483,28 @@ product = "chrome_android" requirements = "requirements_chrome_android.txt" - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError - def find_binary(self): + def find_binary(self, venv_path=None, channel=None): raise NotImplementedError def find_webdriver(self): return find_executable("chromedriver") - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): chrome = Chrome() - return chrome.install_webdriver(dest) + return chrome.install_webdriver(dest, channel) def version(self, binary): return None +class ChromeWebDriver(Chrome): + """Chrome-specific interface for chrome without using selenium. + + Includes webdriver installation. + """ + product = "chrome_webdriver" class Opera(Browser): """Opera-specific interface. @@ -425,7 +523,7 @@ logger.warn("Unable to find the browser binary.") return None - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError def platform_string(self): @@ -447,13 +545,13 @@ return "%s%s" % (platform, bits) - def find_binary(self): + def find_binary(self, venv_path=None, channel=None): raise NotImplementedError def find_webdriver(self): return find_executable("operadriver") - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): if dest is None: dest = os.pwd latest = get("https://api.github.com/repos/operasoftware/operachromiumdriver/releases/latest").json()["tag_name"] @@ -487,38 +585,42 @@ product = "edge" requirements = "requirements_edge.txt" - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError - def find_binary(self): + def find_binary(self, venv_path=None, channel=None): raise NotImplementedError def find_webdriver(self): return find_executable("MicrosoftWebDriver") - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): raise NotImplementedError def version(self, binary): return None +class EdgeWebDriver(Edge): + product = "edge_webdriver" + + class InternetExplorer(Browser): """Internet Explorer-specific interface.""" product = "ie" requirements = "requirements_ie.txt" - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError - def find_binary(self): + def find_binary(self, venv_path=None, channel=None): raise NotImplementedError def find_webdriver(self): return find_executable("IEDriverServer.exe") - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): raise NotImplementedError def version(self, binary): @@ -534,22 +636,26 @@ product = "safari" requirements = "requirements_safari.txt" - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError - def find_binary(self): + def find_binary(self, venv_path=None, channel=None): raise NotImplementedError def find_webdriver(self): return find_executable("safaridriver") - def install_webdriver(self): + def install_webdriver(self, dest=None, channel=None): raise NotImplementedError def version(self, binary): return None +class SafariWebDriver(Safari): + product = "safari_webdriver" + + class Servo(Browser): """Servo-specific interface.""" @@ -574,8 +680,10 @@ return (platform, extension, decompress) - def install(self, dest=None): + def install(self, dest=None, channel="nightly"): """Install latest Browser Engine.""" + if channel != "nightly": + raise ValueError("Only nightly versions of Servo are available") if dest is None: dest = os.pwd @@ -588,13 +696,16 @@ os.chmod(path, st.st_mode | stat.S_IEXEC) return path - def find_binary(self): - return find_executable("servo") + def find_binary(self, venv_path=None, channel=None): + path = find_executable("servo", os.path.join(venv_path, "servo")) + if path is None: + path = find_executable("servo") + return path def find_webdriver(self): return None - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): raise NotImplementedError def version(self, binary): @@ -609,16 +720,16 @@ product = "sauce" requirements = "requirements_sauce.txt" - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError - def find_binary(self): + def find_binary(self, venev_path=None, channel=None): raise NotImplementedError def find_webdriver(self): raise NotImplementedError - def install_webdriver(self, dest=None): + def install_webdriver(self, dest=None, channel=None): raise NotImplementedError def version(self, binary): @@ -631,16 +742,16 @@ product = "webkit" requirements = "requirements_webkit.txt" - def install(self, dest=None): + def install(self, dest=None, channel=None): raise NotImplementedError - def find_binary(self, path=None): + def find_binary(self, venv_path=None, channel=None): return None def find_webdriver(self): return None - def install_webdriver(self): + def install_webdriver(self, dest=None, channel=None): raise NotImplementedError def version(self, binary):
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/install.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/install.py index d779651..62c833aa 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/install.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/install.py
@@ -2,20 +2,62 @@ import browser import sys + +latest_channels = { + 'firefox': 'nightly', + 'chrome': 'dev', + 'servo': 'nightly' +} + +channel_by_name = { + 'stable': 'stable', + 'release': 'stable', + 'beta': 'beta', + 'nightly': latest_channels, + 'dev': latest_channels, + 'preview': latest_channels, + 'experimental': latest_channels, +} + + def get_parser(): - parser = argparse.ArgumentParser() - parser.add_argument('browser', choices=['firefox', 'chrome'], + parser = argparse.ArgumentParser(description="""Install a given browser or webdriver frontend. + + For convenience the release channel of the browser accepts various spellings, + but we actually support at most three variants; whatever the latest development + release is (e.g. Firefox nightly or Chrome dev), the latest beta release, and + the most recent stable release.""") + parser.add_argument('browser', choices=['firefox', 'chrome', 'servo'], help='name of web browser product') parser.add_argument('component', choices=['browser', 'webdriver'], help='name of component') + parser.add_argument('--channel', choices=channel_by_name.keys(), + default="nightly", help='Name of browser release channel. ' + '"stable" and "release" are synonyms for the latest browser stable release,' + '"nightly", "dev", "experimental", and "preview" are all synonyms for ' + 'the latest available development release. For WebDriver installs, ' + 'we attempt to select an appropriate, compatible, version for the ' + 'latest browser release on the selected channel.') parser.add_argument('-d', '--destination', help='filesystem directory to place the component') return parser +def get_channel(browser, channel): + channel = channel_by_name[channel] + if isinstance(channel, dict): + channel = channel[browser] + return channel + + def run(venv, **kwargs): browser = kwargs["browser"] destination = kwargs["destination"] + channel = get_channel(browser, kwargs["channel"]) + + if channel != kwargs["channel"]: + print "Interpreting channel '%s' as '%s'" % (kwargs["channel"], + channel) if destination is None: if venv: @@ -27,10 +69,10 @@ raise argparse.ArgumentError(None, "No --destination argument, and no default for the environment") - install(browser, kwargs["component"], destination) + install(browser, kwargs["component"], destination, channel) -def install(name, component, destination): +def install(name, component, destination, channel="nightly"): if component == 'webdriver': method = 'install_webdriver' else: @@ -38,4 +80,6 @@ subclass = getattr(browser, name.title()) sys.stdout.write('Now installing %s %s...\n' % (name, component)) - getattr(subclass(), method)(dest=destination) + path = getattr(subclass(), method)(dest=destination, channel=channel) + if path: + sys.stdout.write('Binary installed as %s\n' % (path,))
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py index 6b098b4..d08b0f9 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/run.py
@@ -7,7 +7,7 @@ wpt_root = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) sys.path.insert(0, os.path.abspath(os.path.join(wpt_root, "tools"))) -from . import browser, utils, virtualenv +from . import browser, install, utils, virtualenv from ..serve import serve logger = None @@ -47,7 +47,17 @@ parser.add_argument("--yes", "-y", dest="prompt", action="store_false", default=True, help="Don't prompt before installing components") parser.add_argument("--install-browser", action="store_true", - help="Install the latest development version of the browser") + help="Install the browser from the release channel specified by --channel " + "(or the nightly channel by default).") + parser.add_argument("--channel", action="store", + choices=install.channel_by_name.keys(), + default=None, help='Name of browser release channel. ' + '"stable" and "release" are synonyms for the latest browser stable ' + 'release, "nightly", "dev", "experimental", and "preview" are all ' + 'synonyms for the latest available development release. (For WebDriver ' + 'installs, we attempt to select an appropriate, compatible version for ' + 'the latest browser release on the selected channel.) ' + 'This flag overrides --browser-channel.') parser._add_container_actions(wptcommandline.create_parser()) return parser @@ -105,7 +115,7 @@ missing_hosts = set(expected_hosts) if is_windows: - hosts_path = "C:\Windows\System32\drivers\etc\hosts" + hosts_path = "%s\System32\drivers\etc\hosts" % os.environ.get("SystemRoot", "C:\Windows") else: hosts_path = "/etc/hosts" @@ -120,7 +130,7 @@ if is_windows: message = """Missing hosts file configuration. Run -python wpt make-hosts-file | Out-File %SystemRoot%\System32\drivers\etc\hosts -Encoding ascii -Append +python wpt make-hosts-file | Out-File %s -Encoding ascii -Append in PowerShell with Administrator privileges.""" % hosts_path else: @@ -150,9 +160,9 @@ elif resp == "n": return False - def install(self, venv): + def install(self, venv, channel=None): if self.prompt_install(self.name): - return self.browser.install(venv.path) + return self.browser.install(venv.path, channel) def install_requirements(self): self.venv.install_requirements(os.path.join(wpt_root, "tools", "wptrunner", self.browser.requirements)) @@ -167,7 +177,11 @@ def setup_kwargs(self, kwargs): if kwargs["binary"] is None: - binary = self.browser.find_binary(self.venv.path) + if kwargs["browser_channel"] is None: + logger.info("No browser channel specified. Running nightly instead.") + + binary = self.browser.find_binary(self.venv.path, + kwargs["browser_channel"]) if binary is None: raise WptrunError("""Firefox binary not found on $PATH. @@ -205,9 +219,18 @@ kwargs["test_types"].remove("wdspec") if kwargs["prefs_root"] is None: - prefs_root = self.browser.install_prefs(kwargs["binary"], self.venv.path) + prefs_root = self.browser.install_prefs(kwargs["binary"], + self.venv.path, + channel=kwargs["browser_channel"]) kwargs["prefs_root"] = prefs_root + if kwargs["headless"] is None: + kwargs["headless"] = True + logger.info("Running in headless mode, pass --no-headless to disable") + + # Allow WebRTC tests to call getUserMedia. + kwargs["extra_prefs"].append("media.navigator.streams.fake=true") + class Fennec(BrowserSetup): name = "fennec" @@ -238,6 +261,12 @@ kwargs["webdriver_binary"] = webdriver_binary else: raise WptrunError("Unable to locate or install chromedriver binary") + if kwargs["browser_channel"] == "dev": + logger.info("Automatically turning on experimental features for Chrome Dev") + kwargs["binary_args"].append("--enable-experimental-web-platform-features") + + # Allow WebRTC tests to call getUserMedia. + kwargs["binary_args"] += ["--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream"] class ChromeAndroid(BrowserSetup): @@ -263,6 +292,11 @@ raise WptrunError("Unable to locate or install chromedriver binary") +class ChromeWebDriver(Chrome): + name = "chrome_webdriver" + browser_cls = browser.ChromeWebDriver + + class Opera(BrowserSetup): name = "opera" browser_cls = browser.Opera @@ -290,7 +324,7 @@ name = "edge" browser_cls = browser.Edge - def install(self, venv): + def install(self, venv, channel=None): raise NotImplementedError def setup_kwargs(self, kwargs): @@ -307,11 +341,16 @@ kwargs["webdriver_binary"] = webdriver_binary +class EdgeWebDriver(Edge): + name = "edge_webdriver" + browser_cls = browser.EdgeWebDriver + + class InternetExplorer(BrowserSetup): name = "ie" browser_cls = browser.InternetExplorer - def install(self, venv): + def install(self, venv, channel=None): raise NotImplementedError def setup_kwargs(self, kwargs): @@ -332,7 +371,7 @@ name = "safari" browser_cls = browser.Safari - def install(self, venv): + def install(self, venv, channel=None): raise NotImplementedError def setup_kwargs(self, kwargs): @@ -345,11 +384,16 @@ kwargs["webdriver_binary"] = webdriver_binary +class SafariWebDriver(Safari): + name = "safari_webdriver" + browser_cls = browser.SafariWebDriver + + class Sauce(BrowserSetup): name = "sauce" browser_cls = browser.Sauce - def install(self, venv): + def install(self, venv, channel=None): raise NotImplementedError def setup_kwargs(self, kwargs): @@ -362,13 +406,13 @@ name = "servo" browser_cls = browser.Servo - def install(self, venv): + def install(self, venv, channel=None): if self.prompt_install(self.name): return self.browser.install(venv.path) def setup_kwargs(self, kwargs): if kwargs["binary"] is None: - binary = self.browser.find_binary() + binary = self.browser.find_binary(self.venv.path, None) if binary is None: raise WptrunError("Unable to find servo binary on the PATH") @@ -379,7 +423,7 @@ name = "webkit" browser_cls = browser.WebKit - def install(self, venv): + def install(self, venv, channel=None): raise NotImplementedError def setup_kwargs(self, kwargs): @@ -391,9 +435,12 @@ "firefox": Firefox, "chrome": Chrome, "chrome_android": ChromeAndroid, + "chrome_webdriver": ChromeWebDriver, "edge": Edge, + "edge_webdriver": EdgeWebDriver, "ie": InternetExplorer, "safari": Safari, + "safari_webdriver": SafariWebDriver, "servo": Servo, "sauce": Sauce, "opera": Opera, @@ -401,7 +448,7 @@ } -def setup_wptrunner(venv, prompt=True, install=False, **kwargs): +def setup_wptrunner(venv, prompt=True, install_browser=False, **kwargs): from wptrunner import wptrunner, wptcommandline global logger @@ -424,9 +471,21 @@ setup_cls = product_setup[kwargs["product"]](venv, prompt, sub_product) setup_cls.install_requirements() - if install: + if install_browser and not kwargs["channel"]: + logger.info("--install-browser is given but --channel is not set, default to nightly channel") + kwargs["channel"] = "nightly" + + if kwargs["channel"]: + channel = install.get_channel(kwargs["product"], kwargs["channel"]) + if channel != kwargs["channel"]: + logger.info("Interpreting channel '%s' as '%s'" % (kwargs["channel"], + channel)) + kwargs["browser_channel"] = channel + del kwargs["channel"] + + if install_browser: logger.info("Installing browser") - kwargs["binary"] = setup_cls.install(venv) + kwargs["binary"] = setup_cls.install(venv, channel=channel) setup_cls.setup(kwargs) @@ -441,13 +500,13 @@ def run(venv, **kwargs): - #Remove arguments that aren't passed to wptrunner + # Remove arguments that aren't passed to wptrunner prompt = kwargs.pop("prompt", True) install_browser = kwargs.pop("install_browser", False) kwargs = setup_wptrunner(venv, prompt=prompt, - install=install_browser, + install_browser=install_browser, **kwargs) rv = run_single(venv, **kwargs) > 0
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py index f4eecce2..55802461 100644 --- a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py +++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wpt/wpt.py
@@ -101,9 +101,6 @@ main_args, command_args = parse_args(argv, commands) - if not(len(argv) and argv[0] in commands): - sys.exit(1) - command = main_args.command props = commands[command] venv = None
diff --git a/third_party/boringssl/BUILD.generated_tests.gni b/third_party/boringssl/BUILD.generated_tests.gni index ff5955f..02fa36c 100644 --- a/third_party/boringssl/BUILD.generated_tests.gni +++ b/third_party/boringssl/BUILD.generated_tests.gni
@@ -70,6 +70,7 @@ "src/crypto/refcount_test.cc", "src/crypto/rsa_extra/rsa_test.cc", "src/crypto/self_test.cc", + "src/crypto/stack/stack_test.cc", "src/crypto/test/file_test_gtest.cc", "src/crypto/test/gtest_main.cc", "src/crypto/thread_test.cc",
diff --git a/tools/binary_size/trybot_commit_size_checker.py b/tools/binary_size/trybot_commit_size_checker.py index d93b46ae..5ef7939 100755 --- a/tools/binary_size/trybot_commit_size_checker.py +++ b/tools/binary_size/trybot_commit_size_checker.py
@@ -29,6 +29,30 @@ 'binary_size/metrics.md#Normalized-APK-Size ' 'for an explanation of Normalized APK Size') +_FAILURE_GUIDANCE = """ +Please look at the symbol diffs from the "Show Resource Sizes Diff", +"Show Supersize Diff", and "Dex Method Count", and "Supersize HTML Report" bot +steps. Try and understand the growth and see if it can be mitigated. + +There is guidance at: + +https://chromium.googlesource.com/chromium/src/+/master/docs/speed/apk_size_regressions.md#Debugging-Apk-Size-Increase + +If the growth is expected / justified, then you can bypass this bot failure by +adding "Binary-Size: $JUSTIFICATION" to your commit description. Here are some +examples: + +Binary-Size: Increase is due to translations and so cannot be avoided. +Binary-Size: Increase is due to new images, which are already optimally encoded. +Binary-Size: Increase is temporary due to a "new way" / "old way" refactoring. + It should go away once the "old way" is removed. +Binary-Size: Increase is temporary and will be reverted before next branch cut. +Binary-Size: Increase needed to reduce RAM of a common user flow. +Binary-Size: Increase needed to reduce runtime of a common user flow. +Binary-Size: Increase needed to implement a feature, and I've already spent a + non-trivial amount of time trying to reduce its size. +""" + class _SizeDelta(collections.namedtuple( 'SizeDelta', ['name', 'units', 'expected', 'actual', 'details'])): @@ -147,10 +171,10 @@ # Normalized APK Size is the main metric we use to monitor binary size. logging.info('Creating sizes diff') - size_deltas.add( - _CreateAndWriteResourceSizesDelta( + resource_sizes_delta = _CreateAndWriteResourceSizesDelta( args.apk_name, args.before_dir, args.after_dir, - args.resource_sizes_diff_path)) + args.resource_sizes_diff_path) + size_deltas.add(resource_sizes_delta) # .ndjson can be consumed by the html viewer. logging.info('Creating HTML Report') @@ -165,8 +189,9 @@ passing_deltas = set(m for m in size_deltas if m._IsAllowable()) failing_deltas = size_deltas - passing_deltas + status_code = len(failing_deltas) - result = 'passed' if is_roller or len(failing_deltas) == 0 else 'failed' + result = 'passed' if is_roller or status_code == 0 else 'failed' message = """ Binary size checks {}. @@ -184,35 +209,23 @@ ******************************************************************************* -Please look at the symbol diffs from the "Show Resource Sizes Diff", -"Show Supersize Diff", and "Dex Method Count", and "Supersize HTML Report" bot -steps. Try and understand the growth and see if it can be mitigated. - -There is guidance at: - -https://chromium.googlesource.com/chromium/src/+/master/docs/speed/apk_size_regressions.md#Debugging-Apk-Size-Increase - -If the growth is expected / justified, then you can bypass this bot failure by \ -adding "Binary-Size: $JUSTIFICATION" to your commit description. Here are some \ -examples: - -Binary-Size: Increase is due to translations and so cannot be avoided. -Binary-Size: Increase is due to new images, which are already optimally encoded. -Binary-Size: Increase is temporary due to a "new way" / "old way" refactoring. - It should go away once the "old way" is removed. -Binary-Size: Increase is temporary and will be reverted before next branch cut. -Binary-Size: Increase needed to reduce RAM of a common user flow. -Binary-Size: Increase needed to reduce runtime of a common user flow. -Binary-Size: Increase needed to implement a feature, and I've already spent a - non-trivial amount of time trying to reduce its size. """.format(result, '\n\n'.join(d.explanation for d in sorted(failing_deltas)), '\n\n'.join(d.explanation for d in sorted(passing_deltas))) + + if status_code != 0: + message += _FAILURE_GUIDANCE + # Make blank lines not blank prevent them from being stripped. # https://crbug.com/855671 message.replace('\n\n', '\n.\n') with open(args.results_path, 'w') as f: - json.dump({'status_code': len(failing_deltas), 'details': message}, f) + results_json = { + 'details': message, + 'normalized_apk_size': resource_sizes_delta.actual, + 'status_code': status_code + } + json.dump(results_json, f) if __name__ == '__main__':
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 3390c178..cf9084c 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -27,7 +27,7 @@ # Do NOT CHANGE this if you don't know what you're doing -- see # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md # Reverting problematic clang rolls is safe, though. -CLANG_REVISION = '343189' +CLANG_REVISION = '342523' use_head_revision = bool(os.environ.get('LLVM_FORCE_HEAD_REVISION', '0') in ('1', 'YES'))
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc index 0fe61ae..ec291e5 100644 --- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc +++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -1524,7 +1524,7 @@ template <> struct FuzzTraits<url::Origin> { static bool Fuzz(url::Origin* p, Fuzzer* fuzzer) { - bool opaque = p->unique(); + bool opaque = p->opaque(); if (!FuzzParam(&opaque, fuzzer)) return false; std::string scheme = p->GetTupleOrPrecursorTupleIfOpaque().scheme();
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 75cdcb8..8cc40b9 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -279,12 +279,16 @@ 'Android FYI Release (NVIDIA Shield TV)': 'android_release_trybot_arm64', 'Android FYI 32 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot', 'Android FYI 32 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot', + 'Android FYI 32 Vk Release (Pixel XL)': 'gpu_tests_android_vulkan_release_trybot', 'Android FYI 64 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot_arm64', 'Android FYI 64 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot_arm64', + 'Android FYI 64 Vk Release (Pixel XL)': 'gpu_tests_android_vulkan_release_trybot_arm64', 'Android FYI 32 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot', 'Android FYI 32 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot', + 'Android FYI 32 dEQP Vk Release (Pixel XL)': 'deqp_android_vulkan_release_trybot', 'Android FYI 64 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot_arm64', 'Android FYI 64 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot_arm64', + 'Android FYI 64 dEQP Vk Release (Pixel XL)': 'deqp_android_vulkan_release_trybot_arm64', 'GPU FYI Linux Builder': 'gpu_fyi_tests_release_trybot', 'GPU FYI Linux Ozone Builder': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot', 'GPU FYI Linux Builder (dbg)': 'gpu_fyi_tests_debug_trybot', @@ -560,6 +564,10 @@ 'gpu-manual-try-android-p-pixel-2-32-deqp': 'deqp_android_vulkan_release_trybot', 'gpu-manual-try-android-p-pixel-2-64': 'gpu_tests_android_vulkan_release_trybot_arm64', 'gpu-manual-try-android-p-pixel-2-64-deqp': 'deqp_android_vulkan_release_trybot_arm64', + 'gpu-manual-try-android-p-pixel-xl-32': 'gpu_tests_android_vulkan_release_trybot', + 'gpu-manual-try-android-p-pixel-xl-32-deqp': 'deqp_android_vulkan_release_trybot', + 'gpu-manual-try-android-p-pixel-xl-64': 'gpu_tests_android_vulkan_release_trybot_arm64', + 'gpu-manual-try-android-p-pixel-xl-64-deqp': 'deqp_android_vulkan_release_trybot_arm64', 'linux_android_dbg_ng': 'android_debug_trybot', 'try-nougat-phone-tester': 'android_debug_trybot_arm64', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 11f8dcc1..f6f891d2 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -4756,6 +4756,11 @@ <int value="1" label="Connection's visitor is a nullptr"/> </enum> +<enum name="BooleanOffered"> + <int value="0" label="Not offered"/> + <int value="1" label="Offered"/> +</enum> + <enum name="BooleanOnBattery"> <int value="0" label="Not on battery"/> <int value="1" label="On Battery"/> @@ -4935,7 +4940,7 @@ </enum> <enum name="BooleanSelected"> - <int value="0" label="No selection"/> + <int value="0" label="Not selected"/> <int value="1" label="Selected"/> </enum> @@ -16875,6 +16880,7 @@ <int value="1280" label="AUTOTESTPRIVATE_LAUNCHAPP"/> <int value="1281" label="AUTOTESTPRIVATE_BOOTSTRAPMACHINELEARNINGSERVICE"/> <int value="1282" label="AUTOTESTPRIVATE_RUNCROSTINIUNINSTALLER"/> + <int value="1283" label="AUTOTESTPRIVATE_TAKESCREENSHOT"/> </enum> <enum name="ExtensionIconState"> @@ -20239,6 +20245,12 @@ <int value="2546" label="SerialRequestPort"/> <int value="2547" label="SerialPortOpen"/> <int value="2548" label="SerialPortClose"/> + <int value="2549" label="BackgroundFetchManagerFetch"/> + <int value="2550" label="BackgroundFetchManagerGet"/> + <int value="2551" label="BackgroundFetchManagerGetIds"/> + <int value="2552" label="BackgroundFetchRegistrationAbort"/> + <int value="2553" label="BackgroundFetchRegistrationMatch"/> + <int value="2554" label="BackgroundFetchRegistrationMatchAll"/> </enum> <enum name="FeaturePolicyFeature"> @@ -25133,6 +25145,10 @@ </enum> <enum name="IE7LookupResultStatus"> + <obsolete> + Deprecated as of 07/2018. The corresponding metric was deleted in + https://chromium-review.googlesource.com/c/chromium/src/+/1131495. + </obsolete> <int value="0" label="No stored passwords from IE7 found."/> <int value="1" label="Some stored passwords from IE7 found."/> </enum>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 0d7799e..1db9907 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -68386,7 +68386,7 @@ </summary> </histogram> -<histogram name="Omnibox.SuggestionUsed.OfferedTabMatch" units="Boolean"> +<histogram name="Omnibox.SuggestionUsed.OfferedTabMatch" enum="BooleanOffered"> <owner>krb@chromium.org</owner> <owner>jdonnelly@chromium.org</owner> <summary> @@ -68518,7 +68518,8 @@ </summary> </histogram> -<histogram name="Omnibox.SuggestionUsed.SelectedTabMatch" units="Boolean"> +<histogram name="Omnibox.SuggestionUsed.SelectedTabMatch" + enum="BooleanSelected"> <owner>krb@chromium.org</owner> <owner>jdonnelly@chromium.org</owner> <summary>
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 6146e8d..53fdd3d 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -90,6 +90,7 @@ <item id="doodle_service" hash_code="41154842" type="0" deprecated="2017-08-28" content_hash_code="28273962" file_path=""/> <item id="download_internals_webui_source" hash_code="38670228" type="0" content_hash_code="129391056" os_list="linux,windows" file_path="chrome/browser/ui/webui/download_internals/download_internals_ui_message_handler.cc"/> <item id="download_manager_resume" hash_code="35380758" type="0" content_hash_code="41227674" os_list="linux,windows" file_path="components/download/internal/common/download_item_impl.cc"/> + <item id="download_recovery_component" hash_code="131711536" type="0" content_hash_code="110581751" os_list="windows" file_path="chrome/chrome_cleaner/components/recovery_component.cc"/> <item id="download_web_contents_frame" hash_code="56351037" type="0" content_hash_code="3657889" os_list="linux,windows" file_path="content/browser/web_contents/web_contents_impl.cc"/> <item id="downloads_api_run_async" hash_code="121068967" type="0" content_hash_code="87443585" os_list="linux,windows" file_path="chrome/browser/extensions/api/downloads/downloads_api.cc"/> <item id="drag_download_file" hash_code="95910019" type="0" content_hash_code="126492858" os_list="linux,windows" file_path="content/browser/download/drag_download_file.cc"/>
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 4ca78b4..76f70cf 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -171,4 +171,6 @@ IsMultiProcessMash(); } +const base::Feature kDarkMode = {"DarkMode", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index dce8a9f..45936e1 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -90,6 +90,10 @@ UI_BASE_EXPORT extern const base::Feature kEnableOzoneDrmMojo; UI_BASE_EXPORT bool IsOzoneDrmMojo(); +// Whether default UI should use a dark mode color scheme, if enabled on +// macOS Mojave/Windows 10, or the --force-dark-mode flag is provided. +UI_BASE_EXPORT extern const base::Feature kDarkMode; + } // namespace features #endif // UI_BASE_UI_BASE_FEATURES_H_
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 5135d30..e78872c 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -54,6 +54,11 @@ all_dependent_configs = [ ":flags" ] public = [ + # TODO(ccameron): Move these sources to the views_bridge_mac component + "../views_bridge_mac/bridge_factory_impl.h", + "../views_bridge_mac/bridged_native_widget_impl.h", + "../views_bridge_mac/native_widget_mac_nswindow.h", + "../views_bridge_mac/window_touch_bar_delegate.h", "accessibility/view_accessibility.h", "accessibility/view_accessibility_utils.h", "accessible_pane_view.h", @@ -86,10 +91,6 @@ "bubble/tooltip_icon.h", "button_drag_utils.h", "cocoa/bridge_factory_host.h", - "cocoa/bridge_factory_impl.h", - "cocoa/bridged_native_widget.h", - "cocoa/native_widget_mac_nswindow.h", - "cocoa/window_touch_bar_delegate.h", "color_chooser/color_chooser_listener.h", "color_chooser/color_chooser_view.h", "context_menu_controller.h", @@ -260,6 +261,9 @@ ] sources = [ + # TODO(ccameron): Move these sources to the views_bridge_mac component + "../views_bridge_mac/bridged_native_widget_impl.mm", + "../views_bridge_mac/native_widget_mac_nswindow.mm", "accessibility/view_accessibility.cc", "accessibility/view_accessibility_utils.cc", "accessible_pane_view.cc", @@ -286,8 +290,6 @@ "bubble/info_bubble.cc", "bubble/tooltip_icon.cc", "button_drag_utils.cc", - "cocoa/bridged_native_widget.mm", - "cocoa/native_widget_mac_nswindow.mm", "color_chooser/color_chooser_view.cc", "controls/animated_icon_view.cc", "controls/button/blue_button.cc", @@ -440,26 +442,27 @@ # Internal sources. TODO(https://crbug.com/871123): Move more headers from # public into this list, along with the implementation file. sources += [ + # TODO(ccameron): Move these sources to the views_bridge_mac component + "../views_bridge_mac/bridge_factory_impl.mm", + "../views_bridge_mac/bridged_content_view.h", + "../views_bridge_mac/bridged_content_view.mm", + "../views_bridge_mac/bridged_content_view_touch_bar.mm", + "../views_bridge_mac/bridged_native_widget_owner.h", + "../views_bridge_mac/cocoa_window_move_loop.h", + "../views_bridge_mac/cocoa_window_move_loop.mm", + "../views_bridge_mac/views_nswindow_delegate.h", + "../views_bridge_mac/views_nswindow_delegate.mm", + "../views_bridge_mac/views_scrollbar_bridge.h", + "../views_bridge_mac/views_scrollbar_bridge.mm", + "../views_bridge_mac/widget_owner_nswindow_adapter.h", + "../views_bridge_mac/widget_owner_nswindow_adapter.mm", "cocoa/bridge_factory_host.cc", - "cocoa/bridge_factory_impl.mm", - "cocoa/bridged_content_view.h", - "cocoa/bridged_content_view.mm", - "cocoa/bridged_content_view_touch_bar.mm", "cocoa/bridged_native_widget_host_impl.h", "cocoa/bridged_native_widget_host_impl.mm", - "cocoa/bridged_native_widget_owner.h", - "cocoa/cocoa_window_move_loop.h", - "cocoa/cocoa_window_move_loop.mm", "cocoa/drag_drop_client_mac.h", "cocoa/drag_drop_client_mac.mm", "cocoa/tooltip_manager_mac.h", "cocoa/tooltip_manager_mac.mm", - "cocoa/views_nswindow_delegate.h", - "cocoa/views_nswindow_delegate.mm", - "cocoa/views_scrollbar_bridge.h", - "cocoa/views_scrollbar_bridge.mm", - "cocoa/widget_owner_nswindow_adapter.h", - "cocoa/widget_owner_nswindow_adapter.mm", "controls/button/label_button_label.cc", "controls/button/label_button_label.h", "controls/menu/menu_pre_target_handler.h",
diff --git a/ui/views/DEPS b/ui/views/DEPS index 020d58c..a2d0ab1 100644 --- a/ui/views/DEPS +++ b/ui/views/DEPS
@@ -21,6 +21,7 @@ "+ui/resources/grit/ui_resources.h", "+ui/strings/grit/ui_strings.h", "+ui/touch_selection", + "+ui/views_bridge_mac", "+ui/wm/core", "+ui/wm/public",
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h index 6ce0158..8d65614 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view.h +++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -186,8 +186,9 @@ void UpdateAnchorWidgetRenderState(bool visible); // Update the button highlight, which may be the anchor view or an explicit - // view set in |highlighted_button_tracker_|. - void UpdateHighlightedButton(bool highlighted); + // view set in |highlighted_button_tracker_|. This can be overridden to + // provide different highlight effects. + virtual void UpdateHighlightedButton(bool highlighted); // A flag controlling bubble closure on deactivation. bool close_on_deactivate_;
diff --git a/ui/views/cocoa/DEPS b/ui/views/cocoa/DEPS index fcaeee7..440d45f5 100644 --- a/ui/views/cocoa/DEPS +++ b/ui/views/cocoa/DEPS
@@ -1,5 +1,4 @@ include_rules = [ - "+components/viz/common", "+ui/accelerated_widget_mac", "+ui/views_bridge_mac", ]
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm index ebeed25..eb7c6016 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.mm +++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -14,8 +14,6 @@ #include "ui/display/screen.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/native_theme/native_theme_mac.h" -#include "ui/views/cocoa/bridged_native_widget.h" -#include "ui/views/cocoa/native_widget_mac_nswindow.h" #include "ui/views/cocoa/tooltip_manager_mac.h" #include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_controller.h" @@ -26,7 +24,9 @@ #include "ui/views/window/dialog_client_view.h" #include "ui/views/window/dialog_delegate.h" #include "ui/views/word_lookup_client.h" +#include "ui/views_bridge_mac/bridged_native_widget_impl.h" #include "ui/views_bridge_mac/cocoa_mouse_capture.h" +#include "ui/views_bridge_mac/native_widget_mac_nswindow.h" using views_bridge_mac::mojom::BridgedNativeWidgetInitParams; using views_bridge_mac::mojom::WindowVisibilityState;
diff --git a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm index 37c289d..38f7167 100644 --- a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm +++ b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" #import <Cocoa/Cocoa.h>
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm index d607ad8..3d3c149 100644 --- a/ui/views/cocoa/bridged_native_widget_unittest.mm +++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" #import <Cocoa/Cocoa.h> @@ -25,10 +25,7 @@ #include "ui/base/test/material_design_controller_test_api.h" #include "ui/events/test/cocoa_test_event_utils.h" #import "ui/gfx/mac/coordinate_conversion.h" -#import "ui/views/cocoa/bridged_content_view.h" #import "ui/views/cocoa/bridged_native_widget_host_impl.h" -#import "ui/views/cocoa/native_widget_mac_nswindow.h" -#import "ui/views/cocoa/views_nswindow_delegate.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/controls/textfield/textfield_model.h" @@ -38,6 +35,9 @@ #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" +#import "ui/views_bridge_mac/bridged_content_view.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" +#import "ui/views_bridge_mac/views_nswindow_delegate.h" using base::ASCIIToUTF16; using base::SysNSStringToUTF8;
diff --git a/ui/views/cocoa/drag_drop_client_mac.mm b/ui/views/cocoa/drag_drop_client_mac.mm index 7a4741e..2df3335 100644 --- a/ui/views/cocoa/drag_drop_client_mac.mm +++ b/ui/views/cocoa/drag_drop_client_mac.mm
@@ -10,9 +10,9 @@ #import "ui/base/dragdrop/os_exchange_data_provider_mac.h" #include "ui/gfx/image/image_skia_util_mac.h" #include "ui/views/drag_utils.h" -#import "ui/views/cocoa/bridged_content_view.h" -#import "ui/views/cocoa/bridged_native_widget.h" #include "ui/views/widget/native_widget_mac.h" +#import "ui/views_bridge_mac/bridged_content_view.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" @interface CocoaDragDropDataProvider () - (id)initWithData:(const ui::OSExchangeData&)data;
diff --git a/ui/views/cocoa/drag_drop_client_mac_unittest.mm b/ui/views/cocoa/drag_drop_client_mac_unittest.mm index 47c8ffe6..4202d53 100644 --- a/ui/views/cocoa/drag_drop_client_mac_unittest.mm +++ b/ui/views/cocoa/drag_drop_client_mac_unittest.mm
@@ -13,12 +13,12 @@ #include "base/threading/thread_task_runner_handle.h" #import "ui/base/clipboard/clipboard_util_mac.h" #include "ui/gfx/image/image_unittest_util.h" -#import "ui/views/cocoa/bridged_native_widget.h" #import "ui/views/cocoa/bridged_native_widget_host_impl.h" #include "ui/views/test/widget_test.h" #include "ui/views/view.h" #include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" using base::ASCIIToUTF16;
diff --git a/ui/views/cocoa/tooltip_manager_mac.mm b/ui/views/cocoa/tooltip_manager_mac.mm index 3699ae9..8762de8 100644 --- a/ui/views/cocoa/tooltip_manager_mac.mm +++ b/ui/views/cocoa/tooltip_manager_mac.mm
@@ -7,8 +7,8 @@ #include "ui/base/cocoa/cocoa_base_utils.h" #include "ui/gfx/font_list.h" #import "ui/gfx/mac/coordinate_conversion.h" -#import "ui/views/cocoa/bridged_content_view.h" -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_content_view.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace {
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/ui/views/controls/scrollbar/cocoa_scroll_bar.h index a0c8872..c69087a 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.h +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -5,13 +5,13 @@ #ifndef UI_VIEWS_CONTROLS_SCROLLBAR_COCOA_SCROLL_BAR_H_ #define UI_VIEWS_CONTROLS_SCROLLBAR_COCOA_SCROLL_BAR_H_ -#include "base/macros.h" #import "base/mac/scoped_nsobject.h" +#include "base/macros.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/gfx/animation/slide_animation.h" -#import "ui/views/cocoa/views_scrollbar_bridge.h" #include "ui/views/controls/scrollbar/base_scroll_bar.h" #include "ui/views/views_export.h" +#import "ui/views_bridge_mac/views_scrollbar_bridge.h" namespace views {
diff --git a/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm b/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm index ece41dd..e87f913 100644 --- a/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm +++ b/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm
@@ -5,7 +5,7 @@ #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" #import "base/mac/foundation_util.h" -#import "ui/views/cocoa/native_widget_mac_nswindow.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" namespace views {
diff --git a/ui/views/test/platform_test_helper_cocoa.mm b/ui/views/test/platform_test_helper_cocoa.mm index 5354cd4..50c91e9 100644 --- a/ui/views/test/platform_test_helper_cocoa.mm +++ b/ui/views/test/platform_test_helper_cocoa.mm
@@ -9,9 +9,9 @@ #import "base/mac/scoped_nsobject.h" #import "base/mac/scoped_objc_class_swizzler.h" #include "base/macros.h" -#import "ui/views/cocoa/bridged_native_widget.h" #include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views {
diff --git a/ui/views/test/widget_test_mac.mm b/ui/views/test/widget_test_mac.mm index f4f45c9..05bae8b 100644 --- a/ui/views/test/widget_test_mac.mm +++ b/ui/views/test/widget_test_mac.mm
@@ -9,10 +9,10 @@ #import "base/mac/scoped_nsobject.h" #import "base/mac/scoped_objc_class_swizzler.h" #include "base/macros.h" -#import "ui/views/cocoa/bridged_native_widget.h" #include "ui/views/cocoa/bridged_native_widget_host_impl.h" #include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/root_view.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views { namespace test {
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index e14e355..680434d5 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -24,15 +24,15 @@ #import "ui/gfx/mac/nswindow_frame_controls.h" #include "ui/native_theme/native_theme.h" #include "ui/native_theme/native_theme_mac.h" -#import "ui/views/cocoa/bridged_content_view.h" -#import "ui/views/cocoa/bridged_native_widget.h" #import "ui/views/cocoa/bridged_native_widget_host_impl.h" #import "ui/views/cocoa/drag_drop_client_mac.h" -#import "ui/views/cocoa/native_widget_mac_nswindow.h" -#import "ui/views/cocoa/views_nswindow_delegate.h" #include "ui/views/widget/drop_helper.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/window/native_frame_view.h" +#import "ui/views_bridge_mac/bridged_content_view.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" +#import "ui/views_bridge_mac/views_nswindow_delegate.h" using views_bridge_mac::mojom::WindowVisibilityState;
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm index b4ae028..6f9b147b 100644 --- a/ui/views/widget/native_widget_mac_unittest.mm +++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -28,9 +28,6 @@ #include "ui/events/test/event_generator.h" #import "ui/gfx/mac/coordinate_conversion.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" -#import "ui/views/cocoa/bridged_content_view.h" -#import "ui/views/cocoa/bridged_native_widget.h" -#import "ui/views/cocoa/native_widget_mac_nswindow.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/label.h" #include "ui/views/controls/native/native_view_host.h" @@ -42,6 +39,9 @@ #include "ui/views/widget/native_widget_private.h" #include "ui/views/window/dialog_client_view.h" #include "ui/views/window/dialog_delegate.h" +#import "ui/views_bridge_mac/bridged_content_view.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" // Donates an implementation of -[NSAnimation stopAnimation] which calls the // original implementation, then quits a nested run loop.
diff --git a/ui/views/widget/widget_utils_mac.mm b/ui/views/widget/widget_utils_mac.mm index 37eb7bf..990e17fa 100644 --- a/ui/views/widget/widget_utils_mac.mm +++ b/ui/views/widget/widget_utils_mac.mm
@@ -4,7 +4,7 @@ #include "ui/views/widget/widget_utils_mac.h" -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views {
diff --git a/ui/views_bridge_mac/DEPS b/ui/views_bridge_mac/DEPS index 5022afb..612029d 100644 --- a/ui/views_bridge_mac/DEPS +++ b/ui/views_bridge_mac/DEPS
@@ -1,5 +1,17 @@ include_rules = [ + "+components/crash/core/common/crash_key.h", + "+components/viz/common", + "+mojo/public/cpp/bindings", + "+skia/ext", + "+ui/accelerated_widget_mac", "+ui/base", + "+ui/compositor", + "+ui/display", "+ui/events", "+ui/gfx", + # TODO(ccameron): This can be removed when sources are moved to the + # views_bridge_mac component. + "+ui/views/views_export.h", + # TODO(ccameron): This file should be moved to forward declarations. + "+ui/views/widget/util_mac.h", ]
diff --git a/ui/views/cocoa/bridge_factory_impl.h b/ui/views_bridge_mac/bridge_factory_impl.h similarity index 89% rename from ui/views/cocoa/bridge_factory_impl.h rename to ui/views_bridge_mac/bridge_factory_impl.h index 1723c305..197820e5 100644 --- a/ui/views/cocoa/bridge_factory_impl.h +++ b/ui/views_bridge_mac/bridge_factory_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_BRIDGE_FACTORY_IMPL_H_ -#define UI_VIEWS_COCOA_BRIDGE_FACTORY_IMPL_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_ +#define UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_ #include "mojo/public/cpp/bindings/binding.h" #include "ui/views/views_export.h" @@ -38,4 +38,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_COCOA_BRIDGE_FACTORY_IMPL_H_ +#endif // UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_
diff --git a/ui/views/cocoa/bridge_factory_impl.mm b/ui/views_bridge_mac/bridge_factory_impl.mm similarity index 95% rename from ui/views/cocoa/bridge_factory_impl.mm rename to ui/views_bridge_mac/bridge_factory_impl.mm index f909e24..947249d 100644 --- a/ui/views/cocoa/bridge_factory_impl.mm +++ b/ui/views_bridge_mac/bridge_factory_impl.mm
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/views/cocoa/bridge_factory_impl.h" +#include "ui/views_bridge_mac/bridge_factory_impl.h" #include "base/no_destructor.h" -#include "ui/views/cocoa/bridged_native_widget.h" #include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" +#include "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views_bridge_mac {
diff --git a/ui/views/cocoa/bridged_content_view.h b/ui/views_bridge_mac/bridged_content_view.h similarity index 94% rename from ui/views/cocoa/bridged_content_view.h rename to ui/views_bridge_mac/bridged_content_view.h index 46ee823..a4848e67 100644 --- a/ui/views/cocoa/bridged_content_view.h +++ b/ui/views_bridge_mac/bridged_content_view.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_ -#define UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_ +#define UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_ #import <Cocoa/Cocoa.h> @@ -82,4 +82,4 @@ @end -#endif // UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_ +#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_
diff --git a/ui/views/cocoa/bridged_content_view.mm b/ui/views_bridge_mac/bridged_content_view.mm similarity index 98% rename from ui/views/cocoa/bridged_content_view.mm rename to ui/views_bridge_mac/bridged_content_view.mm index 89b149b..d4115a0 100644 --- a/ui/views/cocoa/bridged_content_view.mm +++ b/ui/views_bridge_mac/bridged_content_view.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/bridged_content_view.h" +#import "ui/views_bridge_mac/bridged_content_view.h" #include "base/logging.h" #import "base/mac/foundation_util.h" @@ -31,9 +31,9 @@ #include "ui/gfx/path.h" #import "ui/gfx/path_mac.h" #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" -#import "ui/views/cocoa/bridged_native_widget.h" -#import "ui/views/cocoa/drag_drop_client_mac.h" #include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#import "ui/views_bridge_mac/drag_drop_client.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h" namespace { @@ -48,9 +48,9 @@ gfx::Point MovePointToWindow(const NSPoint& point, NSWindow* source_window, NSWindow* target_window) { - NSPoint point_in_screen = source_window - ? ui::ConvertPointFromWindowToScreen(source_window, point) - : point; + NSPoint point_in_screen = + source_window ? ui::ConvertPointFromWindowToScreen(source_window, point) + : point; NSPoint point_in_window = ui::ConvertPointFromScreenToWindow(target_window, point_in_screen); @@ -1338,8 +1338,9 @@ // or (string, string). BOOL valid = textInputClient_ && ((canWrite && (canRead || !returnType)) || (canRead && (canWrite || !sendType))); - return valid ? self : [super validRequestorForSendType:sendType - returnType:returnType]; + return valid + ? self + : [super validRequestorForSendType:sendType returnType:returnType]; } // NSServicesMenuRequestor protocol @@ -1380,9 +1381,9 @@ // |self|) that we're trying to invalidate in -setTextInputClient:. // See https://crbug.com/817097#c12 for further details on this atrocity. -- (NSAttributedString*) - attributedSubstringForProposedRange:(NSRange)range - actualRange:(NSRangePointer)actualRange { +- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range + actualRange: + (NSRangePointer)actualRange { // On TouchBar Macs, the IME subsystem sometimes sends an invalid range with a // non-zero length. This will cause a DCHECK in gfx::Range, so repair it here. // See https://crbug.com/888782.
diff --git a/ui/views/cocoa/bridged_content_view_touch_bar.mm b/ui/views_bridge_mac/bridged_content_view_touch_bar.mm similarity index 96% rename from ui/views/cocoa/bridged_content_view_touch_bar.mm rename to ui/views_bridge_mac/bridged_content_view_touch_bar.mm index 0c88d28..008f7ff 100644 --- a/ui/views/cocoa/bridged_content_view_touch_bar.mm +++ b/ui/views_bridge_mac/bridged_content_view_touch_bar.mm
@@ -7,8 +7,8 @@ #import "base/mac/sdk_forward_declarations.h" #include "base/strings/sys_string_conversions.h" #import "ui/base/cocoa/touch_bar_forward_declarations.h" -#import "ui/views/cocoa/bridged_content_view.h" -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_content_view.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h" namespace {
diff --git a/ui/views/cocoa/bridged_native_widget.h b/ui/views_bridge_mac/bridged_native_widget_impl.h similarity index 97% rename from ui/views/cocoa/bridged_native_widget.h rename to ui/views_bridge_mac/bridged_native_widget_impl.h index 8758fa4..450b3ef 100644 --- a/ui/views/cocoa/bridged_native_widget.h +++ b/ui/views_bridge_mac/bridged_native_widget_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_ -#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_ +#define UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_ #import <Cocoa/Cocoa.h> @@ -18,8 +18,8 @@ #include "ui/accelerated_widget_mac/display_ca_layer_tree.h" #include "ui/base/ime/text_input_client.h" #include "ui/display/display_observer.h" -#import "ui/views/cocoa/bridged_native_widget_owner.h" #include "ui/views/views_export.h" +#import "ui/views_bridge_mac/bridged_native_widget_owner.h" #import "ui/views_bridge_mac/cocoa_mouse_capture_delegate.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h" @@ -346,4 +346,4 @@ } // namespace views -#endif // UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_ +#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views_bridge_mac/bridged_native_widget_impl.mm similarity index 98% rename from ui/views/cocoa/bridged_native_widget.mm rename to ui/views_bridge_mac/bridged_native_widget_impl.mm index 6a538dc..8766a0f 100644 --- a/ui/views/cocoa/bridged_native_widget.mm +++ b/ui/views_bridge_mac/bridged_native_widget_impl.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" #import <objc/runtime.h> #include <stddef.h> @@ -27,15 +27,14 @@ #include "ui/gfx/geometry/dip_util.h" #import "ui/gfx/mac/coordinate_conversion.h" #import "ui/gfx/mac/nswindow_frame_controls.h" -#import "ui/views/cocoa/bridged_content_view.h" -#import "ui/views/cocoa/cocoa_window_move_loop.h" -#import "ui/views/cocoa/drag_drop_client_mac.h" -#import "ui/views/cocoa/native_widget_mac_nswindow.h" -#import "ui/views/cocoa/views_nswindow_delegate.h" -#import "ui/views/cocoa/widget_owner_nswindow_adapter.h" +#import "ui/views_bridge_mac/bridged_content_view.h" #import "ui/views_bridge_mac/bridged_native_widget_host_helper.h" #import "ui/views_bridge_mac/cocoa_mouse_capture.h" +#import "ui/views_bridge_mac/cocoa_window_move_loop.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" +#import "ui/views_bridge_mac/views_nswindow_delegate.h" +#import "ui/views_bridge_mac/widget_owner_nswindow_adapter.h" using views_bridge_mac::mojom::VisibilityTransition; using views_bridge_mac::mojom::WindowVisibilityState; @@ -596,8 +595,7 @@ parent_window_number = [parent_->GetNSWindow() windowNumber]; } - [window_ orderWindow:NSWindowAbove - relativeTo:parent_window_number]; + [window_ orderWindow:NSWindowAbove relativeTo:parent_window_number]; } DCHECK(window_visible_); @@ -1139,8 +1137,8 @@ void BridgedNativeWidgetImpl::RemoveChildWindow( BridgedNativeWidgetImpl* child) { - auto location = std::find( - child_windows_.begin(), child_windows_.end(), child); + auto location = + std::find(child_windows_.begin(), child_windows_.end(), child); DCHECK(location != child_windows_.end()); child_windows_.erase(location);
diff --git a/ui/views/cocoa/bridged_native_widget_owner.h b/ui/views_bridge_mac/bridged_native_widget_owner.h similarity index 87% rename from ui/views/cocoa/bridged_native_widget_owner.h rename to ui/views_bridge_mac/bridged_native_widget_owner.h index c9e15b5e..1e87e8dce 100644 --- a/ui/views/cocoa/bridged_native_widget_owner.h +++ b/ui/views_bridge_mac/bridged_native_widget_owner.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_OWNER_H_ -#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_OWNER_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_OWNER_H_ +#define UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_OWNER_H_ namespace gfx { class Vector2d; @@ -41,4 +41,4 @@ } // namespace views -#endif // UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_OWNER_H_ +#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_OWNER_H_
diff --git a/ui/views_bridge_mac/cocoa_mouse_capture.h b/ui/views_bridge_mac/cocoa_mouse_capture.h index 5ac379b..b7dedad 100644 --- a/ui/views_bridge_mac/cocoa_mouse_capture.h +++ b/ui/views_bridge_mac/cocoa_mouse_capture.h
@@ -50,4 +50,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_COCOA_COCOA_MOUSE_CAPTURE_H_ +#endif // UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_H_
diff --git a/ui/views/cocoa/cocoa_window_move_loop.h b/ui/views_bridge_mac/cocoa_window_move_loop.h similarity index 87% rename from ui/views/cocoa/cocoa_window_move_loop.h rename to ui/views_bridge_mac/cocoa_window_move_loop.h index 68699ff..ff074d8 100644 --- a/ui/views/cocoa/cocoa_window_move_loop.h +++ b/ui/views_bridge_mac/cocoa_window_move_loop.h
@@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_COCOA_WINDOW_MOVE_LOOP_H_ -#define UI_VIEWS_COCOA_COCOA_WINDOW_MOVE_LOOP_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_ +#define UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_ #import <Cocoa/Cocoa.h> #include "base/callback.h" #include "base/memory/weak_ptr.h" -#include "ui/views/widget/widget.h" namespace views { class BridgedNativeWidgetImpl; @@ -51,4 +50,4 @@ } // namespace views -#endif // UI_VIEWS_COCOA_COCOA_WINDOW_MOVE_LOOP_H_ +#endif // UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_
diff --git a/ui/views/cocoa/cocoa_window_move_loop.mm b/ui/views_bridge_mac/cocoa_window_move_loop.mm similarity index 97% rename from ui/views/cocoa/cocoa_window_move_loop.mm rename to ui/views_bridge_mac/cocoa_window_move_loop.mm index 2d7dfdc..4b2c64f0 100644 --- a/ui/views/cocoa/cocoa_window_move_loop.mm +++ b/ui/views_bridge_mac/cocoa_window_move_loop.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/views/cocoa/cocoa_window_move_loop.h" +#include "ui/views_bridge_mac/cocoa_window_move_loop.h" #include "base/debug/stack_trace.h" #include "base/run_loop.h" @@ -10,7 +10,7 @@ #include "components/crash/core/common/crash_key.h" #include "ui/display/screen.h" #import "ui/gfx/mac/coordinate_conversion.h" -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" // When event monitors process the events the full list of monitors is cached, // and if we unregister the event monitor that's at the end of the list while
diff --git a/ui/views/cocoa/native_widget_mac_nswindow.h b/ui/views_bridge_mac/native_widget_mac_nswindow.h similarity index 90% rename from ui/views/cocoa/native_widget_mac_nswindow.h rename to ui/views_bridge_mac/native_widget_mac_nswindow.h index 8686a4f..ef8afe1 100644 --- a/ui/views/cocoa/native_widget_mac_nswindow.h +++ b/ui/views_bridge_mac/native_widget_mac_nswindow.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NSWINDOW_H_ -#define UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NSWINDOW_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_ +#define UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_ #import <Cocoa/Cocoa.h> @@ -53,4 +53,4 @@ @property(assign, nonatomic) uint64_t bridgedNativeWidgetId; @end -#endif // UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NSWINDOW_H_ +#endif // UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_
diff --git a/ui/views/cocoa/native_widget_mac_nswindow.mm b/ui/views_bridge_mac/native_widget_mac_nswindow.mm similarity index 97% rename from ui/views/cocoa/native_widget_mac_nswindow.mm rename to ui/views_bridge_mac/native_widget_mac_nswindow.mm index 7af14d0..f0e7ac7 100644 --- a/ui/views/cocoa/native_widget_mac_nswindow.mm +++ b/ui/views_bridge_mac/native_widget_mac_nswindow.mm
@@ -2,18 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/native_widget_mac_nswindow.h" +#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" #include "base/mac/foundation_util.h" #import "base/mac/sdk_forward_declarations.h" #import "ui/base/cocoa/user_interface_item_command_handler.h" #import "ui/base/cocoa/window_size_constants.h" -#import "ui/views/cocoa/bridged_native_widget.h" -#import "ui/views/cocoa/views_nswindow_delegate.h" -#import "ui/views/cocoa/window_touch_bar_delegate.h" -#include "ui/views/controls/menu/menu_controller.h" #include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h" +#import "ui/views_bridge_mac/views_nswindow_delegate.h" +#import "ui/views_bridge_mac/window_touch_bar_delegate.h" @interface NSWindow (Private) + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle;
diff --git a/ui/views/cocoa/views_nswindow_delegate.h b/ui/views_bridge_mac/views_nswindow_delegate.h similarity index 90% rename from ui/views/cocoa/views_nswindow_delegate.h rename to ui/views_bridge_mac/views_nswindow_delegate.h index 98b41f3..bc9f33af 100644 --- a/ui/views/cocoa/views_nswindow_delegate.h +++ b/ui/views_bridge_mac/views_nswindow_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_VIEWS_NSWINDOW_DELEGATE_H_ -#define UI_VIEWS_COCOA_VIEWS_NSWINDOW_DELEGATE_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_ +#define UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_ #import <Cocoa/Cocoa.h> @@ -47,4 +47,4 @@ @end -#endif // UI_VIEWS_COCOA_VIEWS_NSWINDOW_DELEGATE_H_ +#endif // UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_
diff --git a/ui/views/cocoa/views_nswindow_delegate.mm b/ui/views_bridge_mac/views_nswindow_delegate.mm similarity index 96% rename from ui/views/cocoa/views_nswindow_delegate.mm rename to ui/views_bridge_mac/views_nswindow_delegate.mm index 24ab2be..ca77131 100644 --- a/ui/views/cocoa/views_nswindow_delegate.mm +++ b/ui/views_bridge_mac/views_nswindow_delegate.mm
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/views_nswindow_delegate.h" +#import "ui/views_bridge_mac/views_nswindow_delegate.h" #include "base/bind.h" #include "base/logging.h" #include "base/threading/thread_task_runner_handle.h" -#import "ui/views/cocoa/bridged_content_view.h" -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_content_view.h" #include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h" @implementation ViewsNSWindowDelegate @@ -60,7 +60,7 @@ break; currentWindow = parentWindow; if ([currentWindow isKeyWindow]) { - [(newCursor ? newCursor : [NSCursor arrowCursor]) set]; + [(newCursor ? newCursor : [NSCursor arrowCursor])set]; break; } }
diff --git a/ui/views/cocoa/views_scrollbar_bridge.h b/ui/views_bridge_mac/views_scrollbar_bridge.h similarity index 88% rename from ui/views/cocoa/views_scrollbar_bridge.h rename to ui/views_bridge_mac/views_scrollbar_bridge.h index eb070a1..7b5809e 100644 --- a/ui/views/cocoa/views_scrollbar_bridge.h +++ b/ui/views_bridge_mac/views_scrollbar_bridge.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_VIEWS_SCROLLBAR_BRIDGE_DELEGATE_H_ -#define UI_VIEWS_COCOA_VIEWS_SCROLLBAR_BRIDGE_DELEGATE_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_VIEWS_SCROLLBAR_BRIDGE_H_ +#define UI_VIEWS_BRIDGE_MAC_VIEWS_SCROLLBAR_BRIDGE_H_ #import <Cocoa/Cocoa.h> @@ -30,11 +30,11 @@ - (id)initWithDelegate:(ViewsScrollbarBridgeDelegate*)delegate; // Sets |delegate_| to nullptr. --(void)clearDelegate; +- (void)clearDelegate; // Returns the style of scrollers that OSX is using. + (NSScrollerStyle)getPreferredScrollerStyle; @end -#endif \ No newline at end of file +#endif
diff --git a/ui/views/cocoa/views_scrollbar_bridge.mm b/ui/views_bridge_mac/views_scrollbar_bridge.mm similarity index 95% rename from ui/views/cocoa/views_scrollbar_bridge.mm rename to ui/views_bridge_mac/views_scrollbar_bridge.mm index d80dece..c720483 100644 --- a/ui/views/cocoa/views_scrollbar_bridge.mm +++ b/ui/views_bridge_mac/views_scrollbar_bridge.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/views_scrollbar_bridge.h" +#import "ui/views_bridge_mac/views_scrollbar_bridge.h" #import "base/mac/sdk_forward_declarations.h"
diff --git a/ui/views/cocoa/widget_owner_nswindow_adapter.h b/ui/views_bridge_mac/widget_owner_nswindow_adapter.h similarity index 86% rename from ui/views/cocoa/widget_owner_nswindow_adapter.h rename to ui/views_bridge_mac/widget_owner_nswindow_adapter.h index 76d84c5..715306d6 100644 --- a/ui/views/cocoa/widget_owner_nswindow_adapter.h +++ b/ui/views_bridge_mac/widget_owner_nswindow_adapter.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_WIDGET_OWNER_NSWINDOW_ADAPTER_H_ -#define UI_VIEWS_COCOA_WIDGET_OWNER_NSWINDOW_ADAPTER_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_WIDGET_OWNER_NSWINDOW_ADAPTER_H_ +#define UI_VIEWS_BRIDGE_MAC_WIDGET_OWNER_NSWINDOW_ADAPTER_H_ #import "base/mac/scoped_nsobject.h" #include "base/macros.h" -#import "ui/views/cocoa/bridged_native_widget_owner.h" +#import "ui/views_bridge_mac/bridged_native_widget_owner.h" @class NSView; @class NSWindow; @@ -51,4 +51,4 @@ } // namespace views -#endif // UI_VIEWS_COCOA_WIDGET_OWNER_NSWINDOW_ADAPTER_H_ +#endif // UI_VIEWS_BRIDGE_MAC_WIDGET_OWNER_NSWINDOW_ADAPTER_H_
diff --git a/ui/views/cocoa/widget_owner_nswindow_adapter.mm b/ui/views_bridge_mac/widget_owner_nswindow_adapter.mm similarity index 97% rename from ui/views/cocoa/widget_owner_nswindow_adapter.mm rename to ui/views_bridge_mac/widget_owner_nswindow_adapter.mm index cbaabaf8..47ae95c3 100644 --- a/ui/views/cocoa/widget_owner_nswindow_adapter.mm +++ b/ui/views_bridge_mac/widget_owner_nswindow_adapter.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views/cocoa/widget_owner_nswindow_adapter.h" +#import "ui/views_bridge_mac/widget_owner_nswindow_adapter.h" #import <Cocoa/Cocoa.h> @@ -11,7 +11,7 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" #import "ui/gfx/mac/coordinate_conversion.h" -#import "ui/views/cocoa/bridged_native_widget.h" +#import "ui/views_bridge_mac/bridged_native_widget_impl.h" // Bridges an AppKit observer to observe when the (non-views) NSWindow owning a // views::Widget will close or change occlusion state.
diff --git a/ui/views/cocoa/window_touch_bar_delegate.h b/ui/views_bridge_mac/window_touch_bar_delegate.h similarity index 73% rename from ui/views/cocoa/window_touch_bar_delegate.h rename to ui/views_bridge_mac/window_touch_bar_delegate.h index ad9ea8f9..9de8671 100644 --- a/ui/views/cocoa/window_touch_bar_delegate.h +++ b/ui/views_bridge_mac/window_touch_bar_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_COCOA_WINDOW_TOUCH_BAR_DELEGATE_H_ -#define UI_VIEWS_COCOA_WINDOW_TOUCH_BAR_DELEGATE_H_ +#ifndef UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_ +#define UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_ #import <Cocoa/Cocoa.h> @@ -18,4 +18,4 @@ @end -#endif // UI_VIEWS_COCOA_WINDOW_TOUCH_BAR_DELEGATE_H_ +#endif // UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_
diff --git a/url/mojom/url_gurl_mojom_traits_unittest.cc b/url/mojom/url_gurl_mojom_traits_unittest.cc index cdacd51..a331ba2 100644 --- a/url/mojom/url_gurl_mojom_traits_unittest.cc +++ b/url/mojom/url_gurl_mojom_traits_unittest.cc
@@ -78,7 +78,7 @@ Origin output; EXPECT_TRUE(proxy->BounceOrigin(non_unique, &output)); EXPECT_EQ(non_unique, output); - EXPECT_FALSE(output.unique()); + EXPECT_FALSE(output.opaque()); Origin unique1; Origin unique2 = non_unique.DeriveNewOpaqueOrigin(); @@ -86,7 +86,7 @@ EXPECT_NE(unique2, unique1); EXPECT_NE(unique2, non_unique); EXPECT_TRUE(proxy->BounceOrigin(unique1, &output)); - EXPECT_TRUE(output.unique()); + EXPECT_TRUE(output.opaque()); EXPECT_EQ(unique1, output); Origin output2; EXPECT_TRUE(proxy->BounceOrigin(unique2, &output2)); @@ -100,7 +100,7 @@ EXPECT_TRUE(proxy->BounceOrigin(normalized, &output)); EXPECT_EQ(normalized, output); EXPECT_EQ(non_unique, output); - EXPECT_FALSE(output.unique()); + EXPECT_FALSE(output.opaque()); } } // namespace url
diff --git a/url/origin.cc b/url/origin.cc index fa334de..1c78bc9 100644 --- a/url/origin.cc +++ b/url/origin.cc
@@ -54,7 +54,7 @@ if (url.IsAboutBlank()) return base_origin; Origin result = Origin::Create(url); - if (!result.unique()) + if (!result.opaque()) return result; return base_origin.DeriveNewOpaqueOrigin(); } @@ -122,7 +122,7 @@ } std::string Origin::Serialize() const { - if (unique()) + if (opaque()) return "null"; if (scheme() == kFileScheme) @@ -132,7 +132,7 @@ } GURL Origin::GetURL() const { - if (unique()) + if (opaque()) return GURL(); if (scheme() == kFileScheme) @@ -155,7 +155,7 @@ } bool Origin::DomainIs(base::StringPiece canonical_domain) const { - return !unique() && url::DomainIs(tuple_.host(), canonical_domain); + return !opaque() && url::DomainIs(tuple_.host(), canonical_domain); } bool Origin::operator<(const Origin& other) const { @@ -167,14 +167,14 @@ } Origin::Origin(SchemeHostPort tuple) : tuple_(std::move(tuple)) { - DCHECK(!unique()); + DCHECK(!opaque()); DCHECK(!tuple_.IsInvalid()); } // Constructs an opaque origin derived from |precursor|. Origin::Origin(const Nonce& nonce, SchemeHostPort precursor) : tuple_(std::move(precursor)), nonce_(std::move(nonce)) { - DCHECK(unique()); + DCHECK(opaque()); // |precursor| is retained, but not accessible via scheme()/host()/port(). DCHECK_EQ("", scheme()); DCHECK_EQ("", host()); @@ -184,7 +184,7 @@ std::ostream& operator<<(std::ostream& out, const url::Origin& origin) { out << origin.Serialize(); - if (origin.unique()) { + if (origin.opaque()) { // For opaque origins, log the nonce and precursor as well. Without this, // EXPECT_EQ failures between opaque origins are nearly impossible to // understand.
diff --git a/url/origin.h b/url/origin.h index 4e1d349..c34779f 100644 --- a/url/origin.h +++ b/url/origin.h
@@ -104,7 +104,7 @@ // origin.scheme(); // "https" // origin.host(); // "example.com" // origin.port(); // 443 -// origin.unique(); // false +// origin.opaque(); // false // // * To answer the question "Are |this| and |that| "same-origin" with each // other?", use |Origin::IsSameOriginWith|: @@ -171,15 +171,14 @@ // For opaque origins, these return ("", "", 0). const std::string& scheme() const { - return !unique() ? tuple_.scheme() : base::EmptyString(); + return !opaque() ? tuple_.scheme() : base::EmptyString(); } const std::string& host() const { - return !unique() ? tuple_.host() : base::EmptyString(); + return !opaque() ? tuple_.host() : base::EmptyString(); } - uint16_t port() const { return !unique() ? tuple_.port() : 0; } + uint16_t port() const { return !opaque() ? tuple_.port() : 0; } - // TODO(dcheng): Rename this to opaque(). - bool unique() const { return nonce_.has_value(); } + bool opaque() const { return nonce_.has_value(); } // An ASCII serialization of the Origin as per Section 6.2 of RFC 6454, with // the addition that all Origins with a 'file' scheme serialize to "file://". @@ -228,7 +227,7 @@ // URL (e.g. with a path component). GURL GetURL() const; - // Same as GURL::DomainIs. If |this| origin is unique, then returns false. + // Same as GURL::DomainIs. If |this| origin is opaque, then returns false. bool DomainIs(base::StringPiece canonical_domain) const; // Allows Origin to be used as a key in STL (for example, a std::set or @@ -343,7 +342,7 @@ // given |nonce|. Origin(const Nonce& nonce, SchemeHostPort precursor); - // Get the nonce associated with this origin, if it is unique. This should be + // Get the nonce associated with this origin, if it is opaque. This should be // used only when trying to send an Origin across an IPC pipe. base::Optional<base::UnguessableToken> GetNonceForSerialization() const;
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc index b377d8e..86554e4 100644 --- a/url/origin_unittest.cc +++ b/url/origin_unittest.cc
@@ -80,7 +80,7 @@ } bool HasNonceTokenBeenInitialized(const url::Origin& origin) { - EXPECT_TRUE(origin.unique()); + EXPECT_TRUE(origin.opaque()); // Avoid calling nonce_.token() here, to not trigger lazy initialization. return !origin.nonce_->token_.is_empty(); } @@ -110,14 +110,14 @@ // A default-constructed Origin should should be cross origin to everything // but itself. url::Origin opaque_a, opaque_b; - EXPECT_TRUE(opaque_a.unique()); + EXPECT_TRUE(opaque_a.opaque()); EXPECT_EQ("", opaque_a.scheme()); EXPECT_EQ("", opaque_a.host()); EXPECT_EQ(0, opaque_a.port()); EXPECT_EQ(SchemeHostPort(), opaque_a.GetTupleOrPrecursorTupleIfOpaque()); EXPECT_TRUE(opaque_a.GetTupleOrPrecursorTupleIfOpaque().IsInvalid()); - EXPECT_TRUE(opaque_b.unique()); + EXPECT_TRUE(opaque_b.opaque()); EXPECT_EQ("", opaque_b.scheme()); EXPECT_EQ("", opaque_b.host()); EXPECT_EQ(0, opaque_b.port()); @@ -222,7 +222,7 @@ EXPECT_EQ("", origin.scheme()); EXPECT_EQ("", origin.host()); EXPECT_EQ(0, origin.port()); - EXPECT_TRUE(origin.unique()); + EXPECT_TRUE(origin.opaque()); // An origin is always same-origin with itself. EXPECT_EQ(origin, origin); EXPECT_NE(origin, url::Origin()); @@ -232,7 +232,7 @@ EXPECT_EQ("", origin_copy.scheme()); EXPECT_EQ("", origin_copy.host()); EXPECT_EQ(0, origin_copy.port()); - EXPECT_TRUE(origin_copy.unique()); + EXPECT_TRUE(origin_copy.opaque()); EXPECT_EQ(origin, origin_copy); // And it should always be cross-origin to another opaque Origin. EXPECT_NE(origin, opaque_origin); @@ -362,7 +362,7 @@ EXPECT_EQ(test_case.expected_scheme, origin.scheme()); EXPECT_EQ(test_case.expected_host, origin.host()); EXPECT_EQ(test_case.expected_port, origin.port()); - EXPECT_FALSE(origin.unique()); + EXPECT_FALSE(origin.opaque()); EXPECT_EQ(origin, origin); EXPECT_NE(different_origin, origin); EXPECT_NE(origin, different_origin); @@ -374,7 +374,7 @@ url::Origin derived_opaque = Origin::Resolve(GURL("about:blank?bar#foo"), origin) .DeriveNewOpaqueOrigin(); - EXPECT_TRUE(derived_opaque.unique()); + EXPECT_TRUE(derived_opaque.opaque()); EXPECT_NE(origin, derived_opaque); EXPECT_FALSE(derived_opaque.GetTupleOrPrecursorTupleIfOpaque().IsInvalid()); EXPECT_EQ(origin.GetTupleOrPrecursorTupleIfOpaque(), @@ -383,7 +383,7 @@ url::Origin derived_opaque_via_data_url = Origin::Resolve(GURL("data:text/html,baz"), origin); - EXPECT_TRUE(derived_opaque_via_data_url.unique()); + EXPECT_TRUE(derived_opaque_via_data_url.opaque()); EXPECT_NE(origin, derived_opaque_via_data_url); EXPECT_FALSE(derived_opaque_via_data_url.GetTupleOrPrecursorTupleIfOpaque() .IsInvalid()); @@ -485,7 +485,7 @@ EXPECT_EQ(test.scheme, origin->scheme()); EXPECT_EQ(test.host, origin->host()); EXPECT_EQ(test.port, origin->port()); - EXPECT_FALSE(origin->unique()); + EXPECT_FALSE(origin->opaque()); EXPECT_TRUE(origin->IsSameOriginWith(*origin)); ExpectParsedUrlsEqual(GURL(origin->Serialize()), origin->GetURL()); @@ -495,7 +495,7 @@ UnsafelyCreateOpaqueOriginWithoutNormalization( test.scheme, test.host, test.port, CreateNonce(nonce)); ASSERT_TRUE(opaque_origin); - EXPECT_TRUE(opaque_origin->unique()); + EXPECT_TRUE(opaque_origin->opaque()); EXPECT_FALSE(*opaque_origin == origin); EXPECT_EQ(opaque_origin->GetTupleOrPrecursorTupleIfOpaque(), origin->GetTupleOrPrecursorTupleIfOpaque()); @@ -556,7 +556,7 @@ << "An invalid tuple is a valid input to " << "UnsafelyCreateOpaqueOriginWithoutNormalization, so long as it is " << "the canonical form of the invalid tuple."; - EXPECT_TRUE(anonymous_opaque->unique()); + EXPECT_TRUE(anonymous_opaque->opaque()); EXPECT_EQ(GetNonce(anonymous_opaque.value()), token); EXPECT_EQ(anonymous_opaque->GetTupleOrPrecursorTupleIfOpaque(), url::SchemeHostPort());