diff --git a/DEPS b/DEPS index bd7999e..d4454b5 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'e305cc1f2a44e47d6a0dcc0ff34e2692349aed5d', + 'skia_revision': '56ff9a1c9dfdaf1cd6db3b62a5c2b739cd242032', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '285b9f5a26decb9cc11e14e2101ed707a321b542', + 'v8_revision': 'b55ff5c9e19b3cc0a945ed363ea926f3406e6af4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '0d73909e89a5c93917b9cb73fe5c03c484f2793d', + 'pdfium_revision': 'c7739322e5cdcc5779bdde2a1560ea3dee891e51', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '6a5ce5c1dff46439e735135316e21b7355dde479', + 'catapult_revision': '788644ef37e7f17a8d6183a5e19cd66b5953c1d9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/android_webview/tools/cts_config/webview_cts_gcs_path.json b/android_webview/tools/cts_config/webview_cts_gcs_path.json index ad22503..5abb2fa35 100644 --- a/android_webview/tools/cts_config/webview_cts_gcs_path.json +++ b/android_webview/tools/cts_config/webview_cts_gcs_path.json
@@ -2,14 +2,17 @@ "arm_64": { "L": { "filename": "arm_64/L/android-cts-arm_64-3500656.zip", + "apk": "arm_64/L/3500656/CtsWebkitTestCases.apk", "_origin": "aosp-lollipop-mr1-cts-dev@3500656" }, "M": { "filename": "arm_64/M/android-cts-arm_64-3505727.zip", + "apk": "arm_64/M/3505727/CtsWebkitTestCases.apk", "_origin": "aosp-marshmallow-cts-dev@3505727" }, "N": { "filename": "arm_64/N/android-cts-arm_64-3367285.zip", + "apk": "arm_64/N/3367285/CtsWebkitTestCases.apk", "_origin": "aosp-nougat-cts-release@3367285" } }
diff --git a/android_webview/tools/pylintrc b/android_webview/tools/pylintrc index 19d502ce..d14f91a 100644 --- a/android_webview/tools/pylintrc +++ b/android_webview/tools/pylintrc
@@ -15,6 +15,7 @@ disable= fixme, invalid-name, + locally-disabled, missing-docstring, too-few-public-methods, too-many-arguments,
diff --git a/android_webview/tools/run_cts.py b/android_webview/tools/run_cts.py new file mode 100755 index 0000000..07fc8cf2 --- /dev/null +++ b/android_webview/tools/run_cts.py
@@ -0,0 +1,124 @@ +#!/usr/bin/env python +# +# 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. + +"""Runs the CTS test APKs stored in GS.""" + +import argparse +import json +import os +import shutil +import sys +import tempfile + + +sys.path.append(os.path.join( + os.path.dirname(__file__), os.pardir, os.pardir, 'build', 'android')) +import devil_chromium # pylint: disable=import-error +from devil.utils import cmd_helper # pylint: disable=import-error + +sys.path.append(os.path.join( + os.path.dirname(__file__), os.pardir, os.pardir, 'build')) +import find_depot_tools # pylint: disable=import-error + +_CTS_BUCKET = 'gs://chromium-cts' + +_GSUTIL_PATH = os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gsutil.py') +_TEST_RUNNER_PATH = os.path.join( + os.path.dirname(__file__), os.pardir, os.pardir, + 'build', 'android', 'test_runner.py') + +_EXPECTED_FAILURES_FILE = os.path.join( + os.path.dirname(__file__), 'cts_config', 'expected_failure_on_bot.json') +_WEBVIEW_CTS_GCS_PATH_FILE = os.path.join( + os.path.dirname(__file__), 'cts_config', 'webview_cts_gcs_path.json') + + +def GetCtsPath(arch, platform): + """Gets relative path the CTS APK is stored at.""" + with open(_WEBVIEW_CTS_GCS_PATH_FILE) as f: + cts_gcs_path_info = json.load(f) + try: + return cts_gcs_path_info[arch][platform]['apk'] + except KeyError: + raise Exception('No CTS test available for arch:%s, android:%s' % + (arch, platform)) + + +def GetExpectedFailures(): + """Gets list of tests expected to fail.""" + with open(_EXPECTED_FAILURES_FILE) as f: + expected_failures_info = json.load(f) + expected_failures = [] + for class_name, methods in expected_failures_info.iteritems(): + expected_failures.extend(['%s#%s' % (class_name, m['name']) + for m in methods]) + return expected_failures + + +def DownloadAndRunCTS(args, test_runner_args): + base_cts_dir = None + delete_cts_dir = False + try: + relative_cts_path = GetCtsPath(args.arch, args.platform) + + if args.apk_dir: + base_cts_dir = args.apk_dir + else: + base_cts_dir = tempfile.mkdtemp() + delete_cts_dir = True + + local_cts_path = os.path.join(base_cts_dir, relative_cts_path) + google_storage_cts_path = '%s/%s' % (_CTS_BUCKET, relative_cts_path) + + # Download CTS APK if needed. + if not os.path.exists(local_cts_path): + if cmd_helper.RunCmd( + [_GSUTIL_PATH, 'cp', google_storage_cts_path, local_cts_path]): + raise Exception('Error downloading CTS from Google Storage.') + + test_runner_args += ['--test-apk', local_cts_path] + # TODO(mikecase): This doesn't work at all with the + # --gtest-filter test runner option currently. The + # filter options will just override eachother. + if args.skip_expected_failures: + test_runner_args += ['-f=-%s' % ':'.join(GetExpectedFailures())] + return cmd_helper.RunCmd( + [_TEST_RUNNER_PATH, 'instrumentation'] + test_runner_args) + finally: + if delete_cts_dir and base_cts_dir: + shutil.rmtree(base_cts_dir) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--arch', + choices=['arm_64'], + default='arm_64', + help='Arch for CTS tests.') + parser.add_argument( + '--platform', + choices=['L', 'M', 'N'], + required=True, + help='Android platform version for CTS tests.') + parser.add_argument( + '--skip-expected-failures', + action='store_true', + help='Option to skip all tests that are expected to fail.') + parser.add_argument( + '--apk-dir', + help='Directory to load/save CTS APKs. Will try to load CTS APK ' + 'from this directory before downloading from Google Storage ' + 'and will then cache APK here.') + + args, test_runner_args = parser.parse_known_args() + devil_chromium.Initialize() + + return DownloadAndRunCTS(args, test_runner_args) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/ash/common/ash_switches.cc b/ash/common/ash_switches.cc index 10e9190..d3d9571 100644 --- a/ash/common/ash_switches.cc +++ b/ash/common/ash_switches.cc
@@ -60,11 +60,6 @@ // Enables the palette on every display, instead of only the internal one. const char kAshEnablePaletteOnAllDisplays[] = "ash-enable-palette-on-all-displays"; - -// Enables tablet power button behavior for convertible/tablet devices. -// TODO(warx): Enable or remove this switch once crbug.com/633304 is fully -// finished. -const char kAshEnableTabletPowerButton[] = "ash-enable-tablet-power-button"; #endif // Enables the observation of accelerometer events to enter touch-view mode.
diff --git a/ash/common/ash_switches.h b/ash/common/ash_switches.h index 780d236..8a145f6 100644 --- a/ash/common/ash_switches.h +++ b/ash/common/ash_switches.h
@@ -32,7 +32,6 @@ ASH_EXPORT extern const char kAshEnableMagnifierKeyScroller[]; ASH_EXPORT extern const char kAshEnablePalette[]; ASH_EXPORT extern const char kAshEnablePaletteOnAllDisplays[]; -ASH_EXPORT extern const char kAshEnableTabletPowerButton[]; #endif ASH_EXPORT extern const char kAshEnableTouchView[]; ASH_EXPORT extern const char kAshEnableMirroredScreen[];
diff --git a/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc b/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc index 6675c9f..812c999 100644 --- a/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc +++ b/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc
@@ -52,8 +52,6 @@ dbus_setter->SetPowerManagerClient(base::WrapUnique(power_manager_client_)); base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kAshEnableTouchViewTesting); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshEnableTabletPowerButton); AshTestBase::SetUp(); lock_state_controller_ = Shell::GetInstance()->lock_state_controller();
diff --git a/ash/wm/power_button_controller.cc b/ash/wm/power_button_controller.cc index 9ea85af9..8038dec 100644 --- a/ash/wm/power_button_controller.cc +++ b/ash/wm/power_button_controller.cc
@@ -45,7 +45,9 @@ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver( this); if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableTabletPowerButton)) { + switches::kAshEnableTouchView) || + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAshEnableTouchViewTesting)) { tablet_controller_.reset( new TabletPowerButtonController(lock_state_controller_)); }
diff --git a/build/android/tombstones.py b/build/android/tombstones.py index cba1e5a..f2b5904a 100755 --- a/build/android/tombstones.py +++ b/build/android/tombstones.py
@@ -26,6 +26,10 @@ from devil.utils import run_tests_helper from pylib import constants +sys.path.insert(0, os.path.abspath(os.path.join( + constants.DIR_SOURCE_ROOT, 'tools', 'swarming_client'))) +from libs.logdog import bootstrap # pylint: disable=import-error + _TZ_UTC = {'TZ': 'UTC'} @@ -103,6 +107,7 @@ return arch raise RuntimeError('Unknown device ABI: %s' % device_abi) + def _ResolveSymbols(tombstone_data, include_stack, device_abi): """Run the stack tool for given tombstone input. @@ -170,6 +175,7 @@ resolved_tombstones.extend(tombstone) return resolved_tombstones + def _GetTombstonesForDevice(device, resolve_all_tombstones, include_stack_symbols, wipe_tombstones): @@ -216,6 +222,7 @@ return ret + def ClearAllTombstones(device): """Clear all tombstones in the device. @@ -229,6 +236,7 @@ for tombstone_file, _ in all_tombstones: _EraseTombstone(device, tombstone_file) + def ResolveTombstones(device, resolve_all_tombstones, include_stack_symbols, wipe_tombstones, jobs=4): """Resolve tombstones in the device. @@ -239,6 +247,9 @@ include_stack_symbols: Whether to include symbols for stack data. wipe_tombstones: Whether to wipe tombstones. jobs: Number of jobs to use when processing multiple crash stacks. + + Returns: + A list of resolved tombstones. """ return _ResolveTombstones(jobs, _GetTombstonesForDevice(device, @@ -246,6 +257,33 @@ include_stack_symbols, wipe_tombstones)) + +def LogdogTombstones(resolved_tombstones, stream_name): + """Save resolved tombstones to logdog and return the url. + + Args: + stream_name: The name of the logdog stream that records tombstones. + resolved_tombstones: Resolved tombstones (output of ResolveTombstones). + + Returns: + A url link to the recorded tombstones. + """ + try: + tombstones_url = '' + stream_client = bootstrap.ButlerBootstrap.probe().stream_client() + with stream_client.text(stream_name) as logdog_stream: + for tombstones_line in resolved_tombstones: + logdog_stream.write(tombstones_line + '\n') + tombstones_url = logdog_stream.get_viewer_url(stream_name) + except bootstrap.NotBootstrappedError: + logging.exception('Error not bootstrapped. Failed to start logdog') + except (KeyError, ValueError) as e: + logging.exception('Error when creating stream_client/stream: %s.', e) + except Exception as e: # pylint: disable=broad-except + logging.exception('Unknown Error: %s.', e) + return tombstones_url + + def main(): custom_handler = logging.StreamHandler(sys.stdout) custom_handler.setFormatter(run_tests_helper.CustomFormatter()) @@ -300,5 +338,6 @@ for line in resolved_tombstones: logging.info(line) + if __name__ == '__main__': sys.exit(main())
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 8e6b7e5..95c03c6a 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -852,6 +852,7 @@ "output/texture_mailbox_deleter_unittest.cc", "playback/discardable_image_map_unittest.cc", "playback/display_item_list_unittest.cc", + "playback/image_hijack_canvas_unittest.cc", "playback/raster_source_unittest.cc", "playback/recording_source_unittest.cc", "proto/base_conversions_unittest.cc", @@ -987,6 +988,7 @@ cc_test("cc_perftests") { sources = [ "animation/animation_host_perftest.cc", + "base/rtree_perftest.cc", "ipc/cc_serialization_perftest.cc", "layers/layer_perftest.cc", "layers/picture_layer_impl_perftest.cc",
diff --git a/cc/base/DEPS b/cc/base/DEPS index 33b4e8f..1bcb1a1 100644 --- a/cc/base/DEPS +++ b/cc/base/DEPS
@@ -8,5 +8,9 @@ specific_include_rules = { ".*unittest\.cc": [ "+cc/test", - ] + ], + # Allow lap_timer.h for perftests + ".*perftest\.cc": [ + "+cc/debug/lap_timer.h", + ], }
diff --git a/cc/base/rtree_perftest.cc b/cc/base/rtree_perftest.cc new file mode 100644 index 0000000..85aee07 --- /dev/null +++ b/cc/base/rtree_perftest.cc
@@ -0,0 +1,97 @@ +// 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. + +#include "cc/base/rtree.h" +#include "cc/debug/lap_timer.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +namespace cc { +namespace { + +static const int kTimeLimitMillis = 2000; +static const int kWarmupRuns = 5; +static const int kTimeCheckInterval = 10; + +class RTreePerfTest : public testing::Test { + public: + RTreePerfTest() + : timer_(kWarmupRuns, + base::TimeDelta::FromMilliseconds(kTimeLimitMillis), + kTimeCheckInterval) {} + + void RunConstructTest(const std::string& test_name, int rect_count) { + std::vector<gfx::Rect> rects = BuildRects(rect_count); + timer_.Reset(); + do { + RTree rtree; + rtree.Build(rects); + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + perf_test::PrintResult("rtree_construct", "", test_name, + timer_.LapsPerSecond(), "runs/s", true); + } + + void RunSearchTest(const std::string& test_name, int rect_count) { + int large_query = std::sqrt(rect_count); + + std::vector<gfx::Rect> queries = { + gfx::Rect(0, 0, 1, 1), gfx::Rect(100, 100, 2, 2), + gfx::Rect(-10, -10, 1, 1), gfx::Rect(0, 0, 1000, 1000), + gfx::Rect(large_query - 2, large_query - 2, 1, 1)}; + size_t query_index = 0; + + std::vector<gfx::Rect> rects = BuildRects(rect_count); + RTree rtree; + rtree.Build(rects); + + timer_.Reset(); + do { + std::vector<size_t> results; + rtree.Search(queries[query_index], &results); + query_index = (query_index + 1) % queries.size(); + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + perf_test::PrintResult("rtree_search", "", test_name, + timer_.LapsPerSecond(), "runs/s", true); + } + + std::vector<gfx::Rect> BuildRects(int count) { + std::vector<gfx::Rect> result; + int width = std::sqrt(count); + int x = 0; + int y = 0; + for (int i = 0; i < count; ++i) { + result.push_back(gfx::Rect(x, y, 1, 1)); + if (++x > width) { + x = 0; + ++y; + } + } + return result; + } + + protected: + LapTimer timer_; +}; + +TEST_F(RTreePerfTest, Construct) { + RunConstructTest("100", 100); + RunConstructTest("1000", 1000); + RunConstructTest("10000", 10000); + RunConstructTest("100000", 100000); +} + +TEST_F(RTreePerfTest, Search) { + RunSearchTest("100", 100); + RunSearchTest("1000", 1000); + RunSearchTest("10000", 10000); + RunSearchTest("100000", 100000); +} + +} // namespace +} // namespace cc
diff --git a/cc/playback/image_hijack_canvas.cc b/cc/playback/image_hijack_canvas.cc index 98fd4717..a5d596d7 100644 --- a/cc/playback/image_hijack_canvas.cc +++ b/cc/playback/image_hijack_canvas.cc
@@ -83,7 +83,7 @@ SkMatrix matrix; SkShader::TileMode xy[2]; SkImage* image = shader->isAImage(&matrix, xy); - if (!image) + if (!image || !image->isLazyGenerated()) return base::Optional<ScopedImagePaint>(); SkMatrix total_image_matrix = matrix;
diff --git a/cc/playback/image_hijack_canvas.h b/cc/playback/image_hijack_canvas.h index 46495da..be9a6ba 100644 --- a/cc/playback/image_hijack_canvas.h +++ b/cc/playback/image_hijack_canvas.h
@@ -6,13 +6,14 @@ #define CC_PLAYBACK_IMAGE_HIJACK_CANVAS_H_ #include "base/macros.h" +#include "cc/base/cc_export.h" #include "third_party/skia/include/utils/SkNWayCanvas.h" namespace cc { class ImageDecodeCache; -class ImageHijackCanvas : public SkNWayCanvas { +class CC_EXPORT ImageHijackCanvas : public SkNWayCanvas { public: ImageHijackCanvas(int width, int height,
diff --git a/cc/playback/image_hijack_canvas_unittest.cc b/cc/playback/image_hijack_canvas_unittest.cc new file mode 100644 index 0000000..214de87 --- /dev/null +++ b/cc/playback/image_hijack_canvas_unittest.cc
@@ -0,0 +1,65 @@ +// 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. +#include "cc/playback/image_hijack_canvas.h" + +#include "cc/tiles/image_decode_cache.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkPath.h" + +namespace cc { +namespace { + +class MockImageDecodeCache : public ImageDecodeCache { + public: + MOCK_METHOD3(GetTaskForImageAndRef, + bool(const DrawImage& image, + const TracingInfo& tracing_info, + scoped_refptr<TileTask>* task)); + MOCK_METHOD1(UnrefImage, void(const DrawImage& image)); + MOCK_METHOD1(GetDecodedImageForDraw, + DecodedDrawImage(const DrawImage& image)); + MOCK_METHOD2(DrawWithImageFinished, + void(const DrawImage& image, + const DecodedDrawImage& decoded_image)); + MOCK_METHOD0(ReduceCacheUsage, void()); + MOCK_METHOD1(SetShouldAggressivelyFreeResources, + void(bool aggressively_free_resources)); +}; + +TEST(ImageHijackCanvasTest, NonLazyImagesSkipped) { + // Use a strict mock so that if *any* ImageDecodeCache methods are called, we + // will hit an error. + testing::StrictMock<MockImageDecodeCache> image_decode_cache; + ImageHijackCanvas canvas(100, 100, &image_decode_cache); + + // Use an SkBitmap backed image to ensure that the image is not + // lazy-generated. + SkBitmap bitmap; + bitmap.allocN32Pixels(10, 10, true); + sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap); + + SkPaint paint; + canvas.drawImage(image, 0, 0, &paint); + canvas.drawImageRect(image, SkRect::MakeXYWH(0, 0, 10, 10), + SkRect::MakeXYWH(10, 10, 10, 10), &paint); + + SkPaint image_paint; + image_paint.setShader( + image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)); + SkRect paint_rect = SkRect::MakeXYWH(0, 0, 100, 100); + canvas.drawRect(paint_rect, image_paint); + SkPath path; + path.addRect(paint_rect, SkPath::kCW_Direction); + canvas.drawPath(path, image_paint); + canvas.drawOval(paint_rect, image_paint); + canvas.drawArc(paint_rect, 0, 40, true, image_paint); + canvas.drawRRect(SkRRect::MakeRect(paint_rect), image_paint); +} + +} // namespace + +} // namespace cc
diff --git a/cc/test/ordered_simple_task_runner.cc b/cc/test/ordered_simple_task_runner.cc index 161704f..9dc4bbcd 100644 --- a/cc/test/ordered_simple_task_runner.cc +++ b/cc/test/ordered_simple_task_runner.cc
@@ -137,8 +137,6 @@ } base::TimeTicks OrderedSimpleTaskRunner::NextTaskTime() { - RemoveCancelledTasks(); - if (pending_tasks_.size() <= 0) { return AbsoluteMaxNow(); } @@ -148,7 +146,6 @@ base::TimeDelta OrderedSimpleTaskRunner::DelayToNextTaskTime() { DCHECK(thread_checker_.CalledOnValidThread()); - RemoveCancelledTasks(); if (pending_tasks_.size() <= 0) { return AbsoluteMaxNow() - base::TimeTicks(); @@ -201,11 +198,6 @@ } while (pending_tasks_.size() > 0) { - // Skip canceled tasks. - if (pending_tasks_.begin()->task.IsCancelled()) { - pending_tasks_.erase(pending_tasks_.begin()); - continue; - } // Check if we should continue to run pending tasks. bool condition_success = true; for (std::vector<base::Callback<bool(void)>>::iterator it = @@ -352,15 +344,4 @@ return true; } -void OrderedSimpleTaskRunner::RemoveCancelledTasks() { - std::set<TestOrderablePendingTask>::iterator it = pending_tasks_.begin(); - while (it != pending_tasks_.end()) { - if (it->task.IsCancelled()) { - it = pending_tasks_.erase(it); - } else { - it++; - } - } -} - } // namespace cc
diff --git a/cc/test/ordered_simple_task_runner.h b/cc/test/ordered_simple_task_runner.h index 1ba8e95..9620a960 100644 --- a/cc/test/ordered_simple_task_runner.h +++ b/cc/test/ordered_simple_task_runner.h
@@ -130,9 +130,6 @@ // Advance Now() to the next task to run. base::Callback<bool(void)> AdvanceNow(); - // Removes all tasks whose weak pointer has been revoked. - void RemoveCancelledTasks(); - protected: static bool TaskRunCountBelowCallback(size_t max_tasks, size_t* task_run); bool TaskExistedInitiallyCallback(
diff --git a/chrome/android/java/res/drawable-hdpi/ic_download_pause.png b/chrome/android/java/res/drawable-hdpi/ic_download_pause.png new file mode 100644 index 0000000..294a0488 --- /dev/null +++ b/chrome/android/java/res/drawable-hdpi/ic_download_pause.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/ic_download_pending.png b/chrome/android/java/res/drawable-hdpi/ic_download_pending.png new file mode 100644 index 0000000..17c3fff --- /dev/null +++ b/chrome/android/java/res/drawable-hdpi/ic_download_pending.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_download_pause.png b/chrome/android/java/res/drawable-mdpi/ic_download_pause.png new file mode 100644 index 0000000..032cbb6 --- /dev/null +++ b/chrome/android/java/res/drawable-mdpi/ic_download_pause.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_download_pending.png b/chrome/android/java/res/drawable-mdpi/ic_download_pending.png new file mode 100644 index 0000000..0bf58a5 --- /dev/null +++ b/chrome/android/java/res/drawable-mdpi/ic_download_pending.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_download_pause.png b/chrome/android/java/res/drawable-xhdpi/ic_download_pause.png new file mode 100644 index 0000000..141ec2ff --- /dev/null +++ b/chrome/android/java/res/drawable-xhdpi/ic_download_pause.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_download_pending.png b/chrome/android/java/res/drawable-xhdpi/ic_download_pending.png new file mode 100644 index 0000000..803ca65d --- /dev/null +++ b/chrome/android/java/res/drawable-xhdpi/ic_download_pending.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_download_pause.png b/chrome/android/java/res/drawable-xxhdpi/ic_download_pause.png new file mode 100644 index 0000000..bff83ae --- /dev/null +++ b/chrome/android/java/res/drawable-xxhdpi/ic_download_pause.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_download_pending.png b/chrome/android/java/res/drawable-xxhdpi/ic_download_pending.png new file mode 100644 index 0000000..cbf8c33 --- /dev/null +++ b/chrome/android/java/res/drawable-xxhdpi/ic_download_pending.png Binary files differ
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java index 4bbbb4c..312dd77 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/BackgroundSyncLauncher.java
@@ -24,7 +24,7 @@ /** * The {@link BackgroundSyncLauncher} singleton is created and owned by the C++ browser. It * registers interest in waking up the browser the next time the device goes online after the - * browser closes via the {@link #launchBrowserIfStopped} method. + * browser closes via the {@link #setLaunchWhenNextOnline} method. * * Thread model: This class is to be run on the UI thread only. */ @@ -50,9 +50,6 @@ */ private static boolean sGCMEnabled = true; - @VisibleForTesting - protected AsyncTask<Void, Void, Void> mLaunchBrowserIfStoppedTask; - /** * Create a BackgroundSyncLauncher object, which is owned by C++. * @param context The app context. @@ -82,21 +79,18 @@ * Callback for {@link #shouldLaunchBrowserIfStopped}. The run method is invoked on the UI * thread. */ - public interface ShouldLaunchCallback { void run(Boolean shouldLaunch); } + public static interface ShouldLaunchCallback { public void run(Boolean shouldLaunch); } /** * Returns whether the browser should be launched when the device next goes online. * This is set by C++ and reset to false each time {@link BackgroundSyncLauncher}'s singleton is * created (the native browser is started). This call is asynchronous and will run the callback * on the UI thread when complete. - * - * {@link AsyncTask} is necessary as the browser process will not have warmed up the - * {@link SharedPreferences} before it is used here. This is likely the first usage of - * {@link ContextUtils#getAppSharedPreferences}. - * - * @param callback The callback after fetching prefs. + * @param context The application context. + * @param sharedPreferences The shared preferences. */ - protected static void shouldLaunchBrowserIfStopped(final ShouldLaunchCallback callback) { + protected static void shouldLaunchBrowserIfStopped( + final Context context, final ShouldLaunchCallback callback) { new AsyncTask<Void, Void, Boolean>() { @Override protected Boolean doInBackground(Void... params) { @@ -107,7 +101,7 @@ protected void onPostExecute(Boolean shouldLaunch) { callback.run(shouldLaunch); } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + }.execute(); } /** @@ -116,16 +110,15 @@ * This method is called by C++ as background sync registrations are added and removed. When the * {@link BackgroundSyncLauncher} singleton is created (on browser start), this is called to * remove any pre-existing scheduled tasks. - * - * See {@link #shouldLaunchBrowserIfStopped} for {@link AsyncTask}. - * + * @param context The application context. * @param shouldLaunch Whether or not to launch the browser in the background. * @param minDelayMs The minimum time to wait before checking on the browser process. */ @VisibleForTesting @CalledByNative - protected void launchBrowserIfStopped(final boolean shouldLaunch, final long minDelayMs) { - mLaunchBrowserIfStoppedTask = new AsyncTask<Void, Void, Void>() { + protected void launchBrowserIfStopped( + final Context context, final boolean shouldLaunch, final long minDelayMs) { + new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); @@ -140,7 +133,7 @@ if (shouldLaunch) { RecordHistogram.recordBooleanHistogram( "BackgroundSync.LaunchTask.ScheduleSuccess", - scheduleLaunchTask(mScheduler, minDelayMs)); + scheduleLaunchTask(context, mScheduler, minDelayMs)); } else { RecordHistogram.recordBooleanHistogram( "BackgroundSync.LaunchTask.CancelSuccess", @@ -148,7 +141,7 @@ } } } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + }.execute(); } /** @@ -161,7 +154,7 @@ protected BackgroundSyncLauncher(Context context) { mScheduler = GcmNetworkManager.getInstance(context); - launchBrowserIfStopped(false, 0); + launchBrowserIfStopped(context, false, 0); } private static boolean canUseGooglePlayServices(Context context) { @@ -195,7 +188,8 @@ return !sGCMEnabled; } - private static boolean scheduleLaunchTask(GcmNetworkManager scheduler, long minDelayMs) { + private static boolean scheduleLaunchTask( + Context context, GcmNetworkManager scheduler, long minDelayMs) { // Google Play Services may not be up to date, if the application was not installed through // the Play Store. In this case, scheduling the task will fail silently. final long minDelaySecs = minDelayMs / 1000; @@ -258,11 +252,11 @@ // without delay and let the browser reschedule if necessary. // TODO(iclelland): If this fails, report the failure via UMA (not now, // since the browser is not running, but on next startup.) - scheduleLaunchTask(scheduler, 0); + scheduleLaunchTask(context, scheduler, 0); } } }; - BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(callback); + BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(context, callback); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java index 2bafb9b..f8c0063 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
@@ -93,6 +93,11 @@ */ public static final String MARKET_URL_FOR_TESTING = "market-url-for-testing"; + /** + * Disable multiwindow tab merging for testing. + */ + public static final String DISABLE_TAB_MERGING_FOR_TESTING = "disable-tab-merging"; + /////////////////////////////////////////////////////////////////////////////////////////////// // Native Switches ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index d5620d1..d44997c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -848,10 +848,12 @@ // Used by the Account management screen to open a new incognito tab. // Account management screen collects its metrics separately. getTabCreator(true).launchUrl( - UrlConstants.NTP_URL, TabLaunchType.FROM_CHROME_UI); + UrlConstants.NTP_URL, TabLaunchType.FROM_CHROME_UI, + intent, mIntentHandlingTimeMs); } else { getTabCreator(true).launchUrl( - UrlConstants.NTP_URL, TabLaunchType.FROM_EXTERNAL_APP); + UrlConstants.NTP_URL, TabLaunchType.FROM_EXTERNAL_APP, + intent, mIntentHandlingTimeMs); RecordUserAction.record("MobileReceivedExternalIntent"); } } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java index ceed07d..59d530e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -271,7 +271,7 @@ String contentText = mContext.getResources().getString(isDownloadPending ? R.string.download_notification_pending : R.string.download_started); - int resId = isDownloadPending ? android.R.drawable.stat_sys_download_done + int resId = isDownloadPending ? R.drawable.ic_download_pending : android.R.drawable.stat_sys_download; NotificationCompat.Builder builder = buildNotification(resId, fileName, contentText); builder.setOngoing(true); @@ -374,7 +374,7 @@ String contentText = mContext.getResources().getString( R.string.download_notification_paused); NotificationCompat.Builder builder = buildNotification( - android.R.drawable.ic_media_pause, entry.fileName, contentText); + R.drawable.ic_download_pause, entry.fileName, contentText); // Clicking on an in-progress download sends the user to see all their downloads. Intent downloadHomeIntent = buildActionIntent(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java index da44d60..fe76018 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java
@@ -50,7 +50,7 @@ public static PendingIntent getRemoveAllIncognitoTabsIntent(Context context) { Intent intent = new Intent(context, IncognitoNotificationService.class); intent.setAction(ACTION_CLOSE_ALL_INCOGNITO); - return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); + return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } /** Empty public constructor needed by Android. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java index e0f7ad1c..36eff359 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilder.java
@@ -166,9 +166,6 @@ // Notification.Builder.setPublicVersion was added in Android L. builder.setPublicVersion(createPublicNotification(mContext)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - builder.setExtras(mExtras); - } Notification notification = builder.build(); notification.bigContentView = bigView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java index 94ee796..6635ecca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java
@@ -18,7 +18,6 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Icon; import android.os.Build; -import android.os.Bundle; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.widget.RoundedIconGenerator; @@ -122,7 +121,6 @@ protected long[] mVibratePattern; protected long mTimestamp; protected boolean mRenotify; - protected Bundle mExtras; private Bitmap mLargeIcon; @@ -311,18 +309,6 @@ } /** - * Sets the extras bundle on supported platforms. - */ - @TargetApi(Build.VERSION_CODES.M) - public NotificationBuilderBase setExtras(Bundle extras) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return this; - } - mExtras = extras; - return this; - } - - /** * Gets the large icon for the notification. * * If a large icon was supplied to the builder, returns this icon, scaled to an appropriate size
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxy.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxy.java index f601d75..fd9ae67 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxy.java
@@ -4,10 +4,7 @@ package org.chromium.chrome.browser.notifications; -import android.annotation.TargetApi; import android.app.Notification; -import android.os.Build; -import android.service.notification.StatusBarNotification; /** * A proxy for the Android Notification Manager. This allows tests to be written without having to @@ -21,7 +18,4 @@ void cancelAll(); void notify(int id, Notification notification); void notify(String tag, int id, Notification notification); - - @TargetApi(Build.VERSION_CODES.M) - StatusBarNotification[] getActiveNotifications(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxyImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxyImpl.java index ece1f75c..b05fd0047 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxyImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationManagerProxyImpl.java
@@ -6,7 +6,6 @@ import android.app.Notification; import android.app.NotificationManager; -import android.service.notification.StatusBarNotification; /** * Default implementation of the NotificationManagerProxy, which passes through all calls to the @@ -43,9 +42,4 @@ public void notify(String tag, int id, Notification notification) { mNotificationManager.notify(tag, id, notification); } - - @Override - public StatusBarNotification[] getActiveNotifications() { - return mNotificationManager.getActiveNotifications(); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java index d1c4d1b..26a96f9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -15,7 +15,6 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.service.notification.StatusBarNotification; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -44,8 +43,6 @@ import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; import javax.annotation.Nullable; @@ -575,15 +572,6 @@ makeDefaults(vibrationPattern.length, silent, vibrateEnabled)); notificationBuilder.setVibrate(makeVibrationPattern(vibrationPattern)); - // The extras bundle is available from API 20 but it's currenlty only used to retrieve - // notifications which is only available from 23 (Marshmallow) onwards. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - Bundle extras = new Bundle(); - extras.putString(NotificationConstants.EXTRA_NOTIFICATION_ID, notificationId); - extras.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, profileId); - notificationBuilder.setExtras(extras); - } - String platformTag = makePlatformTag(notificationId, origin, tag); if (webApkPackage.isEmpty()) { mNotificationManager.notify(platformTag, PLATFORM_ID, notificationBuilder.build()); @@ -688,35 +676,6 @@ } /** - * Returns the notification ids on disply for a given |profileId|. - * - * @param profileId of the profile to retrieve notifications for. - */ - @CalledByNative - private String[] getNotificationsForProfile(String profileId) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - return null; - } - - StatusBarNotification[] displayedNotifications = - mNotificationManager.getActiveNotifications(); - List<String> notifications = new ArrayList<String>(); - for (StatusBarNotification notification : displayedNotifications) { - Bundle extras = notification.getNotification().extras; - String notificationId = extras.getString(NotificationConstants.EXTRA_NOTIFICATION_ID); - String notificationProfileId = - extras.getString(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID); - if (notificationId != null && profileId.equals(notificationProfileId)) { - notifications.add(notificationId); - } - } - if (notifications.size() == 0) return null; - - String[] result = new String[notifications.size()]; - return notifications.toArray(result); - } - - /** * Calls NotificationPlatformBridgeAndroid::OnNotificationClicked in native code to indicate * that the notification with the given parameters has been clicked on. *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java index 705d7c0..337b6f4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilder.java
@@ -60,9 +60,6 @@ // Notification.Builder.setPublicVersion was added in Android L. builder.setPublicVersion(createPublicNotification(mContext)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - builder.setExtras(mExtras); - } return builder.build(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java index 8caa3ef..88a22fb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -234,6 +234,9 @@ * @return True if tab model merging for Android N+ is enabled. */ public static boolean isTabModelMergingEnabled() { + if (CommandLine.getInstance().hasSwitch(ChromeSwitches.DISABLE_TAB_MERGING_FOR_TESTING)) { + return false; + } return Build.VERSION.SDK_INT > Build.VERSION_CODES.M; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java index 1d89766..042f609 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java
@@ -49,11 +49,6 @@ boolean exitFromVr(int requestCode, final Intent intent); /** - * Sets VR Mode to |enabled|. - */ - void setVrModeEnabled(boolean enabled); - - /** * @return Whether the current Viewer is a Daydream Viewer. */ Boolean isDaydreamCurrentViewer();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java index 5d4f546..2947d37d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java
@@ -9,7 +9,6 @@ import android.content.ComponentName; import android.content.Intent; -import com.google.vr.ndk.base.AndroidCompat; import com.google.vr.ndk.base.DaydreamApi; import com.google.vr.ndk.base.GvrApi; @@ -71,11 +70,6 @@ } @Override - public void setVrModeEnabled(boolean enabled) { - AndroidCompat.setVrModeEnabled(mActivity, enabled); - } - - @Override public Boolean isDaydreamCurrentViewer() { DaydreamApi daydreamApi = DaydreamApi.create(mActivity); if (daydreamApi == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java index 204b630..45a38a7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
@@ -34,6 +34,11 @@ void teardown(); /** + * Sets VR Mode to |enabled|. + */ + void setVrModeEnabled(boolean enabled); + + /** * Sets whether we're presenting WebVR content or not. */ void setWebVrModeEnabled(boolean enabled);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java index 1a91c98..6e45dbea 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -90,11 +90,9 @@ public VrShellDelegate(ChromeTabbedActivity activity) { mActivity = activity; - // TODO(bshe): refactor code so that mCardboardSupportOnly does not depend on mVrAvailable - // and mVrAvailable does not depend on createVrDaydreamApi. - mVrAvailable = createVrClassesBuilder() && isVrCoreCompatible() && createVrDaydreamApi(); - // Only Cardboard mode is supported on non-daydream devices. - if (mVrDaydreamApi != null && mVrDaydreamApi.isDaydreamReadyDevice()) { + mVrAvailable = createVrClassesBuilder() && isVrCoreCompatible(); + // Daydream ready devices support both Cardboard and Daydream mode. + if (mVrAvailable && createVrDaydreamApi() && mVrDaydreamApi.isDaydreamReadyDevice()) { mCardboardSupportOnly = false; } @@ -181,7 +179,7 @@ } else { if (mRequestedWebVR) nativeSetPresentResult(mNativeVrShellDelegate, false); if (!mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent())) { - mVrDaydreamApi.setVrModeEnabled(false); + mVrShell.setVrModeEnabled(false); } } @@ -190,7 +188,6 @@ private boolean enterVR() { if (mInVr) return true; - mVrDaydreamApi.setVrModeEnabled(true); Tab tab = mActivity.getActivityTab(); if (!canEnterVR(tab)) return false; @@ -201,6 +198,7 @@ mActivity.setRequestedOrientation(mRestoreOrientation); return false; } + mVrShell.setVrModeEnabled(true); mInVr = true; mTab = tab; mTab.addObserver(mTabObserver); @@ -402,11 +400,11 @@ public void onExitVRResult(int resultCode) { assert mVrAvailable; if (resultCode == Activity.RESULT_OK) { - mVrDaydreamApi.setVrModeEnabled(false); + mVrShell.setVrModeEnabled(false); } else { // For now, we don't handle re-entering VR when exit fails, so keep trying to exit. if (!mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent())) { - mVrDaydreamApi.setVrModeEnabled(false); + mVrShell.setVrModeEnabled(false); } } } @@ -464,10 +462,10 @@ mRequestedWebVR = false; if (!isPausing) { if (!showTransition || !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent())) { - mVrDaydreamApi.setVrModeEnabled(false); + mVrShell.setVrModeEnabled(false); } } else { - mVrDaydreamApi.setVrModeEnabled(false); + mVrShell.setVrModeEnabled(false); mLastVRExit = SystemClock.uptimeMillis(); } mActivity.setRequestedOrientation(mRestoreOrientation);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java index cf7e4a5..35783b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -297,6 +297,11 @@ } @Override + public void setVrModeEnabled(boolean enabled) { + AndroidCompat.setVrModeEnabled(mActivity, enabled); + } + + @Override public void setWebVrModeEnabled(boolean enabled) { nativeSetWebVrMode(mNativeVrShell, enabled); }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 078ec55..0ecd02d 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1289,6 +1289,7 @@ "javatests/src/org/chromium/chrome/browser/media/ui/AutoplayMutedNotificationTest.java", "javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java", "javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java", + "javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java", "javatests/src/org/chromium/chrome/browser/notifications/CustomNotificationBuilderTest.java", "javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java index 2b1f41f..f26d62d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BackgroundSyncLauncherTest.java
@@ -13,7 +13,6 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Semaphore; /** @@ -52,7 +51,7 @@ } }; - BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(callback); + BackgroundSyncLauncher.shouldLaunchBrowserIfStopped(mContext, callback); try { // Wait on the callback to be called. semaphore.acquire(); @@ -62,16 +61,6 @@ return mShouldLaunchResult; } - private void waitForLaunchBrowserTask() { - try { - mLauncher.mLaunchBrowserIfStoppedTask.get(); - } catch (InterruptedException e) { - fail("Launch task was interrupted"); - } catch (ExecutionException e) { - fail("Launch task had execution exception"); - } - } - @SmallTest @Feature({"BackgroundSync"}) @RetryOnFailure @@ -92,11 +81,9 @@ @RetryOnFailure public void testSetLaunchWhenNextOnline() { assertFalse(shouldLaunchBrowserIfStoppedSync()); - mLauncher.launchBrowserIfStopped(true, 0); - waitForLaunchBrowserTask(); + mLauncher.launchBrowserIfStopped(mContext, true, 0); assertTrue(shouldLaunchBrowserIfStoppedSync()); - mLauncher.launchBrowserIfStopped(false, 0); - waitForLaunchBrowserTask(); + mLauncher.launchBrowserIfStopped(mContext, false, 0); assertFalse(shouldLaunchBrowserIfStoppedSync()); } @@ -104,8 +91,7 @@ @Feature({"BackgroundSync"}) @RetryOnFailure public void testNewLauncherDisablesNextOnline() { - mLauncher.launchBrowserIfStopped(true, 0); - waitForLaunchBrowserTask(); + mLauncher.launchBrowserIfStopped(mContext, true, 0); assertTrue(shouldLaunchBrowserIfStoppedSync()); // Simulate restarting the browser by deleting the launcher and creating a new one.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index 5f8438b..611c703 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -84,6 +84,7 @@ // NOTE: Disable online detection so we we'll default to online on test bots with no network. @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @CommandLineFlags.Add(ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED) +@RetryOnFailure public class ContextualSearchManagerTest extends ChromeActivityTestCaseBase<ChromeActivity> { private static final String TEST_PAGE = "/chrome/test/data/android/contextualsearch/tap_test.html"; @@ -1019,7 +1020,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testHidesWhenOmniboxFocused() throws InterruptedException, TimeoutException { clickWordNode("intelligence"); @@ -1038,7 +1038,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testDoesContainAWord() { assertTrue(mSelectionController.doesContainAWord("word")); assertTrue(mSelectionController.doesContainAWord("word ")); @@ -1057,7 +1056,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testIsValidSelection() { StubbedContentViewCore stubbedCvc = new StubbedContentViewCore( getActivity().getBaseContext()); @@ -1081,7 +1079,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTap() throws InterruptedException, TimeoutException { clickWordNode("intelligence"); @@ -1097,7 +1094,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testLongPress() throws InterruptedException, TimeoutException { longPressNode("states"); @@ -1190,7 +1186,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testPrefetchFailoverRequestMadeAfterOpen() throws InterruptedException, TimeoutException { mFakeServer.reset(); @@ -1219,7 +1214,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapDisablePreload() throws InterruptedException, TimeoutException { clickWordNode("intelligence"); @@ -1235,7 +1229,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testLongPressGestureSelects() throws InterruptedException, TimeoutException { longPressNode("intelligence"); assertEquals("Intelligence", getSelectedText()); @@ -1255,7 +1248,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapGestureSelects() throws InterruptedException, TimeoutException { clickWordNode("intelligence"); assertEquals("Intelligence", getSelectedText()); @@ -1273,7 +1265,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapGestureOnSpecialCharacterDoesntSelect() throws InterruptedException, TimeoutException { clickNode("question-mark"); @@ -1288,7 +1279,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapGestureFollowedByScrollClearsSelection() throws InterruptedException, TimeoutException { clickWordNode("intelligence"); @@ -1306,7 +1296,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapGestureFollowedByInvalidTextTapCloses() throws InterruptedException, TimeoutException { clickWordNode("states-far"); @@ -1321,7 +1310,6 @@ * Tests that a Tap gesture followed by tapping a non-text character doesn't select. * @SmallTest * @Feature({"ContextualSearch"}) - * @RetryOnFailure * crbug.com/665633 */ @DisabledTest @@ -1337,7 +1325,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapGestureFarAwayTogglesSelecting() throws InterruptedException, TimeoutException { clickWordNode("states"); @@ -1358,7 +1345,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapGesturesNearbyKeepSelecting() throws InterruptedException, TimeoutException { clickWordNode("states"); assertEquals("States", getSelectedText()); @@ -1443,8 +1429,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - - @RetryOnFailure public void testContextualSearchNotDismissedOnBackgroundTabCrash() throws InterruptedException, TimeoutException { ChromeTabUtils.newTabFromMenu(getInstrumentation(), @@ -1480,7 +1464,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapSearchBarPromotesToTab() throws InterruptedException, TimeoutException { // -------- SET UP --------- // Track Tab creation with this helper. @@ -1527,7 +1510,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapOnRoleIgnored() throws InterruptedException, TimeoutException { PanelState initialState = mPanel.getPanelState(); clickNode("role"); @@ -1540,7 +1522,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapOnARIAIgnored() throws InterruptedException, TimeoutException { PanelState initialState = mPanel.getPanelState(); clickNode("aria"); @@ -1552,7 +1533,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapOnFocusableIgnored() throws InterruptedException, TimeoutException { PanelState initialState = mPanel.getPanelState(); clickNode("focusable"); @@ -1566,7 +1546,6 @@ @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) @DisableIf.Build(supported_abis_includes = "arm64-v8a", message = "crbug.com/596533") - @RetryOnFailure public void testTapLimitForDecided() throws InterruptedException, TimeoutException { mPolicy.setTapLimitForDecidedForTesting(2); clickToTriggerPrefetch(); @@ -1596,7 +1575,6 @@ @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) @DisableIf.Build(supported_abis_includes = "arm64-v8a", message = "crbug.com/596533") - @RetryOnFailure public void testTapLimitForUndecided() throws InterruptedException, TimeoutException { mPolicy.setTapLimitForUndecidedForTesting(2); mPolicy.overrideDecidedStateForTesting(false); @@ -1627,7 +1605,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testExpandBeforeSearchTermResolution() throws InterruptedException, TimeoutException { clickWordNode("states"); @@ -1651,7 +1628,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testSearchTermResolutionError() throws InterruptedException, TimeoutException { clickWordNode("states"); assertSearchTermRequested(); @@ -1670,7 +1646,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testHttpsBeforeAcceptForOptOut() throws InterruptedException, TimeoutException { mPolicy.overrideDecidedStateForTesting(false); mFakeServer.setShouldUseHttps(true); @@ -1685,7 +1660,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testHttpsAfterAcceptForOptOut() throws InterruptedException, TimeoutException { mPolicy.overrideDecidedStateForTesting(true); mFakeServer.setShouldUseHttps(true); @@ -1698,7 +1672,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testHttpBeforeAcceptForOptOut() throws InterruptedException, TimeoutException { mPolicy.overrideDecidedStateForTesting(false); @@ -1710,7 +1683,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testHttpAfterAcceptForOptOut() throws InterruptedException, TimeoutException { mPolicy.overrideDecidedStateForTesting(true); @@ -1747,7 +1719,6 @@ @SmallTest @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) - @RetryOnFailure @DisableIf.Build(supported_abis_includes = "arm64-v8a", message = "crbug.com/596533") public void testAppMenuSuppressedWhenExpanded() throws InterruptedException, TimeoutException { clickWordNode("states"); @@ -1767,7 +1738,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testAppMenuSuppressedWhenMaximized() throws InterruptedException, TimeoutException { clickWordNode("states"); flingPanelUpToTop(); @@ -1794,7 +1764,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testPromoTapCount() throws InterruptedException, TimeoutException { mPolicy.setPromoTapTriggeredLimitForTesting(2); mPolicy.overrideDecidedStateForTesting(false); @@ -1869,7 +1838,6 @@ @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) @DisableIf.Build(supported_abis_includes = "arm64-v8a", message = "crbug.com/596533") - @RetryOnFailure public void testPromoOpenCountForDecided() throws InterruptedException, TimeoutException { mPolicy.overrideDecidedStateForTesting(true); @@ -1925,7 +1893,6 @@ @SmallTest @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) - @RetryOnFailure public void testNotifyObserverHideAfterLongPress() throws InterruptedException, TimeoutException { TestContextualSearchObserver observer = new TestContextualSearchObserver(); @@ -1976,7 +1943,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testNotifyObserverHideOnClearSelectionAfterTap() throws InterruptedException, TimeoutException { TestContextualSearchObserver observer = new TestContextualSearchObserver(); @@ -2006,7 +1972,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testPreventHandlingCurrentSelectionModification() throws InterruptedException, TimeoutException { simulateLongPressSearch("search"); @@ -2040,7 +2005,6 @@ @SmallTest @Feature({"ContextualSearch"}) @CommandLineFlags.Add(ContextualSearchFieldTrial.SUPPRESSION_TAPS + "=" + PLENTY_OF_TAPS) - @RetryOnFailure public void testTapALot() throws InterruptedException, TimeoutException { mPolicy.setTapLimitForDecidedForTesting(PLENTY_OF_TAPS); mPolicy.setTapLimitForUndecidedForTesting(PLENTY_OF_TAPS); @@ -2082,7 +2046,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testRedirectedExternalNavigationWithUserGesture() { final ExternalNavigationHandler externalNavHandler = new ExternalNavigationHandler(getActivity().getActivityTab()); @@ -2116,7 +2079,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testExternalNavigationWithoutUserGesture() { final ExternalNavigationHandler externalNavHandler = new ExternalNavigationHandler(getActivity().getActivityTab()); @@ -2138,7 +2100,6 @@ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testSelectionExpansionOnSearchTermResolution() throws InterruptedException, TimeoutException { mFakeServer.reset(); @@ -2156,11 +2117,9 @@ @SmallTest @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) - @CommandLineFlags - .Add(ContextualSearchFieldTrial.PEEK_PROMO_ENABLED + "=true") - @DisableIf.Build(supported_abis_includes = "arm64-v8a", message = "crbug.com/596533") - @RetryOnFailure - public void testLongPressShowsPeekPromo() + @CommandLineFlags.Add(ContextualSearchFieldTrial.PEEK_PROMO_ENABLED + "=true") + @DisableIf.Build(supported_abis_includes = "arm64-v8a", message = "crbug.com/596533") + public void testLongPressShowsPeekPromo() throws InterruptedException, TimeoutException { // Must be in undecided state in order to trigger the Peek Promo. mPolicy.overrideDecidedStateForTesting(false); @@ -2201,7 +2160,6 @@ @SmallTest @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) - @RetryOnFailure public void testTapContentVisibility() throws InterruptedException, TimeoutException { // Simulate a tap and make sure Content is not visible. simulateTapSearch("search"); @@ -2280,7 +2238,6 @@ @SmallTest @Feature({"ContextualSearch"}) @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE) - @RetryOnFailure public void testLongPressMultipleSwipeOnlyLoadsContentOnce() throws InterruptedException, TimeoutException { // Simulate a long press and make sure no Content is created. @@ -2316,7 +2273,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testChainedSearchCreatesNewContent() throws InterruptedException, TimeoutException { // Simulate a tap and make sure Content is not visible. simulateTapSearch("search"); @@ -2399,7 +2355,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testChainedSearchContentVisibility() throws InterruptedException, TimeoutException { // Simulate a tap and make sure Content is not visible. simulateTapSearch("search"); @@ -2433,7 +2388,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testTapCloseRemovedFromHistory() throws InterruptedException, TimeoutException { // Simulate a tap and make sure a URL was loaded. simulateTapSearch("search"); @@ -2474,7 +2428,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testChainedTapsRemovedFromHistory() throws InterruptedException, TimeoutException { // Simulate a tap and make sure a URL was loaded. simulateTapSearch("search"); @@ -2515,7 +2468,6 @@ @SmallTest @Feature({"ContextualSearch"}) @CommandLineFlags.Add(ContextualSearchFieldTrial.ENABLE_TRANSLATION + "=true") - @RetryOnFailure public void testTapWithLanguage() throws InterruptedException, TimeoutException { // Tapping a German word should trigger translation. simulateTapSearch("german"); @@ -2548,7 +2500,6 @@ @Feature({"ContextualSearch"}) @CommandLineFlags.Add({ContextualSearchFieldTrial.ENABLE_TRANSLATION + "=true", ContextualSearchFieldTrial.ENABLE_SERVER_CONTROLLED_ONEBOX + "=true"}) - @RetryOnFailure public void testTapWithoutLanguageCanBeForced() throws InterruptedException, TimeoutException { // Tapping an English word should trigger translation. simulateTapSearch("search"); @@ -2563,7 +2514,6 @@ @SmallTest @Feature({"ContextualSearch"}) @CommandLineFlags.Add(ContextualSearchFieldTrial.ENABLE_TRANSLATION + "=true") - @RetryOnFailure public void testLongpressTranslates() throws InterruptedException, TimeoutException { // LongPress on any word should trigger translation. simulateLongPressSearch("search"); @@ -2579,7 +2529,6 @@ @Feature({"ContextualSearch"}) @CommandLineFlags.Add({ContextualSearchFieldTrial.ENABLE_TRANSLATION + "=true", ContextualSearchFieldTrial.DISABLE_AUTO_DETECT_TRANSLATION_ONEBOX + "=true"}) - @RetryOnFailure public void testLongpressAutoDetectDisabledDoesNotTranslate() throws InterruptedException, TimeoutException { // Unless disabled, LongPress on any word should trigger translation. @@ -2596,7 +2545,6 @@ @Feature({"ContextualSearch"}) @CommandLineFlags.Add({ContextualSearchFieldTrial.ENABLE_TRANSLATION + "=true", ContextualSearchFieldTrial.DISABLE_FORCE_TRANSLATION_ONEBOX + "=true"}) - @RetryOnFailure public void testLongpressTranslateDisabledDoesNotTranslate() throws InterruptedException, TimeoutException { // Unless disabled, LongPress on any word should trigger translation. @@ -2637,7 +2585,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure public void testPanelDismissedOnToggleFullscreen() throws InterruptedException, TimeoutException { // Simulate a tap and assert that the panel peeks. @@ -2717,7 +2664,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure // NOTE: Remove the flag so we will run just this test with onLine detection enabled. @CommandLineFlags.Remove(ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED) public void testNetworkDisconnectedDeactivatesSearch() @@ -2743,7 +2689,6 @@ */ @SmallTest @Feature({"ContextualSearch"}) - @RetryOnFailure // crbug.com/673681 public void testQuickActionCaptionAndImage() throws InterruptedException, TimeoutException { // Simulate a tap to show the Bar, then set the quick action data. simulateTapSearch("search");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java new file mode 100644 index 0000000..b6a8536 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java
@@ -0,0 +1,115 @@ +// 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. + +package org.chromium.chrome.browser.multiwindow; + +import static org.chromium.chrome.browser.multiwindow.MultiWindowUtilsTest.createSecondChromeTabbedActivity; + +import android.annotation.TargetApi; +import android.app.ActivityManager; +import android.content.Context; +import android.os.Build; +import android.test.suitebuilder.annotation.MediumTest; + +import org.chromium.base.ActivityState; +import org.chromium.base.ApplicationStatus; +import org.chromium.base.ContextUtils; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.MinAndroidSdkLevel; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.ChromeTabbedActivity2; +import org.chromium.chrome.browser.firstrun.FirstRunStatus; +import org.chromium.chrome.browser.tabmodel.TabWindowManager; +import org.chromium.chrome.test.ChromeTabbedActivityTestBase; +import org.chromium.chrome.test.util.MenuUtils; +import org.chromium.content.browser.test.util.Criteria; +import org.chromium.content.browser.test.util.CriteriaHelper; + +import java.util.concurrent.Callable; + +/** + * Integration testing for Android's N+ MultiWindow. + */ +@MinAndroidSdkLevel(Build.VERSION_CODES.N) +public class MultiWindowIntegrationTest extends ChromeTabbedActivityTestBase { + + @Override + public void startMainActivity() throws InterruptedException { + startMainActivityOnBlankPage(); + } + + @MediumTest + @Feature("MultiWindow") + @TargetApi(Build.VERSION_CODES.N) + @CommandLineFlags.Add(ChromeSwitches.DISABLE_TAB_MERGING_FOR_TESTING) + public void testIncognitoNtpHandledCorrectly() throws InterruptedException { + try { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + FirstRunStatus.setFirstRunFlowComplete(true); + } + }); + + newIncognitoTabFromMenu(); + assertTrue(getActivity().getActivityTab().isIncognito()); + final int incognitoTabId = getActivity().getActivityTab().getId(); + final ChromeTabbedActivity2 cta2 = createSecondChromeTabbedActivity(getActivity()); + + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + Context context = ContextUtils.getApplicationContext(); + ActivityManager activityManager = + (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + for (ActivityManager.AppTask task : activityManager.getAppTasks()) { + if (getActivity().getTaskId() == task.getTaskInfo().id) { + task.moveToFront(); + break; + } + } + } + }); + CriteriaHelper.pollUiThread(Criteria.equals(ActivityState.RESUMED, + new Callable<Integer>() { + @Override + public Integer call() throws Exception { + return ApplicationStatus.getStateForActivity(getActivity()); + } + })); + + MenuUtils.invokeCustomMenuActionSync( + getInstrumentation(), getActivity(), R.id.move_to_other_window_menu_id); + + CriteriaHelper.pollUiThread(Criteria.equals(1, + new Callable<Integer>() { + @Override + public Integer call() throws Exception { + return cta2.getTabModelSelector().getModel(true).getCount(); + } + })); + + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + assertEquals(1, TabWindowManager.getInstance().getIncognitoTabCount()); + + // Ensure the same tab exists in the new activity. + assertEquals(incognitoTabId, cta2.getActivityTab().getId()); + } + }); + } finally { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + FirstRunStatus.setFirstRunFlowComplete(false); + } + }); + } + } + +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java index 37b585c..9d0bbe6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java
@@ -28,8 +28,7 @@ /** * Class for testing MultiWindowUtils. */ -// TODO(twellington): Replace with Build.VERSION_CODES.N when available. -@MinAndroidSdkLevel(24) +@MinAndroidSdkLevel(Build.VERSION_CODES.N) public class MultiWindowUtilsTest extends ChromeTabbedActivityTestBase { @Override
diff --git a/chrome/browser/android/background_sync_launcher_android.cc b/chrome/browser/android/background_sync_launcher_android.cc index bac2de6..0b13a14 100644 --- a/chrome/browser/android/background_sync_launcher_android.cc +++ b/chrome/browser/android/background_sync_launcher_android.cc
@@ -44,7 +44,8 @@ JNIEnv* env = base::android::AttachCurrentThread(); Java_BackgroundSyncLauncher_launchBrowserIfStopped( - env, java_launcher_, launch_when_next_online, min_delay_ms); + env, java_launcher_, base::android::GetApplicationContext(), + launch_when_next_online, min_delay_ms); } // static
diff --git a/chrome/browser/android/bookmarks/bookmark_bridge.cc b/chrome/browser/android/bookmarks/bookmark_bridge.cc index f56a182..dab16324 100644 --- a/chrome/browser/android/bookmarks/bookmark_bridge.cc +++ b/chrome/browser/android/bookmarks/bookmark_bridge.cc
@@ -19,10 +19,10 @@ #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/undo/bookmark_undo_service_factory.h" -#include "components/bookmarks/browser/bookmark_match.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_utils.h" #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/bookmarks/common/android/bookmark_type.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/bookmarks/managed/managed_bookmark_service.h" @@ -586,13 +586,13 @@ jint max_results) { DCHECK(bookmark_model_->loaded()); - std::vector<bookmarks::BookmarkMatch> results; + std::vector<bookmarks::TitledUrlMatch> results; bookmark_model_->GetBookmarksMatching( base::android::ConvertJavaStringToUTF16(env, j_query), max_results, query_parser::MatchingAlgorithm::ALWAYS_PREFIX_SEARCH, &results); - for (const bookmarks::BookmarkMatch& match : results) { + for (const bookmarks::TitledUrlMatch& match : results) { const BookmarkNode* node = static_cast<const BookmarkNode*>(match.node); std::vector<int> title_match_start_positions;
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index 428c7ea6..caee5129 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -177,7 +177,6 @@ #endif app_list::switches::kDisableSyncAppList, app_list::switches::kEnableSyncAppList, - ash::switches::kAshEnableTabletPowerButton, ash::switches::kAshEnableTouchView, ash::switches::kAshEnablePalette, ash::switches::kAshEnablePaletteOnAllDisplays,
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.cc b/chrome/browser/chromeos/login/ui/webui_login_display.cc index 5eb3a38e..74ff645 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_display.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_display.cc
@@ -227,8 +227,11 @@ } void WebUILoginDisplay::LoadSigninWallpaper() { - WallpaperManager::Get()->SetDefaultWallpaperDelayed( - user_manager::SignInAccountId()); + if (!WallpaperManager::Get()->SetDeviceWallpaperIfApplicable( + user_manager::SignInAccountId())) { + WallpaperManager::Get()->SetDefaultWallpaperDelayed( + user_manager::SignInAccountId()); + } } void WebUILoginDisplay::OnSigninScreenReady() {
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index e2e49ef..2b7b988 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -15,6 +15,7 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/path_service.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" #include "base/sys_info.h" @@ -29,6 +30,7 @@ #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/users/avatar/user_image_loader.h" #include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/image_decoder.h" #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/common/chrome_paths.h" @@ -49,7 +51,9 @@ #include "content/public/browser/notification_service.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_manager_connection.h" +#include "crypto/sha2.h" #include "services/service_manager/public/cpp/connector.h" +#include "url/gurl.h" using content::BrowserThread; using wallpaper::WallpaperManagerBase; @@ -78,6 +82,11 @@ // Known user keys. const char kWallpaperFilesId[] = "wallpaper-files-id"; +// The directory and file name to save the downloaded device policy controlled +// wallpaper. +const char kDeviceWallpaperDir[] = "device_wallpaper"; +const char kDeviceWallpaperFile[] = "device_wallpaper_image.jpg"; + // These global default values are used to set customized default // wallpaper path in WallpaperManager::InitializeWallpaper(). base::FilePath GetCustomizedWallpaperDefaultRescaledFileName( @@ -195,6 +204,21 @@ } } +// A helper function to check the existing/downloaded device wallpaper file's +// hash value matches with the hash value provided in the policy settings. +bool CheckDeviceWallpaperMatchHash(const base::FilePath& device_wallpaper_file, + const std::string& hash) { + std::string image_data; + if (base::ReadFileToString(device_wallpaper_file, &image_data)) { + std::string sha_hash = crypto::SHA256HashString(image_data); + if (base::ToLowerASCII(base::HexEncode( + sha_hash.c_str(), sha_hash.size())) == base::ToLowerASCII(hash)) { + return true; + } + } + return false; +} + } // namespace // This is "wallpaper either scheduled to load, or loading right now". @@ -347,6 +371,7 @@ WallpaperManager::~WallpaperManager() { show_user_name_on_signin_subscription_.reset(); + device_wallpaper_image_subscription_.reset(); user_manager::UserManager::Get()->RemoveSessionStateObserver(this); weak_factory_.InvalidateWeakPtrs(); } @@ -386,6 +411,11 @@ kAccountsPrefShowUserNamesOnSignIn, base::Bind(&WallpaperManager::InitializeRegisteredDeviceWallpaper, weak_factory_.GetWeakPtr())); + device_wallpaper_image_subscription_ = + CrosSettings::Get()->AddSettingsObserver( + kDeviceWallpaperImage, + base::Bind(&WallpaperManager::OnDeviceWallpaperPolicyChanged, + weak_factory_.GetWeakPtr())); } void WallpaperManager::EnsureLoggedInUserWallpaperLoaded() { @@ -697,6 +727,12 @@ return; } + // For a enterprise managed user, set the device wallpaper if we're at the + // login screen. + if (!user_manager::UserManager::Get()->IsUserLoggedIn() && + SetDeviceWallpaperIfApplicable(account_id)) + return; + // Guest user or regular user in ephemeral mode. if ((user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral( account_id) && @@ -734,16 +770,23 @@ } if (info.type == user_manager::User::CUSTOMIZED || - info.type == user_manager::User::POLICY) { - const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); - // Wallpaper is not resized when layout is - // wallpaper::WALLPAPER_LAYOUT_CENTER. - // Original wallpaper should be used in this case. - // TODO(bshe): Generates cropped custom wallpaper for CENTER layout. - if (info.layout == wallpaper::WALLPAPER_LAYOUT_CENTER) - sub_dir = wallpaper::kOriginalWallpaperSubDir; - base::FilePath wallpaper_path = GetCustomWallpaperDir(sub_dir); - wallpaper_path = wallpaper_path.Append(info.location); + info.type == user_manager::User::POLICY || + info.type == user_manager::User::DEVICE) { + base::FilePath wallpaper_path; + if (info.type != user_manager::User::DEVICE) { + const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); + // Wallpaper is not resized when layout is + // wallpaper::WALLPAPER_LAYOUT_CENTER. + // Original wallpaper should be used in this case. + // TODO(bshe): Generates cropped custom wallpaper for CENTER layout. + if (info.layout == wallpaper::WALLPAPER_LAYOUT_CENTER) + sub_dir = wallpaper::kOriginalWallpaperSubDir; + wallpaper_path = GetCustomWallpaperDir(sub_dir); + wallpaper_path = wallpaper_path.Append(info.location); + } else { + wallpaper_path = GetDeviceWallpaperFilePath(); + } + CustomWallpaperMap::iterator it = wallpaper_cache_.find(account_id); // Do not try to load the wallpaper if the path is the same. Since loading // could still be in progress, we ignore the existence of the image. @@ -891,6 +934,114 @@ true /* update wallpaper */); } +void WallpaperManager::OnDeviceWallpaperPolicyChanged() { + SetDeviceWallpaperIfApplicable( + user_manager::UserManager::Get()->IsUserLoggedIn() + ? user_manager::UserManager::Get()->GetActiveUser()->GetAccountId() + : user_manager::SignInAccountId()); +} + +void WallpaperManager::OnDeviceWallpaperExists(const AccountId& account_id, + const std::string& url, + const std::string& hash, + bool exist) { + if (exist) { + base::PostTaskAndReplyWithResult( + BrowserThread::GetBlockingPool(), FROM_HERE, + base::Bind(&CheckDeviceWallpaperMatchHash, GetDeviceWallpaperFilePath(), + hash), + base::Bind(&WallpaperManager::OnCheckDeviceWallpaperMatchHash, + weak_factory_.GetWeakPtr(), account_id, url, hash)); + } else { + GURL device_wallpaper_url(url); + device_wallpaper_downloader_.reset(new CustomizationWallpaperDownloader( + g_browser_process->system_request_context(), device_wallpaper_url, + GetDeviceWallpaperDir(), GetDeviceWallpaperFilePath(), + base::Bind(&WallpaperManager::OnDeviceWallpaperDownloaded, + weak_factory_.GetWeakPtr(), account_id, hash))); + device_wallpaper_downloader_->Start(); + } +} + +void WallpaperManager::OnDeviceWallpaperDownloaded(const AccountId& account_id, + const std::string& hash, + bool success, + const GURL& url) { + if (!success) { + LOG(ERROR) << "Failed to download the device wallpaper. Fallback to " + "default wallpaper."; + SetDefaultWallpaperDelayed(account_id); + return; + } + + base::PostTaskAndReplyWithResult( + BrowserThread::GetBlockingPool(), FROM_HERE, + base::Bind(&CheckDeviceWallpaperMatchHash, GetDeviceWallpaperFilePath(), + hash), + base::Bind(&WallpaperManager::OnCheckDeviceWallpaperMatchHash, + weak_factory_.GetWeakPtr(), account_id, url.spec(), hash)); +} + +void WallpaperManager::OnCheckDeviceWallpaperMatchHash( + const AccountId& account_id, + const std::string& url, + const std::string& hash, + bool match) { + if (!match) { + if (retry_download_if_failed_) { + // We only retry to download the device wallpaper one more time if the + // hash doesn't match. + retry_download_if_failed_ = false; + GURL device_wallpaper_url(url); + device_wallpaper_downloader_.reset(new CustomizationWallpaperDownloader( + g_browser_process->system_request_context(), device_wallpaper_url, + GetDeviceWallpaperDir(), GetDeviceWallpaperFilePath(), + base::Bind(&WallpaperManager::OnDeviceWallpaperDownloaded, + weak_factory_.GetWeakPtr(), account_id, hash))); + device_wallpaper_downloader_->Start(); + } else { + LOG(ERROR) << "The device wallpaper hash doesn't match with provided " + "hash value. Fallback to default wallpaper! "; + SetDefaultWallpaperDelayed(account_id); + + // Reset the boolean variable so that it can retry to download when the + // next device wallpaper request comes in. + retry_download_if_failed_ = true; + } + return; + } + + user_image_loader::StartWithFilePath( + task_runner_, GetDeviceWallpaperFilePath(), + ImageDecoder::ROBUST_JPEG_CODEC, + 0, // Do not crop. + base::Bind(&WallpaperManager::OnDeviceWallpaperDecoded, + weak_factory_.GetWeakPtr(), account_id)); +} + +void WallpaperManager::OnDeviceWallpaperDecoded( + const AccountId& account_id, + std::unique_ptr<user_manager::UserImage> user_image) { + WallpaperInfo wallpaper_info = {GetDeviceWallpaperFilePath().value(), + wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, + user_manager::User::DEVICE, + base::Time::Now().LocalMidnight()}; + if (user_manager::UserManager::Get()->IsUserLoggedIn()) { + // In a user's session treat the device wallpaper as a normal custom + // wallpaper. It should be persistent and can be overriden by other user + // selected wallpapers. + SetUserWallpaperInfo(account_id, wallpaper_info, true /* is_persistent */); + GetPendingWallpaper(account_id, false) + ->ResetSetWallpaperImage(user_image->image(), wallpaper_info); + wallpaper_cache_[account_id] = CustomWallpaperElement( + GetDeviceWallpaperFilePath(), user_image->image()); + } else { + // In the login screen set the device wallpaper as the wallpaper. + GetPendingWallpaper(user_manager::SignInAccountId(), false) + ->ResetSetWallpaperImage(user_image->image(), wallpaper_info); + } +} + void WallpaperManager::InitializeRegisteredDeviceWallpaper() { if (user_manager::UserManager::Get()->IsUserLoggedIn()) return; @@ -907,7 +1058,8 @@ int public_session_user_index = FindPublicSession(users); if ((!show_users && public_session_user_index == -1) || users.empty()) { // Boot into sign in form, preload default wallpaper. - SetDefaultWallpaperDelayed(user_manager::SignInAccountId()); + if (!SetDeviceWallpaperIfApplicable(user_manager::SignInAccountId())) + SetDefaultWallpaperDelayed(user_manager::SignInAccountId()); return; } @@ -966,6 +1118,53 @@ return true; } +bool WallpaperManager::ShouldSetDeviceWallpaper(const AccountId& account_id, + std::string* url, + std::string* hash) { + // Only allow the device wallpaper for enterprise managed devices. + if (!g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->IsEnterpriseManaged()) { + return false; + } + + const base::DictionaryValue* dict = nullptr; + if (!CrosSettings::Get()->GetDictionary(kDeviceWallpaperImage, &dict) || + !dict->GetStringWithoutPathExpansion("url", url) || + !dict->GetStringWithoutPathExpansion("hash", hash)) { + return false; + } + + // Only set the device wallpaper if 1) we're at the login screen or 2) there + // is no user policy wallpaper in a user session and the user has the default + // wallpaper or device wallpaper in a user session. Note in the latter case, + // the device wallpaper can be overridden by user-selected wallpapers. + if (user_manager::UserManager::Get()->IsUserLoggedIn()) { + WallpaperInfo info; + if (GetUserWallpaperInfo(account_id, &info) && + (info.type == user_manager::User::POLICY || + (info.type != user_manager::User::DEFAULT && + info.type != user_manager::User::DEVICE))) { + return false; + } + } + + return true; +} + +base::FilePath WallpaperManager::GetDeviceWallpaperDir() { + base::FilePath wallpaper_dir; + if (!PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir)) { + LOG(ERROR) << "Unable to get wallpaper dir."; + return base::FilePath(); + } + return wallpaper_dir.Append(kDeviceWallpaperDir); +} + +base::FilePath WallpaperManager::GetDeviceWallpaperFilePath() { + return GetDeviceWallpaperDir().Append(kDeviceWallpaperFile); +} + void WallpaperManager::OnWallpaperDecoded( const AccountId& account_id, wallpaper::WallpaperLayout layout, @@ -1071,6 +1270,36 @@ return loading_.size(); } +wallpaper::WallpaperFilesId WallpaperManager::GetFilesId( + const AccountId& account_id) const { + std::string stored_value; + if (user_manager::known_user::GetStringPref(account_id, kWallpaperFilesId, + &stored_value)) { + return wallpaper::WallpaperFilesId::FromString(stored_value); + } + const std::string& old_id = account_id.GetUserEmail(); // Migrated + const wallpaper::WallpaperFilesId files_id = HashWallpaperFilesIdStr(old_id); + SetKnownUserWallpaperFilesId(account_id, files_id); + return files_id; +} + +bool WallpaperManager::SetDeviceWallpaperIfApplicable( + const AccountId& account_id) { + std::string url; + std::string hash; + if (ShouldSetDeviceWallpaper(account_id, &url, &hash)) { + // Check if the device wallpaper exists and matches the hash. If so, use it + // directly. Otherwise download it first. + base::PostTaskAndReplyWithResult( + BrowserThread::GetBlockingPool(), FROM_HERE, + base::Bind(&base::PathExists, GetDeviceWallpaperFilePath()), + base::Bind(&WallpaperManager::OnDeviceWallpaperExists, + weak_factory_.GetWeakPtr(), account_id, url, hash)); + return true; + } + return false; +} + void WallpaperManager::UserChangedChildStatus(user_manager::User* user) { SetUserWallpaperNow(user->GetAccountId()); } @@ -1157,17 +1386,4 @@ DoSetDefaultWallpaper(EmptyAccountId(), MovableOnDestroyCallbackHolder()); } -wallpaper::WallpaperFilesId WallpaperManager::GetFilesId( - const AccountId& account_id) const { - std::string stored_value; - if (user_manager::known_user::GetStringPref(account_id, kWallpaperFilesId, - &stored_value)) { - return wallpaper::WallpaperFilesId::FromString(stored_value); - } - const std::string& old_id = account_id.GetUserEmail(); // Migrated - const wallpaper::WallpaperFilesId files_id = HashWallpaperFilesIdStr(old_id); - SetKnownUserWallpaperFilesId(account_id, files_id); - return files_id; -} - } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h index 206bcfef..f4c1a952 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/ref_counted_memory.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/customization/customization_wallpaper_downloader.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "components/user_manager/user.h" #include "components/user_manager/user_image/user_image.h" @@ -81,6 +82,7 @@ size_t GetPendingListSizeForTesting() const override; wallpaper::WallpaperFilesId GetFilesId( const AccountId& account_id) const override; + bool SetDeviceWallpaperIfApplicable(const AccountId& account_id) override; // ash::mojom::WallpaperPicker: void Open() override; @@ -115,10 +117,40 @@ const AccountId& account_id, std::unique_ptr<user_manager::UserImage> user_image); + // This is called when the device wallpaper policy changes. + void OnDeviceWallpaperPolicyChanged(); + // This is call after checking if the device wallpaper exists. + void OnDeviceWallpaperExists(const AccountId& account_id, + const std::string& url, + const std::string& hash, + bool exist); + // This is called after the device wallpaper is download (either successful or + // failed). + void OnDeviceWallpaperDownloaded(const AccountId& account_id, + const std::string& hash, + bool success, + const GURL& url); + // Check if the device wallpaper matches the hash that's provided in the + // device wallpaper policy setting. + void OnCheckDeviceWallpaperMatchHash(const AccountId& account_id, + const std::string& url, + const std::string& hash, + bool match); + // This is called when the device wallpaper is decoded successfully. + void OnDeviceWallpaperDecoded( + const AccountId& account_id, + std::unique_ptr<user_manager::UserImage> user_image); + // wallpaper::WallpaperManagerBase: void InitializeRegisteredDeviceWallpaper() override; bool GetUserWallpaperInfo(const AccountId& account_id, wallpaper::WallpaperInfo* info) const override; + // Returns true if the device wallpaper should be set for the account. + bool ShouldSetDeviceWallpaper(const AccountId& account_id, + std::string* url, + std::string* hash) override; + base::FilePath GetDeviceWallpaperDir() override; + base::FilePath GetDeviceWallpaperFilePath() override; void OnWallpaperDecoded( const AccountId& account_id, wallpaper::WallpaperLayout layout, @@ -165,6 +197,12 @@ std::unique_ptr<CrosSettings::ObserverSubscription> show_user_name_on_signin_subscription_; + std::unique_ptr<CrosSettings::ObserverSubscription> + device_wallpaper_image_subscription_; + std::unique_ptr<CustomizationWallpaperDownloader> + device_wallpaper_downloader_; + bool retry_download_if_failed_ = true; + // Pointer to last inactive (waiting) entry of 'loading_' list. // NULL when there is no inactive request. PendingWallpaper* pending_inactive_;
diff --git a/chrome/browser/importer/profile_writer_unittest.cc b/chrome/browser/importer/profile_writer_unittest.cc index dbed3192..8a48a67 100644 --- a/chrome/browser/importer/profile_writer_unittest.cc +++ b/chrome/browser/importer/profile_writer_unittest.cc
@@ -16,17 +16,17 @@ #include "chrome/browser/importer/importer_unittest_utils.h" #include "chrome/common/importer/imported_bookmark_entry.h" #include "chrome/test/base/testing_profile.h" -#include "components/bookmarks/browser/bookmark_match.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_utils.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/bookmarks/test/bookmark_test_helpers.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" -using bookmarks::BookmarkMatch; using bookmarks::BookmarkModel; +using bookmarks::TitledUrlMatch; class TestProfileWriter : public ProfileWriter { public: @@ -81,7 +81,7 @@ const std::vector<BookmarkModel::URLAndTitle>& bookmarks_record, BookmarkModel* bookmark_model, size_t expected) { - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; for (size_t i = 0; i < bookmarks_record.size(); ++i) { bookmark_model->GetBookmarksMatching( bookmarks_record[i].title, 10, &matches);
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win.cc b/chrome/browser/metrics/antivirus_metrics_provider_win.cc index 44772e5fe..ada7c8a 100644 --- a/chrome/browser/metrics/antivirus_metrics_provider_win.cc +++ b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
@@ -176,6 +176,8 @@ result = FillAntiVirusProductsFromWMI(&av_products); } + MaybeAddUnregisteredAntiVirusProducts(&av_products); + UMA_HISTOGRAM_ENUMERATION("UMA.AntiVirusMetricsProvider.Result", result, RESULT_COUNT); @@ -426,3 +428,48 @@ return RESULT_SUCCESS; } + +void AntiVirusMetricsProvider::MaybeAddUnregisteredAntiVirusProducts( + std::vector<AvProduct>* products) { + base::ThreadRestrictions::AssertIOAllowed(); + + // Trusteer Rapport does not register with WMI or Security Center so do some + // "best efforts" detection here. + + // Rapport always installs into 32-bit Program Files in directory + // %DIR_PROGRAM_FILESX86%\Trusteer\Rapport + base::FilePath binary_path; + if (!PathService::Get(base::DIR_PROGRAM_FILESX86, &binary_path)) + return; + + binary_path = binary_path.AppendASCII("Trusteer") + .AppendASCII("Rapport") + .AppendASCII("bin") + .AppendASCII("RapportService.exe"); + + if (!base::PathExists(binary_path)) + return; + + std::wstring mutable_path_str(binary_path.value()); + std::string product_version; + + if (!GetProductVersion(&mutable_path_str, &product_version)) + return; + + AvProduct av_product; + + // Assume enabled, no easy way of knowing for sure. + av_product.set_product_state(metrics::SystemProfileProto::AntiVirusState:: + SystemProfileProto_AntiVirusState_STATE_ON); + + // Taken from Add/Remove programs as the product name. + std::string product_name("Trusteer Endpoint Protection"); + if (ShouldReportFullNames()) { + av_product.set_product_name(product_name); + av_product.set_product_version(product_version); + } + av_product.set_product_name_hash(metrics::HashName(product_name)); + av_product.set_product_version_hash(metrics::HashName(product_version)); + + products->push_back(av_product); +}
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win.h b/chrome/browser/metrics/antivirus_metrics_provider_win.h index 13a6b49..0bf86852 100644 --- a/chrome/browser/metrics/antivirus_metrics_provider_win.h +++ b/chrome/browser/metrics/antivirus_metrics_provider_win.h
@@ -72,10 +72,17 @@ // interface is only available on Windows 8 and above. static ResultCode FillAntiVirusProductsFromWSC( std::vector<AvProduct>* products); + // Query WMI ROOT\SecurityCenter2 for installed AV products. This interface is // only available on Windows Vista and above. static ResultCode FillAntiVirusProductsFromWMI( std::vector<AvProduct>* products); + + // Query local machine configuration for other products that might not be + // registered in WMI or Security Center and add them to the product vector. + static void MaybeAddUnregisteredAntiVirusProducts( + std::vector<AvProduct>* products); + static std::vector<AvProduct> GetAntiVirusProductsOnFileThread(); // Called when metrics are done being gathered from the FILE thread.
diff --git a/chrome/browser/notifications/notification_platform_bridge_android.cc b/chrome/browser/notifications/notification_platform_bridge_android.cc index 3f64247..0c8c82f 100644 --- a/chrome/browser/notifications/notification_platform_bridge_android.cc +++ b/chrome/browser/notifications/notification_platform_bridge_android.cc
@@ -7,7 +7,6 @@ #include <utility> #include <vector> -#include "base/android/build_info.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/command_line.h" @@ -316,30 +315,8 @@ const std::string& profile_id, bool incognito, std::set<std::string>* notifications) const { - DCHECK(notifications); - JNIEnv* env = AttachCurrentThread(); - - // Android only supports retrieving existing notifications from M+ - if (base::android::BuildInfo::GetInstance()->sdk_int() < - base::android::SDK_VERSION_MARSHMALLOW) { - return false; - } - - const ScopedJavaLocalRef<jstring> j_profile_id = - ConvertUTF8ToJavaString(env, profile_id); - - ScopedJavaLocalRef<jobjectArray> j_notification_ids = - Java_NotificationPlatformBridge_getNotificationsForProfile( - env, java_object_, j_profile_id); - if (j_notification_ids.obj()) { - std::vector<std::string> notification_ids; - base::android::AppendJavaStringArrayToStringVector( - env, j_notification_ids.obj(), ¬ification_ids); - for (const auto& id : notification_ids) { - notifications->insert(id); - } - } - return true; + // TODO(miguelg): This can actually be implemented for M+ + return false; } // static
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html index 5e4e36e..0e191ae 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -95,7 +95,7 @@ color: var(--google-grey-700); } - paper-dropdown-menu-light, + .md-select, paper-input { --paper-input-container-color: var(--google-grey-500); --paper-input-container-input: {
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html index b9f0f59..d8c6145 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc index 57fb60de..c66f40e 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -13,11 +13,9 @@ #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" #include "ui/accessibility/ax_node_data.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/base/models/menu_model.h" #include "ui/display/display.h" #include "ui/display/screen.h" -#include "ui/strings/grit/ui_strings.h" #include "ui/views/controls/button/label_button_border.h" #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/menu_model_adapter.h" @@ -131,9 +129,11 @@ void ToolbarButton::GetAccessibleNodeData(ui::AXNodeData* node_data) { CustomButton::GetAccessibleNodeData(node_data); node_data->role = ui::AX_ROLE_BUTTON_DROP_DOWN; - node_data->AddStringAttribute( - ui::AX_ATTR_ACTION, l10n_util::GetStringUTF8(IDS_APP_ACCACTION_PRESS)); node_data->AddStateFlag(ui::AX_STATE_HASPOPUP); + if (enabled()) { + node_data->AddIntAttribute(ui::AX_ATTR_ACTION, + ui::AX_SUPPORTED_ACTION_PRESS); + } } std::unique_ptr<views::LabelButtonBorder> ToolbarButton::CreateDefaultBorder()
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn index 0f37e54b..65df57c 100644 --- a/chrome/installer/mini_installer/BUILD.gn +++ b/chrome/installer/mini_installer/BUILD.gn
@@ -69,6 +69,7 @@ ] deps = [ "//base", + "//base/test:test_support", "//testing/gtest", ] }
diff --git a/chrome/installer/mini_installer/chrome_appid.cc b/chrome/installer/mini_installer/chrome_appid.cc index 801cad8..34d3134 100644 --- a/chrome/installer/mini_installer/chrome_appid.cc +++ b/chrome/installer/mini_installer/chrome_appid.cc
@@ -5,8 +5,16 @@ #include "chrome/installer/mini_installer/appid.h" namespace google_update { + +#if defined(GOOGLE_CHROME_BUILD) const wchar_t kAppGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; const wchar_t kMultiInstallAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; const wchar_t kSxSAppGuid[] = L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}"; -} +#else +const wchar_t kAppGuid[] = L""; +const wchar_t kMultiInstallAppGuid[] = L""; +const wchar_t kSxSAppGuid[] = L""; +#endif + +} // namespace google_update
diff --git a/chrome/installer/mini_installer/configuration.cc b/chrome/installer/mini_installer/configuration.cc index 6d20d6d..8b6857c 100644 --- a/chrome/installer/mini_installer/configuration.cc +++ b/chrome/installer/mini_installer/configuration.cc
@@ -11,6 +11,7 @@ #include "chrome/installer/mini_installer/appid.h" #include "chrome/installer/mini_installer/mini_installer_constants.h" #include "chrome/installer/mini_installer/mini_installer_resource.h" +#include "chrome/installer/mini_installer/mini_string.h" #include "chrome/installer/mini_installer/regkey.h" namespace mini_installer { @@ -36,54 +37,10 @@ Clear(); } -// When multi_install is true, we are potentially: -// 1. Performing a multi-install of some product(s) on a clean machine. -// Neither the product(s) nor the multi-installer will have a -// ClientState key in the registry, so there is no key to be modified. -// 2. Upgrading an existing multi-install. The multi-installer will have -// a ClientState key in the registry. Only it need be modified. -// 3. Migrating a single-install into a multi-install. The product will -// have a ClientState key in the registry. Only it need be modified. -// To handle all cases, we inspect the product's ClientState to see if it -// exists and its "ap" value does not contain "-multi". This is case 3, -// so we modify the product's ClientState. Otherwise, we check the -// multi-installer's ClientState and modify it if it exists. -// TODO(bcwhite): Write a unit test for this that uses registry virtualization. -void Configuration::SetChromeAppGuid() { - const HKEY root_key = - is_system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - const wchar_t* app_guid = - is_side_by_side_ ? google_update::kSxSAppGuid - : google_update::kAppGuid; - - // This is the value for single-install and case 3. - chrome_app_guid_ = app_guid; - - if (is_multi_install_) { - ValueString value; - LONG ret = ERROR_SUCCESS; - if (ReadClientStateRegistryValue(root_key, app_guid, &ret, value)) { - // The product has a client state key. See if it's a single-install. - if (ret == ERROR_FILE_NOT_FOUND || - (ret == ERROR_SUCCESS && - !FindTagInStr(value.get(), kMultiInstallTag, NULL))) { - // yes -- case 3: use the existing key. - return; - } - } - // error, case 1, or case 2: modify the multi-installer's key. - chrome_app_guid_ = google_update::kMultiInstallAppGuid; - } -} - -bool Configuration::ReadClientStateRegistryValue( - const HKEY root_key, const wchar_t* app_guid, - LONG* retval, ValueString& value) { - RegKey key; - if (!OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key)) - return false; - *retval = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); - return true; +bool Configuration::Initialize(HMODULE module) { + Clear(); + ReadResources(module); + return ParseCommandLine(::GetCommandLine()); } const wchar_t* Configuration::program() const { @@ -99,20 +56,13 @@ command_line_ = NULL; operation_ = INSTALL_PRODUCT; argument_count_ = 0; - has_chrome_ = false; - is_multi_install_ = false; is_system_level_ = false; is_side_by_side_ = false; + is_updating_multi_chrome_ = false; has_invalid_switch_ = false; previous_version_ = NULL; } -bool Configuration::Initialize(HMODULE module) { - Clear(); - ReadResources(module); - return ParseCommandLine(::GetCommandLine()); -} - // |command_line| is shared with this instance in the sense that this // instance may refer to it at will throughout its lifetime, yet it will // not release it. @@ -123,25 +73,24 @@ return false; for (int i = 1; i < argument_count_; ++i) { - if (0 == ::lstrcmpi(args_[i], L"--chrome-sxs")) - is_side_by_side_ = true; - else if (0 == ::lstrcmpi(args_[i], L"--chrome")) - has_chrome_ = true; - else if (0 == ::lstrcmpi(args_[i], L"--multi-install")) - is_multi_install_ = true; - else if (0 == ::lstrcmpi(args_[i], L"--system-level")) + if (0 == ::lstrcmpi(args_[i], L"--system-level")) { is_system_level_ = true; - else if (0 == ::lstrcmpi(args_[i], L"--cleanup")) +#if defined(GOOGLE_CHROME_BUILD) + } else if (0 == ::lstrcmpi(args_[i], L"--chrome-sxs")) { + is_side_by_side_ = true; + chrome_app_guid_ = google_update::kSxSAppGuid; +#endif + } else if (0 == ::lstrcmpi(args_[i], L"--cleanup")) { operation_ = CLEANUP; - else if (0 == ::lstrcmpi(args_[i], L"--chrome-frame")) + } else if (0 == ::lstrcmpi(args_[i], L"--chrome-frame")) { has_invalid_switch_ = true; + } } if (!is_system_level_) is_system_level_ = GetGoogleUpdateIsMachineEnvVar(); - SetChromeAppGuid(); - if (!is_multi_install_) - has_chrome_ = true; + + is_updating_multi_chrome_ = IsUpdatingMultiChrome(); return true; } @@ -175,4 +124,29 @@ previous_version_ = version_string; } +bool Configuration::IsUpdatingMultiChrome() const { +#if defined(GOOGLE_CHROME_BUILD) + // SxS/canary does not support multi-install. + if (is_side_by_side_) + return false; + + // Is Chrome already installed as multi-install? + const HKEY root = is_system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + StackString<128> value; + RegKey key; + return (OpenClientsKey(root, google_update::kAppGuid, KEY_QUERY_VALUE, + &key) == ERROR_SUCCESS && + key.ReadSZValue(kPvRegistryValue, value.get(), value.capacity()) == + ERROR_SUCCESS && + value.length() != 0 && + OpenClientStateKey(root, google_update::kAppGuid, KEY_QUERY_VALUE, + &key) == ERROR_SUCCESS && + key.ReadSZValue(kUninstallArgumentsRegistryValue, value.get(), + value.capacity()) == ERROR_SUCCESS && + value.findi(L"--multi-install") != nullptr); +#else + return false; +#endif +} + } // namespace mini_installer
diff --git a/chrome/installer/mini_installer/configuration.h b/chrome/installer/mini_installer/configuration.h index d35127a..f455883 100644 --- a/chrome/installer/mini_installer/configuration.h +++ b/chrome/installer/mini_installer/configuration.h
@@ -7,8 +7,6 @@ #include <windows.h> -#include "chrome/installer/mini_installer/mini_string.h" - namespace mini_installer { // A simple container of the mini_installer's configuration, as dictated by the @@ -40,23 +38,21 @@ // Returns the original command line. const wchar_t* command_line() const { return command_line_; } - // Returns the app guid to be used for Chrome. --chrome-sxs on the command - // line makes this the canary's app guid. + // Returns the app guid to be used for Chrome. --chrome-sxs on the command + // line makes this the canary's app guid (Google Chrome only). const wchar_t* chrome_app_guid() const { return chrome_app_guid_; } - // Returns true if --chrome is explicitly or implicitly on the command line. - bool has_chrome() const { return has_chrome_; } - - // Returns true if --multi-install is on the command line. - bool is_multi_install() const { return is_multi_install_; } - // Returns true if --system-level is on the command line or if // GoogleUpdateIsMachine=1 is set in the process's environment. bool is_system_level() const { return is_system_level_; } - // Retuns true if --chrome-sxs is on the command line. + // Retuns true if --chrome-sxs is on the command line (Google Chrome only). bool is_side_by_side() const { return is_side_by_side_; } + // Returns true if an existing multi-install Chrome is being updated (Google + // Chrome only). + bool is_updating_multi_chrome() const { return is_updating_multi_chrome_; } + // Returns true if any invalid switch is found on the command line. bool has_invalid_switch() const { return has_invalid_switch_; } @@ -73,26 +69,18 @@ const wchar_t* command_line_; int argument_count_; Operation operation_; - bool has_chrome_; - bool is_multi_install_; bool is_system_level_; bool is_side_by_side_; + bool is_updating_multi_chrome_; bool has_invalid_switch_; const wchar_t* previous_version_; - protected: - typedef StackString<128> ValueString; - - // Virtual for testing. - virtual bool ReadClientStateRegistryValue( - const HKEY root_key, const wchar_t* app_guid, - LONG* retval, ValueString& value); - private: - Configuration(const Configuration&); - Configuration& operator=(const Configuration&); + Configuration(const Configuration&) = delete; + Configuration& operator=(const Configuration&) = delete; - void SetChromeAppGuid(); + // Returns true if multi-install Chrome is already present on the machine. + bool IsUpdatingMultiChrome() const; }; } // namespace mini_installer
diff --git a/chrome/installer/mini_installer/configuration_test.cc b/chrome/installer/mini_installer/configuration_test.cc index 3d9766e..9c43921 100644 --- a/chrome/installer/mini_installer/configuration_test.cc +++ b/chrome/installer/mini_installer/configuration_test.cc
@@ -8,12 +8,16 @@ #include <stdlib.h> #include <memory> +#include <vector> #include "base/environment.h" +#include "base/test/test_reg_util_win.h" +#include "base/win/registry.h" #include "chrome/installer/mini_installer/appid.h" +#include "chrome/installer/mini_installer/mini_installer_constants.h" #include "testing/gtest/include/gtest/gtest.h" -using mini_installer::Configuration; +namespace mini_installer { namespace { @@ -33,47 +37,66 @@ std::unique_ptr<base::Environment> env_; }; -} // namespace - class TestConfiguration : public Configuration { public: - explicit TestConfiguration(const wchar_t* command_line) - : Configuration(), - open_registry_key_result_(false), - read_registry_value_result_(0), - read_registry_value_(L"") { - Initialize(command_line); + explicit TestConfiguration(const wchar_t* command_line) { + EXPECT_TRUE(ParseCommandLine(command_line)); } - explicit TestConfiguration(const wchar_t* command_line, - LONG ret, const wchar_t* value) - : Configuration(), - open_registry_key_result_(true), - read_registry_value_result_(ret), - read_registry_value_(value) { - Initialize(command_line); - } - void SetRegistryResults(bool openkey, LONG ret, const wchar_t* value) { - } - private: - bool open_registry_key_result_; - LONG read_registry_value_result_; - const wchar_t* read_registry_value_ = L""; - void Initialize(const wchar_t* command_line) { - Clear(); - ASSERT_TRUE(ParseCommandLine(command_line)); + private: + DISALLOW_COPY_AND_ASSIGN(TestConfiguration); +}; + +} // namespace + +class MiniInstallerConfigurationTest : public ::testing::Test { + protected: + MiniInstallerConfigurationTest() { + registry_overrides_.OverrideRegistry(HKEY_CURRENT_USER); + registry_overrides_.OverrideRegistry(HKEY_LOCAL_MACHINE); } - bool ReadClientStateRegistryValue( - const HKEY root_key, const wchar_t* app_guid, - LONG* retval, ValueString& value) override { - *retval = read_registry_value_result_; - value.assign(read_registry_value_); - return open_registry_key_result_; + + // Adds sufficient state in the registry for Configuration to think that + // Chrome is already installed at |system_level| as per |multi_install|. + void AddChromeRegistryState(bool system_level, bool multi_install) { +#if defined(GOOGLE_CHROME_BUILD) + static constexpr wchar_t kClientsPath[] = + L"SOFTWARE\\Google\\Update\\Clients\\" + L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; + static constexpr wchar_t kClientStatePath[] = + L"SOFTWARE\\Google\\Update\\ClientState\\" + L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; +#else + static constexpr wchar_t kClientsPath[] = L"SOFTWARE\\Chromium"; + static constexpr wchar_t kClientStatePath[] = L"SOFTWARE\\Chromium"; +#endif + static constexpr const wchar_t* kUninstallArguments[] = { + L"--uninstall", L"--uninstall --multi-install --chrome", + L"--uninstall --system-level", + L"--uninstall --system-level --multi-install --chrome", + }; + const int uninstall_index = + ((system_level ? 0x02 : 0) | (multi_install ? 0x01 : 0)); + const HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + base::win::RegKey key; + ASSERT_EQ(ERROR_SUCCESS, + key.Create(root, kClientsPath, KEY_WOW64_32KEY | KEY_SET_VALUE)); + ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"pv", L"4.3.2.1")); + ASSERT_EQ(ERROR_SUCCESS, key.Create(root, kClientStatePath, + KEY_WOW64_32KEY | KEY_SET_VALUE)); + ASSERT_EQ(ERROR_SUCCESS, + key.WriteValue(L"UninstallArguments", + kUninstallArguments[uninstall_index])); } + + private: + registry_util::RegistryOverrideManager registry_overrides_; + + DISALLOW_COPY_AND_ASSIGN(MiniInstallerConfigurationTest); }; // Test that the operation type is CLEANUP iff --cleanup is on the cmdline. -TEST(MiniInstallerConfigurationTest, Operation) { +TEST_F(MiniInstallerConfigurationTest, Operation) { EXPECT_EQ(Configuration::INSTALL_PRODUCT, TestConfiguration(L"spam.exe").operation()); EXPECT_EQ(Configuration::INSTALL_PRODUCT, @@ -87,7 +110,7 @@ TestConfiguration(L"spam.exe --cleanup now").operation()); } -TEST(MiniInstallerConfigurationTest, Program) { +TEST_F(MiniInstallerConfigurationTest, Program) { EXPECT_TRUE(NULL == mini_installer::Configuration().program()); EXPECT_TRUE(std::wstring(L"spam.exe") == TestConfiguration(L"spam.exe").program()); @@ -97,13 +120,13 @@ TestConfiguration(L"c:\\blaz\\spam.exe --with args").program()); } -TEST(MiniInstallerConfigurationTest, ArgumentCount) { +TEST_F(MiniInstallerConfigurationTest, ArgumentCount) { EXPECT_EQ(1, TestConfiguration(L"spam.exe").argument_count()); EXPECT_EQ(2, TestConfiguration(L"spam.exe --foo").argument_count()); EXPECT_EQ(3, TestConfiguration(L"spam.exe --foo --bar").argument_count()); } -TEST(MiniInstallerConfigurationTest, CommandLine) { +TEST_F(MiniInstallerConfigurationTest, CommandLine) { static const wchar_t* const kCommandLines[] = { L"", L"spam.exe", @@ -115,52 +138,47 @@ } } -TEST(MiniInstallerConfigurationTest, ChromeAppGuid) { - EXPECT_TRUE(std::wstring(google_update::kAppGuid) == - TestConfiguration(L"spam.exe").chrome_app_guid()); - EXPECT_TRUE(std::wstring(google_update::kAppGuid) == - TestConfiguration(L"spam.exe --chrome").chrome_app_guid()); - EXPECT_TRUE(std::wstring(google_update::kSxSAppGuid) == - TestConfiguration(L"spam.exe --chrome-sxs").chrome_app_guid()); - EXPECT_TRUE(std::wstring(google_update::kMultiInstallAppGuid) == - TestConfiguration(L"spam.exe --multi-install --chrome") - .chrome_app_guid()); - EXPECT_TRUE(std::wstring(google_update::kMultiInstallAppGuid) == - TestConfiguration(L"spam.exe --multi-install --chrome", - ERROR_INVALID_FUNCTION, L"") - .chrome_app_guid()); - EXPECT_TRUE(std::wstring(google_update::kAppGuid) == - TestConfiguration(L"spam.exe --multi-install --chrome", - ERROR_FILE_NOT_FOUND, L"") - .chrome_app_guid()); - EXPECT_TRUE(std::wstring(google_update::kAppGuid) == - TestConfiguration(L"spam.exe --multi-install --chrome", - ERROR_SUCCESS, L"foo-bar") - .chrome_app_guid()); - EXPECT_TRUE(std::wstring(google_update::kMultiInstallAppGuid) == - TestConfiguration(L"spam.exe --multi-install --chrome", - ERROR_SUCCESS, L"foo-multi") - .chrome_app_guid()); +TEST_F(MiniInstallerConfigurationTest, IsUpdatingUserSingle) { + AddChromeRegistryState(false /* !system_level */, false /* !multi_install */); + EXPECT_FALSE(TestConfiguration(L"spam.exe").is_updating_multi_chrome()); } -TEST(MiniInstallerConfigurationTest, HasChrome) { - EXPECT_TRUE(TestConfiguration(L"spam.exe").has_chrome()); - EXPECT_TRUE(TestConfiguration(L"spam.exe --chrome").has_chrome()); - EXPECT_TRUE(TestConfiguration(L"spam.exe --multi-install --chrome") - .has_chrome()); - EXPECT_FALSE(TestConfiguration(L"spam.exe --multi-install").has_chrome()); +TEST_F(MiniInstallerConfigurationTest, IsUpdatingSystemSingle) { + AddChromeRegistryState(true /* system_level */, false /* !multi_install */); + EXPECT_FALSE( + TestConfiguration(L"spam.exe --system-level").is_updating_multi_chrome()); } -TEST(MiniInstallerConfigurationTest, IsMultiInstall) { - EXPECT_FALSE(TestConfiguration(L"spam.exe").is_multi_install()); - EXPECT_FALSE(TestConfiguration(L"spam.exe --chrome").is_multi_install()); - EXPECT_TRUE(TestConfiguration(L"spam.exe --multi-install --chrome") - .is_multi_install()); - EXPECT_TRUE(TestConfiguration(L"spam.exe --multi-install") - .is_multi_install()); +TEST_F(MiniInstallerConfigurationTest, IsUpdatingUserMulti) { + AddChromeRegistryState(false /* !system_level */, true /* multi_install */); +#if defined(GOOGLE_CHROME_BUILD) + EXPECT_TRUE(TestConfiguration(L"spam.exe").is_updating_multi_chrome()); +#else + EXPECT_FALSE(TestConfiguration(L"spam.exe").is_updating_multi_chrome()); +#endif } -TEST(MiniInstallerConfigurationTest, IsSystemLevel) { +TEST_F(MiniInstallerConfigurationTest, IsUpdatingSystemMulti) { + AddChromeRegistryState(true /* system_level */, true /* multi_install */); +#if defined(GOOGLE_CHROME_BUILD) + EXPECT_TRUE( + TestConfiguration(L"spam.exe --system-level").is_updating_multi_chrome()); +#else + EXPECT_FALSE( + TestConfiguration(L"spam.exe --system-level").is_updating_multi_chrome()); +#endif +} + +TEST_F(MiniInstallerConfigurationTest, ChromeAppGuid) { +#if defined(GOOGLE_CHROME_BUILD) + EXPECT_STREQ(google_update::kAppGuid, + TestConfiguration(L"spam.exe").chrome_app_guid()); + EXPECT_STREQ(google_update::kSxSAppGuid, + TestConfiguration(L"spam.exe --chrome-sxs").chrome_app_guid()); +#endif +} + +TEST_F(MiniInstallerConfigurationTest, IsSystemLevel) { EXPECT_FALSE(TestConfiguration(L"spam.exe").is_system_level()); EXPECT_FALSE(TestConfiguration(L"spam.exe --chrome").is_system_level()); EXPECT_TRUE(TestConfiguration(L"spam.exe --system-level").is_system_level()); @@ -176,8 +194,19 @@ } } -TEST(MiniInstallerConfigurationTest, HasInvalidSwitch) { +TEST_F(MiniInstallerConfigurationTest, IsSideBySide) { + EXPECT_FALSE(TestConfiguration(L"spam.exe").is_side_by_side()); +#if defined(GOOGLE_CHROME_BUILD) + EXPECT_TRUE(TestConfiguration(L"spam.exe --chrome-sxs").is_side_by_side()); +#else + EXPECT_FALSE(TestConfiguration(L"spam.exe --chrome-sxs").is_side_by_side()); +#endif +} + +TEST_F(MiniInstallerConfigurationTest, HasInvalidSwitch) { EXPECT_FALSE(TestConfiguration(L"spam.exe").has_invalid_switch()); EXPECT_TRUE(TestConfiguration(L"spam.exe --chrome-frame") .has_invalid_switch()); } + +} // namespace mini_installer
diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc index 9656ca2d..7ca6e9f1 100644 --- a/chrome/installer/mini_installer/mini_installer.cc +++ b/chrome/installer/mini_installer/mini_installer.cc
@@ -74,89 +74,99 @@ PathString* setup_resource_path; }; - -// Opens the Google Update ClientState key for the current install -// configuration. This includes locating the correct key in the face of -// multi-install. The flag will by default be written to HKCU, but if -// --system-level is included in the command line, it will be written to -// HKLM instead. -bool OpenInstallStateKey(const Configuration& configuration, RegKey* key) { +#if defined(GOOGLE_CHROME_BUILD) +// Opens the Google Update ClientState key. If |binaries| is false, opens the +// key for Google Chrome or Chrome SxS (canary). If |binaries| is true and an +// existing multi-install Chrome is being updated, opens the key for the +// binaries; otherwise, returns false. +bool OpenInstallStateKey(const Configuration& configuration, + bool binaries, + RegKey* key) { + if (binaries && !configuration.is_updating_multi_chrome()) + return false; const HKEY root_key = configuration.is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - const wchar_t* app_guid = configuration.chrome_app_guid(); + const wchar_t* app_guid = binaries ? google_update::kMultiInstallAppGuid + : configuration.chrome_app_guid(); const REGSAM key_access = KEY_QUERY_VALUE | KEY_SET_VALUE; - return OpenClientStateKey(root_key, app_guid, key_access, key); + return OpenClientStateKey(root_key, app_guid, key_access, key) == + ERROR_SUCCESS; } -// Writes install results into registry where it is read by Google Update. +// Writes install results into the registry where it is read by Google Update. // Don't write anything if there is already a result present, likely // written by setup.exe. void WriteInstallResults(const Configuration& configuration, ProcessExitResult result) { -#if defined(GOOGLE_CHROME_BUILD) // Calls to setup.exe will write a "success" result if everything was good // so we don't need to write anything from here. if (result.IsSuccess()) return; - RegKey key; - DWORD value; - if (OpenInstallStateKey(configuration, &key)) { - if (key.ReadDWValue(kInstallerResultRegistryValue, &value) - != ERROR_SUCCESS || value == 0) { - key.WriteDWValue(kInstallerResultRegistryValue, - result.exit_code ? 1 /* FAILED_CUSTOM_ERROR */ - : 0 /* SUCCESS */); - key.WriteDWValue(kInstallerErrorRegistryValue, result.exit_code); - key.WriteDWValue(kInstallerExtraCode1RegistryValue, result.windows_error); + // Write the value in Chrome ClientState key and in the binaries' if an + // existing multi-install Chrome is being updated. + for (int i = 0; i < 2; ++i) { + RegKey key; + DWORD value; + if (OpenInstallStateKey(configuration, i != 0, &key)) { + if (key.ReadDWValue(kInstallerResultRegistryValue, &value) != + ERROR_SUCCESS || + value == 0) { + key.WriteDWValue(kInstallerResultRegistryValue, + result.exit_code ? 1 /* FAILED_CUSTOM_ERROR */ + : 0 /* SUCCESS */); + key.WriteDWValue(kInstallerErrorRegistryValue, result.exit_code); + key.WriteDWValue(kInstallerExtraCode1RegistryValue, + result.windows_error); + } } - key.Close(); } -#endif } // This function sets the flag in registry to indicate that Google Update // should try full installer next time. If the current installer works, this // flag is cleared by setup.exe at the end of install. void SetInstallerFlags(const Configuration& configuration) { - RegKey key; StackString<128> value; - LONG ret = ERROR_SUCCESS; - if (!OpenInstallStateKey(configuration, &key)) - return; + for (int i = 0; i < 2; ++i) { + RegKey key; + if (!OpenInstallStateKey(configuration, i != 0, &key)) + continue; - ret = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); + LONG ret = key.ReadSZValue(kApRegistryValue, value.get(), value.capacity()); - // The conditions below are handling two cases: - // 1. When ap value is present, we want to add the required tag only if it is - // not present. - // 2. When ap value is missing, we are going to create it with the required - // tag. - if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { - if (ret == ERROR_FILE_NOT_FOUND) - value.clear(); + // The conditions below are handling two cases: + // 1. When ap value is present, we want to add the required tag only if it + // is not present. + // 2. When ap value is missing, we are going to create it with the required + // tag. + if ((ret == ERROR_SUCCESS) || (ret == ERROR_FILE_NOT_FOUND)) { + if (ret == ERROR_FILE_NOT_FOUND) + value.clear(); - if (!StrEndsWith(value.get(), kFullInstallerSuffix) && - value.append(kFullInstallerSuffix)) { - key.WriteSZValue(kApRegistryValue, value.get()); + if (!StrEndsWith(value.get(), kFullInstallerSuffix) && + value.append(kFullInstallerSuffix)) { + key.WriteSZValue(kApRegistryValue, value.get()); + } } } } +#endif // GOOGLE_CHROME_BUILD // Gets the setup.exe path from Registry by looking at the value of Uninstall // string. |size| is measured in wchar_t units. ProcessExitResult GetSetupExePathForAppGuid(bool system_level, - const wchar_t* app_guid, - const wchar_t* previous_version, - wchar_t* path, - size_t size) { + const wchar_t* app_guid, + const wchar_t* previous_version, + wchar_t* path, + size_t size) { const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; RegKey key; - if (!OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key)) - return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY); - DWORD result = key.ReadSZValue(kUninstallRegistryValue, path, size); + LONG result = OpenClientStateKey(root_key, app_guid, KEY_QUERY_VALUE, &key); + if (result == ERROR_SUCCESS) + result = key.ReadSZValue(kUninstallRegistryValue, path, size); if (result != ERROR_SUCCESS) return ProcessExitResult(UNABLE_TO_FIND_REGISTRY_KEY, result); @@ -173,24 +183,23 @@ // in the Uninstall string in the registry. A previous version number specified // in |configuration| is used if available. |size| is measured in wchar_t units. ProcessExitResult GetPreviousSetupExePath(const Configuration& configuration, - wchar_t* path, - size_t size) { + wchar_t* path, + size_t size) { bool system_level = configuration.is_system_level(); const wchar_t* previous_version = configuration.previous_version(); ProcessExitResult exit_code = ProcessExitResult(GENERIC_ERROR); - // If this is a multi install, first try looking in the binaries for the path. - if (configuration.is_multi_install()) { - exit_code = GetSetupExePathForAppGuid( - system_level, google_update::kMultiInstallAppGuid, previous_version, - path, size); - } + // Check Chrome's ClientState key for the path to setup.exe. This will have + // the correct path for all well-functioning installs. + exit_code = + GetSetupExePathForAppGuid(system_level, configuration.chrome_app_guid(), + previous_version, path, size); - // Make a last-ditch effort to look in the Chrome client state key. - if (!exit_code.IsSuccess()) { - exit_code = GetSetupExePathForAppGuid( - system_level, configuration.chrome_app_guid(), previous_version, - path, size); + // Failing that, check the binaries if updating multi-install Chrome. + if (!exit_code.IsSuccess() && configuration.is_updating_multi_chrome()) { + exit_code = GetSetupExePathForAppGuid(system_level, + google_update::kMultiInstallAppGuid, + previous_version, path, size); } return exit_code; @@ -451,8 +460,8 @@ // Executes setup.exe, waits for it to finish and returns the exit code. ProcessExitResult RunSetup(const Configuration& configuration, - const wchar_t* archive_path, - const wchar_t* setup_path) { + const wchar_t* archive_path, + const wchar_t* setup_path) { // There could be three full paths in the command line for setup.exe (path // to exe itself, path to archive and path to log file), so we declare // total size as three + one additional to hold command line options. @@ -848,8 +857,9 @@ #if defined(GOOGLE_CHROME_BUILD) // Set the magic suffix in registry to try full installer next time. We ignore // any errors here and we try to set the suffix for user level unless - // --system-level is on the command line in which case we set it for system - // level instead. This only applies to the Google Chrome distribution. + // GoogleUpdateIsMachine=1 is present in the environment or --system-level is + // on the command line in which case we set it for system level instead. This + // only applies to the Google Chrome distribution. SetInstallerFlags(configuration); #endif @@ -869,7 +879,10 @@ if (ShouldDeleteExtractedFiles()) DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); +#if defined(GOOGLE_CHROME_BUILD) WriteInstallResults(configuration, exit_code); +#endif + return exit_code; }
diff --git a/chrome/installer/mini_installer/mini_installer_constants.cc b/chrome/installer/mini_installer/mini_installer_constants.cc index e21e433..751d25b 100644 --- a/chrome/installer/mini_installer/mini_installer_constants.cc +++ b/chrome/installer/mini_installer/mini_installer_constants.cc
@@ -50,12 +50,16 @@ const wchar_t kInstallerErrorRegistryValue[] = L"InstallerError"; const wchar_t kInstallerExtraCode1RegistryValue[] = L"InstallerExtraCode1"; const wchar_t kInstallerResultRegistryValue[] = L"InstallerResult"; +const wchar_t kPvRegistryValue[] = L"pv"; +const wchar_t kUninstallArgumentsRegistryValue[] = L"UninstallArguments"; // The name of an app's Client State registry value that holds the path to its // uninstaller. const wchar_t kUninstallRegistryValue[] = L"UninstallString"; // Registry key paths. #if defined(GOOGLE_CHROME_BUILD) +// The path to the key containing each app's Clients registry key. +const wchar_t kClientsKeyBase[] = L"Software\\Google\\Update\\Clients\\"; // The path to the key containing each app's Client State registry key. const wchar_t kClientStateKeyBase[] = L"Software\\Google\\Update\\ClientState\\"; @@ -63,6 +67,9 @@ const wchar_t kCleanupRegistryKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Google Chrome"; #else +// The path to the key containing each app's Clients registry key. +// No trailing slash on this one because the app's GUID is not appended. +const wchar_t kClientsKeyBase[] = L"Software\\Chromium"; // The path to the key containing each app's Client State registry key. // No trailing slash on this one because the app's GUID is not appended. const wchar_t kClientStateKeyBase[] = L"Software\\Chromium";
diff --git a/chrome/installer/mini_installer/mini_installer_constants.h b/chrome/installer/mini_installer/mini_installer_constants.h index bd80c696..a176df99c 100644 --- a/chrome/installer/mini_installer/mini_installer_constants.h +++ b/chrome/installer/mini_installer/mini_installer_constants.h
@@ -37,9 +37,12 @@ extern const wchar_t kInstallerErrorRegistryValue[]; extern const wchar_t kInstallerExtraCode1RegistryValue[]; extern const wchar_t kInstallerResultRegistryValue[]; +extern const wchar_t kPvRegistryValue[]; +extern const wchar_t kUninstallArgumentsRegistryValue[]; extern const wchar_t kUninstallRegistryValue[]; // Registry key paths. +extern const wchar_t kClientsKeyBase[]; extern const wchar_t kClientStateKeyBase[]; extern const wchar_t kCleanupRegistryKey[];
diff --git a/chrome/installer/mini_installer/regkey.cc b/chrome/installer/mini_installer/regkey.cc index 44bdb5d..ca95507 100644 --- a/chrome/installer/mini_installer/regkey.cc +++ b/chrome/installer/mini_installer/regkey.cc
@@ -72,7 +72,6 @@ } } - // static bool RegKey::ReadSZValue(HKEY root_key, const wchar_t *sub_key, const wchar_t *value_name, wchar_t *value, @@ -82,17 +81,34 @@ key.ReadSZValue(value_name, value, size) == ERROR_SUCCESS); } -// Opens the Google Update ClientState key for a product. This finds only -// registry entries for Chrome; it does not support the Chromium registry -// layout. -bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, - REGSAM access, RegKey* key) { +// Opens the Google Update Clients key for a product. +LONG OpenClientsKey(HKEY root_key, + const wchar_t* app_guid, + REGSAM access, + RegKey* key) { + StackString<MAX_PATH> clients_key; + if (!clients_key.assign(kClientsKeyBase)) + return ERROR_BUFFER_OVERFLOW; +#if defined(GOOGLE_CHROME_BUILD) + if (!clients_key.append(app_guid)) + return ERROR_BUFFER_OVERFLOW; +#endif + return key->Open(root_key, clients_key.get(), access | KEY_WOW64_32KEY); +} + +// Opens the Google Update ClientState key for a product. +LONG OpenClientStateKey(HKEY root_key, + const wchar_t* app_guid, + REGSAM access, + RegKey* key) { StackString<MAX_PATH> client_state_key; - return client_state_key.assign(kClientStateKeyBase) && - client_state_key.append(app_guid) && - (key->Open(root_key, - client_state_key.get(), - access | KEY_WOW64_32KEY) == ERROR_SUCCESS); + if (!client_state_key.assign(kClientStateKeyBase)) + return ERROR_BUFFER_OVERFLOW; +#if defined(GOOGLE_CHROME_BUILD) + if (!client_state_key.append(app_guid)) + return ERROR_BUFFER_OVERFLOW; +#endif + return key->Open(root_key, client_state_key.get(), access | KEY_WOW64_32KEY); } } // namespace mini_installer
diff --git a/chrome/installer/mini_installer/regkey.h b/chrome/installer/mini_installer/regkey.h index f323b7c6..86dbf8b1 100644 --- a/chrome/installer/mini_installer/regkey.h +++ b/chrome/installer/mini_installer/regkey.h
@@ -55,11 +55,19 @@ HKEY key_; }; // class RegKey +// Initializes |key| with the desired |access| to |app_guid|'s Clients key. +// Returns ERROR_SUCCESS on success, or a Windows error code on failure. +LONG OpenClientsKey(HKEY root_key, + const wchar_t* app_guid, + REGSAM access, + RegKey* key); -// Helper function to get the RegKey associated with the "client state" of -// the given |app_guid|. -bool OpenClientStateKey(HKEY root_key, const wchar_t* app_guid, - REGSAM access, RegKey* key); +// Initializes |key| with the desired |access| to |app_guid|'s ClientState key. +// Returns ERROR_SUCCESS on success, or a Windows error code on failure. +LONG OpenClientStateKey(HKEY root_key, + const wchar_t* app_guid, + REGSAM access, + RegKey* key); } // namespace mini_installer
diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index 9b36e81..b180811 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc
@@ -897,12 +897,9 @@ return; } - const ProductState* chrome_state = original_state.GetProductState( - installer_state.system_install(), - BrowserDistribution::CHROME_BROWSER); - // Bail out if there is not an existing multi-install Chrome that is being - // updated. - if (!chrome_state || !chrome_state->is_multi_install()) { + // Bail out if an existing multi-install Chrome is not being migrated to + // single-install. + if (!installer_state.is_migrating_to_single()) { VLOG(1) << "No multi-install Chrome found to migrate to single-install."; return; }
diff --git a/chrome/installer/setup/installer_state.cc b/chrome/installer/setup/installer_state.cc index 17ad8616..b6a9ffb 100644 --- a/chrome/installer/setup/installer_state.cc +++ b/chrome/installer/setup/installer_state.cc
@@ -73,7 +73,8 @@ root_key_(NULL), msi_(false), background_mode_(false), - verbose_logging_(false) {} + verbose_logging_(false), + is_migrating_to_single_(false) {} InstallerState::InstallerState(Level level) : operation_(UNINITIALIZED), @@ -84,7 +85,8 @@ root_key_(NULL), msi_(false), background_mode_(false), - verbose_logging_(false) { + verbose_logging_(false), + is_migrating_to_single_(false) { // Use set_level() so that root_key_ is updated properly. set_level(level); } @@ -138,6 +140,10 @@ // For a single-install, the current browser dist is the operand. operand = BrowserDistribution::GetDistribution(); operation_ = SINGLE_INSTALL_OR_UPDATE; + // Is this a migration from multi-install to single-install? + const ProductState* state = + machine_state.GetProductState(system_install(), operand->GetType()); + is_migrating_to_single_ = state && state->is_multi_install(); } else if (IsMultiInstallUpdate(prefs, machine_state)) { // Updates driven by Google Update take place under the multi-installer's // app guid. @@ -473,6 +479,7 @@ root_key_ = NULL; msi_ = false; verbose_logging_ = false; + is_migrating_to_single_ = false; } bool InstallerState::AnyExistsAndIsInUse(const InstallationState& machine_state, @@ -625,6 +632,24 @@ InstallUtil::AddInstallerResultItems( system_install, multi_package_binaries_distribution()->GetStateKey(), status, string_resource_id, launch_cmd, install_list.get()); + } else if (is_migrating_to_single() && + InstallUtil::GetInstallReturnCode(status)) { +#if defined(GOOGLE_CHROME_BUILD) + // Also write to the binaries on error if this is a migration back to + // single-install for Google Chrome builds. Skip this for Chromium builds + // because they lump the "ClientState" and "Clients" keys into a single + // key. As a consequence, writing this value causes Software\Chromium to be + // re-created after it was deleted during the migration to single-install. + // Google Chrome builds don't suffer this since the two keys are distinct + // and have different lifetimes. The result is only written on failure since + // for success, the binaries have been uninstalled and therefore the result + // will not be read by Google Update. + InstallUtil::AddInstallerResultItems( + system_install, BrowserDistribution::GetSpecificDistribution( + BrowserDistribution::CHROME_BINARIES) + ->GetStateKey(), + status, string_resource_id, launch_cmd, install_list.get()); +#endif } install_list->Do(); }
diff --git a/chrome/installer/setup/installer_state.h b/chrome/installer/setup/installer_state.h index 9a5e9704..2c25f3c 100644 --- a/chrome/installer/setup/installer_state.h +++ b/chrome/installer/setup/installer_state.h
@@ -148,6 +148,10 @@ // with the ClientState key we will be interacting with. BrowserDistribution::Type state_type() const { return state_type_; } + // Returns true if this is an update of multi-install Chrome to + // single-install. + bool is_migrating_to_single() const { return is_migrating_to_single_; } + // Returns the BrowserDistribution instance corresponding to the binaries for // this run if we're operating on a multi-package product. BrowserDistribution* multi_package_binaries_distribution() const { @@ -270,6 +274,7 @@ bool msi_; bool background_mode_; bool verbose_logging_; + bool is_migrating_to_single_; private: DISALLOW_COPY_AND_ASSIGN(InstallerState);
diff --git a/chrome/installer/setup/installer_state_unittest.cc b/chrome/installer/setup/installer_state_unittest.cc index c34c3a09..9f82c5c 100644 --- a/chrome/installer/setup/installer_state_unittest.cc +++ b/chrome/installer/setup/installer_state_unittest.cc
@@ -123,12 +123,16 @@ std::wstring value; DWORD dw_value; - // check results for a fresh install of single Chrome - { + // Check results for a fresh install of single Chrome and the same for an + // attempt at multi-install, which is now ignored. + static constexpr const wchar_t* kCommandLines[] = { + L"setup.exe --system-level", + L"setup.exe --system-level --multi-install --chrome", + }; + for (const wchar_t* command_line : kCommandLines) { RegistryOverrideManager override_manager; override_manager.OverrideRegistry(root); - base::CommandLine cmd_line = - base::CommandLine::FromString(L"setup.exe --system-level"); + base::CommandLine cmd_line = base::CommandLine::FromString(command_line); const MasterPreferences prefs(cmd_line); InstallationState machine_state; machine_state.Initialize(); @@ -154,38 +158,6 @@ key.ReadValue(installer::kInstallerSuccessLaunchCmdLine, &value)); EXPECT_EQ(launch_cmd, value); } - - // check results for a fresh install of multi Chrome - { - RegistryOverrideManager override_manager; - override_manager.OverrideRegistry(root); - base::CommandLine cmd_line = base::CommandLine::FromString( - L"setup.exe --system-level --multi-install --chrome"); - const MasterPreferences prefs(cmd_line); - InstallationState machine_state; - machine_state.Initialize(); - InstallerState state; - state.Initialize(cmd_line, prefs, machine_state); - state.WriteInstallerResult(installer::FIRST_INSTALL_SUCCESS, 0, - &launch_cmd); - BrowserDistribution* distribution = - BrowserDistribution::GetSpecificDistribution( - BrowserDistribution::CHROME_BROWSER); - BrowserDistribution* binaries = - BrowserDistribution::GetSpecificDistribution( - BrowserDistribution::CHROME_BINARIES); - EXPECT_EQ(ERROR_SUCCESS, - key.Open(root, distribution->GetStateKey().c_str(), KEY_READ)); - EXPECT_EQ(ERROR_SUCCESS, - key.ReadValue(installer::kInstallerSuccessLaunchCmdLine, &value)); - EXPECT_EQ(launch_cmd, value); - EXPECT_EQ(ERROR_SUCCESS, - key.Open(root, binaries->GetStateKey().c_str(), KEY_READ)); - EXPECT_EQ(ERROR_SUCCESS, - key.ReadValue(installer::kInstallerSuccessLaunchCmdLine, &value)); - EXPECT_EQ(launch_cmd, value); - key.Close(); - } } // Test GetCurrentVersion when migrating single Chrome to multi @@ -259,27 +231,27 @@ InstallerState installer_state; - // Initialize the instance to install multi Chrome. + // Initialize the instance to install user-level Chrome. { - base::CommandLine cmd_line( - base::CommandLine::FromString(L"setup.exe --multi-install --chrome")); + base::CommandLine cmd_line(base::CommandLine::FromString(L"setup.exe")); MasterPreferences prefs(cmd_line); installer_state.Initialize(cmd_line, prefs, machine_state); } // Confirm the expected state. EXPECT_EQ(InstallerState::USER_LEVEL, installer_state.level()); - EXPECT_EQ(InstallerState::MULTI_PACKAGE, installer_state.package_type()); - EXPECT_EQ(InstallerState::MULTI_INSTALL, installer_state.operation()); + EXPECT_EQ(InstallerState::SINGLE_PACKAGE, installer_state.package_type()); + EXPECT_EQ(InstallerState::SINGLE_INSTALL_OR_UPDATE, + installer_state.operation()); EXPECT_TRUE(wcsstr(installer_state.target_path().value().c_str(), BrowserDistribution::GetSpecificDistribution( - BrowserDistribution::CHROME_BINARIES)-> - GetInstallSubDir().c_str())); + BrowserDistribution::CHROME_BROWSER) + ->GetInstallSubDir() + .c_str())); EXPECT_FALSE(installer_state.verbose_logging()); EXPECT_EQ(installer_state.state_key(), BrowserDistribution::GetSpecificDistribution( BrowserDistribution::CHROME_BROWSER)->GetStateKey()); EXPECT_EQ(installer_state.state_type(), BrowserDistribution::CHROME_BROWSER); - EXPECT_TRUE(installer_state.multi_package_binaries_distribution()); EXPECT_TRUE(installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER)); // Now initialize it to install system-level single Chrome.
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index d0d02980..94f3853 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc
@@ -1705,6 +1705,9 @@ InstallerState installer_state; installer_state.Initialize(cmd_line, prefs, original_state); + VLOG(1) << "is_migrating_to_single is " + << installer_state.is_migrating_to_single(); + persistent_histogram_storage.set_storage_dir( installer::PersistentHistogramStorage::GetReportedStorageDir( installer_state.target_path()));
diff --git a/chrome/installer/util/master_preferences.cc b/chrome/installer/util/master_preferences.cc index 8ec3e04..ef58f813 100644 --- a/chrome/installer/util/master_preferences.cc +++ b/chrome/installer/util/master_preferences.cc
@@ -75,34 +75,19 @@ namespace installer { -MasterPreferences::MasterPreferences() : distribution_(NULL), - preferences_read_from_file_(false), - chrome_(true), - multi_install_(false) { +MasterPreferences::MasterPreferences() { InitializeFromCommandLine(*base::CommandLine::ForCurrentProcess()); } -MasterPreferences::MasterPreferences(const base::CommandLine& cmd_line) - : distribution_(NULL), - preferences_read_from_file_(false), - chrome_(true), - multi_install_(false) { +MasterPreferences::MasterPreferences(const base::CommandLine& cmd_line) { InitializeFromCommandLine(cmd_line); } -MasterPreferences::MasterPreferences(const base::FilePath& prefs_path) - : distribution_(NULL), - preferences_read_from_file_(false), - chrome_(true), - multi_install_(false) { +MasterPreferences::MasterPreferences(const base::FilePath& prefs_path) { InitializeFromFilePath(prefs_path); } -MasterPreferences::MasterPreferences(const std::string& prefs) - : distribution_(NULL), - preferences_read_from_file_(false), - chrome_(true), - multi_install_(false) { +MasterPreferences::MasterPreferences(const std::string& prefs) { InitializeFromString(prefs); } @@ -129,14 +114,10 @@ const char* cmd_line_switch; const char* distribution_switch; } translate_switches[] = { - { installer::switches::kChrome, - installer::master_preferences::kChrome }, { installer::switches::kDisableLogging, installer::master_preferences::kDisableLogging }, { installer::switches::kMsi, installer::master_preferences::kMsi }, - { installer::switches::kMultiInstall, - installer::master_preferences::kMultiInstall }, { installer::switches::kDoNotRegisterForUpdateLaunch, installer::master_preferences::kDoNotRegisterForUpdateLaunch }, { installer::switches::kDoNotLaunchChrome, @@ -181,11 +162,17 @@ } } + // Strip multi-install from the dictionary, if present. This ensures that any + // code that probes the dictionary directly to check for multi-install (rather + // than calling is_multi_install()) receives false. The updated dictionary is + // not written back to disk. + master_dictionary_->Remove(std::string(master_preferences::kDistroDict) + + '.' + master_preferences::kMultiInstall, + nullptr); + // Cache a pointer to the distribution dictionary. Ignore errors if any. master_dictionary_->GetDictionary(installer::master_preferences::kDistroDict, &distribution_); - - InitializeProductFlags(); #endif } @@ -217,30 +204,10 @@ installer::master_preferences::kDistroDict, &distribution_); } - InitializeProductFlags(); EnforceLegacyPreferences(); return data_is_valid; } -void MasterPreferences::InitializeProductFlags() { - // Make sure we start out with the correct defaults. - multi_install_ = false; - chrome_ = true; - - GetBool(installer::master_preferences::kMultiInstall, &multi_install_); - - // When multi-install is specified, the checks are pretty simple (in theory): - // In order to be installed/uninstalled, each product must have its switch - // present on the command line. - // When multi-install is not set, operate on Chrome. - if (multi_install_) { - if (!GetBool(installer::master_preferences::kChrome, &chrome_)) - chrome_ = false; - } else { - chrome_ = true; - } -} - void MasterPreferences::EnforceLegacyPreferences() { // If create_all_shortcuts was explicitly set to false, set // do_not_create_(desktop|quick_launch)_shortcut to true.
diff --git a/chrome/installer/util/master_preferences.h b/chrome/installer/util/master_preferences.h index 424c4df..c2ffc62 100644 --- a/chrome/installer/util/master_preferences.h +++ b/chrome/installer/util/master_preferences.h
@@ -170,13 +170,9 @@ return preferences_read_from_file_; } - bool install_chrome() const { - return chrome_; - } + bool install_chrome() const { return true; } - bool is_multi_install() const { - return multi_install_; - } + bool is_multi_install() const { return false; } // Returns a reference to this MasterPreferences' root dictionary of values. const base::DictionaryValue& master_dictionary() const { @@ -197,8 +193,6 @@ // string was successfully parsed. bool InitializeFromString(const std::string& json_data); - void InitializeProductFlags(); - // Enforces legacy preferences that should no longer be used, but could be // found in older master_preferences files. void EnforceLegacyPreferences(); @@ -209,10 +203,8 @@ std::string ExtractPrefString(const std::string& name) const; std::unique_ptr<base::DictionaryValue> master_dictionary_; - base::DictionaryValue* distribution_; - bool preferences_read_from_file_; - bool chrome_; - bool multi_install_; + base::DictionaryValue* distribution_ = nullptr; + bool preferences_read_from_file_ = false; private: DISALLOW_COPY_AND_ASSIGN(MasterPreferences);
diff --git a/chrome/installer/util/master_preferences_constants.cc b/chrome/installer/util/master_preferences_constants.cc index 27eeed8..e65450b 100644 --- a/chrome/installer/util/master_preferences_constants.cc +++ b/chrome/installer/util/master_preferences_constants.cc
@@ -6,7 +6,6 @@ namespace installer { namespace master_preferences { - const char kChrome[] = "chrome"; const char kCreateAllShortcuts[] = "create_all_shortcuts"; const char kDisableLogging[] = "disable_logging"; const char kDistroDict[] = "distribution";
diff --git a/chrome/installer/util/master_preferences_constants.h b/chrome/installer/util/master_preferences_constants.h index d49947b..cb394167 100644 --- a/chrome/installer/util/master_preferences_constants.h +++ b/chrome/installer/util/master_preferences_constants.h
@@ -15,8 +15,6 @@ // is specified in master preference as well as command line, the command line // value takes precedence. -// Boolean. This is to be a Chrome install. (When using MultiInstall) -extern const char kChrome[]; // Boolean. This is a legacy preference and should no longer be used; it is // kept around so that old master_preferences which specify // "create_all_shortcuts":false still enforce the new
diff --git a/chrome/installer/util/master_preferences_unittest.cc b/chrome/installer/util/master_preferences_unittest.cc index 93a8c19..a8bfba3 100644 --- a/chrome/installer/util/master_preferences_unittest.cc +++ b/chrome/installer/util/master_preferences_unittest.cc
@@ -326,7 +326,7 @@ EXPECT_TRUE(pref_chrome.install_chrome()); } -TEST_F(MasterPreferencesTest, TestMultiInstallConfig) { +TEST_F(MasterPreferencesTest, TestMultiInstallIgnoredConfig) { using installer::switches::kMultiInstall; using installer::switches::kChrome; @@ -338,7 +338,7 @@ installer::MasterPreferences pref_chrome(chrome_install); - EXPECT_TRUE(pref_chrome.is_multi_install()); + EXPECT_FALSE(pref_chrome.is_multi_install()); EXPECT_TRUE(pref_chrome.install_chrome()); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/notifications/MockNotificationManagerProxy.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/notifications/MockNotificationManagerProxy.java index 0d774e2..bd9b9b7 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/notifications/MockNotificationManagerProxy.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/notifications/MockNotificationManagerProxy.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.test.util.browser.notifications; import android.app.Notification; -import android.service.notification.StatusBarNotification; import org.chromium.chrome.browser.notifications.NotificationManagerProxy; @@ -102,11 +101,6 @@ mMutationCount++; } - @Override - public StatusBarNotification[] getActiveNotifications() { - return null; - } - private static String makeKey(int id, @Nullable String tag) { String key = Integer.toString(id); if (tag != null) key += KEY_SEPARATOR + tag;
diff --git a/chrome/test/mini_installer/config/chrome_multi_system_installed.prop b/chrome/test/mini_installer/config/chrome_multi_system_installed.prop new file mode 100644 index 0000000..9a8dd5df3 --- /dev/null +++ b/chrome/test/mini_installer/config/chrome_multi_system_installed.prop
@@ -0,0 +1,49 @@ +{ + "Files": { + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome.dll": + {"exists": true}, + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll": + {"exists": true}, + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\chrome.7z": + {"exists": true}, + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe": + {"exists": true}, + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\$MINI_INSTALLER_FILE_VERSION.manifest": + {"exists": true}, + "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION": + {"exists": false} + }, + "RegistryEntries": { + "HKEY_LOCAL_MACHINE\\$CHROME_UPDATE_REGISTRY_SUBKEY": { + "exists": "required", + "values": { + "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} + } + }, + "HKEY_LOCAL_MACHINE\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { + "exists": "required", + "values": { + "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} + } + }, + "HKEY_LOCAL_MACHINE\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { + "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", + "exists": "forbidden" + }, + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME": { + "exists": "required", + "values": { + "UninstallString": { + "type": "SZ", + "data": "\"$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --multi-install --chrome --system-level --verbose-logging" + }, + "Version": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} + } + }, + "HKEY_LOCAL_MACHINE\\Software\\Classes\\$CHROME_SHORT_NAME": { + "exists": "forbidden" + } + } +}
diff --git a/chrome/test/mini_installer/config/chrome_single_user_installed.prop b/chrome/test/mini_installer/config/chrome_multi_user_installed.prop similarity index 80% rename from chrome/test/mini_installer/config/chrome_single_user_installed.prop rename to chrome/test/mini_installer/config/chrome_multi_user_installed.prop index 5d02054..0ec67d1 100644 --- a/chrome/test/mini_installer/config/chrome_single_user_installed.prop +++ b/chrome/test/mini_installer/config/chrome_multi_user_installed.prop
@@ -1,6 +1,7 @@ { "Files": { "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, + "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll": @@ -10,7 +11,9 @@ "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\$MINI_INSTALLER_FILE_VERSION.manifest": - {"exists": true} + {"exists": true}, + "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION": + {"exists": false} }, "RegistryEntries": { "HKEY_CURRENT_USER\\$CHROME_UPDATE_REGISTRY_SUBKEY": { @@ -20,7 +23,10 @@ } }, "HKEY_CURRENT_USER\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { - "exists": "forbidden" + "exists": "required", + "values": { + "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} + } }, "HKEY_CURRENT_USER\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", @@ -31,7 +37,7 @@ "values": { "UninstallString": { "type": "SZ", - "data": "\"$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --verbose-logging" + "data": "\"$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --multi-install --chrome --verbose-logging" }, "Version": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} }
diff --git a/chrome/test/mini_installer/config/chrome_system_installed.prop b/chrome/test/mini_installer/config/chrome_system_installed.prop index 9a8dd5df3..bc1c7c4 100644 --- a/chrome/test/mini_installer/config/chrome_system_installed.prop +++ b/chrome/test/mini_installer/config/chrome_system_installed.prop
@@ -23,10 +23,7 @@ } }, "HKEY_LOCAL_MACHINE\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { - "exists": "required", - "values": { - "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} - } + "exists": "forbidden" }, "HKEY_LOCAL_MACHINE\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", @@ -37,7 +34,7 @@ "values": { "UninstallString": { "type": "SZ", - "data": "\"$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --multi-install --chrome --system-level --verbose-logging" + "data": "\"$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --system-level --verbose-logging" }, "Version": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} }
diff --git a/chrome/test/mini_installer/config/chrome_system_updated.prop b/chrome/test/mini_installer/config/chrome_system_updated.prop index 2e7be0c8..dddf793b 100644 --- a/chrome/test/mini_installer/config/chrome_system_updated.prop +++ b/chrome/test/mini_installer/config/chrome_system_updated.prop
@@ -23,12 +23,7 @@ } }, "HKEY_LOCAL_MACHINE\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { - "exists": "required", - "values": { - "pv": {"type": "SZ", "data": "$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION"}, - "opv": {}, - "cmd": {} - } + "exists": "forbidden" }, "HKEY_LOCAL_MACHINE\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", @@ -39,7 +34,7 @@ "values": { "UninstallString": { "type": "SZ", - "data": "\"$PROGRAM_FILES\\$CHROME_DIR\\Application\\$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --multi-install --chrome --system-level --verbose-logging" + "data": "\"$PROGRAM_FILES\\$CHROME_DIR\\Application\\$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --system-level --verbose-logging" }, "Version": {"type": "SZ", "data": "$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION"} }
diff --git a/chrome/test/mini_installer/config/chrome_user_installed.prop b/chrome/test/mini_installer/config/chrome_user_installed.prop index 0ec67d1..1dccebf 100644 --- a/chrome/test/mini_installer/config/chrome_user_installed.prop +++ b/chrome/test/mini_installer/config/chrome_user_installed.prop
@@ -23,10 +23,7 @@ } }, "HKEY_CURRENT_USER\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { - "exists": "required", - "values": { - "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} - } + "exists": "forbidden" }, "HKEY_CURRENT_USER\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", @@ -37,7 +34,7 @@ "values": { "UninstallString": { "type": "SZ", - "data": "\"$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --multi-install --chrome --verbose-logging" + "data": "\"$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --verbose-logging" }, "Version": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} }
diff --git a/chrome/test/mini_installer/config/chrome_user_updated.prop b/chrome/test/mini_installer/config/chrome_user_updated.prop index d8b478fa..a0e74a1 100644 --- a/chrome/test/mini_installer/config/chrome_user_updated.prop +++ b/chrome/test/mini_installer/config/chrome_user_updated.prop
@@ -23,12 +23,7 @@ } }, "HKEY_CURRENT_USER\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { - "exists": "required", - "values": { - "pv": {"type": "SZ", "data": "$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION"}, - "opv": {}, - "cmd": {} - } + "exists": "forbidden" }, "HKEY_CURRENT_USER\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", @@ -39,7 +34,7 @@ "values": { "UninstallString": { "type": "SZ", - "data": "\"$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --multi-install --chrome --verbose-logging" + "data": "\"$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION\\Installer\\setup.exe\" --uninstall --verbose-logging" }, "Version": {"type": "SZ", "data": "$NEXT_VERSION_MINI_INSTALLER_FILE_VERSION"} }
diff --git a/chrome/test/mini_installer/config/config.config b/chrome/test/mini_installer/config/config.config index 9467fb2b..6860526 100644 --- a/chrome/test/mini_installer/config/config.config +++ b/chrome/test/mini_installer/config/config.config
@@ -21,8 +21,8 @@ "chrome_user_not_inuse.prop", "chrome_canary_not_inuse.prop", "chrome_system_not_inuse.prop"]], - ["chrome_single_user_installed_not_inuse", - ["chrome_single_user_installed.prop", + ["chrome_multi_user_installed_not_inuse", + ["chrome_multi_user_installed.prop", "chrome_canary_not_installed.prop", "chrome_system_not_installed.prop", "chrome_user_not_inuse.prop", @@ -80,16 +80,14 @@ "chrome_system_not_inuse.prop"]] ], "actions": [ - ["delete_user_chrome_lastrun", - "reg.exe delete \"HKEY_CURRENT_USER\\$CHROME_CLIENT_STATE_KEY\" /v lastrun /f /reg:32"], ["install_chrome_canary", "\"$MINI_INSTALLER\" --chrome-sxs --verbose-logging --do-not-launch-chrome"], - ["install_chrome_single_user", - "\"$MINI_INSTALLER\" --verbose-logging --do-not-launch-chrome"], ["install_chrome_system", - "\"$MINI_INSTALLER\" --chrome --multi-install --verbose-logging --system-level --do-not-launch-chrome"], + "\"$MINI_INSTALLER\" --verbose-logging --system-level --do-not-launch-chrome"], ["install_chrome_user", - "\"$MINI_INSTALLER\" --chrome --multi-install --verbose-logging --do-not-launch-chrome"], + "\"$MINI_INSTALLER\" --verbose-logging --do-not-launch-chrome"], + ["make_chrome_user_multi", + "python make_chrome_multi.py --chrome-long-name \"$CHROME_LONG_NAME\" --chrome-clients-key \"$CHROME_UPDATE_REGISTRY_SUBKEY\" --chrome-client-state-key \"$CHROME_CLIENT_STATE_KEY\" --binaries-clients-key \"$BINARIES_UPDATE_REGISTRY_SUBKEY\""], ["kill_user_binaries", "reg.exe delete \"HKEY_CURRENT_USER\\$BINARIES_UPDATE_REGISTRY_SUBKEY\" /v pv /f /reg:32"], ["kill_user_chrome", @@ -115,88 +113,14 @@ ["update_chrome_canary", "\"$NEXT_VERSION_MINI_INSTALLER\" --chrome-sxs --verbose-logging --do-not-launch-chrome"], ["update_chrome_system", - "\"$NEXT_VERSION_MINI_INSTALLER\" --multi-install --verbose-logging --system-level --do-not-launch-chrome"], + "\"$NEXT_VERSION_MINI_INSTALLER\" --verbose-logging --system-level --do-not-launch-chrome"], ["update_chrome_user", - "\"$NEXT_VERSION_MINI_INSTALLER\" --multi-install --verbose-logging --do-not-launch-chrome"], - ["update_multi_chrome_user", - "\"$MINI_INSTALLER\" --multi-install --verbose-logging --do-not-launch-chrome"], - ["update_user_chrome_lastrun", - "python update_lastrun.py \"$CHROME_CLIENT_STATE_KEY\""] + "\"$NEXT_VERSION_MINI_INSTALLER\" --verbose-logging --do-not-launch-chrome"] ], "tests": [ { - "name": "RepairChromeStrandedBinaries", - "description": "Verifies that a multi-install update will repair Chrome if Chrome is missing from the Clients key yet appears to be actively used.", - "traversal": [ - "no_pv", - "install_chrome_user", "chrome_user_installed_not_inuse", - "update_user_chrome_lastrun", "chrome_user_installed_not_inuse", - "kill_user_chrome", "no_chrome_user", - "update_multi_chrome_user", "chrome_user_installed_not_inuse", - "uninstall_chrome_user", "clean" - ] - }, - { - "name": "RemoveStrandedBinaries", - "description": "Verifies that a multi-install update will uninstall Chrome and the binaries if Chrome is missing from the Clients key and does not appear to be actively used.", - "traversal": [ - "no_pv", - "install_chrome_user", "chrome_user_installed_not_inuse", - "update_user_chrome_lastrun", "chrome_user_installed_not_inuse", - "delete_user_chrome_lastrun", "chrome_user_installed_not_inuse", - "kill_user_chrome", "no_chrome_user", - "update_multi_chrome_user", "clean" - ] - }, - { - "name": "MultiToSingle", - "description": "Verifies that a single-install update on top of multi-install Chrome will migrate.", - "traversal": [ - "no_pv", - "install_chrome_user", "chrome_user_installed_not_inuse", - "install_chrome_single_user", "chrome_single_user_installed_not_inuse", - "uninstall_chrome_user", "clean" - ] - }, - { - "name": "MultiToSingleNoBinaries", - "description": "Verifies that a single-install update on top of multi-install Chrome will migrate when the binaries are missing from the Clients key.", - "traversal": [ - "no_pv", - "install_chrome_user", "chrome_user_installed_not_inuse", - "kill_user_binaries", "no_chrome_user_binaries", - "install_chrome_single_user", "chrome_single_user_installed_not_inuse", - "uninstall_chrome_user", "clean" - ] - }, - { - "name": "MultiToSingleNoChromeRepairActive", - "description": "Verifies that a single-install update on top of multi-install Chrome will migrate when Chrome is missing from the Clients key yet appears to be actively used.", - "traversal": [ - "no_pv", - "install_chrome_user", "chrome_user_installed_not_inuse", - "update_user_chrome_lastrun", "chrome_user_installed_not_inuse", - "kill_user_chrome", "no_chrome_user", - "install_chrome_single_user", "chrome_single_user_installed_not_inuse", - "uninstall_chrome_user", "clean" - ] - }, - { - "name": "MultiToSingleNoChromeRepairInactive", - "description": "Verifies that a single-install update on top of multi-install Chrome will migrate if Chrome is missing from the Clients key and does not appear to be actively used.", - "traversal": [ - "no_pv", - "install_chrome_user", "chrome_user_installed_not_inuse", - "update_user_chrome_lastrun", "chrome_user_installed_not_inuse", - "delete_user_chrome_lastrun", "chrome_user_installed_not_inuse", - "kill_user_chrome", "no_chrome_user", - "install_chrome_single_user", "chrome_single_user_installed_not_inuse", - "uninstall_chrome_user", "clean" - ] - }, - { "name": "ChromeUserLevel", - "description": "Verifies that multi-install user-level Chrome can be installed and uninstalled.", + "description": "Verifies that user-level Chrome can be installed and uninstalled.", "traversal": [ "no_pv", "install_chrome_user", "chrome_user_installed_not_inuse", @@ -205,7 +129,7 @@ }, { "name": "ChromeUserLevelUpdate", - "description": "Verifies that multi-install user-level Chrome can be updated.", + "description": "Verifies that user-level Chrome can be updated.", "traversal": [ "no_pv", "install_chrome_user", "chrome_user_installed_not_inuse", @@ -236,7 +160,7 @@ }, { "name": "ChromeSystemLevel", - "description": "Verifies that multi-install system-level Chrome can be installed and uninstalled.", + "description": "Verifies that system-level Chrome can be installed and uninstalled.", "traversal": [ "no_pv", "install_chrome_system", "chrome_system_installed_not_inuse", @@ -245,7 +169,7 @@ }, { "name": "ChromeSystemLevelUpdate", - "description": "Verifies that multi-install system-level Chrome can be updated.", + "description": "Verifies that system-level Chrome can be updated.", "traversal": [ "no_pv", "install_chrome_system", "chrome_system_installed_not_inuse", @@ -255,7 +179,7 @@ }, { "name": "ChromeUserLevelWithCanary", - "description": "Verifies that multi-install user-level Chrome and Chrome SxS can be installed simultaneously.", + "description": "Verifies that user-level Chrome and Chrome SxS can be installed simultaneously.", "condition": "$SUPPORTS_SXS", "traversal": [ "no_pv", @@ -264,6 +188,53 @@ "uninstall_chrome_user", "chrome_canary_installed_not_inuse", "uninstall_chrome_canary", "clean" ] + }, + { + "name": "MigrateMultiSimple", + "description": "Verifies that an update on top of multi-install Chrome will migrate.", + "traversal": [ + "no_pv", + "install_chrome_user", "chrome_user_installed_not_inuse", + "make_chrome_user_multi", "chrome_multi_user_installed_not_inuse", + "update_chrome_user", "chrome_user_updated_not_inuse", + "uninstall_chrome_user", "clean" + ] + }, + { + "name": "MigrateMultiStrandedBinariesOnUpdate", + "description": "Verifies that an update on top of multi-install Chrome where Chrome is missing from the Clients key will repair and migrate.", + "traversal": [ + "no_pv", + "install_chrome_user", "chrome_user_installed_not_inuse", + "make_chrome_user_multi", "chrome_multi_user_installed_not_inuse", + "kill_user_chrome", "no_chrome_user", + "update_chrome_user", "chrome_user_updated_not_inuse", + "uninstall_chrome_user", "clean" + ] + }, + { + "name": "MigrateMultiStrandedBinariesOnInstall", + "description": "Verifies that a same-version install on top of multi-install Chrome where Chrome is missing from the Clients key will repair and migrate.", + "traversal": [ + "no_pv", + "install_chrome_user", "chrome_user_installed_not_inuse", + "make_chrome_user_multi", "chrome_multi_user_installed_not_inuse", + "kill_user_chrome", "no_chrome_user", + "install_chrome_user", "chrome_user_installed_not_inuse", + "uninstall_chrome_user", "clean" + ] + }, + { + "name": "MigrateMultiNoBinaries", + "description": "Verifies that an update on top of multi-install Chrome where the binaries are missing from the Clients key will repair and migrate.", + "traversal": [ + "no_pv", + "install_chrome_user", "chrome_user_installed_not_inuse", + "make_chrome_user_multi", "chrome_multi_user_installed_not_inuse", + "kill_user_binaries", "no_chrome_user_binaries", + "update_chrome_user", "chrome_user_updated_not_inuse", + "uninstall_chrome_user", "clean" + ] } ] }
diff --git a/chrome/test/mini_installer/make_chrome_multi.py b/chrome/test/mini_installer/make_chrome_multi.py new file mode 100644 index 0000000..8910a45 --- /dev/null +++ b/chrome/test/mini_installer/make_chrome_multi.py
@@ -0,0 +1,79 @@ +# 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. + +"""Makes an existing per-user Chrome appear to be multi-install Chrome. + +This script makes minimal mutations to the Windows registry to make ordinary +single-install Chrome appear to be multi-install for purposes of testing multi- +to single- migrations. +""" + +import _winreg +import argparse +import sys + + +def MakeChromeMulti(chrome_long_name, chrome_clients_key, + chrome_client_state_key, binaries_clients_key): + # Update the control panel's uninstall string. + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, + ('Software\\Microsoft\\Windows\\CurrentVersion\\' + 'Uninstall\\%s' % chrome_long_name), 0, + _winreg.KEY_QUERY_VALUE | _winreg.KEY_SET_VALUE | + _winreg.KEY_WOW64_32KEY) + string = _winreg.QueryValueEx(key, 'UninstallString')[0] + string = string.replace('--uninstall', '--uninstall --multi-install --chrome') + _winreg.SetValueEx(key, 'UninstallString', 0, _winreg.REG_SZ, string) + + # Read Chrome's version number. + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, + chrome_clients_key, 0, + _winreg.KEY_QUERY_VALUE | _winreg.KEY_WOW64_32KEY) + pv = _winreg.QueryValueEx(key, 'pv')[0] + _winreg.CloseKey(key) + + # Write that version for the binaries. + key = _winreg.CreateKeyEx(_winreg.HKEY_CURRENT_USER, + binaries_clients_key, 0, + _winreg.KEY_SET_VALUE | _winreg.KEY_WOW64_32KEY) + _winreg.SetValueEx(key, 'pv', 0, _winreg.REG_SZ, pv) + _winreg.CloseKey(key) + + # Add "--multi-install --chrome" to Chrome's UninstallArguments. + key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, + chrome_client_state_key, 0, + _winreg.KEY_QUERY_VALUE | _winreg.KEY_SET_VALUE | + _winreg.KEY_WOW64_32KEY) + args = _winreg.QueryValueEx(key, 'UninstallArguments')[0] + args += ' --multi-install --chrome' + _winreg.SetValueEx(key, 'UninstallArguments', 0, _winreg.REG_SZ, args) + + +def main(): + parser = argparse.ArgumentParser( + description='Transforms single-install Chrome into multi-install.') + parser.add_argument('--chrome-long-name', default='Google Chrome', + help='The full name of the product.') + parser.add_argument('--chrome-clients-key', + default='Software\\Google\\Update\\Clients\\' + '{8A69D345-D564-463c-AFF1-A69D9E530F96}', + help='Chrome\'s Clients registry key path.') + parser.add_argument('--chrome-client-state-key', + default='Software\\Google\\Update\\ClientState\\' + '{8A69D345-D564-463c-AFF1-A69D9E530F96}', + help='Chrome\'s ClientState registry key path.') + parser.add_argument('--binaries-clients-key', + default='Software\\Google\\Update\\Clients\\' + '{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}', + help='Chrome Binaries\' Clients registry key path.') + args = parser.parse_args() + MakeChromeMulti(args.chrome_long_name, + args.chrome_clients_key, + args.chrome_client_state_key, + args.binaries_clients_key) + return 0 + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/components/bookmarks/browser/BUILD.gn b/components/bookmarks/browser/BUILD.gn index 6188b10..a4df5f1a 100644 --- a/components/bookmarks/browser/BUILD.gn +++ b/components/bookmarks/browser/BUILD.gn
@@ -14,10 +14,6 @@ "bookmark_codec.h", "bookmark_expanded_state_tracker.cc", "bookmark_expanded_state_tracker.h", - "bookmark_index.cc", - "bookmark_index.h", - "bookmark_match.cc", - "bookmark_match.h", "bookmark_model.cc", "bookmark_model.h", "bookmark_model_observer.h", @@ -39,6 +35,10 @@ "scoped_group_bookmark_actions.h", "startup_task_runner_service.cc", "startup_task_runner_service.h", + "titled_url_index.cc", + "titled_url_index.h", + "titled_url_match.cc", + "titled_url_match.h", "titled_url_node.h", "titled_url_node_sorter.h", "typed_count_sorter.cc",
diff --git a/components/bookmarks/browser/bookmark_index_unittest.cc b/components/bookmarks/browser/bookmark_index_unittest.cc index 50be374a..5e80f39 100644 --- a/components/bookmarks/browser/bookmark_index_unittest.cc +++ b/components/bookmarks/browser/bookmark_index_unittest.cc
@@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/bookmarks/browser/bookmark_index.h" - #include <stddef.h> #include <string> @@ -15,8 +13,8 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "components/bookmarks/browser/bookmark_match.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/bookmarks/test/bookmark_test_helpers.h" #include "components/bookmarks/test/test_bookmark_client.h" #include "testing/gtest/include/gtest/gtest.h" @@ -93,7 +91,7 @@ void ExpectMatches(const std::string& query, query_parser::MatchingAlgorithm matching_algorithm, const std::vector<std::string>& expected_titles) { - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; model_->GetBookmarksMatching(ASCIIToUTF16(query), 1000, matching_algorithm, &matches); ASSERT_EQ(expected_titles.size(), matches.size()); @@ -112,14 +110,14 @@ } void ExtractMatchPositions(const std::string& string, - BookmarkMatch::MatchPositions* matches) { + TitledUrlMatch::MatchPositions* matches) { for (const base::StringPiece& match : base::SplitStringPiece(string, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { std::vector<base::StringPiece> chunks = base::SplitStringPiece( match, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); ASSERT_EQ(2U, chunks.size()); - matches->push_back(BookmarkMatch::MatchPosition()); + matches->push_back(TitledUrlMatch::MatchPosition()); int chunks0, chunks1; EXPECT_TRUE(base::StringToInt(chunks[0], &chunks0)); EXPECT_TRUE(base::StringToInt(chunks[1], &chunks1)); @@ -129,8 +127,8 @@ } void ExpectMatchPositions( - const BookmarkMatch::MatchPositions& actual_positions, - const BookmarkMatch::MatchPositions& expected_positions) { + const TitledUrlMatch::MatchPositions& actual_positions, + const TitledUrlMatch::MatchPositions& expected_positions) { ASSERT_EQ(expected_positions.size(), actual_positions.size()); for (size_t i = 0; i < expected_positions.size(); ++i) { EXPECT_EQ(expected_positions[i].first, actual_positions[i].first); @@ -359,7 +357,7 @@ GURL url(kAboutBlankURL); for (size_t i = 0; i < arraysize(data); ++i) { model_->AddURL(model_->other_node(), 0, UTF8ToUTF16(data[i].title), url); - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; model_->GetBookmarksMatching(UTF8ToUTF16(data[i].query), 10, &matches); EXPECT_EQ(1u, matches.size()); model_ = TestBookmarkClient::CreateModel(); @@ -389,11 +387,11 @@ bookmarks.push_back(bookmark); AddBookmarks(bookmarks); - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; model_->GetBookmarksMatching(ASCIIToUTF16(data[i].query), 1000, &matches); ASSERT_EQ(1U, matches.size()); - BookmarkMatch::MatchPositions expected_title_matches; + TitledUrlMatch::MatchPositions expected_title_matches; ExtractMatchPositions(data[i].expected_title_match_positions, &expected_title_matches); ExpectMatchPositions(matches[0].title_match_positions, @@ -441,11 +439,11 @@ bookmarks.push_back(bookmark); AddBookmarks(bookmarks); - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; model_->GetBookmarksMatching(UTF8ToUTF16(data[i].query), 1000, &matches); ASSERT_EQ(1U, matches.size()) << data[i].url << data[i].query; - BookmarkMatch::MatchPositions expected_url_matches; + TitledUrlMatch::MatchPositions expected_url_matches; ExtractMatchPositions(data[i].expected_url_match_positions, &expected_url_matches); ExpectMatchPositions(matches[0].url_match_positions, expected_url_matches); @@ -493,7 +491,7 @@ const char* urls[] = {kAboutBlankURL, kAboutBlankURL}; AddBookmarks(titles, urls, arraysize(titles)); - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; model_->GetBookmarksMatching(ASCIIToUTF16("ABc"), 1, &matches); EXPECT_EQ(1U, matches.size()); } @@ -505,7 +503,7 @@ base::WideToUTF16(L"\u0130 i"), GURL("http://www.google.com")); - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; model_->GetBookmarksMatching(ASCIIToUTF16("i"), 100, &matches); ASSERT_EQ(1U, matches.size()); EXPECT_EQ(n1, matches[0].node); @@ -538,7 +536,7 @@ model->other_node(), i, UTF8ToUTF16(data[i].title), data[i].url); // Populate match nodes. - std::vector<BookmarkMatch> matches; + std::vector<TitledUrlMatch> matches; model->GetBookmarksMatching(ASCIIToUTF16("google"), 4, &matches); // The resulting order should be:
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index 29fdef5..8639f752 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -18,13 +18,13 @@ #include "base/profiler/scoped_tracker.h" #include "base/strings/string_util.h" #include "components/bookmarks/browser/bookmark_expanded_state_tracker.h" -#include "components/bookmarks/browser/bookmark_index.h" -#include "components/bookmarks/browser/bookmark_match.h" #include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_node_data.h" #include "components/bookmarks/browser/bookmark_storage.h" #include "components/bookmarks/browser/bookmark_undo_delegate.h" #include "components/bookmarks/browser/bookmark_utils.h" +#include "components/bookmarks/browser/titled_url_index.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/bookmarks/browser/typed_count_sorter.h" #include "components/favicon_base/favicon_types.h" #include "grit/components_strings.h" @@ -718,7 +718,7 @@ void BookmarkModel::GetBookmarksMatching(const base::string16& text, size_t max_count, - std::vector<BookmarkMatch>* matches) { + std::vector<TitledUrlMatch>* matches) { GetBookmarksMatching(text, max_count, query_parser::MatchingAlgorithm::DEFAULT, matches); } @@ -727,7 +727,7 @@ const base::string16& text, size_t max_count, query_parser::MatchingAlgorithm matching_algorithm, - std::vector<BookmarkMatch>* matches) { + std::vector<TitledUrlMatch>* matches) { if (!loaded_) return; @@ -1116,7 +1116,7 @@ base::MakeUnique<TypedCountSorter>(client_.get()); return std::unique_ptr<BookmarkLoadDetails>(new BookmarkLoadDetails( bb_node, other_node, mobile_node, client_->GetLoadExtraNodesCallback(), - new BookmarkIndex(std::move(node_sorter)), next_node_id_)); + new TitledUrlIndex(std::move(node_sorter)), next_node_id_)); } void BookmarkModel::SetUndoDelegate(BookmarkUndoDelegate* undo_delegate) {
diff --git a/components/bookmarks/browser/bookmark_model.h b/components/bookmarks/browser/bookmark_model.h index 309e806..2a52eb1e 100644 --- a/components/bookmarks/browser/bookmark_model.h +++ b/components/bookmarks/browser/bookmark_model.h
@@ -46,14 +46,14 @@ class BookmarkCodecTest; class BookmarkExpandedStateTracker; -class BookmarkIndex; class BookmarkLoadDetails; class BookmarkModelObserver; class BookmarkStorage; class BookmarkUndoDelegate; class ScopedGroupBookmarkActions; class TestBookmarkClient; -struct BookmarkMatch; +class TitledUrlIndex; +struct TitledUrlMatch; // BookmarkModel -------------------------------------------------------------- @@ -243,14 +243,14 @@ // in either the title or the URL. It uses default matching algorithm. void GetBookmarksMatching(const base::string16& text, size_t max_count, - std::vector<BookmarkMatch>* matches); + std::vector<TitledUrlMatch>* matches); // Returns up to |max_count| of bookmarks containing each term from |text| // in either the title or the URL. void GetBookmarksMatching(const base::string16& text, size_t max_count, query_parser::MatchingAlgorithm matching_algorithm, - std::vector<BookmarkMatch>* matches); + std::vector<TitledUrlMatch>* matches); // Sets the store to NULL, making it so the BookmarkModel does not persist // any changes to disk. This is only useful during testing to speed up @@ -450,7 +450,7 @@ // Reads/writes bookmarks to disk. std::unique_ptr<BookmarkStorage> store_; - std::unique_ptr<BookmarkIndex> index_; + std::unique_ptr<TitledUrlIndex> index_; base::WaitableEvent loaded_signal_;
diff --git a/components/bookmarks/browser/bookmark_storage.cc b/components/bookmarks/browser/bookmark_storage.cc index a71c3e3d..d32a90c 100644 --- a/components/bookmarks/browser/bookmark_storage.cc +++ b/components/bookmarks/browser/bookmark_storage.cc
@@ -18,8 +18,8 @@ #include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "components/bookmarks/browser/bookmark_codec.h" -#include "components/bookmarks/browser/bookmark_index.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "components/bookmarks/browser/titled_url_index.h" #include "components/bookmarks/common/bookmark_constants.h" using base::TimeTicks; @@ -124,7 +124,7 @@ BookmarkPermanentNode* other_folder_node, BookmarkPermanentNode* mobile_folder_node, const LoadExtraCallback& load_extra_callback, - BookmarkIndex* index, + TitledUrlIndex* index, int64_t max_id) : bb_node_(bb_node), other_folder_node_(other_folder_node),
diff --git a/components/bookmarks/browser/bookmark_storage.h b/components/bookmarks/browser/bookmark_storage.h index 2496e42c3..6f86188 100644 --- a/components/bookmarks/browser/bookmark_storage.h +++ b/components/bookmarks/browser/bookmark_storage.h
@@ -17,8 +17,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "components/bookmarks/browser/bookmark_index.h" #include "components/bookmarks/browser/bookmark_node.h" +#include "components/bookmarks/browser/titled_url_index.h" namespace base { class SequencedTaskRunner; @@ -51,7 +51,7 @@ BookmarkPermanentNode* other_folder_node, BookmarkPermanentNode* mobile_folder_node, const LoadExtraCallback& load_extra_callback, - BookmarkIndex* index, + TitledUrlIndex* index, int64_t max_id); ~BookmarkLoadDetails(); @@ -79,8 +79,8 @@ BookmarkPermanentNodeList owned_extra_nodes() { return std::move(extra_nodes_); } - BookmarkIndex* index() { return index_.get(); } - std::unique_ptr<BookmarkIndex> owned_index() { return std::move(index_); } + TitledUrlIndex* index() { return index_.get(); } + std::unique_ptr<TitledUrlIndex> owned_index() { return std::move(index_); } const BookmarkNode::MetaInfoMap& model_meta_info_map() const { return model_meta_info_map_; @@ -125,7 +125,7 @@ std::unique_ptr<BookmarkPermanentNode> mobile_folder_node_; LoadExtraCallback load_extra_callback_; BookmarkPermanentNodeList extra_nodes_; - std::unique_ptr<BookmarkIndex> index_; + std::unique_ptr<TitledUrlIndex> index_; BookmarkNode::MetaInfoMap model_meta_info_map_; int64_t model_sync_transaction_version_; int64_t max_id_;
diff --git a/components/bookmarks/browser/bookmark_index.cc b/components/bookmarks/browser/titled_url_index.cc similarity index 90% rename from components/bookmarks/browser/bookmark_index.cc rename to components/bookmarks/browser/titled_url_index.cc index 5413be63..abde1aa 100644 --- a/components/bookmarks/browser/bookmark_index.cc +++ b/components/bookmarks/browser/titled_url_index.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 "components/bookmarks/browser/bookmark_index.h" +#include "components/bookmarks/browser/titled_url_index.h" #include <stdint.h> @@ -11,8 +11,8 @@ #include "base/stl_util.h" #include "base/strings/utf_offset_string_conversions.h" #include "build/build_config.h" -#include "components/bookmarks/browser/bookmark_match.h" #include "components/bookmarks/browser/bookmark_utils.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/bookmarks/browser/titled_url_node.h" #include "components/bookmarks/browser/titled_url_node_sorter.h" #include "components/query_parser/snippet.h" @@ -48,14 +48,14 @@ } // namespace -BookmarkIndex::BookmarkIndex(std::unique_ptr<TitledUrlNodeSorter> sorter) +TitledUrlIndex::TitledUrlIndex(std::unique_ptr<TitledUrlNodeSorter> sorter) : sorter_(std::move(sorter)) { } -BookmarkIndex::~BookmarkIndex() { +TitledUrlIndex::~TitledUrlIndex() { } -void BookmarkIndex::Add(const TitledUrlNode* node) { +void TitledUrlIndex::Add(const TitledUrlNode* node) { std::vector<base::string16> terms = ExtractQueryWords(Normalize(node->GetTitledUrlNodeTitle())); for (size_t i = 0; i < terms.size(); ++i) @@ -66,7 +66,7 @@ RegisterNode(terms[i], node); } -void BookmarkIndex::Remove(const TitledUrlNode* node) { +void TitledUrlIndex::Remove(const TitledUrlNode* node) { std::vector<base::string16> terms = ExtractQueryWords(Normalize(node->GetTitledUrlNodeTitle())); for (size_t i = 0; i < terms.size(); ++i) @@ -77,11 +77,11 @@ UnregisterNode(terms[i], node); } -void BookmarkIndex::GetResultsMatching( +void TitledUrlIndex::GetResultsMatching( const base::string16& input_query, size_t max_count, query_parser::MatchingAlgorithm matching_algorithm, - std::vector<BookmarkMatch>* results) { + std::vector<TitledUrlMatch>* results) { const base::string16 query = Normalize(input_query); std::vector<base::string16> terms = ExtractQueryWords(query); if (terms.empty()) @@ -116,7 +116,7 @@ AddMatchToResults(*i, &parser, query_nodes, results); } -void BookmarkIndex::SortMatches(const TitledUrlNodeSet& matches, +void TitledUrlIndex::SortMatches(const TitledUrlNodeSet& matches, TitledUrlNodes* sorted_nodes) const { if (sorter_) { sorter_->SortMatches(matches, sorted_nodes); @@ -125,11 +125,11 @@ } } -void BookmarkIndex::AddMatchToResults( +void TitledUrlIndex::AddMatchToResults( const TitledUrlNode* node, query_parser::QueryParser* parser, const query_parser::QueryNodeVector& query_nodes, - std::vector<BookmarkMatch>* results) { + std::vector<TitledUrlMatch>* results) { if (!node) { return; } @@ -156,7 +156,7 @@ query_parser::QueryParser::SortAndCoalesceMatchPositions(&title_matches); query_parser::QueryParser::SortAndCoalesceMatchPositions(&url_matches); } - BookmarkMatch match; + TitledUrlMatch match; if (lower_title.length() == node->GetTitledUrlNodeTitle().length()) { // Only use title matches if the lowercase string is the same length // as the original string, otherwise the matches are meaningless. @@ -167,16 +167,16 @@ // matches in |url_matches| so they point to offsets in the original URL // spec, not the cleaned-up URL string that we used for matching. std::vector<size_t> offsets = - BookmarkMatch::OffsetsFromMatchPositions(url_matches); + TitledUrlMatch::OffsetsFromMatchPositions(url_matches); base::OffsetAdjuster::UnadjustOffsets(adjustments, &offsets); url_matches = - BookmarkMatch::ReplaceOffsetsInMatchPositions(url_matches, offsets); + TitledUrlMatch::ReplaceOffsetsInMatchPositions(url_matches, offsets); match.url_match_positions.swap(url_matches); match.node = node; results->push_back(match); } -bool BookmarkIndex::GetResultsMatchingTerm( +bool TitledUrlIndex::GetResultsMatchingTerm( const base::string16& term, bool first_term, query_parser::MatchingAlgorithm matching_algorithm, @@ -227,7 +227,7 @@ return !matches->empty(); } -std::vector<base::string16> BookmarkIndex::ExtractQueryWords( +std::vector<base::string16> TitledUrlIndex::ExtractQueryWords( const base::string16& query) { std::vector<base::string16> terms; if (query.empty()) @@ -239,12 +239,12 @@ return terms; } -void BookmarkIndex::RegisterNode(const base::string16& term, +void TitledUrlIndex::RegisterNode(const base::string16& term, const TitledUrlNode* node) { index_[term].insert(node); } -void BookmarkIndex::UnregisterNode(const base::string16& term, +void TitledUrlIndex::UnregisterNode(const base::string16& term, const TitledUrlNode* node) { Index::iterator i = index_.find(term); if (i == index_.end()) {
diff --git a/components/bookmarks/browser/bookmark_index.h b/components/bookmarks/browser/titled_url_index.h similarity index 70% rename from components/bookmarks/browser/bookmark_index.h rename to components/bookmarks/browser/titled_url_index.h index 52a510d..13a6455 100644 --- a/components/bookmarks/browser/bookmark_index.h +++ b/components/bookmarks/browser/titled_url_index.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 COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_INDEX_H_ -#define COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_INDEX_H_ +#ifndef COMPONENTS_BOOKMARKS_BROWSER_TITLED_URL_INDEX_H_ +#define COMPONENTS_BOOKMARKS_BROWSER_TITLED_URL_INDEX_H_ #include <stddef.h> @@ -20,19 +20,17 @@ class TitledUrlNode; class TitledUrlNodeSorter; -struct BookmarkMatch; +struct TitledUrlMatch; -// BookmarkIndex maintains an index of the titles and URLs of bookmarks for -// quick look up. BookmarkIndex is owned and maintained by BookmarkModel, you -// shouldn't need to interact directly with BookmarkIndex. +// TitledUrlIndex maintains an index of paired titles and URLs for quick lookup. // -// BookmarkIndex maintains the index (index_) as a map of sets. The map (type -// Index) maps from a lower case string to the set (type NodeSet) of +// TitledUrlIndex maintains the index (index_) as a map of sets. The map (type +// Index) maps from a lower case string to the set (type TitledUrlNodeSet) of // TitledUrlNodes that contain that string in their title or URL. -class BookmarkIndex { +class TitledUrlIndex { public: - BookmarkIndex(std::unique_ptr<TitledUrlNodeSorter> sorter); - ~BookmarkIndex(); + TitledUrlIndex(std::unique_ptr<TitledUrlNodeSorter> sorter); + ~TitledUrlIndex(); // Invoked when a title/URL pair has been added to the model. void Add(const TitledUrlNode* node); @@ -45,16 +43,15 @@ void GetResultsMatching(const base::string16& query, size_t max_count, query_parser::MatchingAlgorithm matching_algorithm, - std::vector<BookmarkMatch>* results); + std::vector<TitledUrlMatch>* results); private: using TitledUrlNodes = std::vector<const TitledUrlNode*>; using TitledUrlNodeSet = std::set<const TitledUrlNode*>; using Index = std::map<base::string16, TitledUrlNodeSet>; - // Constructs |sorted_nodes| by taking the matches in |matches| and sorting - // them in decreasing order of typed count (if supported by the client) and - // deduping them. + // Constructs |sorted_nodes| by copying the matches in |matches| and sorting + // them. void SortMatches(const TitledUrlNodeSet& matches, TitledUrlNodes* sorted_nodes) const; @@ -62,7 +59,7 @@ void AddMatchToResults(const TitledUrlNode* node, query_parser::QueryParser* parser, const query_parser::QueryNodeVector& query_nodes, - std::vector<BookmarkMatch>* results); + std::vector<TitledUrlMatch>* results); // Populates |matches| for the specified term. If |first_term| is true, this // is the first term in the query. Returns true if there is at least one node @@ -86,9 +83,9 @@ std::unique_ptr<TitledUrlNodeSorter> sorter_; - DISALLOW_COPY_AND_ASSIGN(BookmarkIndex); + DISALLOW_COPY_AND_ASSIGN(TitledUrlIndex); }; } // namespace bookmarks -#endif // COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_INDEX_H_ +#endif // COMPONENTS_BOOKMARKS_BROWSER_TITLED_URL_INDEX_H_
diff --git a/components/bookmarks/browser/bookmark_match.cc b/components/bookmarks/browser/titled_url_match.cc similarity index 78% rename from components/bookmarks/browser/bookmark_match.cc rename to components/bookmarks/browser/titled_url_match.cc index f813cbb..313ae4ef 100644 --- a/components/bookmarks/browser/bookmark_match.cc +++ b/components/bookmarks/browser/titled_url_match.cc
@@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/bookmarks/browser/bookmark_match.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "base/logging.h" #include "base/strings/string16.h" namespace bookmarks { -BookmarkMatch::BookmarkMatch() : node(NULL) {} +TitledUrlMatch::TitledUrlMatch() : node(NULL) {} -BookmarkMatch::BookmarkMatch(const BookmarkMatch& other) = default; +TitledUrlMatch::TitledUrlMatch(const TitledUrlMatch& other) = default; -BookmarkMatch::~BookmarkMatch() {} +TitledUrlMatch::~TitledUrlMatch() {} // static -std::vector<size_t> BookmarkMatch::OffsetsFromMatchPositions( +std::vector<size_t> TitledUrlMatch::OffsetsFromMatchPositions( const MatchPositions& match_positions) { std::vector<size_t> offsets; for (MatchPositions::const_iterator i = match_positions.begin(); @@ -28,7 +28,7 @@ } // static -BookmarkMatch::MatchPositions BookmarkMatch::ReplaceOffsetsInMatchPositions( +TitledUrlMatch::MatchPositions TitledUrlMatch::ReplaceOffsetsInMatchPositions( const MatchPositions& match_positions, const std::vector<size_t>& offsets) { DCHECK_EQ(2 * match_positions.size(), offsets.size());
diff --git a/components/bookmarks/browser/bookmark_match.h b/components/bookmarks/browser/titled_url_match.h similarity index 81% rename from components/bookmarks/browser/bookmark_match.h rename to components/bookmarks/browser/titled_url_match.h index 76cb0bf..767a190 100644 --- a/components/bookmarks/browser/bookmark_match.h +++ b/components/bookmarks/browser/titled_url_match.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 COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MATCH_H_ -#define COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MATCH_H_ +#ifndef COMPONENTS_BOOKMARKS_BROWSER_TITLED_URL_MATCH_H_ +#define COMPONENTS_BOOKMARKS_BROWSER_TITLED_URL_MATCH_H_ #include <stddef.h> @@ -15,15 +15,15 @@ class TitledUrlNode; -struct BookmarkMatch { +struct TitledUrlMatch { // Each MatchPosition is the [begin, end) positions of a match within a // string. using MatchPosition = std::pair<size_t, size_t>; using MatchPositions = std::vector<MatchPosition>; - BookmarkMatch(); - BookmarkMatch(const BookmarkMatch& other); - ~BookmarkMatch(); + TitledUrlMatch(); + TitledUrlMatch(const TitledUrlMatch& other); + ~TitledUrlMatch(); // Extracts and returns the offsets from |match_positions|. static std::vector<size_t> OffsetsFromMatchPositions( @@ -48,4 +48,4 @@ } // namespace bookmarks -#endif // COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_MATCH_H_ +#endif // COMPONENTS_BOOKMARKS_BROWSER_TITLED_URL_MATCH_H_
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 6635a19..88e6ad03 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -428,7 +428,7 @@ compositor_frame_sink_holder_), base::Bind(&CompositorFrameSinkHolder::Require, compositor_frame_sink_holder_), - content_size_, contents_surface_to_layer_scale, content_size_); + content_size_, contents_surface_to_layer_scale); window_->layer()->SetFillsBoundsOpaquely( state_.blend_mode == SkBlendMode::kSrc || state_.opaque_region.contains(
diff --git a/components/omnibox/browser/bookmark_provider.cc b/components/omnibox/browser/bookmark_provider.cc index 1976e8d..cee15775a 100644 --- a/components/omnibox/browser/bookmark_provider.cc +++ b/components/omnibox/browser/bookmark_provider.cc
@@ -12,8 +12,8 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" -#include "components/bookmarks/browser/bookmark_match.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/metrics/proto/omnibox_input_type.pb.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_result.h" @@ -23,9 +23,9 @@ #include "components/url_formatter/url_formatter.h" #include "url/url_constants.h" -using bookmarks::BookmarkMatch; -using BookmarkMatches = std::vector<BookmarkMatch>; using bookmarks::BookmarkNode; +using bookmarks::TitledUrlMatch; +using TitledUrlMatches = std::vector<TitledUrlMatch>; namespace { @@ -34,7 +34,7 @@ // characters are highlighted. void CorrectTitleAndMatchPositions( base::string16* title, - BookmarkMatch::MatchPositions* title_match_positions) { + TitledUrlMatch::MatchPositions* title_match_positions) { size_t leading_whitespace_chars = title->length(); base::TrimWhitespace(*title, base::TRIM_LEADING, title); leading_whitespace_chars-= title->length(); @@ -78,7 +78,7 @@ if (!bookmark_model_) return; - BookmarkMatches matches; + TitledUrlMatches matches; // Retrieve enough bookmarks so that we have a reasonable probability of // suggesting the one that the user desires. const size_t kMaxBookmarkMatches = 50; @@ -98,7 +98,7 @@ // - Multiple terms enclosed in quotes will require those exact words in that // exact order to match. // - // Please refer to the code for BookmarkIndex::GetBookmarksMatching for + // Please refer to the code for TitledUrlIndex::GetResultsMatching for // complete details of how searches are performed against the user's // bookmarks. bookmark_model_->GetBookmarksMatching(input.text(), @@ -107,11 +107,11 @@ if (matches.empty()) return; // There were no matches. const base::string16 fixed_up_input(FixupUserInput(input).second); - for (BookmarkMatches::const_iterator i = matches.begin(); i != matches.end(); + for (TitledUrlMatches::const_iterator i = matches.begin(); i != matches.end(); ++i) { // Create and score the AutocompleteMatch. If its score is 0 then the // match is discarded. - AutocompleteMatch match(BookmarkMatchToACMatch(input, fixed_up_input, *i)); + AutocompleteMatch match(TitledUrlMatchToACMatch(input, fixed_up_input, *i)); if (match.relevance > 0) matches_.push_back(match); } @@ -155,17 +155,17 @@ } // namespace -AutocompleteMatch BookmarkProvider::BookmarkMatchToACMatch( +AutocompleteMatch BookmarkProvider::TitledUrlMatchToACMatch( const AutocompleteInput& input, const base::string16& fixed_up_input_text, - const BookmarkMatch& bookmark_match) { + const TitledUrlMatch& bookmark_match) { // The AutocompleteMatch we construct is non-deletable because the only // way to support this would be to delete the underlying bookmark, which is // unlikely to be what the user intends. AutocompleteMatch match(this, 0, false, AutocompleteMatchType::BOOKMARK_TITLE); base::string16 title(bookmark_match.node->GetTitledUrlNodeTitle()); - BookmarkMatch::MatchPositions new_title_match_positions = + TitledUrlMatch::MatchPositions new_title_match_positions = bookmark_match.title_match_positions; CorrectTitleAndMatchPositions(&title, &new_title_match_positions); const GURL& url(bookmark_match.node->GetTitledUrlNodeUrl()); @@ -177,7 +177,7 @@ 0 : bookmark_match.url_match_positions[0].first; const bool trim_http = !AutocompleteInput::HasHTTPScheme(input.text()) && ((match_start == base::string16::npos) || (match_start != 0)); - std::vector<size_t> offsets = BookmarkMatch::OffsetsFromMatchPositions( + std::vector<size_t> offsets = TitledUrlMatch::OffsetsFromMatchPositions( bookmark_match.url_match_positions); // In addition to knowing how |offsets| is transformed, we need to know how // |inline_autocomplete_offset| is transformed. We add it to the end of @@ -190,8 +190,8 @@ net::UnescapeRule::SPACES, nullptr, nullptr, &offsets); inline_autocomplete_offset = offsets.back(); offsets.pop_back(); - BookmarkMatch::MatchPositions new_url_match_positions = - BookmarkMatch::ReplaceOffsetsInMatchPositions( + TitledUrlMatch::MatchPositions new_url_match_positions = + TitledUrlMatch::ReplaceOffsetsInMatchPositions( bookmark_match.url_match_positions, offsets); match.contents_class = ClassificationsFromMatch(new_url_match_positions,
diff --git a/components/omnibox/browser/bookmark_provider.h b/components/omnibox/browser/bookmark_provider.h index 228400f1..bb2c71b 100644 --- a/components/omnibox/browser/bookmark_provider.h +++ b/components/omnibox/browser/bookmark_provider.h
@@ -20,7 +20,7 @@ namespace bookmarks { class BookmarkModel; -struct BookmarkMatch; +struct TitledUrlMatch; } // This class is an autocomplete provider which quickly (and synchronously) @@ -60,10 +60,10 @@ // title, as the description. |input| is used to compute the match's // inline_autocompletion. |fixed_up_input_text| is used in that way as well; // it's passed separately so this function doesn't have to compute it. - AutocompleteMatch BookmarkMatchToACMatch( + AutocompleteMatch TitledUrlMatchToACMatch( const AutocompleteInput& input, const base::string16& fixed_up_input_text, - const bookmarks::BookmarkMatch& match); + const bookmarks::TitledUrlMatch& match); // Converts |positions| into ACMatchClassifications and returns the // classifications. |text_length| is used to determine the need to add an
diff --git a/components/omnibox/browser/bookmark_provider_unittest.cc b/components/omnibox/browser/bookmark_provider_unittest.cc index c962ad3..277f3c38 100644 --- a/components/omnibox/browser/bookmark_provider_unittest.cc +++ b/components/omnibox/browser/bookmark_provider_unittest.cc
@@ -18,8 +18,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" -#include "components/bookmarks/browser/bookmark_match.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "components/bookmarks/browser/titled_url_match.h" #include "components/bookmarks/test/test_bookmark_client.h" #include "components/metrics/proto/omnibox_event.pb.h" #include "components/omnibox/browser/autocomplete_provider.h" @@ -28,9 +28,9 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using bookmarks::BookmarkMatch; using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; +using bookmarks::TitledUrlMatch; namespace { @@ -420,9 +420,9 @@ provider_->FixupUserInput(input).second); BookmarkNode node(GURL(query_data[i].url)); node.SetTitle(base::ASCIIToUTF16(query_data[i].url)); - BookmarkMatch bookmark_match; + TitledUrlMatch bookmark_match; bookmark_match.node = &node; - const AutocompleteMatch& ac_match = provider_->BookmarkMatchToACMatch( + const AutocompleteMatch& ac_match = provider_->TitledUrlMatchToACMatch( input, fixed_up_input, bookmark_match); EXPECT_EQ(query_data[i].allowed_to_be_default_match, ac_match.allowed_to_be_default_match) << description;
diff --git a/components/security_state/core/BUILD.gn b/components/security_state/core/BUILD.gn index 3ce60b7..bb28c1f 100644 --- a/components/security_state/core/BUILD.gn +++ b/components/security_state/core/BUILD.gn
@@ -11,6 +11,8 @@ sources = [ "security_state.cc", "security_state.h", + "security_state_ui.cc", + "security_state_ui.h", "switches.cc", "switches.h", ]
diff --git a/components/security_state/core/security_state_ui.cc b/components/security_state/core/security_state_ui.cc new file mode 100644 index 0000000..31aff66 --- /dev/null +++ b/components/security_state/core/security_state_ui.cc
@@ -0,0 +1,27 @@ +// 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. + +#include "components/security_state/core/security_state_ui.h" + +namespace security_state { + +bool ShouldAlwaysShowIcon(SecurityLevel security_level) { + // Enumerate all |SecurityLevel| values for compile-time enforcement that all + // cases are explicitly handled. + switch (security_level) { + case NONE: + return false; + case HTTP_SHOW_WARNING: + case EV_SECURE: + case SECURE: + case SECURITY_WARNING: + case SECURE_WITH_POLICY_INSTALLED_CERT: + case DANGEROUS: + return true; + } + NOTREACHED(); + return false; +} + +} // namespace security_state
diff --git a/components/security_state/core/security_state_ui.h b/components/security_state/core/security_state_ui.h new file mode 100644 index 0000000..035091f --- /dev/null +++ b/components/security_state/core/security_state_ui.h
@@ -0,0 +1,21 @@ +// 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 COMPONENTS_SECURITY_STATE_SECURITY_STATE_UI_H_ +#define COMPONENTS_SECURITY_STATE_SECURITY_STATE_UI_H_ + +#include "components/security_state/core/security_state.h" + +// Provides helper methods that encapsulate platform-independent security UI +// logic. +namespace security_state { + +// On some (mobile) form factors, the security indicator icon is hidden to save +// UI space. This returns whether the icon should always be shown for the given +// |security_level|, i.e. whether to override the hiding behaviour. +bool ShouldAlwaysShowIcon(SecurityLevel security_level); + +} // namespace security_state + +#endif // COMPONENTS_SECURITY_STATE_SECURITY_STATE_UI_H_
diff --git a/components/user_manager/user.h b/components/user_manager/user.h index c48fd6eb..cce5f4fe 100644 --- a/components/user_manager/user.h +++ b/components/user_manager/user.h
@@ -78,7 +78,10 @@ ONLINE = 4, // WallpaperInfo.location denotes an URL. POLICY = 5, // Controlled by policy, can't be changed by the user. THIRDPARTY = 6, // Current wallpaper is set by a third party app. - WALLPAPER_TYPE_COUNT = 7 + DEVICE = 7, // Current wallpaper is the device policy controlled + // wallpaper. It shows on the login screen if the device + // is an enterprise managed device. + WALLPAPER_TYPE_COUNT = 8 }; // Returns true if user type has gaia account.
diff --git a/components/wallpaper/wallpaper_manager_base.cc b/components/wallpaper/wallpaper_manager_base.cc index e387fba..7e6f39c4 100644 --- a/components/wallpaper/wallpaper_manager_base.cc +++ b/components/wallpaper/wallpaper_manager_base.cc
@@ -473,7 +473,13 @@ GetUserWallpaperInfo(account_id, &info); info.type = user_manager::User::DEFAULT; SetUserWallpaperInfo(account_id, info, true /* is_persistent */); - SetDefaultWallpaperNow(account_id); + // If the user's policy is cleared, try to set the device wallpaper first. + // Note We have to modify the user wallpaper info first. Otherwise, we won't + // be able to override the current user policy wallpaper. The wallpaper info + // will be set correctly if the device wallpaper is set successfully. + if (!SetDeviceWallpaperIfApplicable(account_id)) { + SetDefaultWallpaperNow(account_id); + } } // static @@ -615,6 +621,15 @@ current_user_wallpaper_info_.type = user_manager::User::DEFAULT; current_user_wallpaper_info_.date = base::Time::Now().LocalMidnight(); + std::string device_wallpaper_url; + std::string device_wallpaper_hash; + if (ShouldSetDeviceWallpaper(account_id, &device_wallpaper_url, + &device_wallpaper_hash)) { + current_user_wallpaper_info_.location = + GetDeviceWallpaperFilePath().value(); + current_user_wallpaper_info_.type = user_manager::User::DEVICE; + } + WallpaperInfo info = current_user_wallpaper_info_; SetUserWallpaperInfo(account_id, info, is_persistent); } @@ -708,10 +723,15 @@ base::FilePath wallpaper_dir; base::FilePath wallpaper_path; if (info.type == user_manager::User::CUSTOMIZED || - info.type == user_manager::User::POLICY) { - const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); - base::FilePath wallpaper_path = GetCustomWallpaperDir(sub_dir); - wallpaper_path = wallpaper_path.Append(info.location); + info.type == user_manager::User::POLICY || + info.type == user_manager::User::DEVICE) { + base::FilePath wallpaper_path; + if (info.type == user_manager::User::DEVICE) { + wallpaper_path = GetDeviceWallpaperFilePath(); + } else { + const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); + wallpaper_path = GetCustomWallpaperDir(sub_dir).Append(info.location); + } // Set the path to the cache. wallpaper_cache_[account_id] = CustomWallpaperElement(wallpaper_path, gfx::ImageSkia());
diff --git a/components/wallpaper/wallpaper_manager_base.h b/components/wallpaper/wallpaper_manager_base.h index a734d2f..cd18065d 100644 --- a/components/wallpaper/wallpaper_manager_base.h +++ b/components/wallpaper/wallpaper_manager_base.h
@@ -354,6 +354,14 @@ // Ruturns files identifier for the |account_id|. virtual WallpaperFilesId GetFilesId(const AccountId& account_id) const = 0; + // If the device is enterprise managed and we're at the login screen, set the + // device wallpaper as the login screen wallpaper. If the device is enterprise + // managed and we're in a user session, only set the device wallpaper if there + // is no user policy wallpaper and the user hasn't changed the default or the + // device wallpaper. Returns true if the device wallpaper should be set as the + // wallpaper, otherwise returns false. + virtual bool SetDeviceWallpaperIfApplicable(const AccountId& account_id) = 0; + protected: friend class TestApi; friend class WallpaperManagerBrowserTest; @@ -402,7 +410,8 @@ gfx::ImageSkia* large_wallpaper_image); // Initialize wallpaper for the specified user to default and saves this - // settings in local state. + // settings in local state. Note if the device policy controlled wallpaper + // exists, use the device wallpaper as the default wallpaper. virtual void InitInitialUserWallpaper(const AccountId& account_id, bool is_persistent); @@ -472,6 +481,17 @@ virtual bool GetUserWallpaperInfo(const AccountId& account_id, WallpaperInfo* info) const = 0; + // Returns true if the device wallpaper should be set for the account. + virtual bool ShouldSetDeviceWallpaper(const AccountId& account_id, + std::string* url, + std::string* hash) = 0; + + // Returns the file directory where the downloaded device wallpaper is saved. + virtual base::FilePath GetDeviceWallpaperDir() = 0; + + // Returns the full path for the downloaded device wallpaper. + virtual base::FilePath GetDeviceWallpaperFilePath() = 0; + // Sets wallpaper to the decoded wallpaper if |update_wallpaper| is true. // Otherwise, cache wallpaper to memory if not logged in. (Takes a UserImage // because that's the callback interface provided by UserImageLoader.)
diff --git a/content/app/strings/content_strings.grd b/content/app/strings/content_strings.grd index 172afb17..f2f53d6a 100644 --- a/content/app/strings/content_strings.grd +++ b/content/app/strings/content_strings.grd
@@ -511,31 +511,7 @@ tree item </message> </if> - <message name="IDS_AX_BUTTON_ACTION_VERB" desc="Verb stating the action that will occur when a button is pressed, as used by accessibility."> - press - </message> - <message name="IDS_AX_RADIO_BUTTON_ACTION_VERB" desc="Verb stating the action that will occur when a radio button is clicked, as used by accessibility."> - select - </message> - <message name="IDS_AX_TEXT_FIELD_ACTION_VERB" desc="Verb stating the action that will occur when a text field is selected, as used by accessibility."> - activate - </message> - <message name="IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB" desc="Verb stating the action that will occur when a checked checkbox is clicked, as used by accessibility."> - uncheck - </message> - <message name="IDS_AX_UNCHECKED_CHECK_BOX_ACTION_VERB" desc="Verb stating the action that will occur when an unchecked checkbox is clicked, as used by accessibility."> - check - </message> - <message name="IDS_AX_LINK_ACTION_VERB" desc="Verb stating the action that will occur when a link is clicked, as used by accessibility."> - jump - </message> - <message name="IDS_AX_POP_UP_BUTTON_ACTION_VERB" desc="Verb stating the action that will occur when a pop-up button is clicked, as used by accessibility."> - open - </message> - <message name="IDS_AX_DEFAULT_ACTION_VERB" desc="Verb stating the action that will occur when clicking on a generic clickable object, when we don't know what that action is, as used by accessibility."> - click - </message> - + <message name="IDS_AX_AM_PM_FIELD_TEXT" desc="Accessible description of the AM/PM field in a date/time control"> AM/PM </message>
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 78f886f..e7b891e6 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -184,6 +184,8 @@ "$target_gen_dir/devtools/protocol/schema.h", "$target_gen_dir/devtools/protocol/security.cc", "$target_gen_dir/devtools/protocol/security.h", + "$target_gen_dir/devtools/protocol/service_worker.cc", + "$target_gen_dir/devtools/protocol/service_worker.h", "$target_gen_dir/devtools/protocol/storage.cc", "$target_gen_dir/devtools/protocol/storage.h", "$target_gen_dir/devtools/protocol/system_info.cc",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc index 5e9c8bd..00d9a069 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -40,9 +40,6 @@ const BrowserAccessibility& node, base::DictionaryValue* dict) { dict->SetInteger("id", node.GetId()); - auto lines = node.GetLineStartOffsets(); - for (auto& l : lines) - DLOG(ERROR) << "Nektar: ui::ToString(node.GetData().role)" << l; dict->SetString("internalRole", ui::ToString(node.GetData().role));
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 6ae417f..4258eaf 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -11,7 +11,6 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/common/accessibility_messages.h" #include "ui/accessibility/ax_text_utils.h"
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 4c873c94..934cdc6 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -155,7 +155,7 @@ bool BrowserAccessibilityAndroid::IsClickable() const { // If it has a default action, it's definitely clickable. - if (HasStringAttribute(ui::AX_ATTR_ACTION)) + if (HasIntAttribute(ui::AX_ATTR_ACTION)) return true; // Otherwise return true if it's focusable, but skip web areas and iframes.
diff --git a/content/browser/accessibility/browser_accessibility_auralinux.cc b/content/browser/accessibility/browser_accessibility_auralinux.cc index 1af9cccd..c990120 100644 --- a/content/browser/accessibility/browser_accessibility_auralinux.cc +++ b/content/browser/accessibility/browser_accessibility_auralinux.cc
@@ -7,9 +7,11 @@ #include <stdint.h> #include <string.h> +#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/accessibility/browser_accessibility_manager_auralinux.h" #include "content/common/accessibility_messages.h" +#include "ui/accessibility/ax_text_utils.h" namespace content { @@ -91,9 +93,14 @@ BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(atk_action); if (!obj) - return 0; + return nullptr; - return obj->GetStringAttribute(ui::AX_ATTR_ACTION).c_str(); + int action; + if (!obj->GetIntAttribute(ui::AX_ATTR_ACTION, &action)) + return nullptr; + base::string16 action_verb = + ui::ActionToUnlocalizedString(static_cast<ui::AXSupportedAction>(action)); + return base::UTF16ToUTF8(action_verb).c_str(); } static const gchar* browser_accessibility_get_keybinding(AtkAction* atk_action,
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index e2ad1da..d40a576 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -421,7 +421,7 @@ return E_INVALIDARG; // Return an error if it's not clickable. - if (!target->HasStringAttribute(ui::AX_ATTR_ACTION)) + if (!target->HasIntAttribute(ui::AX_ATTR_ACTION)) return DISP_E_MEMBERNOTFOUND; manager()->DoDefaultAction(*target); @@ -577,8 +577,7 @@ if (!target) return E_INVALIDARG; - return target->GetStringAttributeAsBstr( - ui::AX_ATTR_ACTION, def_action); + return target->get_localizedName(0, def_action); } STDMETHODIMP BrowserAccessibilityWin::get_accDescription(VARIANT var_id, @@ -2839,7 +2838,7 @@ // |IsHyperlink| is required for |IAccessibleHyperlink::anchor/anchorTarget| // to work properly because the |IAccessibleHyperlink| interface inherits from // |IAccessibleAction|. - if (IsHyperlink() || HasStringAttribute(ui::AX_ATTR_ACTION)) { + if (IsHyperlink() || HasIntAttribute(ui::AX_ATTR_ACTION)) { *n_actions = 1; } else { *n_actions = 0; @@ -2853,7 +2852,7 @@ if (!instance_active()) return E_FAIL; - if (!HasStringAttribute(ui::AX_ATTR_ACTION) || action_index != 0) + if (!HasIntAttribute(ui::AX_ATTR_ACTION) || action_index != 0) return E_INVALIDARG; manager()->DoDefaultAction(*this); @@ -2882,13 +2881,19 @@ if (!name) return E_INVALIDARG; - base::string16 action_verb; - if (!GetString16Attribute(ui::AX_ATTR_ACTION, &action_verb) || - action_index != 0) { + int action; + if (!GetIntAttribute(ui::AX_ATTR_ACTION, &action) || action_index != 0) { *name = nullptr; return E_INVALIDARG; } + base::string16 action_verb = + ui::ActionToUnlocalizedString(static_cast<ui::AXSupportedAction>(action)); + if (action_verb.empty() || action_verb == L"none") { + *name = nullptr; + return S_FALSE; + } + *name = SysAllocString(action_verb.c_str()); DCHECK(name); return S_OK; @@ -2898,7 +2903,28 @@ BrowserAccessibilityWin::get_localizedName(long action_index, BSTR* localized_name) { WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_LOCALIZED_NAME); - return E_NOTIMPL; + if (!instance_active()) + return E_FAIL; + + if (!localized_name) + return E_INVALIDARG; + + int action; + if (!GetIntAttribute(ui::AX_ATTR_ACTION, &action) || action_index != 0) { + *localized_name = nullptr; + return E_INVALIDARG; + } + + base::string16 action_verb = + ui::ActionToString(static_cast<ui::AXSupportedAction>(action)); + if (action_verb.empty()) { + *localized_name = nullptr; + return S_FALSE; + } + + *localized_name = SysAllocString(action_verb.c_str()); + DCHECK(localized_name); + return S_OK; } //
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn index 5ef4994..ddda5baf 100644 --- a/content/browser/devtools/BUILD.gn +++ b/content/browser/devtools/BUILD.gn
@@ -76,6 +76,8 @@ "protocol/schema.h", "protocol/security.cc", "protocol/security.h", + "protocol/service_worker.cc", + "protocol/service_worker.h", "protocol/storage.cc", "protocol/storage.h", "protocol/system_info.cc",
diff --git a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py index 823d2185c..60178dd 100755 --- a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py +++ b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -643,7 +643,7 @@ includes = [] fields_init = [] -browser_domains_list = ["Target", "ServiceWorker", "Input"] +browser_domains_list = ["Target", "Input"] browser_commands_list = [] async_commands_list = [ "Input.synthesizePinchGesture",
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc index c34d15a1..62a962d3 100644 --- a/content/browser/devtools/protocol/service_worker_handler.cc +++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -33,10 +33,7 @@ #include "url/gurl.h" namespace content { -namespace devtools { -namespace service_worker { - -using Response = DevToolsProtocolClient::Response; +namespace protocol { namespace { @@ -58,13 +55,15 @@ EmbeddedWorkerStatus running_status) { switch (running_status) { case EmbeddedWorkerStatus::STOPPED: - return kServiceWorkerVersionRunningStatusStopped; + return ServiceWorker::ServiceWorkerVersionRunningStatusEnum::Stopped; case EmbeddedWorkerStatus::STARTING: - return kServiceWorkerVersionRunningStatusStarting; + return ServiceWorker::ServiceWorkerVersionRunningStatusEnum::Starting; case EmbeddedWorkerStatus::RUNNING: - return kServiceWorkerVersionRunningStatusRunning; + return ServiceWorker::ServiceWorkerVersionRunningStatusEnum::Running; case EmbeddedWorkerStatus::STOPPING: - return kServiceWorkerVersionRunningStatusStopping; + return ServiceWorker::ServiceWorkerVersionRunningStatusEnum::Stopping; + default: + NOTREACHED(); } return std::string(); } @@ -73,83 +72,23 @@ content::ServiceWorkerVersion::Status status) { switch (status) { case content::ServiceWorkerVersion::NEW: - return kServiceWorkerVersionStatusNew; + return ServiceWorker::ServiceWorkerVersionStatusEnum::New; case content::ServiceWorkerVersion::INSTALLING: - return kServiceWorkerVersionStatusInstalling; + return ServiceWorker::ServiceWorkerVersionStatusEnum::Installing; case content::ServiceWorkerVersion::INSTALLED: - return kServiceWorkerVersionStatusInstalled; + return ServiceWorker::ServiceWorkerVersionStatusEnum::Installed; case content::ServiceWorkerVersion::ACTIVATING: - return kServiceWorkerVersionStatusActivating; + return ServiceWorker::ServiceWorkerVersionStatusEnum::Activating; case content::ServiceWorkerVersion::ACTIVATED: - return kServiceWorkerVersionStatusActivated; + return ServiceWorker::ServiceWorkerVersionStatusEnum::Activated; case content::ServiceWorkerVersion::REDUNDANT: - return kServiceWorkerVersionStatusRedundant; + return ServiceWorker::ServiceWorkerVersionStatusEnum::Redundant; + default: + NOTREACHED(); } return std::string(); } -scoped_refptr<ServiceWorkerVersion> CreateVersionDictionaryValue( - const ServiceWorkerVersionInfo& version_info) { - std::vector<std::string> clients; - for (const auto& client : version_info.clients) { - if (client.second.type == SERVICE_WORKER_PROVIDER_FOR_WINDOW) { - RenderFrameHostImpl* render_frame_host = RenderFrameHostImpl::FromID( - client.second.process_id, client.second.route_id); - WebContents* web_contents = - WebContents::FromRenderFrameHost(render_frame_host); - // There is a possibility that the frame is already deleted because of the - // thread hopping. - if (!web_contents) - continue; - scoped_refptr<DevToolsAgentHost> agent_host( - DevToolsAgentHost::GetOrCreateFor(web_contents)); - if (agent_host) - clients.push_back(agent_host->GetId()); - } else if (client.second.type == - SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER) { - scoped_refptr<DevToolsAgentHost> agent_host( - DevToolsAgentHost::GetForWorker(client.second.process_id, - client.second.route_id)); - if (agent_host) - clients.push_back(agent_host->GetId()); - } - } - scoped_refptr<ServiceWorkerVersion> version( - ServiceWorkerVersion::Create() - ->set_version_id(base::Int64ToString(version_info.version_id)) - ->set_registration_id( - base::Int64ToString(version_info.registration_id)) - ->set_script_url(version_info.script_url.spec()) - ->set_running_status( - GetVersionRunningStatusString(version_info.running_status)) - ->set_status(GetVersionStatusString(version_info.status)) - ->set_script_last_modified( - version_info.script_last_modified.ToDoubleT()) - ->set_script_response_time( - version_info.script_response_time.ToDoubleT()) - ->set_controlled_clients(clients)); - scoped_refptr<DevToolsAgentHostImpl> host( - ServiceWorkerDevToolsManager::GetInstance() - ->GetDevToolsAgentHostForWorker( - version_info.process_id, - version_info.devtools_agent_route_id)); - if (host) - version->set_target_id(host->GetId()); - return version; -} - -scoped_refptr<ServiceWorkerRegistration> CreateRegistrationDictionaryValue( - const ServiceWorkerRegistrationInfo& registration_info) { - scoped_refptr<ServiceWorkerRegistration> registration( - ServiceWorkerRegistration::Create() - ->set_registration_id( - base::Int64ToString(registration_info.registration_id)) - ->set_scope_url(registration_info.pattern.spec()) - ->set_is_deleted(registration_info.delete_flag == - ServiceWorkerRegistrationInfo::IS_DELETED)); - return registration; -} - void StopServiceWorkerOnIO(scoped_refptr<ServiceWorkerContextWrapper> context, int64_t version_id) { if (content::ServiceWorkerVersion* version = @@ -173,11 +112,11 @@ } Response CreateContextErrorResponse() { - return Response::InternalError("Could not connect to the context"); + return Response::Error("Could not connect to the context"); } Response CreateInvalidVersionIdErrorResponse() { - return Response::InternalError("Invalid version ID"); + return Response::InvalidParams("Invalid version ID"); } void DidFindRegistrationForDispatchSyncEventOnIO( @@ -217,7 +156,11 @@ } ServiceWorkerHandler::~ServiceWorkerHandler() { - Disable(); +} + +void ServiceWorkerHandler::Wire(UberDispatcher* dispatcher) { + frontend_.reset(new ServiceWorker::Frontend(dispatcher->channel())); + ServiceWorker::Dispatcher::wire(dispatcher, this); } void ServiceWorkerHandler::SetRenderFrameHost( @@ -237,19 +180,11 @@ partition->GetServiceWorkerContext()); } -void ServiceWorkerHandler::SetClient(std::unique_ptr<Client> client) { - client_.swap(client); -} - -void ServiceWorkerHandler::Detached() { - Disable(); -} - Response ServiceWorkerHandler::Enable() { if (enabled_) return Response::OK(); if (!context_) - return Response::InternalError("Could not connect to the context"); + return CreateContextErrorResponse(); enabled_ = true; context_watcher_ = new ServiceWorkerContextWatcher( @@ -409,39 +344,89 @@ void ServiceWorkerHandler::OnWorkerRegistrationUpdated( const std::vector<ServiceWorkerRegistrationInfo>& registrations) { - std::vector<scoped_refptr<ServiceWorkerRegistration>> registration_values; + using Registration = ServiceWorker::ServiceWorkerRegistration; + std::unique_ptr<protocol::Array<Registration>> result = + protocol::Array<Registration>::create(); for (const auto& registration : registrations) { - registration_values.push_back( - CreateRegistrationDictionaryValue(registration)); + result->addItem(Registration::Create() + .SetRegistrationId( + base::Int64ToString(registration.registration_id)) + .SetScopeURL(registration.pattern.spec()) + .SetIsDeleted(registration.delete_flag == + ServiceWorkerRegistrationInfo::IS_DELETED) + .Build()); } - client_->WorkerRegistrationUpdated( - WorkerRegistrationUpdatedParams::Create()->set_registrations( - registration_values)); + frontend_->WorkerRegistrationUpdated(std::move(result)); } void ServiceWorkerHandler::OnWorkerVersionUpdated( const std::vector<ServiceWorkerVersionInfo>& versions) { - std::vector<scoped_refptr<ServiceWorkerVersion>> version_values; + using Version = ServiceWorker::ServiceWorkerVersion; + std::unique_ptr<protocol::Array<Version>> result = + protocol::Array<Version>::create(); for (const auto& version : versions) { - version_values.push_back(CreateVersionDictionaryValue(version)); + std::unique_ptr<protocol::Array<std::string>> clients = + protocol::Array<std::string>::create(); + for (const auto& client : version.clients) { + if (client.second.type == SERVICE_WORKER_PROVIDER_FOR_WINDOW) { + RenderFrameHostImpl* render_frame_host = RenderFrameHostImpl::FromID( + client.second.process_id, client.second.route_id); + WebContents* web_contents = + WebContents::FromRenderFrameHost(render_frame_host); + // There is a possibility that the frame is already deleted + // because of the thread hopping. + if (!web_contents) + continue; + clients->addItem( + DevToolsAgentHost::GetOrCreateFor(web_contents)->GetId()); + } else if (client.second.type == + SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER) { + scoped_refptr<DevToolsAgentHost> agent_host( + DevToolsAgentHost::GetForWorker(client.second.process_id, + client.second.route_id)); + if (agent_host) + clients->addItem(agent_host->GetId()); + } + } + std::unique_ptr<Version> version_value = Version::Create() + .SetVersionId(base::Int64ToString(version.version_id)) + .SetRegistrationId( + base::Int64ToString(version.registration_id)) + .SetScriptURL(version.script_url.spec()) + .SetRunningStatus( + GetVersionRunningStatusString(version.running_status)) + .SetStatus(GetVersionStatusString(version.status)) + .SetScriptLastModified( + version.script_last_modified.ToDoubleT()) + .SetScriptResponseTime( + version.script_response_time.ToDoubleT()) + .SetControlledClients(std::move(clients)) + .Build(); + scoped_refptr<DevToolsAgentHostImpl> host( + ServiceWorkerDevToolsManager::GetInstance() + ->GetDevToolsAgentHostForWorker( + version.process_id, + version.devtools_agent_route_id)); + if (host) + version_value->SetTargetId(host->GetId()); + result->addItem(std::move(version_value)); } - client_->WorkerVersionUpdated( - WorkerVersionUpdatedParams::Create()->set_versions(version_values)); + frontend_->WorkerVersionUpdated(std::move(result)); } void ServiceWorkerHandler::OnErrorReported( int64_t registration_id, int64_t version_id, const ServiceWorkerContextObserver::ErrorInfo& info) { - client_->WorkerErrorReported( - WorkerErrorReportedParams::Create()->set_error_message( - ServiceWorkerErrorMessage::Create() - ->set_error_message(base::UTF16ToUTF8(info.error_message)) - ->set_registration_id(base::Int64ToString(registration_id)) - ->set_version_id(base::Int64ToString(version_id)) - ->set_source_url(info.source_url.spec()) - ->set_line_number(info.line_number) - ->set_column_number(info.column_number))); + frontend_->WorkerErrorReported( + ServiceWorker::ServiceWorkerErrorMessage::Create() + .SetErrorMessage(base::UTF16ToUTF8(info.error_message)) + .SetRegistrationId(base::Int64ToString(registration_id)) + .SetVersionId(base::Int64ToString(version_id)) + .SetSourceURL(info.source_url.spec()) + .SetLineNumber(info.line_number) + .SetColumnNumber(info.column_number) + .Build()); } void ServiceWorkerHandler::ClearForceUpdate() { @@ -449,6 +434,5 @@ context_->SetForceUpdateOnPageLoad(false); } -} // namespace service_worker -} // namespace devtools +} // namespace protocol } // namespace content
diff --git a/content/browser/devtools/protocol/service_worker_handler.h b/content/browser/devtools/protocol/service_worker_handler.h index 892a8c7..359a08e 100644 --- a/content/browser/devtools/protocol/service_worker_handler.h +++ b/content/browser/devtools/protocol/service_worker_handler.h
@@ -11,18 +11,11 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h" +#include "content/browser/devtools/protocol/service_worker.h" #include "content/browser/devtools/service_worker_devtools_agent_host.h" #include "content/browser/devtools/service_worker_devtools_manager.h" #include "content/browser/service_worker/service_worker_context_observer.h" #include "content/browser/service_worker/service_worker_info.h" -#include "content/public/browser/devtools_agent_host.h" -#include "content/public/browser/devtools_agent_host_client.h" - -// Windows headers will redefine SendMessage. -#ifdef SendMessage -#undef SendMessage -#endif namespace content { @@ -30,37 +23,32 @@ class ServiceWorkerContextWatcher; class ServiceWorkerContextWrapper; -namespace devtools { -namespace service_worker { +namespace protocol { -class ServiceWorkerHandler { +class ServiceWorkerHandler : public ServiceWorker::Backend { public: - typedef DevToolsProtocolClient::Response Response; - ServiceWorkerHandler(); - ~ServiceWorkerHandler(); + ~ServiceWorkerHandler() override; + void Wire(UberDispatcher*); void SetRenderFrameHost(RenderFrameHostImpl* render_frame_host); - void SetClient(std::unique_ptr<Client> client); - void Detached(); - // Protocol 'service worker' domain implementation. - Response Enable(); - Response Disable(); - Response Unregister(const std::string& scope_url); - Response StartWorker(const std::string& scope_url); - Response SkipWaiting(const std::string& scope_url); - Response StopWorker(const std::string& version_id); - Response UpdateRegistration(const std::string& scope_url); - Response InspectWorker(const std::string& version_id); - Response SetForceUpdateOnPageLoad(bool force_update_on_page_load); + Response Enable() override; + Response Disable() override; + Response Unregister(const std::string& scope_url) override; + Response StartWorker(const std::string& scope_url) override; + Response SkipWaiting(const std::string& scope_url) override; + Response StopWorker(const std::string& version_id) override; + Response UpdateRegistration(const std::string& scope_url) override; + Response InspectWorker(const std::string& version_id) override; + Response SetForceUpdateOnPageLoad(bool force_update_on_page_load) override; Response DeliverPushMessage(const std::string& origin, const std::string& registration_id, - const std::string& data); + const std::string& data) override; Response DispatchSyncEvent(const std::string& origin, const std::string& registration_id, const std::string& tag, - bool last_chance); + bool last_chance) override; private: void OnWorkerRegistrationUpdated( @@ -75,7 +63,7 @@ void ClearForceUpdate(); scoped_refptr<ServiceWorkerContextWrapper> context_; - std::unique_ptr<Client> client_; + std::unique_ptr<ServiceWorker::Frontend> frontend_; bool enabled_; scoped_refptr<ServiceWorkerContextWatcher> context_watcher_; RenderFrameHostImpl* render_frame_host_; @@ -85,8 +73,7 @@ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerHandler); }; -} // namespace service_worker -} // namespace devtools +} // namespace protocol } // namespace content #endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_SERVICE_WORKER_HANDLER_H_
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index c64ec06c..d1f1d2c 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -52,6 +52,9 @@ "domain": "Security" }, { + "domain": "ServiceWorker" + }, + { "domain": "Storage" }, {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 21f8d39b..ad707efe 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -395,8 +395,6 @@ RenderFrameHostImpl* host) : DevToolsAgentHostImpl(base::GenerateGUID()), input_handler_(new devtools::input::InputHandler()), - service_worker_handler_( - new devtools::service_worker::ServiceWorkerHandler()), target_handler_(new devtools::target::TargetHandler()), frame_trace_recorder_(nullptr), protocol_handler_(new DevToolsProtocolHandler(this)), @@ -406,7 +404,6 @@ frame_tree_node_(host->frame_tree_node()) { DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher(); dispatcher->SetInputHandler(input_handler_.get()); - dispatcher->SetServiceWorkerHandler(service_worker_handler_.get()); dispatcher->SetTargetHandler(target_handler_.get()); SetPending(host); @@ -509,6 +506,10 @@ security_handler_->SetRenderFrameHost(handlers_frame_host_); } + service_worker_handler_.reset(new protocol::ServiceWorkerHandler()); + service_worker_handler_->Wire(session()->dispatcher()); + service_worker_handler_->SetRenderFrameHost(handlers_frame_host_); + storage_handler_.reset(new protocol::StorageHandler()); storage_handler_->Wire(session()->dispatcher()); storage_handler_->SetRenderFrameHost(handlers_frame_host_); @@ -549,6 +550,8 @@ security_handler_->Disable(); security_handler_.reset(); } + service_worker_handler_->Disable(); + service_worker_handler_.reset(); storage_handler_->Disable(); storage_handler_.reset(); tracing_handler_->Disable(); @@ -615,7 +618,6 @@ #if defined(OS_ANDROID) power_save_blocker_.reset(); #endif - service_worker_handler_->Detached(); target_handler_->Detached(); frame_trace_recorder_.reset(); in_navigation_protocol_message_buffer_.clear(); @@ -964,7 +966,8 @@ network_handler_->SetRenderFrameHost(host); if (page_handler_) page_handler_->SetRenderFrameHost(host); - service_worker_handler_->SetRenderFrameHost(host); + if (service_worker_handler_) + service_worker_handler_->SetRenderFrameHost(host); if (security_handler_) security_handler_->SetRenderFrameHost(host); if (storage_handler_)
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index 2b464da..e4fa63e8 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -41,7 +41,6 @@ namespace devtools { namespace input { class InputHandler; } -namespace service_worker { class ServiceWorkerHandler; } namespace target { class TargetHandler; } } @@ -54,6 +53,7 @@ class PageHandler; class SchemaHandler; class SecurityHandler; +class ServiceWorkerHandler; class StorageHandler; class TracingHandler; } // namespace protocol @@ -191,8 +191,7 @@ std::unique_ptr<protocol::PageHandler> page_handler_; std::unique_ptr<protocol::SchemaHandler> schema_handler_; std::unique_ptr<protocol::SecurityHandler> security_handler_; - std::unique_ptr<devtools::service_worker::ServiceWorkerHandler> - service_worker_handler_; + std::unique_ptr<protocol::ServiceWorkerHandler> service_worker_handler_; std::unique_ptr<protocol::StorageHandler> storage_handler_; std::unique_ptr<devtools::target::TargetHandler> target_handler_; std::unique_ptr<protocol::TracingHandler> tracing_handler_;
diff --git a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc index 2cb5b47..e7e5668 100644 --- a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc +++ b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -73,9 +73,13 @@ base::TimeDelta timestamp) override { DoOnIncomingCapturedBuffer(); } - void OnIncomingCapturedVideoFrame( + void OnIncomingCapturedBufferExt( std::unique_ptr<Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override { + const media::VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const media::VideoFrameMetadata& additional_metadata) override { DoOnIncomingCapturedVideoFrame(); } std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
diff --git a/content/browser/media/capture/desktop_capture_device_unittest.cc b/content/browser/media/capture/desktop_capture_device_unittest.cc index 4fe54c08..0d19dec 100644 --- a/content/browser/media/capture/desktop_capture_device_unittest.cc +++ b/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -92,9 +92,13 @@ base::TimeDelta timestamp) override { DoOnIncomingCapturedBuffer(); } - void OnIncomingCapturedVideoFrame( - std::unique_ptr<Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override { + void OnIncomingCapturedBufferExt( + std::unique_ptr<Buffer> buffer, + const media::VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const media::VideoFrameMetadata& additional_metadata) override { DoOnIncomingCapturedVideoFrame(); } std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
diff --git a/content/browser/media/capture/screen_capture_device_android_unittest.cc b/content/browser/media/capture/screen_capture_device_android_unittest.cc index 1eaa60c..3aedf3c 100644 --- a/content/browser/media/capture/screen_capture_device_android_unittest.cc +++ b/content/browser/media/capture/screen_capture_device_android_unittest.cc
@@ -49,9 +49,13 @@ base::TimeDelta timestamp) override { DoOnIncomingCapturedBuffer(); } - void OnIncomingCapturedVideoFrame( + void OnIncomingCapturedBufferExt( std::unique_ptr<Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override { + const media::VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const media::VideoFrameMetadata& additional_metadata) override { DoOnIncomingCapturedVideoFrame(); } std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
diff --git a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc index 3843028..3764d98 100644 --- a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc +++ b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -376,27 +376,32 @@ DoOnIncomingCapturedBuffer(); } - void OnIncomingCapturedVideoFrame( - std::unique_ptr<Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override { - EXPECT_FALSE(frame->visible_rect().IsEmpty()); - EXPECT_EQ(media::PIXEL_FORMAT_I420, frame->format()); - double frame_rate = 0; - EXPECT_TRUE( - frame->metadata()->GetDouble(media::VideoFrameMetadata::FRAME_RATE, - &frame_rate)); - EXPECT_EQ(kTestFramesPerSecond, frame_rate); + void OnIncomingCapturedBufferExt( + std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, + const media::VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const media::VideoFrameMetadata& additional_metadata) override { + EXPECT_FALSE(visible_rect.IsEmpty()); + EXPECT_EQ(media::PIXEL_FORMAT_I420, format.pixel_format); + EXPECT_EQ(kTestFramesPerSecond, format.frame_rate); // TODO(miu): We just look at the center pixel presently, because if the // analysis is too slow, the backlog of frames will grow without bound and // trouble erupts. http://crbug.com/174519 using media::VideoFrame; - const gfx::Point center = frame->visible_rect().CenterPoint(); + auto frame = VideoFrame::WrapExternalSharedMemory( + media::PIXEL_FORMAT_I420, format.frame_size, visible_rect, + format.frame_size, static_cast<uint8_t*>(buffer->data()), + buffer->mapped_size(), base::SharedMemory::NULLHandle(), 0u, + base::TimeDelta()); + const gfx::Point center = visible_rect.CenterPoint(); const int center_offset_y = (frame->stride(VideoFrame::kYPlane) * center.y()) + center.x(); const int center_offset_uv = (frame->stride(VideoFrame::kUPlane) * (center.y() / 2)) + - (center.x() / 2); + (center.x() / 2); report_callback_.Run( SkColorSetRGB(frame->data(VideoFrame::kYPlane)[center_offset_y], frame->data(VideoFrame::kUPlane)[center_offset_uv],
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 31fc6063..a4f25901 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -515,7 +515,7 @@ cc::SurfaceId(frame_sink_id_, local_frame_id_), base::Bind(&SatisfyCallback, base::Unretained(manager)), base::Bind(&RequireCallback, base::Unretained(manager)), frame_size, - frame_device_scale_factor, frame_size_in_dip); + frame_device_scale_factor); current_surface_size_ = frame_size; current_scale_factor_ = frame_device_scale_factor; }
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index 337e6d0..599f34e1 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -160,19 +160,6 @@ void TearDown() override { base::RunLoop().RunUntilIdle(); } - scoped_refptr<media::VideoFrame> WrapBuffer( - gfx::Size dimensions, - uint8_t* data, - media::VideoPixelFormat format = media::PIXEL_FORMAT_I420) { - scoped_refptr<media::VideoFrame> video_frame = - media::VideoFrame::WrapExternalSharedMemory( - format, dimensions, gfx::Rect(dimensions), dimensions, data, - media::VideoFrame::AllocationSize(format, dimensions), - base::SharedMemory::NULLHandle(), 0u, base::TimeDelta()); - EXPECT_TRUE(video_frame); - return video_frame; - } - TestBrowserThreadBundle bundle_; std::unique_ptr<MockVideoCaptureControllerEventHandler> client_a_; std::unique_ptr<MockVideoCaptureControllerEventHandler> client_b_; @@ -180,6 +167,9 @@ std::unique_ptr<media::VideoCaptureDevice::Client> device_client_; MockFrameBufferPool* mock_frame_receiver_observer_; MockConsumerFeedbackObserver* mock_consumer_feedback_observer_; + const float arbitrary_frame_rate_ = 10.0f; + const base::TimeTicks arbitrary_reference_time_ = base::TimeTicks(); + const base::TimeDelta arbitrary_timestamp_ = base::TimeDelta(); private: DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest); @@ -299,19 +289,13 @@ media::VideoCaptureParams session_1 = session_100; - const gfx::Size capture_resolution(444, 200); - - // The device format needn't match the VideoCaptureParams (the camera can do - // what it wants). Pick something random. - media::VideoCaptureFormat device_format( - gfx::Size(10, 10), 25, media::PIXEL_FORMAT_RGB24); + media::VideoCaptureFormat device_format(gfx::Size(444, 200), 25, format); const VideoCaptureControllerID client_a_route_1(0xa1a1a1a1); const VideoCaptureControllerID client_a_route_2(0xa2a2a2a2); const VideoCaptureControllerID client_b_route_1(0xb1b1b1b1); const VideoCaptureControllerID client_b_route_2(0xb2b2b2b2); - // Start with two clients. controller_->AddClient(client_a_route_1, client_a_.get(), 100, @@ -332,8 +316,9 @@ const int arbitrary_frame_feedback_id = 101; ASSERT_EQ(0.0, device_client_->GetBufferPoolUtilization()); std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer( - device_client_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, + device_client_->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, arbitrary_frame_feedback_id)); ASSERT_TRUE(buffer.get()); ASSERT_EQ(1.0 / kPoolSize, device_client_->GetBufferPoolUtilization()); @@ -341,26 +326,24 @@ { InSequence s; EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1); - EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1, capture_resolution)) + EXPECT_CALL(*client_a_, + DoBufferReady(client_a_route_1, device_format.frame_size)) .Times(1); } { InSequence s; EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1); - EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1, capture_resolution)) + EXPECT_CALL(*client_b_, + DoBufferReady(client_b_route_1, device_format.frame_size)) .Times(1); } { InSequence s; EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1); - EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2, capture_resolution)) + EXPECT_CALL(*client_a_, + DoBufferReady(client_a_route_2, device_format.frame_size)) .Times(1); } - scoped_refptr<media::VideoFrame> video_frame = WrapBuffer( - capture_resolution, static_cast<uint8_t*>(buffer->data()), format); - ASSERT_TRUE(video_frame); - ASSERT_FALSE(video_frame->metadata()->HasKey( - media::VideoFrameMetadata::RESOURCE_UTILIZATION)); client_a_->resource_utilization_ = 0.5; client_b_->resource_utilization_ = -1.0; { @@ -376,9 +359,10 @@ .Times(1); } - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); + device_client_->OnIncomingCapturedBuffer(std::move(buffer), + device_format, + arbitrary_reference_time_, + arbitrary_timestamp_); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); @@ -391,17 +375,14 @@ // delay. This shouldn't affect anything. const int arbitrary_frame_feedback_id_2 = 102; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer2 = - device_client_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, + device_client_->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, arbitrary_frame_feedback_id_2); ASSERT_TRUE(buffer2.get()); memset(buffer2->data(), buffer_no++, buffer2->mapped_size()); - video_frame = WrapBuffer(capture_resolution, - static_cast<uint8_t*>(buffer2->data()), format); client_a_->resource_utilization_ = 0.5; client_b_->resource_utilization_ = 3.14; - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); // Expect VideoCaptureController to call the load observer with a // resource utilization of 3.14 (the largest of all reported values). { @@ -418,25 +399,31 @@ .Times(1); } - device_client_->OnIncomingCapturedVideoFrame(std::move(buffer2), video_frame); + device_client_->OnIncomingCapturedBuffer(std::move(buffer2), + device_format, + arbitrary_reference_time_, + arbitrary_timestamp_); // The buffer should be delivered to the clients in any order. { InSequence s; EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1); - EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1, capture_resolution)) + EXPECT_CALL(*client_a_, + DoBufferReady(client_a_route_1, device_format.frame_size)) .Times(1); } { InSequence s; EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1); - EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1, capture_resolution)) + EXPECT_CALL(*client_b_, + DoBufferReady(client_b_route_1, device_format.frame_size)) .Times(1); } { InSequence s; EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1); - EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2, capture_resolution)) + EXPECT_CALL(*client_a_, + DoBufferReady(client_a_route_2, device_format.frame_size)) .Times(1); } base::RunLoop().RunUntilIdle(); @@ -456,42 +443,45 @@ for (int i = 0; i < kPoolSize; i++) { const int arbitrary_frame_feedback_id = 200 + i; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer = - device_client_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, + device_client_->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, arbitrary_frame_feedback_id); ASSERT_TRUE(buffer.get()); memset(buffer->data(), buffer_no++, buffer->mapped_size()); - video_frame = WrapBuffer(capture_resolution, - static_cast<uint8_t*>(buffer->data()), format); - ASSERT_TRUE(video_frame); - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), - video_frame); + device_client_->OnIncomingCapturedBuffer(std::move(buffer), + device_format, + arbitrary_reference_time_, + arbitrary_timestamp_); } // ReserveOutputBuffer ought to fail now, because the pool is depleted. ASSERT_FALSE(device_client_ - ->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, + ->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, arbitrary_frame_feedback_id) .get()); // The new client needs to be notified of the creation of |kPoolSize| buffers; // the old clients only |kPoolSize - 2|. EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize); - EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2, capture_resolution)) + EXPECT_CALL(*client_b_, + DoBufferReady(client_b_route_2, device_format.frame_size)) .Times(kPoolSize); EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)) .Times(kPoolSize - 2); - EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_1, capture_resolution)) + EXPECT_CALL(*client_a_, + DoBufferReady(client_a_route_1, device_format.frame_size)) .Times(kPoolSize); EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)) .Times(kPoolSize - 2); - EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2, capture_resolution)) + EXPECT_CALL(*client_a_, + DoBufferReady(client_a_route_2, device_format.frame_size)) .Times(kPoolSize); EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)) .Times(kPoolSize - 2); - EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_1, capture_resolution)) + EXPECT_CALL(*client_b_, + DoBufferReady(client_b_route_1, device_format.frame_size)) .Times(kPoolSize); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); @@ -505,21 +495,21 @@ controller_->StopSession(300); // Queue up another buffer. std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer3 = - device_client_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, + device_client_->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, arbitrary_frame_feedback_id); ASSERT_TRUE(buffer3.get()); memset(buffer3->data(), buffer_no++, buffer3->mapped_size()); - video_frame = WrapBuffer(capture_resolution, - static_cast<uint8_t*>(buffer3->data()), format); - ASSERT_TRUE(video_frame); - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_client_->OnIncomingCapturedVideoFrame(std::move(buffer3), video_frame); + device_client_->OnIncomingCapturedBuffer(std::move(buffer3), + device_format, + arbitrary_reference_time_, + arbitrary_timestamp_); std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer4 = - device_client_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, + device_client_->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, arbitrary_frame_feedback_id); { // Kill A2 via session close (posts a task to disconnect, but A2 must not @@ -529,15 +519,14 @@ } ASSERT_TRUE(buffer4.get()); memset(buffer4->data(), buffer_no++, buffer4->mapped_size()); - video_frame = WrapBuffer(capture_resolution, - static_cast<uint8_t*>(buffer4->data()), format); - ASSERT_TRUE(video_frame); - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_client_->OnIncomingCapturedVideoFrame(std::move(buffer4), video_frame); + device_client_->OnIncomingCapturedBuffer(std::move(buffer4), + device_format, + arbitrary_reference_time_, + arbitrary_timestamp_); // B2 is the only client left, and is the only one that should // get the buffer. - EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2, capture_resolution)) + EXPECT_CALL(*client_b_, + DoBufferReady(client_b_route_2, device_format.frame_size)) .Times(2); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); @@ -576,18 +565,19 @@ base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_b_.get()); - const int arbitrary_frame_feedback_id = 101; + media::VideoCaptureFormat device_format( + capture_resolution, arbitrary_frame_rate_, media::PIXEL_FORMAT_I420, + media::PIXEL_STORAGE_CPU); + const int arbitrary_frame_feedback_id = 101; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer( - device_client_->ReserveOutputBuffer( - capture_resolution, media::PIXEL_FORMAT_I420, - media::PIXEL_STORAGE_CPU, arbitrary_frame_feedback_id)); - ASSERT_TRUE(buffer.get()); - scoped_refptr<media::VideoFrame> video_frame = - WrapBuffer(capture_resolution, static_cast<uint8_t*>(buffer->data())); - ASSERT_TRUE(video_frame); - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); + device_client_->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, + arbitrary_frame_feedback_id)); + device_client_->OnIncomingCapturedBuffer(std::move(buffer), + device_format, + arbitrary_reference_time_, + arbitrary_timestamp_); base::RunLoop().RunUntilIdle(); } @@ -605,8 +595,6 @@ // Start with one client. controller_->AddClient(route_id, client_a_.get(), 100, session_100); - media::VideoCaptureFormat device_format( - gfx::Size(10, 10), 25, media::PIXEL_FORMAT_ARGB); // Start the device. Then, before the first buffer, signal an error and // deliver the buffer. The error should be propagated to clients; the buffer @@ -614,21 +602,21 @@ base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); - const gfx::Size dims(320, 240); + media::VideoCaptureFormat device_format( + gfx::Size(10, 10), arbitrary_frame_rate_, media::PIXEL_FORMAT_I420); const int arbitrary_frame_feedback_id = 101; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer( - device_client_->ReserveOutputBuffer(dims, media::PIXEL_FORMAT_I420, - media::PIXEL_STORAGE_CPU, + device_client_->ReserveOutputBuffer(device_format.frame_size, + device_format.pixel_format, + device_format.pixel_storage, arbitrary_frame_feedback_id)); ASSERT_TRUE(buffer.get()); - scoped_refptr<media::VideoFrame> video_frame = - WrapBuffer(dims, static_cast<uint8_t*>(buffer->data())); - ASSERT_TRUE(video_frame); device_client_->OnError(FROM_HERE, "Test Error"); - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); + device_client_->OnIncomingCapturedBuffer(std::move(buffer), + device_format, + arbitrary_reference_time_, + arbitrary_timestamp_); EXPECT_CALL(*client_a_, DoError(route_id)).Times(1); base::RunLoop().RunUntilIdle();
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 872234e..a4d142d 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -80,8 +80,6 @@ switch (name) { case WebLocalizedString::AXAMPMFieldText: return IDS_AX_AM_PM_FIELD_TEXT; - case WebLocalizedString::AXButtonActionVerb: - return IDS_AX_BUTTON_ACTION_VERB; case WebLocalizedString::AXCalendarShowMonthSelector: return IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR; case WebLocalizedString::AXCalendarShowNextMonth: @@ -90,20 +88,14 @@ return IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH; case WebLocalizedString::AXCalendarWeekDescription: return IDS_AX_CALENDAR_WEEK_DESCRIPTION; - case WebLocalizedString::AXCheckedCheckBoxActionVerb: - return IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB; case WebLocalizedString::AXDayOfMonthFieldText: return IDS_AX_DAY_OF_MONTH_FIELD_TEXT; - case WebLocalizedString::AXDefaultActionVerb: - return IDS_AX_DEFAULT_ACTION_VERB; case WebLocalizedString::AXHeadingText: return IDS_AX_ROLE_HEADING; case WebLocalizedString::AXHourFieldText: return IDS_AX_HOUR_FIELD_TEXT; case WebLocalizedString::AXImageMapText: return IDS_AX_ROLE_IMAGE_MAP; - case WebLocalizedString::AXLinkActionVerb: - return IDS_AX_LINK_ACTION_VERB; case WebLocalizedString::AXLinkText: return IDS_AX_ROLE_LINK; case WebLocalizedString::AXListMarkerText: @@ -192,16 +184,8 @@ return IDS_AX_MINUTE_FIELD_TEXT; case WebLocalizedString::AXMonthFieldText: return IDS_AX_MONTH_FIELD_TEXT; - case WebLocalizedString::AXPopUpButtonActionVerb: - return IDS_AX_POP_UP_BUTTON_ACTION_VERB; - case WebLocalizedString::AXRadioButtonActionVerb: - return IDS_AX_RADIO_BUTTON_ACTION_VERB; case WebLocalizedString::AXSecondFieldText: return IDS_AX_SECOND_FIELD_TEXT; - case WebLocalizedString::AXTextFieldActionVerb: - return IDS_AX_TEXT_FIELD_ACTION_VERB; - case WebLocalizedString::AXUncheckedCheckBoxActionVerb: - return IDS_AX_UNCHECKED_CHECK_BOX_ACTION_VERB; case WebLocalizedString::AXWebAreaText: return IDS_AX_ROLE_WEB_AREA; case WebLocalizedString::AXWeekOfYearFieldText:
diff --git a/content/renderer/accessibility/blink_ax_enum_conversion.cc b/content/renderer/accessibility/blink_ax_enum_conversion.cc index 55479b4..1ebdb18 100644 --- a/content/renderer/accessibility/blink_ax_enum_conversion.cc +++ b/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -409,6 +409,32 @@ } } +ui::AXSupportedAction AXSupportedActionFromBlink( + blink::WebAXSupportedAction supported_action) { + switch (supported_action) { + case blink::WebAXSupportedAction::None: + return ui::AX_SUPPORTED_ACTION_NONE; + case blink::WebAXSupportedAction::Activate: + return ui::AX_SUPPORTED_ACTION_ACTIVATE; + case blink::WebAXSupportedAction::Check: + return ui::AX_SUPPORTED_ACTION_CHECK; + case blink::WebAXSupportedAction::Click: + return ui::AX_SUPPORTED_ACTION_CLICK; + case blink::WebAXSupportedAction::Jump: + return ui::AX_SUPPORTED_ACTION_JUMP; + case blink::WebAXSupportedAction::Open: + return ui::AX_SUPPORTED_ACTION_OPEN; + case blink::WebAXSupportedAction::Press: + return ui::AX_SUPPORTED_ACTION_PRESS; + case blink::WebAXSupportedAction::Select: + return ui::AX_SUPPORTED_ACTION_SELECT; + case blink::WebAXSupportedAction::Uncheck: + return ui::AX_SUPPORTED_ACTION_UNCHECK; + } + NOTREACHED(); + return ui::AX_SUPPORTED_ACTION_NONE; +} + ui::AXMarkerType AXMarkerTypeFromBlink(blink::WebAXMarkerType marker_type) { switch (marker_type) { case blink::WebAXMarkerTypeSpelling:
diff --git a/content/renderer/accessibility/blink_ax_enum_conversion.h b/content/renderer/accessibility/blink_ax_enum_conversion.h index bf81010..e324989 100644 --- a/content/renderer/accessibility/blink_ax_enum_conversion.h +++ b/content/renderer/accessibility/blink_ax_enum_conversion.h
@@ -24,6 +24,9 @@ // in AXNodeData instead.) uint32_t AXStateFromBlink(const blink::WebAXObject& o); +ui::AXSupportedAction AXSupportedActionFromBlink( + blink::WebAXSupportedAction supported_action); + ui::AXMarkerType AXMarkerTypeFromBlink(blink::WebAXMarkerType marker_type); ui::AXTextDirection AXTextDirectionFromBlink(
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index 5fcf702..bd9b01c 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -427,8 +427,9 @@ dst->AddStringAttribute(ui::AX_ATTR_ACCESS_KEY, src.accessKey().utf8()); } - if (src.actionVerb().length()) { - dst->AddStringAttribute(ui::AX_ATTR_ACTION, src.actionVerb().utf8()); + if (src.action() != blink::WebAXSupportedAction::None) { + dst->AddIntAttribute(ui::AX_ATTR_ACTION, + AXSupportedActionFromBlink(src.action())); } if (src.ariaAutoComplete().length()) {
diff --git a/content/test/data/accessibility/html/action-verbs-expected-blink.txt b/content/test/data/accessibility/html/action-verbs-expected-blink.txt index ac62ce9..c588e67 100644 --- a/content/test/data/accessibility/html/action-verbs-expected-blink.txt +++ b/content/test/data/accessibility/html/action-verbs-expected-blink.txt
@@ -5,18 +5,18 @@ ++heading name='Heading' ++++staticText name='Heading' ++++++inlineTextBox name='Heading' -++button action='press' name='Button' -++link action='jump' name='Link' -++++staticText action='click' name='Link' +++button name='Button' action=6 +++link name='Link' action=4 +++++staticText name='Link' action=3 ++++++inlineTextBox name='Link' ++textField -++checkBox action='check' -++checkBox action='uncheck' -++radioButton action='select' -++switch action='check' name='ARIA Switch' -++popUpButton action='open' +++checkBox action=8 +++checkBox action=2 +++radioButton action=7 +++switch name='ARIA Switch' action=8 +++popUpButton action=5 ++++menuListPopup -++++++menuListOption action='click' name='Pop-up button' -++div action='click' -++++staticText action='click' name='Div with click handler' -++++++inlineTextBox name='Div with click handler' \ No newline at end of file +++++++menuListOption name='Pop-up button' action=3 +++div action=3 +++++staticText name='Div with click handler' action=3 +++++++inlineTextBox name='Div with click handler'
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index d31eac5c..16be527 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -51,7 +51,7 @@ self.Skip('WebglExtension_WEBGL_compressed_texture_atc', ['win', 'mac', 'linux']) self.Skip('WebglExtension_WEBGL_compressed_texture_etc1', - ['mac', 'linux']) + ['win', 'mac', 'linux']) self.Skip('WebglExtension_WEBGL_compressed_texture_pvrtc', ['win', 'mac', 'linux']) self.Skip('WebglExtension_WEBGL_compressed_texture_s3tc_srgb', @@ -62,8 +62,6 @@ ['win', 'd3d9']) self.Fail('WebglExtension_EXT_sRGB', ['win', 'd3d9']) - self.Fail('WebglExtension_WEBGL_compressed_texture_etc1', - ['win', 'd3d9']) self.Fail('WebglExtension_WEBGL_depth_texture', ['win', 'amd', 'd3d9'])
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index c817e12..49b6fca 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -1037,7 +1037,11 @@ validators_.g_l_state.AddValue(GL_TEXTURE_BINDING_EXTERNAL_OES); } - if (extensions.Contains("GL_OES_compressed_ETC1_RGB8_texture")) { + // TODO(kainino): If we add a way to query whether ANGLE is exposing + // native support for ETC1 textures, require that here. Otherwise, we could + // co-opt the native-ETC2-support query discussed below. + if (extensions.Contains("GL_OES_compressed_ETC1_RGB8_texture") && + !gl_version_info_->is_angle) { AddExtensionString("GL_OES_compressed_ETC1_RGB8_texture"); feature_flags_.oes_compressed_etc1_rgb8_texture = true; validators_.compressed_texture_format.AddValue(GL_ETC1_RGB8_OES);
diff --git a/media/capture/content/thread_safe_capture_oracle.cc b/media/capture/content/thread_safe_capture_oracle.cc index 9fc8f93..ad869b7d 100644 --- a/media/capture/content/thread_safe_capture_oracle.cc +++ b/media/capture/content/thread_safe_capture_oracle.cc
@@ -211,26 +211,33 @@ base::AutoLock guard(lock_); - if (oracle_.CompleteCapture(frame_number, success, &reference_time)) { - TRACE_EVENT_INSTANT0("gpu.capture", "CaptureSucceeded", - TRACE_EVENT_SCOPE_THREAD); + if (!oracle_.CompleteCapture(frame_number, success, &reference_time)) + return; - if (!client_) - return; // Capture is stopped. + TRACE_EVENT_INSTANT0("gpu.capture", "CaptureSucceeded", + TRACE_EVENT_SCOPE_THREAD); - frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, - params_.requested_format.frame_rate); - frame->metadata()->SetTimeTicks(VideoFrameMetadata::CAPTURE_BEGIN_TIME, - capture_begin_time); - frame->metadata()->SetTimeTicks(VideoFrameMetadata::CAPTURE_END_TIME, - base::TimeTicks::Now()); - frame->metadata()->SetTimeDelta(VideoFrameMetadata::FRAME_DURATION, - estimated_frame_duration); - frame->metadata()->SetTimeTicks(VideoFrameMetadata::REFERENCE_TIME, - reference_time); + if (!client_) + return; // Capture is stopped. - client_->OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); - } + frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, + params_.requested_format.frame_rate); + frame->metadata()->SetTimeTicks(VideoFrameMetadata::CAPTURE_BEGIN_TIME, + capture_begin_time); + frame->metadata()->SetTimeTicks(VideoFrameMetadata::CAPTURE_END_TIME, + base::TimeTicks::Now()); + frame->metadata()->SetTimeDelta(VideoFrameMetadata::FRAME_DURATION, + estimated_frame_duration); + frame->metadata()->SetTimeTicks(VideoFrameMetadata::REFERENCE_TIME, + reference_time); + + DCHECK(frame->IsMappable()); + media::VideoCaptureFormat format(frame->coded_size(), + params_.requested_format.frame_rate, + frame->format(), media::PIXEL_STORAGE_CPU); + client_->OnIncomingCapturedBufferExt( + std::move(buffer), format, reference_time, frame->timestamp(), + frame->visible_rect(), *frame->metadata()); } void ThreadSafeCaptureOracle::OnConsumerReportingUtilization(
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc index c9bbae9..21563c0 100644 --- a/media/capture/video/fake_video_capture_device_unittest.cc +++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -101,11 +101,13 @@ base::TimeDelta timestamp) override { frame_cb_.Run(format); } - void OnIncomingCapturedVideoFrame( + void OnIncomingCapturedBufferExt( std::unique_ptr<Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override { - VideoCaptureFormat format(frame->natural_size(), 30.0, - PIXEL_FORMAT_I420); + const VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const VideoFrameMetadata& additional_metadata) override { frame_cb_.Run(format); } std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
diff --git a/media/capture/video/linux/v4l2_capture_delegate_unittest.cc b/media/capture/video/linux/v4l2_capture_delegate_unittest.cc index ad67ae5..3febf4456 100644 --- a/media/capture/video/linux/v4l2_capture_delegate_unittest.cc +++ b/media/capture/video/linux/v4l2_capture_delegate_unittest.cc
@@ -170,9 +170,13 @@ DoOnIncomingCapturedBuffer(); } MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void)); - void OnIncomingCapturedVideoFrame( + void OnIncomingCapturedBufferExt( std::unique_ptr<Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override { + const VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const VideoFrameMetadata& additional_metadata) override { DoOnIncomingCapturedVideoFrame(); } MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
diff --git a/media/capture/video/video_capture_device.h b/media/capture/video/video_capture_device.h index e561267..0ac1c3b 100644 --- a/media/capture/video/video_capture_device.h +++ b/media/capture/video/video_capture_device.h
@@ -147,28 +147,30 @@ VideoPixelStorage storage, int frame_feedback_id) = 0; - // Captured new video data, held in |frame| or |buffer|, respectively for - // OnIncomingCapturedVideoFrame() and OnIncomingCapturedBuffer(). - // - // In both cases, as the frame is backed by a reservation returned by - // ReserveOutputBuffer(), delivery is guaranteed and will require no - // additional copies in the browser process. + // Provides VCD::Client with a populated Buffer containing the content of + // the next video frame. The |buffer| must originate from an earlier call to + // ReserveOutputBuffer(). // See OnIncomingCapturedData for details of |reference_time| and // |timestamp|. - // TODO(chfremer): Consider removing one of the two in order to simplify the - // interface. virtual void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer, const VideoCaptureFormat& format, base::TimeTicks reference_time, base::TimeDelta timestamp) = 0; - virtual void OnIncomingCapturedVideoFrame( + + // Extended version of OnIncomingCapturedBuffer() allowing clients to + // pass a custom |visible_rect| and |additional_metadata|. + virtual void OnIncomingCapturedBufferExt( std::unique_ptr<Buffer> buffer, - scoped_refptr<VideoFrame> frame) = 0; + const VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const VideoFrameMetadata& additional_metadata) = 0; // Attempts to reserve the same Buffer provided in the last call to one of - // the OnIncomingCapturedXXX() methods. This will fail if the content of the - // Buffer has not been preserved, or if the |dimensions|, |format|, or - // |storage| disagree with how it was reserved via ReserveOutputBuffer(). + // the OnIncomingCapturedBufferXXX() methods. This will fail if the content + // of the Buffer has not been preserved, or if the |dimensions|, |format|, + // or |storage| disagree with how it was reserved via ReserveOutputBuffer(). // When this operation fails, nullptr will be returned. virtual std::unique_ptr<Buffer> ResurrectLastOutputBuffer( const gfx::Size& dimensions,
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc index 3321633..c7a92be 100644 --- a/media/capture/video/video_capture_device_client.cc +++ b/media/capture/video/video_capture_device_client.cc
@@ -21,6 +21,7 @@ #include "media/capture/video/video_capture_jpeg_decoder.h" #include "media/capture/video/video_frame_receiver.h" #include "media/capture/video_capture_types.h" +#include "mojo/public/cpp/system/platform_handle.h" #include "third_party/libyuv/include/libyuv.h" using media::VideoCaptureFormat; @@ -295,32 +296,46 @@ const VideoCaptureFormat& format, base::TimeTicks reference_time, base::TimeDelta timestamp) { - DCHECK(IsFormatSupported(format.pixel_format)); - DCHECK_EQ(media::PIXEL_STORAGE_CPU, format.pixel_storage); + OnIncomingCapturedBufferExt(std::move(buffer), format, reference_time, + timestamp, gfx::Rect(format.frame_size), + VideoFrameMetadata()); +} - scoped_refptr<VideoFrame> frame; - if (buffer->IsBackedByVideoFrame()) { - frame = buffer->GetVideoFrame(); - frame->set_timestamp(timestamp); - } else { - frame = VideoFrame::WrapExternalSharedMemory( - format.pixel_format, format.frame_size, gfx::Rect(format.frame_size), - format.frame_size, reinterpret_cast<uint8_t*>(buffer->data()), - VideoFrame::AllocationSize(format.pixel_format, format.frame_size), - base::SharedMemory::NULLHandle(), 0u, timestamp); - } - if (!frame) - return; +void VideoCaptureDeviceClient::OnIncomingCapturedBufferExt( + std::unique_ptr<Buffer> buffer, + const VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const VideoFrameMetadata& additional_metadata) { + const int buffer_id = buffer->id(); + + auto buffer_mojo_handle = buffer_pool_->GetHandleForTransit(buffer_id); + base::SharedMemoryHandle memory_handle; + size_t memory_size = 0; + bool read_only_flag = false; + const MojoResult unwrap_result_code = mojo::UnwrapSharedMemoryHandle( + std::move(buffer_mojo_handle), &memory_handle, &memory_size, + &read_only_flag); + DCHECK_EQ(MOJO_RESULT_OK, unwrap_result_code); + + scoped_refptr<media::VideoFrame> frame = + media::VideoFrame::WrapExternalSharedMemory( + format.pixel_format, // format + format.frame_size, // coded_size + visible_rect, // visible_rect + format.frame_size, // natural_size + static_cast<uint8_t*>(buffer->data()), // data + buffer->mapped_size(), // data_size + memory_handle, // handle + 0, // shared_memory_offset + timestamp); // timestamp + frame->metadata()->MergeMetadataFrom(&additional_metadata); frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, format.frame_rate); frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, reference_time); - OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); -} -void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( - std::unique_ptr<Buffer> buffer, - scoped_refptr<VideoFrame> frame) { receiver_->OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); }
diff --git a/media/capture/video/video_capture_device_client.h b/media/capture/video/video_capture_device_client.h index 0c85539..adac1bc1 100644 --- a/media/capture/video/video_capture_device_client.h +++ b/media/capture/video/video_capture_device_client.h
@@ -65,9 +65,13 @@ const VideoCaptureFormat& format, base::TimeTicks reference_time, base::TimeDelta timestamp) override; - void OnIncomingCapturedVideoFrame( + void OnIncomingCapturedBufferExt( std::unique_ptr<Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override; + const VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const VideoFrameMetadata& additional_metadata) override; std::unique_ptr<Buffer> ResurrectLastOutputBuffer( const gfx::Size& dimensions, media::VideoPixelFormat format,
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc index b3289d2..ca6a4a1 100644 --- a/media/capture/video/video_capture_device_unittest.cc +++ b/media/capture/video/video_capture_device_unittest.cc
@@ -135,8 +135,13 @@ base::TimeDelta timestamp) override { DoOnIncomingCapturedBuffer(); } - void OnIncomingCapturedVideoFrame(std::unique_ptr<Buffer> buffer, - scoped_refptr<VideoFrame> frame) override { + void OnIncomingCapturedBufferExt( + std::unique_ptr<Buffer> buffer, + const VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp, + gfx::Rect visible_rect, + const VideoFrameMetadata& additional_metadata) override { DoOnIncomingCapturedVideoFrame(); } std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
diff --git a/net/BUILD.gn b/net/BUILD.gn index f87cacb..9a22c35 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1104,6 +1104,7 @@ generate_jni("net_test_jni_headers") { sources = [ "android/javatests/src/org/chromium/net/AndroidKeyStoreTestUtil.java", + "android/javatests/src/org/chromium/net/AndroidNetworkLibraryTestUtil.java", "test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java", "test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java", ]
diff --git a/net/android/BUILD.gn b/net/android/BUILD.gn index 74142bd..1ff8b2c 100644 --- a/net/android/BUILD.gn +++ b/net/android/BUILD.gn
@@ -112,6 +112,7 @@ testonly = true java_files = [ "javatests/src/org/chromium/net/AndroidKeyStoreTestUtil.java", + "javatests/src/org/chromium/net/AndroidNetworkLibraryTestUtil.java", "javatests/src/org/chromium/net/AndroidProxySelectorTest.java", "javatests/src/org/chromium/net/NetErrorsTest.java", "javatests/src/org/chromium/net/NetworkChangeNotifierTest.java",
diff --git a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java index 1656e2c..d33321c 100644 --- a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java +++ b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
@@ -17,6 +17,7 @@ import android.net.wifi.WifiManager; import android.os.Build; import android.security.KeyChain; +import android.security.NetworkSecurityPolicy; import android.telephony.TelephonyManager; import android.util.Log; @@ -243,4 +244,21 @@ } return ""; } + + /** + * Returns true if cleartext traffic to |host| is allowed by the current app. Always true on L + * and older. + */ + @TargetApi(Build.VERSION_CODES.N) + @CalledByNative + private static boolean isCleartextPermitted(String host) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + NetworkSecurityPolicy policy = NetworkSecurityPolicy.getInstance(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return policy.isCleartextTrafficPermitted(host); + } + return policy.isCleartextTrafficPermitted(); + } + return true; + } }
diff --git a/net/android/javatests/src/org/chromium/net/AndroidNetworkLibraryTestUtil.java b/net/android/javatests/src/org/chromium/net/AndroidNetworkLibraryTestUtil.java new file mode 100644 index 0000000..21f39b8 --- /dev/null +++ b/net/android/javatests/src/org/chromium/net/AndroidNetworkLibraryTestUtil.java
@@ -0,0 +1,32 @@ +// 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. + +package org.chromium.net; + +import android.annotation.TargetApi; +import android.os.Build; +import android.security.NetworkSecurityPolicy; + +import org.chromium.base.annotations.CalledByNative; + +import java.lang.reflect.Method; + +/** + * Utility functions for testing features implemented in AndroidNetworkLibrary. + */ +public class AndroidNetworkLibraryTestUtil { + /** + * Helper for tests that simulates an app disallowing cleartext traffic entirely on M and newer. + */ + @TargetApi(Build.VERSION_CODES.M) + @CalledByNative + private static void setUpSecurityPolicyForTesting(boolean cleartextPermitted) throws Exception { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Method setCleartextTrafficPermitted = NetworkSecurityPolicy.class.getDeclaredMethod( + "setCleartextTrafficPermitted", boolean.class); + setCleartextTrafficPermitted.invoke( + NetworkSecurityPolicy.getInstance(), cleartextPermitted); + } + } +} \ No newline at end of file
diff --git a/net/android/network_library.cc b/net/android/network_library.cc index 6612381..34a9194 100644 --- a/net/android/network_library.cc +++ b/net/android/network_library.cc
@@ -79,6 +79,12 @@ return ret; } +bool IsCleartextPermitted(const std::string& host) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> host_string = ConvertUTF8ToJavaString(env, host); + return Java_AndroidNetworkLibrary_isCleartextPermitted(env, host_string); +} + bool HaveOnlyLoopbackAddresses() { JNIEnv* env = AttachCurrentThread(); return Java_AndroidNetworkLibrary_haveOnlyLoopbackAddresses(env);
diff --git a/net/android/network_library.h b/net/android/network_library.h index 548d43a..60d9abd 100644 --- a/net/android/network_library.h +++ b/net/android/network_library.h
@@ -45,6 +45,10 @@ const uint8_t* private_key, size_t private_len); +// Returns true if cleartext traffic to |host| is allowed by the app. Always +// true on L and older. +bool IsCleartextPermitted(const std::string& host); + // Returns true if it can determine that only loopback addresses are configured. // i.e. if only 127.0.0.1 and ::1 are routable. // Also returns false if it cannot determine this.
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index 0a880f8..27e8005 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h
@@ -116,6 +116,10 @@ // heuristics that point to the possiblility of a cross-site scripting attack. NET_ERROR(BLOCKED_BY_XSS_AUDITOR, -28) +// The request was blocked by system policy disallowing some or all cleartext +// requests. Used for NetworkSecurityPolicy on Android. +NET_ERROR(CLEARTEXT_NOT_PERMITTED, -29) + // A connection was closed (corresponding to a TCP FIN). NET_ERROR(CONNECTION_CLOSED, -100)
diff --git a/net/quic/core/crypto/curve25519_key_exchange.cc b/net/quic/core/crypto/curve25519_key_exchange.cc index 7bb7e30..d2e0082 100644 --- a/net/quic/core/crypto/curve25519_key_exchange.cc +++ b/net/quic/core/crypto/curve25519_key_exchange.cc
@@ -4,9 +4,11 @@ #include "net/quic/core/crypto/curve25519_key_exchange.h" +#include <cstdint> + #include "base/logging.h" -#include "crypto/curve25519.h" #include "net/quic/core/crypto/quic_random.h" +#include "third_party/boringssl/src/include/openssl/curve25519.h" using base::StringPiece; using std::string; @@ -20,35 +22,28 @@ // static Curve25519KeyExchange* Curve25519KeyExchange::New(StringPiece private_key) { Curve25519KeyExchange* ka; - // We don't want to #include the NaCl headers in the public header file, so - // we use literals for the sizes of private_key_ and public_key_. Here we - // assert that those values are equal to the values from the NaCl header. - static_assert(sizeof(ka->private_key_) == crypto::curve25519::kScalarBytes, + // We don't want to #include the BoringSSL headers in the public header file, + // so we use literals for the sizes of private_key_ and public_key_. Here we + // assert that those values are equal to the values from the BoringSSL + static_assert(sizeof(ka->private_key_) == X25519_PRIVATE_KEY_LEN, "header out of sync"); - static_assert(sizeof(ka->public_key_) == crypto::curve25519::kBytes, + static_assert(sizeof(ka->public_key_) == X25519_PUBLIC_VALUE_LEN, "header out of sync"); - if (private_key.size() != crypto::curve25519::kScalarBytes) { + if (private_key.size() != X25519_PRIVATE_KEY_LEN) { return nullptr; } ka = new Curve25519KeyExchange(); - memcpy(ka->private_key_, private_key.data(), - crypto::curve25519::kScalarBytes); - crypto::curve25519::ScalarBaseMult(ka->private_key_, ka->public_key_); + memcpy(ka->private_key_, private_key.data(), X25519_PRIVATE_KEY_LEN); + X25519_public_from_private(ka->public_key_, ka->private_key_); return ka; } // static string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) { - uint8_t private_key[crypto::curve25519::kScalarBytes]; + uint8_t private_key[X25519_PRIVATE_KEY_LEN]; rand->RandBytes(private_key, sizeof(private_key)); - - // This makes |private_key| a valid scalar, as specified on - // http://cr.yp.to/ecdh.html - private_key[0] &= 248; - private_key[31] &= 127; - private_key[31] |= 64; return string(reinterpret_cast<char*>(private_key), sizeof(private_key)); } @@ -59,18 +54,17 @@ bool Curve25519KeyExchange::CalculateSharedKey(StringPiece peer_public_value, string* out_result) const { - if (peer_public_value.size() != crypto::curve25519::kBytes) { + if (peer_public_value.size() != X25519_PUBLIC_VALUE_LEN) { return false; } - uint8_t result[crypto::curve25519::kBytes]; - if (!crypto::curve25519::ScalarMult( - private_key_, - reinterpret_cast<const uint8_t*>(peer_public_value.data()), result)) { + uint8_t result[X25519_PUBLIC_VALUE_LEN]; + if (!X25519(result, private_key_, + reinterpret_cast<const uint8_t*>(peer_public_value.data()))) { return false; } + out_result->assign(reinterpret_cast<char*>(result), sizeof(result)); - return true; }
diff --git a/net/quic/core/crypto/curve25519_key_exchange.h b/net/quic/core/crypto/curve25519_key_exchange.h index ab79294..0515e8d7 100644 --- a/net/quic/core/crypto/curve25519_key_exchange.h +++ b/net/quic/core/crypto/curve25519_key_exchange.h
@@ -5,8 +5,7 @@ #ifndef NET_QUIC_CORE_CRYPTO_CURVE25519_KEY_EXCHANGE_H_ #define NET_QUIC_CORE_CRYPTO_CURVE25519_KEY_EXCHANGE_H_ -#include <stdint.h> - +#include <cstdint> #include <string> #include "base/compiler_specific.h"
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc index 42bcc899..9388ceb 100644 --- a/net/url_request/url_request_context.cc +++ b/net/url_request/url_request_context.cc
@@ -42,7 +42,8 @@ sdch_manager_(nullptr), network_quality_estimator_(nullptr), url_requests_(new std::set<const URLRequest*>), - enable_brotli_(false) { + enable_brotli_(false), + check_cleartext_permitted_(false) { base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( this, "URLRequestContext", base::ThreadTaskRunnerHandle::Get()); } @@ -76,6 +77,7 @@ set_http_user_agent_settings(other->http_user_agent_settings_); set_network_quality_estimator(other->network_quality_estimator_); set_enable_brotli(other->enable_brotli_); + set_check_cleartext_permitted(other->check_cleartext_permitted_); } const HttpNetworkSession::Params* URLRequestContext::GetNetworkSessionParams(
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h index 24b03bb..8aeb1e01 100644 --- a/net/url_request/url_request_context.h +++ b/net/url_request/url_request_context.h
@@ -238,6 +238,15 @@ bool enable_brotli() const { return enable_brotli_; } + // Sets the |check_cleartext_permitted| flag, which controls whether to check + // system policy before allowing a cleartext http or ws request. + void set_check_cleartext_permitted(bool check_cleartext_permitted) { + check_cleartext_permitted_ = check_cleartext_permitted; + } + + // Returns current value of the |check_cleartext_permitted| flag. + bool check_cleartext_permitted() const { return check_cleartext_permitted_; } + // Sets a name for this URLRequestContext. Currently the name is used in // MemoryDumpProvier to annotate memory usage. The name does not need to be // unique. @@ -285,6 +294,9 @@ // Enables Brotli Content-Encoding support. bool enable_brotli_; + // Enables checking system policy before allowing a cleartext http or ws + // request. Only used on Android. + bool check_cleartext_permitted_; // An optional name which can be set to describe this URLRequestContext. // Used in MemoryDumpProvier to annotate memory usage. The name does not need
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 68e708f..6b5300c 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -68,6 +68,10 @@ #include "net/websockets/websocket_handshake_stream_base.h" #include "url/origin.h" +#if defined(OS_ANDROID) +#include "net/android/network_library.h" +#endif + static const char kAvailDictionaryHeader[] = "Avail-Dictionary"; namespace { @@ -169,27 +173,6 @@ EPHEMERALITY_MAX); } -net::URLRequestRedirectJob* MaybeInternallyRedirect( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) { - const GURL& url = request->url(); - if (url.SchemeIsCryptographic()) - return nullptr; - - net::TransportSecurityState* hsts = - request->context()->transport_security_state(); - if (!hsts || !hsts->ShouldUpgradeToSSL(url.host())) - return nullptr; - - GURL::Replacements replacements; - replacements.SetSchemeStr(url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme - : url::kWssScheme); - return new net::URLRequestRedirectJob( - request, network_delegate, url.ReplaceComponents(replacements), - // Use status code 307 to preserve the method, so POST requests work. - net::URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS"); -} - } // namespace namespace net { @@ -208,10 +191,34 @@ request, network_delegate, ERR_INVALID_ARGUMENT); } - URLRequestRedirectJob* redirect = - MaybeInternallyRedirect(request, network_delegate); - if (redirect) - return redirect; + const GURL& url = request->url(); + + // Check for reasons not to return a URLRequestHttpJob. These don't apply to + // https and wss requests. + if (!url.SchemeIsCryptographic()) { + // Check for HSTS upgrade. + TransportSecurityState* hsts = + request->context()->transport_security_state(); + if (hsts && hsts->ShouldUpgradeToSSL(url.host())) { + GURL::Replacements replacements; + replacements.SetSchemeStr( + url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme : url::kWssScheme); + return new URLRequestRedirectJob( + request, network_delegate, url.ReplaceComponents(replacements), + // Use status code 307 to preserve the method, so POST requests work. + URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS"); + } + +#if defined(OS_ANDROID) + // Check whether the app allows cleartext traffic to this host, and return + // ERR_BLOCKED_BY_CLIENT if not. + if (request->context()->check_cleartext_permitted() && + !android::IsCleartextPermitted(url.host())) { + return new URLRequestErrorJob(request, network_delegate, + ERR_CLEARTEXT_NOT_PERMITTED); + } +#endif + } return new URLRequestHttpJob(request, network_delegate,
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index c4490553..dbaea28 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc
@@ -40,6 +40,12 @@ #include "url/gurl.h" #include "url/url_constants.h" +#if defined(OS_ANDROID) +#include "base/android/build_info.h" +#include "base/android/jni_android.h" +#include "jni/AndroidNetworkLibraryTestUtil_jni.h" +#endif + using net::test::IsError; using net::test::IsOk; @@ -938,6 +944,46 @@ request->GetTotalReceivedBytes()); } +#if defined(OS_ANDROID) +TEST_F(URLRequestHttpJobTest, AndroidCleartextPermittedTest) { + context_.set_check_cleartext_permitted(true); + + struct TestCase { + const char* url; + bool cleartext_permitted; + bool should_block; + } cases[] = { + {"http://blocked.test/", true, false}, + {"https://blocked.test/", true, false}, + {"http://blocked.test/", false, true}, + {"https://blocked.test/", false, false}, + }; + + for (const TestCase& test : cases) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_AndroidNetworkLibraryTestUtil_setUpSecurityPolicyForTesting( + env, test.cleartext_permitted); + + TestDelegate delegate; + std::unique_ptr<URLRequest> request = + context_.CreateRequest(GURL(test.url), DEFAULT_PRIORITY, &delegate); + request->Start(); + base::RunLoop().Run(); + + int sdk_int = base::android::BuildInfo::GetInstance()->sdk_int(); + bool expect_blocked = (sdk_int >= base::android::SDK_VERSION_MARSHMALLOW && + test.should_block); + if (expect_blocked) { + EXPECT_THAT(delegate.request_status(), + IsError(ERR_CLEARTEXT_NOT_PERMITTED)); + } else { + // Should fail since there's no test server running + EXPECT_THAT(delegate.request_status(), IsError(ERR_FAILED)); + } + } +} +#endif + // This base class just serves to set up some things before the TestURLRequest // constructor is called. class URLRequestHttpJobWebSocketTestBase : public ::testing::Test {
diff --git a/services/video_capture/test/fake_device_descriptor_unittest.cc b/services/video_capture/test/fake_device_descriptor_unittest.cc index a747e57b..cc455b8 100644 --- a/services/video_capture/test/fake_device_descriptor_unittest.cc +++ b/services/video_capture/test/fake_device_descriptor_unittest.cc
@@ -19,7 +19,7 @@ // Tests that when requesting a second proxy for a device without closing the // first one, the service revokes access to the first one by closing the // connection. -TEST_F(FakeDeviceDescriptorTest, AccessIsRevokedOnSecondAccess) { +TEST_F(FakeDeviceDescriptorTest, DISABLED_AccessIsRevokedOnSecondAccess) { mojom::DevicePtr device_proxy_1; bool device_access_1_revoked = false; MockCreateDeviceProxyCallback create_device_proxy_callback_1; @@ -55,7 +55,7 @@ } // Tests that a second proxy requested for a device can be used successfully. -TEST_F(FakeDeviceDescriptorTest, CanUseSecondRequestedProxy) { +TEST_F(FakeDeviceDescriptorTest, DISABLED_CanUseSecondRequestedProxy) { mojom::DevicePtr device_proxy_1; factory_->CreateDevice( fake_device_descriptor_.device_id, mojo::GetProxy(&device_proxy_1),
diff --git a/services/video_capture/test/fake_device_unittest.cc b/services/video_capture/test/fake_device_unittest.cc index b0ce65b28..eac7fa0 100644 --- a/services/video_capture/test/fake_device_unittest.cc +++ b/services/video_capture/test/fake_device_unittest.cc
@@ -30,7 +30,7 @@ namespace video_capture { -TEST_F(FakeDeviceTest, FrameCallbacksArrive) { +TEST_F(FakeDeviceTest, DISABLED_FrameCallbacksArrive) { base::RunLoop wait_loop; const int kNumFramesToWaitFor = 3; int num_frames_arrived = 0; @@ -51,7 +51,7 @@ // Tests that frames received from a fake capture device match the requested // format and have increasing timestamps. -TEST_F(FakeDeviceTest, ReceiveFramesFromFakeCaptureDevice) { +TEST_F(FakeDeviceTest, DISABLED_ReceiveFramesFromFakeCaptureDevice) { base::RunLoop wait_loop; mojom::ReceiverPtr receiver_proxy; constexpr int num_frames_to_receive = 2;
diff --git a/services/video_capture/test/mock_device_unittest.cc b/services/video_capture/test/mock_device_unittest.cc index f3035fe..40f36b4 100644 --- a/services/video_capture/test/mock_device_unittest.cc +++ b/services/video_capture/test/mock_device_unittest.cc
@@ -12,7 +12,7 @@ // Tests that the service stops the capture device when the client closes the // connection to the device proxy. -TEST_F(MockDeviceTest, DeviceIsStoppedWhenDiscardingDeviceProxy) { +TEST_F(MockDeviceTest, DISABLED_DeviceIsStoppedWhenDiscardingDeviceProxy) { base::RunLoop wait_loop; // The mock device must hold on to the device client that is passed to it. @@ -34,7 +34,7 @@ // Tests that the service stops the capture device when the client closes the // connection to the client proxy it provided to the service. -TEST_F(MockDeviceTest, DeviceIsStoppedWhenDiscardingDeviceClient) { +TEST_F(MockDeviceTest, DISABLED_DeviceIsStoppedWhenDiscardingDeviceClient) { base::RunLoop wait_loop; // The mock device must hold on to the device client that is passed to it.
diff --git a/services/video_capture/test/service_unittest.cc b/services/video_capture/test/service_unittest.cc index c79f964..dff08e3 100644 --- a/services/video_capture/test/service_unittest.cc +++ b/services/video_capture/test/service_unittest.cc
@@ -21,7 +21,7 @@ // Tests that an answer arrives from the service when calling // EnumerateDeviceDescriptors(). -TEST_F(ServiceTest, EnumerateDeviceDescriptorsCallbackArrives) { +TEST_F(ServiceTest, DISABLED_EnumerateDeviceDescriptorsCallbackArrives) { base::RunLoop wait_loop; EXPECT_CALL(descriptor_receiver_, OnEnumerateDeviceDescriptorsCallback(_)) .Times(Exactly(1)) @@ -33,7 +33,7 @@ wait_loop.Run(); } -TEST_F(ServiceTest, FakeDeviceFactoryEnumeratesOneDevice) { +TEST_F(ServiceTest, DISABLED_FakeDeviceFactoryEnumeratesOneDevice) { base::RunLoop wait_loop; size_t num_devices_enumerated = 0; EXPECT_CALL(descriptor_receiver_, OnEnumerateDeviceDescriptorsCallback(_)) @@ -53,7 +53,7 @@ // Tests that VideoCaptureDeviceFactory::CreateDeviceProxy() returns an error // code when trying to create a device for an invalid descriptor. -TEST_F(ServiceTest, ErrorCodeOnCreateDeviceForInvalidDescriptor) { +TEST_F(ServiceTest, DISABLED_ErrorCodeOnCreateDeviceForInvalidDescriptor) { const std::string invalid_device_id = "invalid"; base::RunLoop wait_loop; mojom::DevicePtr fake_device_proxy;
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 2d3b5c1..c9ab944 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -5648,6 +5648,12 @@ "can_use_on_swarming_builders": true }, "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ] },
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index fc67d68..68e8a99 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1212,6 +1212,14 @@ crbug.com/467477 fast/multicol/vertical-rl/nested-columns.html [ Failure ] +crbug.com/674225 [ Mac ] fast/replaced/input-radio-height-inside-auto-container.html [ Failure ] +crbug.com/669867 [ Mac Win ] fast/replaced/table-percent-height-text-controls.html [ NeedsRebaseline ] +crbug.com/669867 [ Mac Win ] fast/replaced/table-percent-height.html [ NeedsRebaseline ] +crbug.com/669867 [ Mac Win ] fast/table/003.html [ NeedsRebaseline ] +crbug.com/669867 [ Mac Win ] fast/table/split-table-section-before-anonymous-block-2.html [ NeedsRebaseline ] +crbug.com/669867 [ Mac Win ] fast/table/split-table-section-before-anonymous-block-4.html [ NeedsRebaseline ] +crbug.com/669867 [ Mac Win ] tables/mozilla/bugs/bug30692.html [ NeedsRebaseline ] + crbug.com/400841 media/video-canvas-draw.html [ Failure ] crbug.com/400829 media/video-object-fit.html [ Failure ] crbug.com/400829 virtual/stable/media/stable/video-object-fit-stable.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/input-radio-height-inside-auto-container-expected.html b/third_party/WebKit/LayoutTests/fast/replaced/input-radio-height-inside-auto-container-expected.html new file mode 100644 index 0000000..f3d79bc --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/replaced/input-radio-height-inside-auto-container-expected.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<p> crbug.com/669867: Inputs and radio boxes get a height of 0 when their container's height is treated as auto. There should be nothing below on Linux and Win. The theme on Mac gives them a full height.</p>
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/input-radio-height-inside-auto-container.html b/third_party/WebKit/LayoutTests/fast/replaced/input-radio-height-inside-auto-container.html new file mode 100644 index 0000000..9bb8784 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/replaced/input-radio-height-inside-auto-container.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<p> crbug.com/669867: Inputs and radio boxes get a height of 0 when their container's height is treated as auto. There should be nothing below on Linux and Win. The theme on Mac gives them a full height.</p> +<div><input type="checkbox" style="height: 100%;"><div> +<div style="display:table-cell;"><input type="checkbox" style="height: 100%;"><div> +<table><tr><td><input type="checkbox" style="height: 100%;"></td></tr></table> +<div><input type="radio" style="height: 100%;"><div> +<div style="display:table-cell;"><input type="radio" style="height: 100%;"><div> +<table><tr><td><input type="radio" style="height: 100%;"></td></tr></table>
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height-text-controls.html b/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height-text-controls.html index ac48549..ea744a7 100644 --- a/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height-text-controls.html +++ b/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height-text-controls.html
@@ -30,11 +30,7 @@ function getFullHeight(id) { var element = document.getElementById(id); - var h = parseFloat(getComputedStyleForElement(element, 'border-top-width')); - h += parseFloat(getComputedStyleForElement(element, 'padding-top')); - h += parseFloat(getComputedStyleForElement(element, 'height')); - h += parseFloat(getComputedStyleForElement(element, 'padding-bottom')); - h += parseFloat(getComputedStyleForElement(element, 'border-bottom-width')); + var h = parseFloat(getComputedStyleForElement(element, 'height')); return h + 'px'; } @@ -47,39 +43,24 @@ return parseFloat(str); } -function is75PercentOf(expression75, expression100) -{ - var str75 = eval(expression75); - var str100 = eval(expression100); - var num75 = parsePixelValue(str75); - var num100 = parsePixelValue(str100); - if (num75 < 0 || num100 < 0) - return; - if (num75 == Math.floor(num100 * 75 / 100)) - testPassed(expression75 + " is 75% of " + expression100 + "."); - else - testFailed(expression75 + " [" + str75 + "] is not 75% of " + expression100 + " [" + str100 + "]."); -} - function test() { description("This test checks that text controls with percentage heights within table cells have the correct height." + - "Text controls are in a different test than other replaced elements because their metrics are platform-specific."); + "Text controls are in a different test than other replaced elements because their metrics are platform-specific." + + "The reason a 75% control is the same height as a 100% control is because a replaced element that depends on the" + + "height of its parent cell is treated as auto. So by itself it will set the height of the row. See https://drafts.csswg.org/css-tables-3/#row-layout"); shouldBe("getWidth('input-password-75')", "getWidth('input-password-100')"); shouldBeTrue("getFullHeight('input-password-75') != '0px'"); - // Note: This behavior doesn't match to IE 8, Firefox 3.5 and Opera 10. - is75PercentOf("getFullHeight('input-password-75')", "getFullHeight('input-password-100')"); + shouldBe("getFullHeight('input-password-75')", "getFullHeight('input-password-100')"); shouldBe("getWidth('input-text-75')", "getWidth('input-text-100')"); shouldBeTrue("getFullHeight('input-text-75') != '0px'"); - // Note: This behavior doesn't match to IE 8, Firefox 3.5 and Opera 10. - is75PercentOf("getFullHeight('input-text-75')", "getFullHeight('input-text-100')"); + shouldBe("getFullHeight('input-text-75')", "getFullHeight('input-text-100')"); shouldBe("getWidth('textarea-75')", "getWidth('textarea-100')"); shouldBeTrue("getFullHeight('textarea-75') != '0px'"); - // Note: This behavior doesn't match to IE 8, Firefox 3.5 and Opera 10. - is75PercentOf("getFullHeight('textarea-75')", "getFullHeight('textarea-100')"); + shouldBe("getFullHeight('textarea-75')", "getFullHeight('textarea-100')"); isSuccessfullyParsed();
diff --git a/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height.html b/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height.html index fce47a1..234104c 100644 --- a/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height.html +++ b/third_party/WebKit/LayoutTests/fast/replaced/table-percent-height.html
@@ -41,21 +41,6 @@ return parseFloat(str); } -function is75PercentOf(expression75, expression100) -{ - var str75 = eval(expression75); - var str100 = eval(expression100); - var num75 = parsePixelValue(str75); - var num100 = parsePixelValue(str100); - if (num75 < 0 || num100 < 0) - return; - var expectedValue = num100 * 75 / 100; - if (num75 == expectedValue) - testPassed(expression75 + " is 75% of " + expression100 + "."); - else - testFailed(expression75 + " [" + str75 + "] is not 75% of " + expression100 + " [" + str100 + "]."); -} - function test() { description("This test checks that replaced elements with percentage heights within table cells have the correct height.<br>Note, some of the button height tests fail on the Windows ports. See bug #34071."); @@ -94,14 +79,12 @@ shouldBe("getHeight('input-button-75')", "getHeight('input-button-100')"); shouldBe("getWidth('input-checkbox-75')", "getWidth('input-checkbox-100')"); - shouldBeTrue("getHeight('input-checkbox-75') != '0px'"); - // Note: This behavior doesn't match to Firefox 3.5 and Opera 10. - is75PercentOf("getHeight('input-checkbox-75')", "getHeight('input-checkbox-100')"); + shouldBeTrue("getHeight('input-checkbox-75') == '0px'"); + shouldBe("getHeight('input-checkbox-75')", "getHeight('input-checkbox-100')"); shouldBe("getWidth('input-file-75')", "getWidth('input-file-100')"); shouldBeTrue("getHeight('input-file-75') != '0px'"); - // Note: This behavior doesn't match to Firefox 3.5 and Opera 10. - is75PercentOf("getHeight('input-file-75')", "getHeight('input-file-100')"); + shouldBe("getHeight('input-file-75')", "getHeight('input-file-100')"); // Note: This behavior doesn't match to Firefox 3.5 and Opera 10. shouldBe("getWidth('input-image-75')", "'75px'"); @@ -110,9 +93,8 @@ shouldBe("getHeight('input-image-100')", "'100px'"); shouldBe("getWidth('input-radio-75')", "getWidth('input-radio-100')"); - shouldBeTrue("getHeight('input-radio-75') != '0px'"); - // Note: This behavior doesn't match to Firefox 3.5 and Opera 10. - is75PercentOf("getHeight('input-radio-75')", "getHeight('input-radio-100')"); + shouldBeTrue("getHeight('input-radio-75') == '0px'"); + shouldBe("getHeight('input-radio-75')", "getHeight('input-radio-100')"); shouldBe("getWidth('input-reset-75')", "getWidth('input-reset-100')"); shouldBeTrue("getHeight('input-reset-75') != '0px'");
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-2-expected.txt b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-2-expected.txt new file mode 100644 index 0000000..9a4644a --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-2-expected.txt
@@ -0,0 +1,4 @@ +Text +crbug.com/669687: Percent height border-box replaced content in a cell gets the correct height. + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-2.html b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-2.html new file mode 100644 index 0000000..ff7c7386 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-2.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<style> +.cell { display:table-cell; } +.div { height: 100%; display: inline-block; box-sizing: border-box; border: 2px solid black; padding: 2px; font: 20px Ahem;} +</style> +<div class="cell"> + <div class="div" data-expected-height=28>Text</div> +</div> +<script src="../../resources/check-layout.js"></script> +<p> crbug.com/669687: Percent height border-box replaced content in a cell gets the correct height. </p> +<div id="output"></div> +<script> +checkLayout('.div', output); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-3-expected.txt b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-3-expected.txt new file mode 100644 index 0000000..c08317d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-3-expected.txt
@@ -0,0 +1,4 @@ +Text +crbug.com/669687: Percent height border-box content in a cell gets the correct height. + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-3.html b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-3.html new file mode 100644 index 0000000..1133ec5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-3.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<style> +.cell { display:table-cell; } +.div { height: 100%; box-sizing: border-box; border: 2px solid black; padding: 2px; font: 20px Ahem;} +</style> +<div class="cell"> + <div class="div" data-expected-height=28>Text</div> +</div> +<script src="../../resources/check-layout.js"></script> +<p> crbug.com/669687: Percent height border-box content in a cell gets the correct height. </p> +<div id="output"></div> +<script> +checkLayout('.div', output); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-expected.html b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-expected.html new file mode 100644 index 0000000..4283e96 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell-expected.html
@@ -0,0 +1,6 @@ +<!DOCTYPE html> +<style> +.button { font: 20px Ahem;} +</style> +<button type="button" class="button">Text</button> +<p> crbug.com/669687: Percent height border-box replaced content in a cell gets the correct height. </p>
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell.html b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell.html new file mode 100644 index 0000000..9fc9fdb --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-border-box-content-in-cell.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<style> +.cell { display:table-cell; } +.button { height: 100%; font: 20px Ahem;} +</style> +<div class="cell"> + <button type="button" class="button" id="button">Text</button> +</div> +<p> crbug.com/669687: Percent height border-box replaced content in a cell gets the correct height. </p>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.png index 2881b6b..cc95422 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.txt index 88484df..1f5a7db8 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/003-expected.txt
@@ -19,8 +19,8 @@ LayoutTableSection {TBODY} at (2,2) size 96x96 LayoutTableRow {TR} at (0,2) size 96x92 LayoutTableCell {TD} at (2,46) size 92x4 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1] - LayoutTable {TABLE} at (0,152) size 191x120 [border: (2px outset #808080)] - LayoutTableSection {TBODY} at (2,2) size 187x116 + LayoutTable {TABLE} at (0,152) size 191x126 [border: (2px outset #808080)] + LayoutTableSection {TBODY} at (2,2) size 187x122 LayoutTableRow {TR} at (0,2) size 187x24 LayoutTableCell {TD} at (2,2) size 183x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1] LayoutText {#text} at (2,2) size 28x19 @@ -33,10 +33,10 @@ LayoutTableCell {TD} at (2,54) size 183x24 [border: (1px inset #808080)] [r=2 c=0 rs=1 cs=1] LayoutText {#text} at (2,2) size 35x19 text run at (2,2) width 35: "world" - LayoutTableRow {TR} at (0,80) size 187x34 - LayoutTableCell {TD} at (2,82) size 183x30 [border: (1px inset #808080)] [r=3 c=0 rs=1 cs=1] + LayoutTableRow {TR} at (0,80) size 187x40 + LayoutTableCell {TD} at (2,80) size 183x40 [border: (1px inset #808080)] [r=3 c=0 rs=1 cs=1] LayoutText {#text} at (0,0) size 0x0 - LayoutTable {TABLE} at (0,272) size 106x86 + LayoutTable {TABLE} at (0,278) size 106x86 LayoutTableSection {TBODY} at (0,0) size 106x86 LayoutTableRow {TR} at (0,2) size 106x82 LayoutTableCell {TD} at (2,2) size 102x82 [r=0 c=0 rs=1 cs=1] @@ -46,7 +46,7 @@ text run at (1,41) width 54: "nowrap. " text run at (55,41) width 41: "I really" text run at (1,61) width 43: "should." - LayoutTable {TABLE} at (0,358) size 106x86 + LayoutTable {TABLE} at (0,364) size 106x86 LayoutTableSection {TBODY} at (0,0) size 106x86 LayoutTableRow {TR} at (0,2) size 106x82 LayoutTableCell {TD} at (2,2) size 102x82 [r=0 c=0 rs=1 cs=1] @@ -57,7 +57,7 @@ text run at (0,40) width 54: "nowrap. " text run at (54,40) width 41: "I really" text run at (0,60) width 43: "should." - LayoutTable {TABLE} at (0,444) size 345x26 + LayoutTable {TABLE} at (0,450) size 345x26 LayoutTableSection {TBODY} at (0,0) size 345x26 LayoutTableRow {TR} at (0,2) size 345x22 LayoutTableCell {TD} at (2,2) size 341x22 [r=0 c=0 rs=1 cs=1] @@ -65,7 +65,7 @@ text run at (1,1) width 138: "I should have nowrap. " text run at (139,1) width 92: "I really should. " text run at (231,1) width 109: "Definitely. Should." - LayoutTable {TABLE} at (0,470) size 345x26 + LayoutTable {TABLE} at (0,476) size 345x26 LayoutTableSection {TBODY} at (0,0) size 345x26 LayoutTableRow {TR} at (0,2) size 345x22 LayoutTableCell {TD} at (2,2) size 341x22 [r=0 c=0 rs=1 cs=1] @@ -76,6 +76,6 @@ text run at (230,0) width 109: "Definitely. Should." layer at (57,14) size 730x16 LayoutBlockFlow {DIV} at (2,3) size 730x16 -layer at (14,246) size 179x26 clip at (15,247) size 177x24 - LayoutTextControl {TEXTAREA} at (2,2) size 179x26 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)] +layer at (14,244) size 179x36 clip at (15,245) size 177x34 + LayoutTextControl {TEXTAREA} at (2,2) size 179x36 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)] LayoutBlockFlow {DIV} at (3,3) size 175x16
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.png index 3305ee0d4..88c0ba4 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.txt index f248aa7..166a2281 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-2-expected.txt
@@ -14,5 +14,5 @@ LayoutTableRow {DIV} at (0,0) size 150x0 LayoutTableRow (anonymous) at (0,0) size 150x20 LayoutTableCell (anonymous) at (0,0) size 150x20 [r=2 c=0 rs=1 cs=1] - LayoutBlockFlow {DIV} at (0,5) size 75x10 [bgcolor=#0000FF] - LayoutBlockFlow {DIV} at (75,5) size 75x10 [bgcolor=#0000FF] + LayoutBlockFlow {DIV} at (0,15) size 75x0 [bgcolor=#0000FF] + LayoutBlockFlow {DIV} at (75,15) size 75x0 [bgcolor=#0000FF]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.png index 3305ee0d4..88c0ba4 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.txt index 22c31f0..4b293af 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/split-table-section-before-anonymous-block-4-expected.txt
@@ -10,8 +10,8 @@ LayoutTableSection {DIV} at (0,0) size 150x20 LayoutTableRow (anonymous) at (0,0) size 150x20 LayoutTableCell (anonymous) at (0,0) size 150x20 [r=0 c=0 rs=1 cs=1] - LayoutBlockFlow {DIV} at (0,5) size 75x10 [bgcolor=#0000FF] - LayoutBlockFlow {DIV} at (75,5) size 75x10 [bgcolor=#0000FF] + LayoutBlockFlow {DIV} at (0,15) size 75x0 [bgcolor=#0000FF] + LayoutBlockFlow {DIV} at (75,15) size 75x0 [bgcolor=#0000FF] LayoutTableRow {DIV} at (0,20) size 150x0 LayoutTableRow (anonymous) at (0,20) size 150x0 LayoutTableCell (anonymous) at (0,20) size 150x0 [r=2 c=0 rs=1 cs=1]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.png index 560562f..cff317d 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.txt index ca08f06c..71313fe 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla/bugs/bug30692-expected.txt
@@ -20,7 +20,7 @@ LayoutTable {TABLE} at (0,38) size 784x100 LayoutTableSection {TBODY} at (0,0) size 784x100 LayoutTableRow {TR} at (0,2) size 784x96 - LayoutTableCell {TD} at (2,13) size 780x73 [bgcolor=#FF0000] [r=0 c=0 rs=1 cs=1] + LayoutTableCell {TD} at (2,11) size 780x77 [bgcolor=#FF0000] [r=0 c=0 rs=1 cs=1] LayoutText {#text} at (0,0) size 0x0 LayoutBlockFlow {HR} at (0,146) size 784x2 [border: (1px inset #EEEEEE)] LayoutTable {TABLE} at (0,156) size 784x100 @@ -44,8 +44,8 @@ LayoutBlockFlow {P} at (1,1) size 622.39x80 [bgcolor=#FFFFE0] LayoutText {#text} at (0,0) size 210x19 text run at (0,0) width 210: "OK: the height of the P is 80 pixels" -layer at (11,100) size 622x71 clip at (12,101) size 620x69 - LayoutTextControl {TEXTAREA} at (1,1) size 622.39x71.19 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)] +layer at (11,98) size 622x75 clip at (12,99) size 620x73 + LayoutTextControl {TEXTAREA} at (1,1) size 622.39x75.19 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)] LayoutBlockFlow {DIV} at (3,3) size 618.39x16 LayoutText {#text} at (0,0) size 336x16 text run at (0,0) width 336: "BUG: the height of the textarea is not 80%"
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-expected.txt index 1901ea8..df407c6 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-expected.txt
@@ -55,32 +55,32 @@ PASS getHeight('object-100') is '150px' PASS getWidth('button-75') is getWidth('button-100') PASS getHeight('button-75') != '0px' is true -FAIL getHeight('button-75') should be 16px. Was 10.5px. +PASS getHeight('button-75') is getHeight('button-100') PASS getWidth('input-button-75') is getWidth('input-button-100') PASS getHeight('input-button-75') != '0px' is true -FAIL getHeight('input-button-75') should be 16px. Was 10.5px. +PASS getHeight('input-button-75') is getHeight('input-button-100') PASS getWidth('input-checkbox-75') is getWidth('input-checkbox-100') -PASS getHeight('input-checkbox-75') != '0px' is true -PASS getHeight('input-checkbox-75') is 75% of getHeight('input-checkbox-100'). +PASS getHeight('input-checkbox-75') == '0px' is true +PASS getHeight('input-checkbox-75') is getHeight('input-checkbox-100') PASS getWidth('input-file-75') is getWidth('input-file-100') PASS getHeight('input-file-75') != '0px' is true -PASS getHeight('input-file-75') is 75% of getHeight('input-file-100'). +PASS getHeight('input-file-75') is getHeight('input-file-100') PASS getWidth('input-image-75') is '75px' PASS getHeight('input-image-75') is '75px' PASS getWidth('input-image-100') is '100px' PASS getHeight('input-image-100') is '100px' PASS getWidth('input-radio-75') is getWidth('input-radio-100') -PASS getHeight('input-radio-75') != '0px' is true -PASS getHeight('input-radio-75') is 75% of getHeight('input-radio-100'). +PASS getHeight('input-radio-75') == '0px' is true +PASS getHeight('input-radio-75') is getHeight('input-radio-100') PASS getWidth('input-reset-75') is getWidth('input-reset-100') PASS getHeight('input-reset-75') != '0px' is true -FAIL getHeight('input-reset-75') should be 16px. Was 10.5px. +PASS getHeight('input-reset-75') is getHeight('input-reset-100') PASS getWidth('input-submit-75') is getWidth('input-submit-100') PASS getHeight('input-submit-75') != '0px' is true -FAIL getHeight('input-submit-75') should be 16px. Was 10.5px. +PASS getHeight('input-submit-75') is getHeight('input-submit-100') PASS getWidth('select-75') is getWidth('select-100') PASS getHeight('select-75') != '0px' is true -FAIL getHeight('select-75') should be 18px. Was 13px. +PASS getHeight('select-75') is getHeight('select-100') PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-text-controls-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-text-controls-expected.txt index 6a84efd..9a2f2e32 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-text-controls-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/replaced/table-percent-height-text-controls-expected.txt
@@ -4,7 +4,7 @@ -This test checks that text controls with percentage heights within table cells have the correct height.Text controls are in a different test than other replaced elements because their metrics are platform-specific. +This test checks that text controls with percentage heights within table cells have the correct height.Text controls are in a different test than other replaced elements because their metrics are platform-specific.The reason a 75% control is the same height as a 100% control is because a replaced element that depends on theheight of its parent cell is treated as auto. So by itself it will set the height of the row. See https://drafts.csswg.org/css-tables-3/#row-layout On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". @@ -14,13 +14,13 @@ TEST COMPLETE PASS getWidth('input-password-75') is getWidth('input-password-100') PASS getFullHeight('input-password-75') != '0px' is true -FAIL getFullHeight('input-password-75') [16.5px] is not 75% of getFullHeight('input-password-100') [22px]. +PASS getFullHeight('input-password-75') is getFullHeight('input-password-100') PASS getWidth('input-text-75') is getWidth('input-text-100') PASS getFullHeight('input-text-75') != '0px' is true -FAIL getFullHeight('input-text-75') [16.5px] is not 75% of getFullHeight('input-text-100') [22px]. +PASS getFullHeight('input-text-75') is getFullHeight('input-text-100') PASS getWidth('textarea-75') is getWidth('textarea-100') PASS getFullHeight('textarea-75') != '0px' is true -PASS getFullHeight('textarea-75') is 75% of getFullHeight('textarea-100'). +PASS getFullHeight('textarea-75') is getFullHeight('textarea-100') PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index dd615e7..d9673fa2 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -3185,19 +3185,16 @@ // always make ourselves be a percentage of the cell's current content // height. if (!cb->hasOverrideLogicalContentHeight()) { - // Normally we would let the cell size intrinsically, but scrolling - // overflow has to be treated differently, since WinIE lets scrolled - // overflow regions shrink as needed. - // While we can't get all cases right, we can at least detect when the - // cell has a specified height or when the table has a specified height. - // In these cases we want to initially have no size and allow the - // flexing of the table or the cell to its specified height to cause us - // to grow to fill the space. This could end up being wrong in some - // cases, but it is preferable to the alternative (sizing intrinsically - // and making the row end up too big). + // https://drafts.csswg.org/css-tables-3/#row-layout: + // For the purpose of calculating [the minimum height of a row], + // descendants of table cells whose height depends on percentages + // of their parent cell's height are considered to have an auto + // height if they have overflow set to visible or hidden or if + // they are replaced elements, and a 0px height if they have not. LayoutTableCell* cell = toLayoutTableCell(cb); if (style()->overflowY() != EOverflow::Visible && style()->overflowY() != EOverflow::Hidden && + !shouldBeConsideredAsReplaced() && (!cell->style()->logicalHeight().isAuto() || !cell->table()->style()->logicalHeight().isAuto())) return LayoutUnit(); @@ -3218,16 +3215,17 @@ availableHeight += cb->paddingLogicalHeight(); LayoutUnit result = valueForLength(height, availableHeight); - bool includeBorderPadding = + // |overrideLogicalContentHeight| is the maximum height made available by the + // cell to its percent height children when we decide they can determine the + // height of the cell. If the percent height child is box-sizing:content-box + // then we must subtract the border and padding from the cell's + // |availableHeight| (given by |overrideLogicalContentHeight|) to arrive + // at the child's computed height. + bool subtractBorderAndPadding = isTable() || (cb->isTableCell() && !skippedAutoHeightContainingBlock && - cb->hasOverrideLogicalContentHeight()); - - if (includeBorderPadding) { - // FIXME: Table cells should default to box-sizing: border-box so we can - // avoid this hack. - // It is necessary to use the border-box to match WinIE's broken - // box model. This is essential for sizing inside - // table cells using percentage heights. + cb->hasOverrideLogicalContentHeight() && + style()->boxSizing() == BoxSizingContentBox); + if (subtractBorderAndPadding) { result -= borderAndPaddingLogicalHeight(); return std::max(LayoutUnit(), result); } @@ -4672,9 +4670,12 @@ } DISABLE_CFI_PERF -static bool shouldBeConsideredAsReplaced(Node* node) { +bool LayoutBox::shouldBeConsideredAsReplaced() const { // Checkboxes and radioboxes are not isAtomicInlineLevel() nor do they have // their own layoutObject in which to override avoidFloats(). + if (isAtomicInlineLevel()) + return true; + Node* node = this->node(); return node && node->isElementNode() && (toElement(node)->isFormControlElement() || isHTMLImageElement(toElement(node))); @@ -4682,10 +4683,9 @@ DISABLE_CFI_PERF bool LayoutBox::avoidsFloats() const { - return isAtomicInlineLevel() || shouldBeConsideredAsReplaced(node()) || - hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || - isFlexItemIncludingDeprecated() || style()->containsPaint() || - style()->containsLayout(); + return shouldBeConsideredAsReplaced() || hasOverflowClip() || isHR() || + isLegend() || isWritingModeRoot() || isFlexItemIncludingDeprecated() || + style()->containsPaint() || style()->containsLayout(); } bool LayoutBox::hasNonCompositedScrollbars() const {
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index d4a1ae1..795abf62 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -1097,6 +1097,7 @@ bool shrinkToAvoidFloats() const; virtual bool avoidsFloats() const; + bool shouldBeConsideredAsReplaced() const; void updateFragmentationInfoForChild(LayoutBox&); bool childNeedsRelayoutForPagination(const LayoutBox&) const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index 759b828..4bb1a926 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1727,15 +1727,18 @@ // Text nodes share style with their parents but the paint properties don't // apply to them, hence the !isText() check. - if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && - diff.needsPaintPropertyUpdate() && !isText()) { + if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && !isText() && + (diff.transformChanged() || diff.opacityChanged() || + diff.zIndexChanged() || diff.filterChanged() || + diff.backdropFilterChanged() || diff.cssClipChanged())) { setNeedsPaintPropertyUpdate(); // We don't need to invalidate paint of objects on SPv2 when only paint // property or paint order change. Mark the painting layer needing repaint // for changed paint property or paint order. Raster invalidation will be // issued if needed during paint. - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && + !shouldDoFullPaintInvalidation()) ObjectPaintInvalidator(*this).slowSetPaintingLayerNeedsRepaint(); } }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp index 8dcca0a..2efec3e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -1110,13 +1110,15 @@ return extraLogicalHeight - remainingExtraLogicalHeight; } -static bool shouldFlexCellChild(LayoutObject* cellDescendant) { - return cellDescendant->isAtomicInlineLevel() || - (cellDescendant->isBox() && - toLayoutBox(cellDescendant)->style()->overflowY() != - EOverflow::Visible && - toLayoutBox(cellDescendant)->style()->overflowY() != - EOverflow::Hidden); +static bool shouldFlexCellChild(const LayoutTableCell& cell, + LayoutObject* cellDescendant) { + if (!cell.style()->logicalHeight().isSpecified()) + return false; + if (cellDescendant->style()->overflowY() == EOverflow::Visible || + cellDescendant->style()->overflowY() == EOverflow::Hidden) + return true; + return cellDescendant->isBox() && + toLayoutBox(cellDescendant)->shouldBeConsideredAsReplaced(); } void LayoutTableSection::layoutRows() { @@ -1902,7 +1904,7 @@ for (LayoutObject* child = cell.firstChild(); child; child = child->nextSibling()) { if (!child->isText() && child->style()->logicalHeight().isPercentOrCalc() && - (flexAllChildren || shouldFlexCellChild(child)) && + (flexAllChildren || shouldFlexCellChild(cell, child)) && (!child->isTable() || toLayoutTable(child)->hasSections())) { cellChildrenFlex = true; break; @@ -1913,7 +1915,7 @@ if (TrackedLayoutBoxListHashSet* percentHeightDescendants = cell.percentHeightDescendants()) { for (auto* descendant : *percentHeightDescendants) { - if (flexAllChildren || shouldFlexCellChild(descendant)) { + if (flexAllChildren || shouldFlexCellChild(cell, descendant)) { cellChildrenFlex = true; break; }
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp index e12eb52..0db07cc 100644 --- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.cpp
@@ -21,6 +21,10 @@ PaintControllerPaintTestForSlimmingPaintV1AndV2, ::testing::Bool()); +INSTANTIATE_TEST_CASE_P(All, + PaintControllerPaintTestForSlimmingPaintV2, + ::testing::Bool()); + TEST_P(PaintControllerPaintTestForSlimmingPaintV1AndV2, FullDocumentPaintingWithCaret) { setBodyInnerHTML( @@ -171,7 +175,7 @@ } } -TEST_F(PaintControllerPaintTestForSlimmingPaintV2, ChunkIdClientCacheFlag) { +TEST_P(PaintControllerPaintTestForSlimmingPaintV2, ChunkIdClientCacheFlag) { setBodyInnerHTML( "<div id='div' style='width: 200px; height: 200px; opacity: 0.5'>" " <div style='width: 100px; height: 100px; background-color: " @@ -185,29 +189,48 @@ LayoutBlock& div = *toLayoutBlock(getLayoutObjectByElementId("div")); LayoutObject& subDiv = *div.firstChild(); LayoutObject& subDiv2 = *subDiv.nextSibling(); - EXPECT_DISPLAY_LIST( - rootPaintController().getDisplayItemList(), 11, - TestDisplayItem(layoutView(), - DisplayItem::kClipFrameToVisibleContentRect), - TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence), - TestDisplayItem(layoutView(), documentBackgroundType), - TestDisplayItem(htmlLayer, DisplayItem::kSubsequence), - TestDisplayItem(div, DisplayItem::kBeginCompositing), - TestDisplayItem(subDiv, backgroundType), - TestDisplayItem(subDiv2, backgroundType), - TestDisplayItem(div, DisplayItem::kEndCompositing), - TestDisplayItem(htmlLayer, DisplayItem::kEndSubsequence), - TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence), - TestDisplayItem(layoutView(), - DisplayItem::clipTypeToEndClipType( - DisplayItem::kClipFrameToVisibleContentRect))); + if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { + EXPECT_DISPLAY_LIST( + rootPaintController().getDisplayItemList(), 9, + TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence), + TestDisplayItem(layoutView(), documentBackgroundType), + TestDisplayItem(htmlLayer, DisplayItem::kSubsequence), + TestDisplayItem(div, DisplayItem::kBeginCompositing), + TestDisplayItem(subDiv, backgroundType), + TestDisplayItem(subDiv2, backgroundType), + TestDisplayItem(div, DisplayItem::kEndCompositing), + TestDisplayItem(htmlLayer, DisplayItem::kEndSubsequence), + TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence)); + } else { + EXPECT_DISPLAY_LIST( + rootPaintController().getDisplayItemList(), 11, + TestDisplayItem(layoutView(), + DisplayItem::kClipFrameToVisibleContentRect), + TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence), + TestDisplayItem(layoutView(), documentBackgroundType), + TestDisplayItem(htmlLayer, DisplayItem::kSubsequence), + TestDisplayItem(div, DisplayItem::kBeginCompositing), + TestDisplayItem(subDiv, backgroundType), + TestDisplayItem(subDiv2, backgroundType), + TestDisplayItem(div, DisplayItem::kEndCompositing), + TestDisplayItem(htmlLayer, DisplayItem::kEndSubsequence), + TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence), + TestDisplayItem(layoutView(), + DisplayItem::clipTypeToEndClipType( + DisplayItem::kClipFrameToVisibleContentRect))); + } const PaintChunk& backgroundChunk = rootPaintController().paintChunks()[0]; EXPECT_TRUE(backgroundChunk.properties.propertyTreeState.scroll()->isRoot()); const EffectPaintPropertyNode* effectNode = div.paintProperties()->effect(); EXPECT_EQ(0.5f, effectNode->opacity()); - const PaintChunk& chunk = rootPaintController().paintChunks()[1]; + + // When RLS is enabled, an additional paint chunk will be created for the + // LayoutView's layer. + unsigned divChunkIndex = + RuntimeEnabledFeatures::rootLayerScrollingEnabled() ? 2 : 1; + const PaintChunk& chunk = rootPaintController().paintChunks()[divChunkIndex]; EXPECT_EQ(*div.layer(), chunk.id->client); EXPECT_EQ(effectNode, chunk.properties.propertyTreeState.effect()); @@ -219,7 +242,7 @@ EXPECT_TRUE(rootPaintController().clientCacheIsValid(subDiv)); } -TEST_F(PaintControllerPaintTestForSlimmingPaintV2, CompositingFold) { +TEST_P(PaintControllerPaintTestForSlimmingPaintV2, CompositingFold) { setBodyInnerHTML( "<div id='div' style='width: 200px; height: 200px; opacity: 0.5'>" " <div style='width: 100px; height: 100px; background-color: " @@ -231,21 +254,36 @@ LayoutBlock& div = *toLayoutBlock(getLayoutObjectByElementId("div")); LayoutObject& subDiv = *div.firstChild(); - EXPECT_DISPLAY_LIST( - rootPaintController().getDisplayItemList(), 8, - TestDisplayItem(layoutView(), - DisplayItem::kClipFrameToVisibleContentRect), - TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence), - TestDisplayItem(layoutView(), documentBackgroundType), - TestDisplayItem(htmlLayer, DisplayItem::kSubsequence), - // The begin and end compositing display items have been folded into this - // one. - TestDisplayItem(subDiv, backgroundType), - TestDisplayItem(htmlLayer, DisplayItem::kEndSubsequence), - TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence), - TestDisplayItem(layoutView(), - DisplayItem::clipTypeToEndClipType( - DisplayItem::kClipFrameToVisibleContentRect))); + if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { + EXPECT_DISPLAY_LIST( + rootPaintController().getDisplayItemList(), 6, + TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence), + TestDisplayItem(layoutView(), documentBackgroundType), + TestDisplayItem(htmlLayer, DisplayItem::kSubsequence), + // The begin and end compositing display items have been folded into + // this + // one. + TestDisplayItem(subDiv, backgroundType), + TestDisplayItem(htmlLayer, DisplayItem::kEndSubsequence), + TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence)); + } else { + EXPECT_DISPLAY_LIST( + rootPaintController().getDisplayItemList(), 8, + TestDisplayItem(layoutView(), + DisplayItem::kClipFrameToVisibleContentRect), + TestDisplayItem(*layoutView().layer(), DisplayItem::kSubsequence), + TestDisplayItem(layoutView(), documentBackgroundType), + TestDisplayItem(htmlLayer, DisplayItem::kSubsequence), + // The begin and end compositing display items have been folded into + // this + // one. + TestDisplayItem(subDiv, backgroundType), + TestDisplayItem(htmlLayer, DisplayItem::kEndSubsequence), + TestDisplayItem(*layoutView().layer(), DisplayItem::kEndSubsequence), + TestDisplayItem(layoutView(), + DisplayItem::clipTypeToEndClipType( + DisplayItem::kClipFrameToVisibleContentRect))); + } } } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h index 8cda2f5..050195e 100644 --- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h +++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
@@ -88,10 +88,13 @@ }; class PaintControllerPaintTestForSlimmingPaintV2 - : public PaintControllerPaintTestBase { + : public PaintControllerPaintTestBase, + public testing::WithParamInterface<bool>, + private ScopedRootLayerScrollingForTest { public: PaintControllerPaintTestForSlimmingPaintV2() - : PaintControllerPaintTestBase(true) {} + : PaintControllerPaintTestBase(true), + ScopedRootLayerScrollingForTest(GetParam()) {} }; class PaintControllerPaintTestForSlimmingPaintV1AndV2
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp index 65a57b66..8cacaeb8a2 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
@@ -27,6 +27,10 @@ PaintLayer* targetPaintLayer = toLayoutBoxModelObject(target->layoutObject())->layer(); ClipRectsContext context(document().layoutView()->layer(), UncachedClipRects); + // When RLS is enabled, the LayoutView will have a composited scrolling layer, + // so don't apply an overflow clip. + if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) + context.setIgnoreOverflowClip(); LayoutRect layerBounds; ClipRect backgroundRect, foregroundRect; targetPaintLayer->clipper().calculateRects(
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index 4a7e199..d822d5bc 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -586,12 +586,10 @@ updatePropertySpecificDifferences(other, diff); - // The following conditions need to be at last, because they may depend on + // The following condition needs to be at last, because it may depend on // conditions in diff computed above. if (scrollAnchorDisablingPropertyChanged(other, diff)) diff.setScrollAnchorDisablingPropertyChanged(); - if (diffNeedsPaintPropertyUpdate(other, diff)) - diff.setNeedsPaintPropertyUpdate(); // Cursors are not checked, since they will be set appropriately in response // to mouse events, so they don't need to cause any paint invalidation or @@ -1132,17 +1130,6 @@ diff.setCSSClipChanged(); } -bool ComputedStyle::diffNeedsPaintPropertyUpdate( - const ComputedStyle& other, - const StyleDifference& diff) const { - if (diff.transformChanged() || diff.opacityChanged() || - diff.zIndexChanged() || diff.filterChanged() || - diff.backdropFilterChanged() || diff.cssClipChanged()) - return true; - - return false; -} - void ComputedStyle::addPaintImage(StyleImage* image) { if (!m_rareNonInheritedData.access()->m_paintImages) { m_rareNonInheritedData.access()->m_paintImages =
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index fcbdce1..85a68d0 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -3918,8 +3918,6 @@ const ComputedStyle& other) const; void updatePropertySpecificDifferences(const ComputedStyle& other, StyleDifference&) const; - bool diffNeedsPaintPropertyUpdate(const ComputedStyle& other, - const StyleDifference&) const; bool requireTransformOrigin(ApplyTransformOrigin applyOrigin, ApplyMotionPath) const;
diff --git a/third_party/WebKit/Source/core/style/StyleDifference.h b/third_party/WebKit/Source/core/style/StyleDifference.h index ed12f68..3003e61 100644 --- a/third_party/WebKit/Source/core/style/StyleDifference.h +++ b/third_party/WebKit/Source/core/style/StyleDifference.h
@@ -33,17 +33,15 @@ m_layoutType(NoLayout), m_recomputeOverflow(false), m_propertySpecificDifferences(0), - m_scrollAnchorDisablingPropertyChanged(false), - m_needsPaintPropertyUpdate(false) {} + m_scrollAnchorDisablingPropertyChanged(false) {} bool hasDifference() const { bool result = m_paintInvalidationType || m_layoutType || m_propertySpecificDifferences; // m_recomputeOverflow, m_scrollAnchorDisablingPropertyChanged and - // m_needsPaintPropertyUpdate are never set without other flags set. + // are never set without other flags set. DCHECK(result || - (!m_recomputeOverflow && !m_scrollAnchorDisablingPropertyChanged && - !m_needsPaintPropertyUpdate)); + (!m_recomputeOverflow && !m_scrollAnchorDisablingPropertyChanged)); return result; } @@ -140,9 +138,6 @@ m_scrollAnchorDisablingPropertyChanged = true; } - bool needsPaintPropertyUpdate() const { return m_needsPaintPropertyUpdate; } - void setNeedsPaintPropertyUpdate() { m_needsPaintPropertyUpdate = true; } - private: enum PaintInvalidationType { NoPaintInvalidation = 0, @@ -156,7 +151,6 @@ unsigned m_recomputeOverflow : 1; unsigned m_propertySpecificDifferences : 7; unsigned m_scrollAnchorDisablingPropertyChanged : 1; - unsigned m_needsPaintPropertyUpdate : 1; }; } // namespace blink
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js index cb7fe59..437a4ed 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleViewMessage.js
@@ -312,7 +312,10 @@ var contentElement = toggleElement.createChild('div', 'console-message-stack-trace-wrapper'); var messageElement = this._buildMessage(consoleMessage); + var icon = UI.Icon.create('smallicon-triangle-right', 'stack-trace-expand-icon'); var clickableElement = contentElement.createChild('div'); + clickableElement.appendChild(icon); + clickableElement.appendChild(messageElement); var stackTraceElement = contentElement.createChild('div'); var stackTracePreview = @@ -324,8 +327,8 @@ * @param {boolean} expand */ function expandStackTrace(expand) { + icon.setIconType(expand ? 'smallicon-triangle-bottom' : 'smallicon-triangle-right'); stackTraceElement.classList.toggle('hidden', !expand); - toggleElement.classList.toggle('expanded', expand); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/console/consoleView.css b/third_party/WebKit/Source/devtools/front_end/console/consoleView.css index 69646aa..6d7e9f8b 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/consoleView.css +++ b/third_party/WebKit/Source/devtools/front_end/console/consoleView.css
@@ -367,27 +367,6 @@ flex: none; } -.console-message-stack-trace-toggle .console-message-text::before { - content: " "; - -webkit-user-select: none; - -webkit-mask-image: url(Images/toolbarButtonGlyphs.png); - -webkit-mask-size: 352px 168px; - color: transparent; - text-shadow: none; - padding-right: 8px; - height: 12px; +.stack-trace-expand-icon { background-color: rgb(110, 110, 110); - width: 12px; - flex: none; - -webkit-mask-position: -4px -96px; -} - -@media (-webkit-min-device-pixel-ratio: 1.1) { -.console-message-stack-trace-toggle .console-message-text::before { - -webkit-mask-image: url(Images/toolbarButtonGlyphs_2x.png); -} -} /* media */ - -.console-message-stack-trace-toggle.expanded .console-message-text::before { - -webkit-mask-position: -20px -96px; }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index e934696..dd1b2fb 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -2109,10 +2109,30 @@ } } + /** + * @override + */ + onexpand() { + this._updateExpandElement(); + } + + /** + * @override + */ + oncollapse() { + this._updateExpandElement(); + } + + _updateExpandElement() { + if (this.expanded) + this._expandElement.setIconType('smallicon-triangle-bottom'); + else + this._expandElement.setIconType('smallicon-triangle-right'); + } + updateTitle() { this._updateState(); - this._expandElement = createElement('span'); - this._expandElement.className = 'expand-element'; + this._expandElement = UI.Icon.create('smallicon-triangle-right', 'expand-icon'); var propertyRenderer = new Elements.StylesSidebarPropertyRenderer(this._style.parentRule, this.node(), this.name, this.value);
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/stylesSectionTree.css b/third_party/WebKit/Source/devtools/front_end/elements/stylesSectionTree.css index 090ef54..592cb40 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/stylesSectionTree.css +++ b/third_party/WebKit/Source/devtools/front_end/elements/stylesSectionTree.css
@@ -179,30 +179,15 @@ margin-left: 0 !important; } -:host-context(.matched-styles) .tree-outline li.parent .expand-element { +.expand-icon { -webkit-user-select: none; - -webkit-mask-image: url(Images/toolbarButtonGlyphs.png); - -webkit-mask-size: 352px 168px; - margin-right: 2px; - margin-left: -6px; background-color: #777; - width: 8px; - height: 10px; - display: inline-block; + margin-left: -6px; + margin-right: 2px; } -@media (-webkit-min-device-pixel-ratio: 1.1) { -:host-context(.matched-styles) .tree-outline li.parent .expand-element { - -webkit-mask-image: url(Images/toolbarButtonGlyphs_2x.png); -} -} /* media */ - -:host-context(.matched-styles) .tree-outline li.parent .expand-element { - -webkit-mask-position: -4px -96px; -} - -:host-context(.matched-styles) .tree-outline li.parent.expanded .expand-element { - -webkit-mask-position: -20px -96px; +.tree-outline li:not(.parent) .expand-icon { + display: none; } :host-context(.matched-styles:not(.read-only):hover) .enabled-button {
diff --git a/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js b/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js index 200b2994..a7a57169 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js +++ b/third_party/WebKit/Source/devtools/front_end/network/BlockedURLsPane.js
@@ -200,7 +200,8 @@ countElement.title = Common.UIString( count === 1 ? '%d request blocked by this pattern' : '%d requests blocked by this pattern', count); - var removeButton = element.createChild('div', 'remove-button'); + var removeButton = UI.Icon.create('smallicon-cross', 'remove-icon'); + element.appendChild(removeButton); removeButton.title = Common.UIString('Remove'); removeButton.addEventListener('click', this._removeBlockedURL.bind(this, index), false);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/blockedURLsPane.css b/third_party/WebKit/Source/devtools/front_end/network/blockedURLsPane.css index 280be41..0e20e389 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/blockedURLsPane.css +++ b/third_party/WebKit/Source/devtools/front_end/network/blockedURLsPane.css
@@ -63,28 +63,15 @@ margin-right: 5px; } -.blocked-url .remove-button { - width: 13px; - height: 13px; - background-image: url(Images/toolbarButtonGlyphs.png); - background-size: 352px 168px; - background-position: -175px -96px; - visibility: hidden; - flex: none; +.remove-icon { opacity: 0.7; - cursor: default; + visibility: hidden; } -@media (-webkit-min-device-pixel-ratio: 1.1) { -.blocked-url .remove-button { - background-image: url(Images/toolbarButtonGlyphs_2x.png); +.blocked-url .remove-icon:hover { + opacity: 1.0; } -} /* media */ -.blocked-url:hover .remove-button { +.blocked-url:hover .remove-icon { visibility: visible; } - -.blocked-url .remove-button:hover { - opacity: 1.0; -} \ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js index 41232ae..45cd812 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
@@ -113,6 +113,7 @@ 'smallicon-triangle-right': {x: -4, y: -98, width: 10, height: 8, spritesheet: 'largeicons', isMask: true}, 'smallicon-triangle-bottom': {x: -20, y: -98, width: 10, height: 8, spritesheet: 'largeicons', isMask: true}, 'smallicon-arrow-in-circle': {x: -10, y: -127, width: 11, height: 11, spritesheet: 'largeicons', isMask: true}, + 'smallicon-cross': {x: -177, y: -98, width: 10, height: 10, spritesheet: 'largeicons'}, 'smallicon-inline-breakpoint': {x: -140, y: -20, width: 10, height: 10, spritesheet: 'smallicons'}, 'smallicon-inline-breakpoint-conditional': {x: -160, y: -20, width: 10, height: 10, spritesheet: 'smallicons'},
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css index 46c5ad6..cedc661 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css
@@ -337,6 +337,11 @@ -webkit-mask-size: 190px 30px; } +.spritesheet-largeicons { + background-image: -webkit-image-set(url(Images/toolbarButtonGlyphs.png) 1x, url(Images/toolbarButtonGlyphs_2x.png) 2x); + background-size: 352px 168px; +} + .spritesheet-largeicons.icon-mask { -webkit-mask-image: -webkit-image-set(url(Images/toolbarButtonGlyphs.png) 1x, url(Images/toolbarButtonGlyphs_2x.png) 2x); -webkit-mask-size: 352px 168px;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp index 9c141b51..bc0a87f 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -904,33 +904,28 @@ return AccessibilityOrientationUndefined; } -static String queryString(WebLocalizedString::Name name) { - return Locale::defaultLocale().queryString(name); -} - -String AXObject::actionVerb() const { +AXSupportedAction AXObject::action() const { if (!actionElement()) - return emptyString(); + return AXSupportedAction::None; switch (roleValue()) { case ButtonRole: case ToggleButtonRole: - return queryString(WebLocalizedString::AXButtonActionVerb); + return AXSupportedAction::Press; case TextFieldRole: - return queryString(WebLocalizedString::AXTextFieldActionVerb); + return AXSupportedAction::Activate; case RadioButtonRole: - return queryString(WebLocalizedString::AXRadioButtonActionVerb); + return AXSupportedAction::Select; case CheckBoxRole: case SwitchRole: - return queryString( - isChecked() ? WebLocalizedString::AXCheckedCheckBoxActionVerb - : WebLocalizedString::AXUncheckedCheckBoxActionVerb); + return isChecked() ? AXSupportedAction::Check + : AXSupportedAction::Uncheck; case LinkRole: - return queryString(WebLocalizedString::AXLinkActionVerb); + return AXSupportedAction::Jump; case PopUpButtonRole: - return queryString(WebLocalizedString::AXPopUpButtonActionVerb); + return AXSupportedAction::Open; default: - return queryString(WebLocalizedString::AXDefaultActionVerb); + return AXSupportedAction::Click; } }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h index 45b7a1a..4f65993d 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.h +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -245,6 +245,18 @@ DefaultBehavior, }; +enum class AXSupportedAction { + None = 0, + Activate, + Check, + Click, + Jump, + Open, + Press, + Select, + Uncheck +}; + enum AccessibilityButtonState { ButtonStateOff = 0, ButtonStateOn, @@ -795,7 +807,7 @@ virtual void wordBoundaries(Vector<AXRange>&) const {} // Properties of interactive elements. - String actionVerb() const; + AXSupportedAction action() const; virtual AccessibilityButtonState checkboxOrRadioValue() const; virtual AriaCurrentState ariaCurrentState() const { return AriaCurrentStateUndefined;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLCompressedTextureETC1.cpp b/third_party/WebKit/Source/modules/webgl/WebGLCompressedTextureETC1.cpp index 9b708b75..f12d9ae 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLCompressedTextureETC1.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLCompressedTextureETC1.cpp
@@ -25,12 +25,8 @@ bool WebGLCompressedTextureETC1::supported(WebGLRenderingContextBase* context) { Extensions3DUtil* extensionsUtil = context->extensionsUtil(); - bool webgl1 = !context->isWebGL2OrHigher(); - bool etc1 = - extensionsUtil->supportsExtension("GL_OES_compressed_ETC1_RGB8_texture"); - bool etc = - extensionsUtil->supportsExtension("GL_CHROMIUM_compressed_texture_etc"); - return (webgl1 || etc) && etc1; + return extensionsUtil->supportsExtension( + "GL_OES_compressed_ETC1_RGB8_texture"); } const char* WebGLCompressedTextureETC1::extensionName() {
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 9685a9a..0a49563d 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1179,7 +1179,6 @@ "scheduler/base/intrusive_heap.h", "scheduler/base/lazy_now.cc", "scheduler/base/lazy_now.h", - "scheduler/base/moveable_auto_lock.h", "scheduler/base/pollable_thread_safe_flag.cc", "scheduler/base/pollable_thread_safe_flag.h", "scheduler/base/queueing_time_estimator.cc",
diff --git a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp index d154e48c..a450200 100644 --- a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp +++ b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp
@@ -55,7 +55,7 @@ // Keep this array in sync with the WebBlendMode enum in // public/platform/WebBlendMode.h. static const SkBlendMode gMapBlendOpsToXfermodeModes[] = { - SkBlendMode::kClear, // WebBlendModeNormal + SkBlendMode::kSrcOver, // WebBlendModeNormal SkBlendMode::kMultiply, // WebBlendModeMultiply SkBlendMode::kScreen, // WebBlendModeScreen SkBlendMode::kOverlay, // WebBlendModeOverlay
diff --git a/third_party/WebKit/Source/platform/scheduler/base/moveable_auto_lock.h b/third_party/WebKit/Source/platform/scheduler/base/moveable_auto_lock.h deleted file mode 100644 index ac2b8a8..0000000 --- a/third_party/WebKit/Source/platform/scheduler/base/moveable_auto_lock.h +++ /dev/null
@@ -1,41 +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 THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_ -#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_ - -#include "base/synchronization/lock.h" - -namespace blink { -namespace scheduler { - -class MoveableAutoLock { - public: - explicit MoveableAutoLock(base::Lock& lock) : lock_(lock), moved_(false) { - lock_.Acquire(); - } - - explicit MoveableAutoLock(MoveableAutoLock&& other) - : lock_(other.lock_), moved_(other.moved_) { - lock_.AssertAcquired(); - other.moved_ = true; - } - - ~MoveableAutoLock() { - if (moved_) - return; - lock_.AssertAcquired(); - lock_.Release(); - } - - private: - base::Lock& lock_; - bool moved_; - DISALLOW_COPY_AND_ASSIGN(MoveableAutoLock); -}; - -} // namespace scheduler -} // namespace blink - -#endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.cc index 8614d7a..80f18b99 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.cc
@@ -46,23 +46,23 @@ task_queue_manager_->MaybeScheduleDelayedWork(FROM_HERE, now, delay); } -base::Optional<base::TimeDelta> RealTimeDomain::DelayTillNextTask( - LazyNow* lazy_now) { +bool RealTimeDomain::MaybeAdvanceTime() { base::TimeTicks next_run_time; if (!NextScheduledRunTime(&next_run_time)) - return base::Optional<base::TimeDelta>(); + return false; - base::TimeTicks now = lazy_now->Now(); + base::TimeTicks now = Now(); if (now >= next_run_time) - return base::TimeDelta(); // Makes DoWork post an immediate continuation. + return true; // Causes DoWork to post a continuation. base::TimeDelta delay = next_run_time - now; - TRACE_EVENT1(tracing_category_, "RealTimeDomain::DelayTillNextTask", + TRACE_EVENT1(tracing_category_, "RealTimeDomain::MaybeAdvanceTime", "delay_ms", delay.InMillisecondsF()); - // The next task is sometime in the future. DoWork will make sure it gets - // run at the right time.. - return delay; + // The next task is sometime in the future, make sure we schedule a DoWork to + // run it. + task_queue_manager_->MaybeScheduleDelayedWork(FROM_HERE, now, delay); + return false; } void RealTimeDomain::AsValueIntoInternal(
diff --git a/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.h b/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.h index 6883599..94d8a59 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.h +++ b/third_party/WebKit/Source/platform/scheduler/base/real_time_domain.h
@@ -23,7 +23,7 @@ // TimeDomain implementation: LazyNow CreateLazyNow() const override; base::TimeTicks Now() const override; - base::Optional<base::TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override; + bool MaybeAdvanceTime() override; const char* GetName() const override; protected:
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc index 2885ccd..8ad3792 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
@@ -154,11 +154,8 @@ TimeDomain* time_domain) : task_queue_manager(task_queue_manager), time_domain(time_domain), - delayed_work_queue( - new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)), - immediate_work_queue(new WorkQueue(task_queue, - "immediate", - WorkQueue::QueueType::IMMEDIATE)), + delayed_work_queue(new WorkQueue(task_queue, "delayed")), + immediate_work_queue(new WorkQueue(task_queue, "immediate")), set_index(0), is_enabled_refcount(0), voter_refcount(0), @@ -186,6 +183,7 @@ } bool TaskQueueImpl::RunsTasksOnCurrentThread() const { + base::AutoLock lock(any_thread_lock_); return base::PlatformThread::CurrentId() == thread_id_; } @@ -327,49 +325,26 @@ base::TimeTicks desired_run_time, EnqueueOrder sequence_number, bool nestable) { + if (any_thread().immediate_incoming_queue.empty()) + any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); // If the |immediate_incoming_queue| is empty we need a DoWork posted to make // it run. if (any_thread().immediate_incoming_queue.empty()) { - // There's no point posting a DoWork for a blocked or disabled queue, - // although we can only determine that on the main thread. - bool ensure_do_work_posted = !RunsTasksOnCurrentThread() || - (IsQueueEnabled() && !BlockedByFenceLocked()); - any_thread().task_queue_manager->OnQueueHasImmediateWork( - this, ensure_do_work_posted); - any_thread().time_domain->OnQueueHasImmediateWork(this); + // There's no point posting a DoWork for a disabled queue, however we can + // only tell if it's disabled from the main thread. + if (base::PlatformThread::CurrentId() == thread_id_) { + if (IsQueueEnabled() && !BlockedByFenceLocked()) + any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); + } else { + any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); + } } - any_thread().immediate_incoming_queue.emplace( - posted_from, task, desired_run_time, sequence_number, nestable, - sequence_number); - any_thread().task_queue_manager->DidQueueTask( - any_thread().immediate_incoming_queue.back()); + posted_from, task, desired_run_time, sequence_number, nestable, sequence_number); + any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming_queue.back()); TraceQueueSize(true); } -void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { - if (!main_thread_only().immediate_work_queue->Empty()) - return; - - base::AutoLock lock(any_thread_lock_); - if (any_thread().immediate_incoming_queue.empty()) - return; - - main_thread_only().immediate_work_queue->SwapLocked( - any_thread().immediate_incoming_queue); -} - -void TaskQueueImpl::OnImmediateWorkQueueHasBecomeEmpty( - std::queue<TaskQueueImpl::Task>* work_queue) { - base::AutoLock lock(any_thread_lock_); - DCHECK(work_queue->empty()); - - if (any_thread().immediate_incoming_queue.empty()) - return; - - std::swap(any_thread().immediate_incoming_queue, *work_queue); -} - bool TaskQueueImpl::IsEmpty() const { if (!main_thread_only().delayed_work_queue->Empty() || !main_thread_only().delayed_incoming_queue.empty() || @@ -419,8 +394,7 @@ return main_thread_only().delayed_incoming_queue.top().delayed_run_time; } -base::Optional<base::TimeTicks> TaskQueueImpl::WakeUpForDelayedWork( - LazyNow* lazy_now) { +void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) { // Enqueue all delayed tasks that should be running now, skipping any that // have been canceled. while (!main_thread_only().delayed_incoming_queue.empty()) { @@ -439,10 +413,25 @@ } // Make sure the next wake up is scheduled. - if (!main_thread_only().delayed_incoming_queue.empty()) - return main_thread_only().delayed_incoming_queue.top().delayed_run_time; + if (!main_thread_only().delayed_incoming_queue.empty()) { + main_thread_only().time_domain->ScheduleDelayedWork( + this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, + lazy_now->Now()); + } +} - return base::Optional<base::TimeTicks>(); +bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { + if (!main_thread_only().task_queue_manager) + return false; + + if (!main_thread_only().immediate_work_queue->Empty()) + return true; + + base::AutoLock lock(any_thread_lock_); + main_thread_only().immediate_work_queue->SwapLocked( + any_thread().immediate_incoming_queue); + // |immediate_work_queue| is now empty so updates are no longer required. + return false; } void TaskQueueImpl::TraceQueueSize(bool is_locked) const { @@ -585,7 +574,8 @@ any_thread().time_domain = time_domain; } - + // We rely here on TimeDomain::MigrateQueue being thread-safe to use with + // TimeDomain::Register/UnregisterAsUpdatableTaskQueue. main_thread_only().time_domain->MigrateQueue(this, time_domain); main_thread_only().time_domain = time_domain; } @@ -681,8 +671,6 @@ } bool TaskQueueImpl::BlockedByFenceLocked() const { - any_thread_lock_.AssertAcquired(); - if (!main_thread_only().current_fence) return false;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h index 814c3eb0..55bfa458 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
@@ -139,16 +139,9 @@ const char* GetName() const override; QueueType GetQueueType() const override; - // As BlockedByFence but only safe to be called while |any_thread_| is locked. - // Must only be called from the thread this task queue was created on. - bool BlockedByFenceLocked() const; - - // Must only be called from the thread this task queue was created on. - void OnImmediateWorkQueueHasBecomeEmpty( - std::queue<TaskQueueImpl::Task>* work_queue); - - // Must only be called from the thread this task queue was created on. - void ReloadImmediateWorkQueueIfEmpty(); + // If this returns false then future updates for this queue are not needed + // unless requested. + bool MaybeUpdateImmediateWorkQueues(); void AsValueInto(base::trace_event::TracedValue* state) const; @@ -179,9 +172,9 @@ } // Enqueues any delayed tasks which should be run now on the - // |delayed_work_queue|. Returns the deadline if a subsequent wakeup is - // required. Must be called from the main thread. - base::Optional<base::TimeTicks> WakeUpForDelayedWork(LazyNow* lazy_now); + // |delayed_work_queue|. It also schedules the next wake up with the + // TimeDomain. Must be called from the main thread. + void WakeUpForDelayedWork(LazyNow* lazy_now); base::TimeTicks scheduled_time_domain_wakeup() const { return main_thread_only().scheduled_time_domain_wakeup; @@ -297,6 +290,9 @@ EnqueueOrder sequence_number, bool nestable); + // As BlockedByFence but safe to be called while locked. + bool BlockedByFenceLocked() const; + void TraceQueueSize(bool is_locked) const; static void QueueAsValueInto(const std::queue<Task>& queue, base::trace_event::TracedValue* state);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc index 252f086..74a311b1 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc
@@ -58,7 +58,7 @@ : real_time_domain_(new RealTimeDomain(tracing_category)), delegate_(delegate), task_was_run_on_quiescence_monitored_queue_(false), - record_task_delay_histograms_(true), + other_thread_pending_wakeup_(false), work_batch_size_(1), task_count_(0), tracing_category_(tracing_category), @@ -75,10 +75,12 @@ "TaskQueueManager", this); selector_.SetTaskQueueSelectorObserver(this); - delayed_do_work_closure_ = - base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), true); - immediate_do_work_closure_ = - base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), false); + from_main_thread_immediate_do_work_closure_ = + base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), + base::TimeTicks(), true); + from_other_thread_immediate_do_work_closure_ = + base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), + base::TimeTicks(), false); // TODO(alexclarke): Change this to be a parameter that's passed in. RegisterTimeDomain(real_time_domain_.get()); @@ -98,11 +100,6 @@ delegate_->RemoveNestingObserver(this); } -TaskQueueManager::AnyThread::AnyThread() - : do_work_running_count(0), - immediate_do_work_posted_count(0), - is_nested(false) {} - void TaskQueueManager::RegisterTimeDomain(TimeDomain* time_domain) { time_domains_.insert(time_domain); time_domain->OnRegisterWithTaskQueueManager(this); @@ -148,72 +145,45 @@ queues_.erase(task_queue); selector_.RemoveQueue(task_queue.get()); - - { - base::AutoLock lock(any_thread_lock_); - any_thread().has_incoming_immediate_work.erase(task_queue.get()); - } } -void TaskQueueManager::UpdateWorkQueues(LazyNow* lazy_now) { +void TaskQueueManager::UpdateWorkQueues(LazyNow lazy_now) { + TRACE_EVENT0(disabled_by_default_tracing_category_, + "TaskQueueManager::UpdateWorkQueues"); + for (TimeDomain* time_domain : time_domains_) { - if (time_domain == real_time_domain_.get()) { - time_domain->WakeupReadyDelayedQueues(lazy_now); - continue; - } - LazyNow time_domain_lazy_now = time_domain->CreateLazyNow(); - time_domain->WakeupReadyDelayedQueues(&time_domain_lazy_now); + LazyNow lazy_now_in_domain = time_domain == real_time_domain_.get() + ? lazy_now + : time_domain->CreateLazyNow(); + time_domain->UpdateWorkQueues(lazy_now_in_domain); } } void TaskQueueManager::OnBeginNestedMessageLoop() { // We just entered a nested message loop, make sure there's a DoWork posted or // the system will grind to a halt. - { - base::AutoLock lock(any_thread_lock_); - any_thread().immediate_do_work_posted_count++; - any_thread().is_nested = true; - } - delegate_->PostTask(FROM_HERE, immediate_do_work_closure_); -} - -void TaskQueueManager::OnQueueHasImmediateWork(internal::TaskQueueImpl* queue, - bool ensure_do_work_posted) { - MoveableAutoLock lock(any_thread_lock_); - any_thread().has_incoming_immediate_work.insert(queue); - if (ensure_do_work_posted) - MaybeScheduleImmediateWorkLocked(FROM_HERE, std::move(lock)); -} - -void TaskQueueManager::NotifyQueuesOfIncomingImmediateWorkOnMainThreadLocked() { - for (internal::TaskQueueImpl* queue : - any_thread().has_incoming_immediate_work) { - queue->ReloadImmediateWorkQueueIfEmpty(); - } - any_thread().has_incoming_immediate_work.clear(); + delegate_->PostTask(FROM_HERE, from_main_thread_immediate_do_work_closure_); } void TaskQueueManager::MaybeScheduleImmediateWork( const tracked_objects::Location& from_here) { - MoveableAutoLock lock(any_thread_lock_); - MaybeScheduleImmediateWorkLocked(from_here, std::move(lock)); -} - -void TaskQueueManager::MaybeScheduleImmediateWorkLocked( - const tracked_objects::Location& from_here, - MoveableAutoLock&& lock) { - { - MoveableAutoLock auto_lock(std::move(lock)); - // Unless we're nested, try to avoid posting redundant DoWorks. - if (!any_thread().is_nested && - (any_thread().do_work_running_count == 1 || - any_thread().immediate_do_work_posted_count > 0)) { + bool on_main_thread = delegate_->BelongsToCurrentThread(); + // De-duplicate DoWork posts. + if (on_main_thread) { + if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second) { return; } - - any_thread().immediate_do_work_posted_count++; + delegate_->PostTask(from_here, from_main_thread_immediate_do_work_closure_); + } else { + { + base::AutoLock lock(other_thread_lock_); + if (other_thread_pending_wakeup_) + return; + other_thread_pending_wakeup_ = true; + } + delegate_->PostTask(from_here, + from_other_thread_immediate_do_work_closure_); } - delegate_->PostTask(from_here, immediate_do_work_closure_); } void TaskQueueManager::MaybeScheduleDelayedWork( @@ -222,74 +192,54 @@ base::TimeDelta delay) { DCHECK(main_thread_checker_.CalledOnValidThread()); DCHECK_GE(delay, base::TimeDelta()); - { - base::AutoLock lock(any_thread_lock_); - // Unless we're nested, don't post a delayed DoWork if there's an immediate - // DoWork in flight or we're inside a DoWork. We can rely on DoWork posting - // a delayed continuation as needed. - if (!any_thread().is_nested && - (any_thread().immediate_do_work_posted_count > 0 || - any_thread().do_work_running_count == 1)) { - return; - } + // If there's a pending immediate DoWork then we rely on + // TryAdvanceTimeDomains getting the TimeDomain to call + // MaybeScheduleDelayedWork again when the immediate DoWork is complete. + if (main_thread_pending_wakeups_.find(base::TimeTicks()) != + main_thread_pending_wakeups_.end()) { + return; } - // De-duplicate DoWork posts. base::TimeTicks run_time = now + delay; - if (next_delayed_do_work_ <= run_time && !next_delayed_do_work_.is_null()) + if (!main_thread_pending_wakeups_.empty() && + *main_thread_pending_wakeups_.begin() <= run_time) { return; - - TRACE_EVENT1(tracing_category_, "MaybeScheduleDelayedWorkInternal", - "delay_ms", delay.InMillisecondsF()); - - cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_); - next_delayed_do_work_ = run_time; + } + main_thread_pending_wakeups_.insert(run_time); delegate_->PostDelayedTask( - from_here, cancelable_delayed_do_work_closure_.callback(), delay); + from_here, base::Bind(&TaskQueueManager::DoWork, + weak_factory_.GetWeakPtr(), run_time, true), + delay); } -void TaskQueueManager::DoWork(bool delayed) { +void TaskQueueManager::DoWork(base::TimeTicks run_time, bool from_main_thread) { DCHECK(main_thread_checker_.CalledOnValidThread()); - TRACE_EVENT1("tracing_category_", "TaskQueueManager::DoWork", "delayed", - delayed); - LazyNow lazy_now(real_time_domain()->CreateLazyNow()); + TRACE_EVENT1(tracing_category_, "TaskQueueManager::DoWork", + "from_main_thread", from_main_thread); - bool is_nested = delegate_->IsNested(); - if (!is_nested) + if (from_main_thread) { + main_thread_pending_wakeups_.erase(run_time); + } else { + base::AutoLock lock(other_thread_lock_); + other_thread_pending_wakeup_ = false; + } + + // Posting a DoWork while a DoWork is running leads to spurious DoWorks. + main_thread_pending_wakeups_.insert(base::TimeTicks()); + + if (!delegate_->IsNested()) queues_to_delete_.clear(); - // This must be done before running any tasks because they could invoke a - // nested message loop and we risk having a stale |next_delayed_do_work_|. - if (delayed) - next_delayed_do_work_ = base::TimeTicks(); + LazyNow lazy_now(real_time_domain()->CreateLazyNow()); + UpdateWorkQueues(lazy_now); for (int i = 0; i < work_batch_size_; i++) { - { - base::AutoLock lock(any_thread_lock_); - any_thread().is_nested = is_nested; - DCHECK_EQ(any_thread().is_nested, delegate_->IsNested()); - - if (i == 0) { - any_thread().do_work_running_count++; - - if (!delayed) { - any_thread().immediate_do_work_posted_count--; - DCHECK_GE(any_thread().immediate_do_work_posted_count, 0); - } - } - - NotifyQueuesOfIncomingImmediateWorkOnMainThreadLocked(); - } - - UpdateWorkQueues(&lazy_now); - - internal::WorkQueue* work_queue = nullptr; + internal::WorkQueue* work_queue; if (!SelectWorkQueueToService(&work_queue)) break; - // NB this may unregister the queue. - switch (ProcessTaskFromWorkQueue(work_queue, is_nested, &lazy_now)) { + switch (ProcessTaskFromWorkQueue(work_queue, &lazy_now)) { case ProcessTaskResult::DEFERRED: // If a task was deferred, try again with another task. continue; @@ -299,111 +249,31 @@ return; // The TaskQueueManager got deleted, we must bail out. } + work_queue = nullptr; // The queue may have been unregistered. + + UpdateWorkQueues(lazy_now); + // Only run a single task per batch in nested run loops so that we can // properly exit the nested loop when someone calls RunLoop::Quit(). - if (is_nested) + if (delegate_->IsNested()) break; } + main_thread_pending_wakeups_.erase(base::TimeTicks()); + // TODO(alexclarke): Consider refactoring the above loop to terminate only // when there's no more work left to be done, rather than posting a // continuation task. - - { - MoveableAutoLock lock(any_thread_lock_); - base::Optional<base::TimeDelta> next_delay = - ComputeDelayTillNextTaskLocked(&lazy_now); - - any_thread().do_work_running_count--; - DCHECK_GE(any_thread().do_work_running_count, 0); - - any_thread().is_nested = is_nested; - DCHECK_EQ(any_thread().is_nested, delegate_->IsNested()); - - PostDoWorkContinuationLocked(next_delay, &lazy_now, std::move(lock)); - } + if (!selector_.EnabledWorkQueuesEmpty() || TryAdvanceTimeDomains()) + MaybeScheduleImmediateWork(FROM_HERE); } -void TaskQueueManager::PostDoWorkContinuationLocked( - base::Optional<base::TimeDelta> next_delay, - LazyNow* lazy_now, - MoveableAutoLock&& lock) { - base::TimeDelta delay; - - { - MoveableAutoLock auto_lock(std::move(lock)); - - // If there are no tasks left then we don't need to post a continuation. - if (!next_delay) { - // If there's a pending delayed DoWork, cancel it because it's not needed. - if (!next_delayed_do_work_.is_null()) { - next_delayed_do_work_ = base::TimeTicks(); - cancelable_delayed_do_work_closure_.Cancel(); - } - return; - } - - // If an immediate DoWork is posted, we don't need to post a continuation. - if (any_thread().immediate_do_work_posted_count > 0) - return; - - delay = next_delay.value(); - - // This isn't supposed to happen, but in case it does convert to - // non-delayed. - if (delay < base::TimeDelta()) - delay = base::TimeDelta(); - - if (delay.is_zero()) { - // If a delayed DoWork is pending then we don't need to post a - // continuation because it should run immediately. - if (!next_delayed_do_work_.is_null() && - next_delayed_do_work_ <= lazy_now->Now()) { - return; - } - - any_thread().immediate_do_work_posted_count++; - } else { - base::TimeTicks run_time = lazy_now->Now() + delay; - if (next_delayed_do_work_ == run_time) - return; - - next_delayed_do_work_ = run_time; - } - } - - // We avoid holding |any_thread_lock_| while posting the task. - if (delay.is_zero()) { - delegate_->PostTask(FROM_HERE, immediate_do_work_closure_); - } else { - cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_); - delegate_->PostDelayedTask( - FROM_HERE, cancelable_delayed_do_work_closure_.callback(), delay); - } -} - -base::Optional<base::TimeDelta> -TaskQueueManager::ComputeDelayTillNextTaskLocked(LazyNow* lazy_now) { - NotifyQueuesOfIncomingImmediateWorkOnMainThreadLocked(); - - // If the selector has non-empty queues we trivially know there is immediate - // word to be done. - if (!selector_.EnabledWorkQueuesEmpty()) - return base::TimeDelta(); - - UpdateWorkQueues(lazy_now); - - // Otherwise we need to find the shortest delay, if any. - base::Optional<base::TimeDelta> next_continuation; +bool TaskQueueManager::TryAdvanceTimeDomains() { + bool can_advance = false; for (TimeDomain* time_domain : time_domains_) { - base::Optional<base::TimeDelta> continuation = - time_domain->DelayTillNextTask(lazy_now); - if (!continuation) - continue; - if (!next_continuation || next_continuation.value() > continuation.value()) - next_continuation = continuation; + can_advance |= time_domain->MaybeAdvanceTime(); } - return next_continuation; + return can_advance; } bool TaskQueueManager::SelectWorkQueueToService( @@ -422,7 +292,6 @@ TaskQueueManager::ProcessTaskResult TaskQueueManager::ProcessTaskFromWorkQueue( internal::WorkQueue* work_queue, - bool is_nested, LazyNow* lazy_now) { DCHECK(main_thread_checker_.CalledOnValidThread()); scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); @@ -437,7 +306,7 @@ if (queue->GetQuiescenceMonitored()) task_was_run_on_quiescence_monitored_queue_ = true; - if (!pending_task.nestable && is_nested) { + if (!pending_task.nestable && delegate_->IsNested()) { // Defer non-nestable work to the main task runner. NOTE these tasks can be // arbitrarily delayed so the additional delay should not be a problem. // TODO(skyostil): Figure out a way to not forget which task queue the @@ -450,8 +319,7 @@ return ProcessTaskResult::DEFERRED; } - if (record_task_delay_histograms_) - MaybeRecordTaskDelayHistograms(pending_task, queue); + MaybeRecordTaskDelayHistograms(pending_task, queue); double task_start_time = 0; TRACE_TASK_EXECUTION("TaskQueueManager::ProcessTaskFromWorkQueue", @@ -602,22 +470,13 @@ for (auto* time_domain : time_domains_) time_domain->AsValueInto(state.get()); state->EndArray(); - - { - base::AutoLock lock(any_thread_lock_); - state->SetBoolean("is_nested", any_thread().is_nested); - state->SetInteger("do_work_running_count", - any_thread().do_work_running_count); - state->SetInteger("immediate_do_work_posted_count", - any_thread().immediate_do_work_posted_count); - } return std::move(state); } void TaskQueueManager::OnTaskQueueEnabled(internal::TaskQueueImpl* queue) { DCHECK(main_thread_checker_.CalledOnValidThread()); // Only schedule DoWork if there's something to do. - if (queue->HasPendingImmediateWork() && !queue->BlockedByFence()) + if (queue->HasPendingImmediateWork()) MaybeScheduleImmediateWork(FROM_HERE); } @@ -635,11 +494,5 @@ return !selector_.EnabledWorkQueuesEmpty(); } -void TaskQueueManager::SetRecordTaskDelayHistograms( - bool record_task_delay_histograms) { - DCHECK(main_thread_checker_.CalledOnValidThread()); - record_task_delay_histograms_ = record_task_delay_histograms; -} - } // namespace scheduler } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h index cd5df92..0fbfa7e 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h
@@ -8,7 +8,6 @@ #include <map> #include "base/atomic_sequence_num.h" -#include "base/cancelable_callback.h" #include "base/debug/task_annotator.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -17,7 +16,6 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" #include "platform/scheduler/base/enqueue_order.h" -#include "platform/scheduler/base/moveable_auto_lock.h" #include "platform/scheduler/base/task_queue_impl.h" #include "platform/scheduler/base/task_queue_selector.h" @@ -142,10 +140,6 @@ // Returns true if there is a task that could be executed immediately. bool HasImmediateWorkForTesting() const; - // There is a small overhead to recording task delay histograms. If you don't - // need them, you can turn them off. - void SetRecordTaskDelayHistograms(bool record_task_delay_histograms); - private: friend class LazyNow; friend class internal::TaskQueueImpl; @@ -158,6 +152,9 @@ }; // Unregisters a TaskQueue previously created by |NewTaskQueue()|. + // NOTE we have to flush the queue from |newly_updatable_| which means as a + // side effect MoveNewlyUpdatableQueuesIntoUpdatableQueueSet is called by this + // function. void UnregisterTaskQueue(scoped_refptr<internal::TaskQueueImpl> task_queue); // TaskQueueSelector::Observer implementation: @@ -172,16 +169,11 @@ void DidQueueTask(const internal::TaskQueueImpl::Task& pending_task); // Use the selector to choose a pending task and run it. - void DoWork(bool delayed); - - // Post a DoWork continuation if |next_delay| is not empty. - void PostDoWorkContinuationLocked(base::Optional<base::TimeDelta> next_delay, - LazyNow* lazy_now, - MoveableAutoLock&& lock); + void DoWork(base::TimeTicks run_time, bool from_main_thread); // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and // reloads any empty work queues. - void UpdateWorkQueues(LazyNow* lazy_now); + void UpdateWorkQueues(LazyNow lazy_now); // Chooses the next work queue to service. Returns true if |out_queue| // indicates the queue from which the next task should be run, false to @@ -197,8 +189,7 @@ TASK_QUEUE_MANAGER_DELETED }; ProcessTaskResult ProcessTaskFromWorkQueue(internal::WorkQueue* work_queue, - bool is_nested, - LazyNow* lazy_now); + LazyNow*); bool RunsTasksOnCurrentThread() const; bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, @@ -207,10 +198,9 @@ internal::EnqueueOrder GetNextSequenceNumber(); - // Calls DelayTillNextTask on all time domains and returns the smallest delay - // requested if any. - base::Optional<base::TimeDelta> ComputeDelayTillNextTaskLocked( - LazyNow* lazy_now); + // Calls MaybeAdvanceTime on all time domains and returns true if one of them + // was able to advance. + bool TryAdvanceTimeDomains(); void MaybeRecordTaskDelayHistograms( const internal::TaskQueueImpl::Task& pending_task, @@ -220,17 +210,6 @@ AsValueWithSelectorResult(bool should_run, internal::WorkQueue* selected_work_queue) const; - void MaybeScheduleImmediateWorkLocked( - const tracked_objects::Location& from_here, - MoveableAutoLock&& lock); - - // Adds |queue| to |has_incoming_immediate_work_| and if - // |ensure_do_work_posted| is true it calls MaybeScheduleImmediateWorkLocked. - void OnQueueHasImmediateWork(internal::TaskQueueImpl* queue, - bool ensure_do_work_posted); - - void NotifyQueuesOfIncomingImmediateWorkOnMainThreadLocked(); - std::set<TimeDomain*> time_domains_; std::unique_ptr<RealTimeDomain> real_time_domain_; @@ -247,35 +226,18 @@ scoped_refptr<TaskQueueManagerDelegate> delegate_; internal::TaskQueueSelector selector_; - base::Closure immediate_do_work_closure_; - base::Closure delayed_do_work_closure_; + base::Closure from_main_thread_immediate_do_work_closure_; + base::Closure from_other_thread_immediate_do_work_closure_; bool task_was_run_on_quiescence_monitored_queue_; - struct AnyThread { - AnyThread(); + // To reduce locking overhead we track pending calls to DoWork separately for + // the main thread and other threads. + std::set<base::TimeTicks> main_thread_pending_wakeups_; - int do_work_running_count; - int immediate_do_work_posted_count; - std::set<internal::TaskQueueImpl*> has_incoming_immediate_work; - bool is_nested; // Whether or not the message loop is currently nested. - }; - - mutable base::Lock any_thread_lock_; - AnyThread any_thread_; - struct AnyThread& any_thread() { - any_thread_lock_.AssertAcquired(); - return any_thread_; - } - const struct AnyThread& any_thread() const { - any_thread_lock_.AssertAcquired(); - return any_thread_; - } - - bool record_task_delay_histograms_; - - base::TimeTicks next_delayed_do_work_; - base::CancelableClosure cancelable_delayed_do_work_closure_; + // Protects |other_thread_pending_wakeup_|. + mutable base::Lock other_thread_lock_; + bool other_thread_pending_wakeup_; int work_batch_size_; size_t task_count_;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc index a7f7454..b0f03a6 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
@@ -32,14 +32,13 @@ PerfTestTimeDomain() : VirtualTimeDomain(nullptr, base::TimeTicks::Now()) {} ~PerfTestTimeDomain() override {} - base::Optional<base::TimeDelta> DelayTillNextTask( - LazyNow* lazy_now) override { + bool MaybeAdvanceTime() override { base::TimeTicks run_time; if (!NextScheduledRunTime(&run_time)) - return base::Optional<base::TimeDelta>(); + return false; AdvanceTo(run_time); - return base::TimeDelta(); // Makes DoWork post an immediate continuation. + return true; } void RequestWakeup(base::TimeTicks now, base::TimeDelta delay) override {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc index 88d9331..97ef5e95 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -117,34 +117,7 @@ } void UpdateWorkQueues(LazyNow lazy_now) { - manager_->UpdateWorkQueues(&lazy_now); - } - - base::Optional<base::TimeDelta> ComputeDelayTillNextTask(LazyNow* lazy_now) { - base::AutoLock lock(manager_->any_thread_lock_); - return manager_->ComputeDelayTillNextTaskLocked(lazy_now); - } - - void PostDoWorkContinuation(base::Optional<base::TimeDelta> next_delay, - LazyNow* lazy_now) { - MoveableAutoLock lock(manager_->any_thread_lock_); - return manager_->PostDoWorkContinuationLocked(next_delay, lazy_now, - std::move(lock)); - } - - int immediate_do_work_posted_count() const { - base::AutoLock lock(manager_->any_thread_lock_); - return manager_->any_thread().immediate_do_work_posted_count; - } - - base::TimeTicks next_delayed_do_work() const { - return manager_->next_delayed_do_work_; - } - - void MaybeScheduleImmediateWorkLocked( - const tracked_objects::Location& from_here) { - MoveableAutoLock lock(manager_->any_thread_lock_); - manager_->MaybeScheduleImmediateWorkLocked(from_here, std::move(lock)); + manager_->UpdateWorkQueues(lazy_now); } // Runs all immediate tasks until there is no more work to do and advances @@ -516,34 +489,6 @@ EXPECT_THAT(run_order, ElementsAre(1)); } -TEST_F(TaskQueueManagerTest, RemovingFenceForDisabledQueueDoesNotPostDoWork) { - Initialize(1u); - - std::vector<EnqueueOrder> run_order; - std::unique_ptr<TaskQueue::QueueEnabledVoter> voter = - runners_[0]->CreateQueueEnabledVoter(); - voter->SetQueueEnabled(false); - runners_[0]->InsertFence(TaskQueue::InsertFencePosition::NOW); - runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); - - runners_[0]->RemoveFence(); - EXPECT_FALSE(test_task_runner_->HasPendingTasks()); -} - -TEST_F(TaskQueueManagerTest, EnablingFencedQueueDoesNotPostDoWork) { - Initialize(1u); - - std::vector<EnqueueOrder> run_order; - std::unique_ptr<TaskQueue::QueueEnabledVoter> voter = - runners_[0]->CreateQueueEnabledVoter(); - voter->SetQueueEnabled(false); - runners_[0]->InsertFence(TaskQueue::InsertFencePosition::NOW); - runners_[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order)); - - voter->SetQueueEnabled(true); - EXPECT_FALSE(test_task_runner_->HasPendingTasks()); -} - TEST_F(TaskQueueManagerTest, DenyRunning_BeforePosting) { Initialize(1u); @@ -2217,199 +2162,5 @@ voter.reset(); } -TEST_F(TaskQueueManagerTest, ComputeDelayTillNextTask) { - Initialize(2u); - - std::unique_ptr<RealTimeDomain> domain2(new RealTimeDomain("test")); - manager_->RegisterTimeDomain(domain2.get()); - runners_[1]->SetTimeDomain(domain2.get()); - - LazyNow lazy_now(now_src_.get()); - EXPECT_FALSE(static_cast<bool>(ComputeDelayTillNextTask(&lazy_now))); - - runners_[0]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(10)); - - EXPECT_EQ(base::TimeDelta::FromSeconds(10), - ComputeDelayTillNextTask(&lazy_now).value()); - - runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(15)); - - EXPECT_EQ(base::TimeDelta::FromSeconds(10), - ComputeDelayTillNextTask(&lazy_now).value()); - - runners_[1]->PostDelayedTask(FROM_HERE, base::Bind(&NopTask), - base::TimeDelta::FromSeconds(5)); - - EXPECT_EQ(base::TimeDelta::FromSeconds(5), - ComputeDelayTillNextTask(&lazy_now).value()); - - runners_[0]->PostTask(FROM_HERE, base::Bind(&NopTask)); - - EXPECT_EQ(base::TimeDelta(), ComputeDelayTillNextTask(&lazy_now).value()); - - // Tidy up. - runners_[1]->UnregisterTaskQueue(); - manager_->UnregisterTimeDomain(domain2.get()); -} - -TEST_F(TaskQueueManagerTest, PostDoWorkContinuation_NoMoreWork) { - Initialize(1u); - - LazyNow lazy_now(now_src_.get()); - PostDoWorkContinuation(base::Optional<base::TimeDelta>(), &lazy_now); - - EXPECT_EQ(0u, test_task_runner_->NumPendingTasks()); - EXPECT_EQ(0, immediate_do_work_posted_count()); - EXPECT_TRUE(next_delayed_do_work().is_null()); -} - -TEST_F(TaskQueueManagerTest, PostDoWorkContinuation_ImmediateWork) { - Initialize(1u); - - LazyNow lazy_now(now_src_.get()); - PostDoWorkContinuation(base::TimeDelta(), &lazy_now); - - EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); - EXPECT_EQ(base::TimeDelta(), test_task_runner_->DelayToNextTaskTime()); - EXPECT_EQ(1, immediate_do_work_posted_count()); - EXPECT_TRUE(next_delayed_do_work().is_null()); -} - -TEST_F(TaskQueueManagerTest, PostDoWorkContinuation_DelayedWork) { - Initialize(1u); - - LazyNow lazy_now(now_src_.get()); - PostDoWorkContinuation(base::TimeDelta::FromSeconds(1), &lazy_now); - - EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); - EXPECT_EQ(base::TimeDelta::FromSeconds(1), - test_task_runner_->DelayToNextTaskTime()); - EXPECT_EQ(0, immediate_do_work_posted_count()); - EXPECT_EQ(lazy_now.Now() + base::TimeDelta::FromSeconds(1), - next_delayed_do_work()); -} - -TEST_F(TaskQueueManagerTest, - PostDoWorkContinuation_DelayedWorkButImmediateDoWorkAlreadyPosted) { - Initialize(1u); - - MaybeScheduleImmediateWorkLocked(FROM_HERE); - EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); - EXPECT_EQ(base::TimeDelta(), test_task_runner_->DelayToNextTaskTime()); - EXPECT_EQ(1, immediate_do_work_posted_count()); - - LazyNow lazy_now(now_src_.get()); - PostDoWorkContinuation(base::TimeDelta::FromSeconds(1), &lazy_now); - - // Test that a delayed task didn't get posted. - EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); - EXPECT_EQ(base::TimeDelta(), test_task_runner_->DelayToNextTaskTime()); - EXPECT_EQ(1, immediate_do_work_posted_count()); - EXPECT_TRUE(next_delayed_do_work().is_null()); -} - -TEST_F(TaskQueueManagerTest, PostDoWorkContinuation_DelayedWorkTimeChanges) { - Initialize(1u); - - LazyNow lazy_now(now_src_.get()); - PostDoWorkContinuation(base::TimeDelta::FromSeconds(1), &lazy_now); - - EXPECT_TRUE(test_task_runner_->HasPendingTasks()); - EXPECT_EQ(0, immediate_do_work_posted_count()); - EXPECT_EQ(base::TimeDelta::FromSeconds(1), - test_task_runner_->DelayToNextTaskTime()); - EXPECT_EQ(lazy_now.Now() + base::TimeDelta::FromSeconds(1), - next_delayed_do_work()); - - PostDoWorkContinuation(base::TimeDelta::FromSeconds(10), &lazy_now); - - // This should have resulted in the previous task getting canceled and a new - // one getting posted. - EXPECT_EQ(2u, test_task_runner_->NumPendingTasks()); - test_task_runner_->RemoveCancelledTasks(); - EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); - EXPECT_EQ(base::TimeDelta::FromSeconds(10), - test_task_runner_->DelayToNextTaskTime()); - EXPECT_EQ(0, immediate_do_work_posted_count()); - EXPECT_EQ(lazy_now.Now() + base::TimeDelta::FromSeconds(10), - next_delayed_do_work()); -} - -TEST_F(TaskQueueManagerTest, - PostDoWorkContinuation_ImmediateWorkButDelayedDoWorkPending) { - Initialize(1u); - - LazyNow lazy_now(now_src_.get()); - PostDoWorkContinuation(base::TimeDelta::FromSeconds(1), &lazy_now); - - now_src_->Advance(base::TimeDelta::FromSeconds(1)); - lazy_now = LazyNow(now_src_.get()); - PostDoWorkContinuation(base::TimeDelta(), &lazy_now); - - // Because the delayed DoWork was pending we don't expect an immediate DoWork - // to get posted. - EXPECT_EQ(1u, test_task_runner_->NumPendingTasks()); - EXPECT_EQ(base::TimeDelta(), test_task_runner_->DelayToNextTaskTime()); - EXPECT_EQ(0, immediate_do_work_posted_count()); - EXPECT_EQ(lazy_now.Now(), next_delayed_do_work()); -} - -namespace { -void MessageLoopTaskWithDelayedQuit( - base::MessageLoop* message_loop, - base::SimpleTestTickClock* now_src, - scoped_refptr<internal::TaskQueueImpl> task_queue) { - base::MessageLoop::ScopedNestableTaskAllower allow(message_loop); - base::RunLoop run_loop; - task_queue->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), - base::TimeDelta::FromMilliseconds(100)); - now_src->Advance(base::TimeDelta::FromMilliseconds(200)); - run_loop.Run(); -} -} // namespace - -TEST_F(TaskQueueManagerTest, DelayedTaskRunsInNestedMessageLoop) { - InitializeWithRealMessageLoop(1u); - base::RunLoop run_loop; - runners_[0]->PostTask( - FROM_HERE, - base::Bind(&MessageLoopTaskWithDelayedQuit, message_loop_.get(), - now_src_.get(), base::RetainedRef(runners_[0]))); - run_loop.RunUntilIdle(); -} - -namespace { -void MessageLoopTaskWithImmediateQuit( - base::MessageLoop* message_loop, - base::Closure non_nested_quit_closure, - scoped_refptr<internal::TaskQueueImpl> task_queue) { - base::MessageLoop::ScopedNestableTaskAllower allow(message_loop); - - base::RunLoop run_loop; - // Needed because entering the nested message loop causes a DoWork to get - // posted. - task_queue->PostTask(FROM_HERE, base::Bind(&NopTask)); - task_queue->PostTask(FROM_HERE, run_loop.QuitClosure()); - run_loop.Run(); - non_nested_quit_closure.Run(); -} -} // namespace - -TEST_F(TaskQueueManagerTest, - DelayedNestedMessageLoopDoesntPreventTasksRunning) { - InitializeWithRealMessageLoop(1u); - base::RunLoop run_loop; - runners_[0]->PostDelayedTask( - FROM_HERE, - base::Bind(&MessageLoopTaskWithImmediateQuit, message_loop_.get(), - run_loop.QuitClosure(), base::RetainedRef(runners_[0])), - base::TimeDelta::FromMilliseconds(100)); - - now_src_->Advance(base::TimeDelta::FromMilliseconds(200)); - run_loop.Run(); -} - } // namespace scheduler } // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc index 0a24636c..d7c5c29 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_selector.cc
@@ -163,14 +163,12 @@ WorkQueue** out_work_queue) const { WorkQueue* immediate_queue; DCHECK_EQ(*out_chose_delayed_over_immediate, false); - EnqueueOrder immediate_enqueue_order; - if (immediate_work_queue_sets_.GetOldestQueueAndEnqueueOrderInSet( - priority, &immediate_queue, &immediate_enqueue_order)) { + if (immediate_work_queue_sets_.GetOldestQueueInSet(priority, + &immediate_queue)) { WorkQueue* delayed_queue; - EnqueueOrder delayed_enqueue_order; - if (delayed_work_queue_sets_.GetOldestQueueAndEnqueueOrderInSet( - priority, &delayed_queue, &delayed_enqueue_order)) { - if (immediate_enqueue_order < delayed_enqueue_order) { + if (delayed_work_queue_sets_.GetOldestQueueInSet(priority, + &delayed_queue)) { + if (immediate_queue->ShouldRunBefore(delayed_queue)) { *out_work_queue = immediate_queue; } else { *out_chose_delayed_over_immediate = true; @@ -191,9 +189,13 @@ // Select an immediate work queue if we are starving immediate tasks. if (task_queue_selector_->immediate_starvation_count_ >= kMaxDelayedStarvationTasks) { - if (ChooseOldestImmediateTaskWithPriority(priority, out_work_queue)) + if (ChooseOldestImmediateTaskWithPriority(priority, out_work_queue)) { return true; - return ChooseOldestDelayedTaskWithPriority(priority, out_work_queue); + } + if (ChooseOldestDelayedTaskWithPriority(priority, out_work_queue)) { + return true; + } + return false; } return ChooseOldestImmediateOrDelayedTaskWithPriority( priority, out_chose_delayed_over_immediate, out_work_queue);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc index d326318..59e3e34 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
@@ -27,6 +27,7 @@ void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) { DCHECK(main_thread_checker_.CalledOnValidThread()); DCHECK_EQ(queue->GetTimeDomain(), this); + UnregisterAsUpdatableTaskQueue(queue); // If no wakeup has been requested then bail out. if (!queue->heap_handle().IsValid()) @@ -44,6 +45,11 @@ DCHECK_EQ(queue->GetTimeDomain(), this); DCHECK(destination_time_domain); + // Make sure we remember to update |queue| if it's got incoming immediate + // work. + if (UnregisterAsUpdatableTaskQueue(queue)) + destination_time_domain->updatable_queue_set_.insert(queue); + // If no wakeup has been requested then bail out. if (!queue->heap_handle().IsValid()) return; @@ -88,11 +94,66 @@ observer_->OnTimeDomainHasDelayedWork(queue); } -void TimeDomain::OnQueueHasImmediateWork(internal::TaskQueueImpl* queue) { +void TimeDomain::RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue) { + { + base::AutoLock lock(newly_updatable_lock_); + newly_updatable_.push_back(queue); + } if (observer_) observer_->OnTimeDomainHasImmediateWork(queue); } +bool TimeDomain::UnregisterAsUpdatableTaskQueue( + internal::TaskQueueImpl* queue) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + bool was_updatable = updatable_queue_set_.erase(queue) != 0; + + base::AutoLock lock(newly_updatable_lock_); + // Remove all copies of |queue| from |newly_updatable_|. + for (size_t i = 0; i < newly_updatable_.size();) { + if (newly_updatable_[i] == queue) { + // Move last element into slot #i and then compact. + newly_updatable_[i] = newly_updatable_.back(); + newly_updatable_.pop_back(); + was_updatable = true; + } else { + i++; + } + } + return was_updatable; +} + +void TimeDomain::UpdateWorkQueues(LazyNow lazy_now) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + // Move any ready delayed tasks into the Incoming queues. + WakeupReadyDelayedQueues(&lazy_now); + + MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); + + std::set<internal::TaskQueueImpl*>::iterator iter = + updatable_queue_set_.begin(); + while (iter != updatable_queue_set_.end()) { + std::set<internal::TaskQueueImpl*>::iterator queue_it = iter++; + internal::TaskQueueImpl* queue = *queue_it; + + // Update the queue and remove from the set if subsequent updates are not + // required. + if (!queue->MaybeUpdateImmediateWorkQueues()) + updatable_queue_set_.erase(queue_it); + } +} + +void TimeDomain::MoveNewlyUpdatableQueuesIntoUpdatableQueueSet() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + base::AutoLock lock(newly_updatable_lock_); + while (!newly_updatable_.empty()) { + updatable_queue_set_.insert(newly_updatable_.back()); + newly_updatable_.pop_back(); + } +} + void TimeDomain::WakeupReadyDelayedQueues(LazyNow* lazy_now) { DCHECK(main_thread_checker_.CalledOnValidThread()); // Wake up any queues with pending delayed work. Note std::multipmap stores @@ -101,18 +162,10 @@ while (!delayed_wakeup_queue_.empty() && delayed_wakeup_queue_.min().time <= lazy_now->Now()) { internal::TaskQueueImpl* queue = delayed_wakeup_queue_.min().queue; - base::Optional<base::TimeTicks> next_wakeup = - queue->WakeUpForDelayedWork(lazy_now); + // O(log n) + delayed_wakeup_queue_.pop(); - if (next_wakeup) { - // O(log n) - delayed_wakeup_queue_.ChangeKey(queue->heap_handle(), - {next_wakeup.value(), queue}); - queue->set_scheduled_time_domain_wakeup(next_wakeup.value()); - } else { - // O(log n) - delayed_wakeup_queue_.pop(); - } + queue->WakeUpForDelayedWork(lazy_now); } } @@ -137,6 +190,10 @@ void TimeDomain::AsValueInto(base::trace_event::TracedValue* state) const { state->BeginDictionary(); state->SetString("name", GetName()); + state->BeginArray("updatable_queue_set"); + for (auto* queue : updatable_queue_set_) + state->AppendString(queue->GetName()); + state->EndArray(); state->SetInteger("registered_delay_count", delayed_wakeup_queue_.size()); if (!delayed_wakeup_queue_.empty()) { base::TimeDelta delay = delayed_wakeup_queue_.min().time - Now();
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h index 4947fd5..639d174 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
@@ -62,11 +62,9 @@ // Evaluate this TimeDomain's Now. Can be called from any thread. virtual base::TimeTicks Now() const = 0; - // Computes the delay until the next task the TimeDomain is aware of, if any. - // Note virtual time domains may return base::TimeDelta() if they have any - // tasks that are eligible to run. - virtual base::Optional<base::TimeDelta> DelayTillNextTask( - LazyNow* lazy_now) = 0; + // Some TimeDomains support virtual time, this method tells us to advance time + // if possible and return true if time was advanced. + virtual bool MaybeAdvanceTime() = 0; // Returns the name of this time domain for tracing. virtual const char* GetName() const = 0; @@ -90,6 +88,10 @@ // the next task was posted to and it returns true. Returns false otherwise. bool NextScheduledTaskQueue(TaskQueue** out_task_queue) const; + // Adds |queue| to the set of task queues that UpdateWorkQueues calls + // UpdateWorkQueue on. + void RegisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue); + // Schedules a call to TaskQueueImpl::WakeUpForDelayedWork when this // TimeDomain reaches |delayed_run_time|. This supersedes any previously // registered wakeup for |queue|. @@ -100,12 +102,15 @@ // Registers the |queue|. void RegisterQueue(internal::TaskQueueImpl* queue); + // Removes |queue| from the set of task queues that UpdateWorkQueues calls + // UpdateWorkQueue on. Returns true if |queue| was updatable. + bool UnregisterAsUpdatableTaskQueue(internal::TaskQueueImpl* queue); + // Removes |queue| from all internal data structures. void UnregisterQueue(internal::TaskQueueImpl* queue); - // Tells the time domain that |queue| went from having no immediate work to - // having some. - void OnQueueHasImmediateWork(internal::TaskQueueImpl* queue); + // Updates active queues associated with this TimeDomain. + void UpdateWorkQueues(LazyNow lazy_now); // Called by the TaskQueueManager when the TimeDomain is registered. virtual void OnRegisterWithTaskQueueManager( @@ -131,6 +136,8 @@ } private: + void MoveNewlyUpdatableQueuesIntoUpdatableQueueSet(); + struct DelayedWakeup { base::TimeTicks time; internal::TaskQueueImpl* queue; @@ -157,6 +164,15 @@ IntrusiveHeap<DelayedWakeup> delayed_wakeup_queue_; + // This lock guards only |newly_updatable_|. It's not expected to be heavily + // contended. + base::Lock newly_updatable_lock_; + std::vector<internal::TaskQueueImpl*> newly_updatable_; + + // Set of task queues with avaliable work on the incoming queue. This should + // only be accessed from the main thread. + std::set<internal::TaskQueueImpl*> updatable_queue_set_; + Observer* observer_; // NOT OWNED. base::ThreadChecker main_thread_checker_;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc index 09a253c..69224757 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
@@ -34,8 +34,8 @@ using TimeDomain::NextScheduledTaskQueue; using TimeDomain::ScheduleDelayedWork; using TimeDomain::UnregisterQueue; - using TimeDomain::OnQueueHasImmediateWork; - using TimeDomain::WakeupReadyDelayedQueues; + using TimeDomain::UpdateWorkQueues; + using TimeDomain::RegisterAsUpdatableTaskQueue; // TimeSource implementation: LazyNow CreateLazyNow() const override { return LazyNow(now_); } @@ -44,10 +44,7 @@ void AsValueIntoInternal( base::trace_event::TracedValue* state) const override {} - base::Optional<base::TimeDelta> DelayTillNextTask( - LazyNow* lazy_now) override { - return base::Optional<base::TimeDelta>(); - } + bool MaybeAdvanceTime() override { return false; } const char* GetName() const override { return "Test"; } void OnRegisterWithTaskQueueManager( TaskQueueManager* task_queue_manager) override {} @@ -194,7 +191,7 @@ EXPECT_FALSE(time_domain_->NextScheduledTaskQueue(&next_task_queue)); } -TEST_F(TimeDomainTest, WakeupReadyDelayedQueues) { +TEST_F(TimeDomainTest, UpdateWorkQueues) { base::TimeDelta delay = base::TimeDelta::FromMilliseconds(50); EXPECT_CALL(*time_domain_.get(), RequestWakeup(_, delay)); base::TimeTicks now = time_domain_->Now(); @@ -206,13 +203,13 @@ EXPECT_EQ(delayed_runtime, next_run_time); LazyNow lazy_now = time_domain_->CreateLazyNow(); - time_domain_->WakeupReadyDelayedQueues(&lazy_now); + time_domain_->UpdateWorkQueues(lazy_now); ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time)); EXPECT_EQ(delayed_runtime, next_run_time); time_domain_->SetNow(delayed_runtime); lazy_now = time_domain_->CreateLazyNow(); - time_domain_->WakeupReadyDelayedQueues(&lazy_now); + time_domain_->UpdateWorkQueues(lazy_now); ASSERT_FALSE(time_domain_->NextScheduledRunTime(&next_run_time)); } @@ -238,7 +235,7 @@ TEST_F(TimeDomainWithObserverTest, OnTimeDomainHasImmediateWork) { EXPECT_CALL(*observer_, OnTimeDomainHasImmediateWork(task_queue_.get())); - time_domain_->OnQueueHasImmediateWork(task_queue_.get()); + time_domain_->RegisterAsUpdatableTaskQueue(task_queue_.get()); } TEST_F(TimeDomainWithObserverTest, OnTimeDomainHasDelayedWork) {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.cc index f40c6307..a22796c5d 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.cc
@@ -41,9 +41,8 @@ // needed. } -base::Optional<base::TimeDelta> VirtualTimeDomain::DelayTillNextTask( - LazyNow* lazy_now) { - return base::Optional<base::TimeDelta>(); +bool VirtualTimeDomain::MaybeAdvanceTime() { + return false; } void VirtualTimeDomain::AsValueIntoInternal(
diff --git a/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.h b/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.h index a841226..715948d 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.h +++ b/third_party/WebKit/Source/platform/scheduler/base/virtual_time_domain.h
@@ -21,7 +21,7 @@ // TimeDomain implementation: LazyNow CreateLazyNow() const override; base::TimeTicks Now() const override; - base::Optional<base::TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override; + bool MaybeAdvanceTime() override; const char* GetName() const override; // Advances this time domain to |now|. NOTE |now| is supposed to be
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue.cc b/third_party/WebKit/Source/platform/scheduler/base/work_queue.cc index ac312f9..fe16858 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue.cc
@@ -10,15 +10,12 @@ namespace scheduler { namespace internal { -WorkQueue::WorkQueue(TaskQueueImpl* task_queue, - const char* name, - QueueType queue_type) +WorkQueue::WorkQueue(TaskQueueImpl* task_queue, const char* name) : work_queue_sets_(nullptr), task_queue_(task_queue), work_queue_set_index_(0), name_(name), - fence_(0), - queue_type_(queue_type) {} + fence_(0) {} void WorkQueue::AsValueInto(base::trace_event::TracedValue* state) const { // Remove const to search |work_queue_| in the destructive manner. Restore the @@ -119,10 +116,6 @@ TaskQueueImpl::Task pending_task = std::move(const_cast<TaskQueueImpl::Task&>(work_queue_.front())); work_queue_.pop(); - // NB immediate tasks have a different pipeline to delayed ones. - if (queue_type_ == QueueType::IMMEDIATE && work_queue_.empty()) - task_queue_->OnImmediateWorkQueueHasBecomeEmpty(&work_queue_); - // OnPopQueue checks BlockedByFence() so we don't need to here. work_queue_sets_->OnPopQueue(this); task_queue_->TraceQueueSize(false); return pending_task;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue.h b/third_party/WebKit/Source/platform/scheduler/base/work_queue.h index 9fedd55..998fc62d 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue.h +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue.h
@@ -31,9 +31,7 @@ // throttling mechanisms. class BLINK_PLATFORM_EXPORT WorkQueue { public: - enum class QueueType { DELAYED, IMMEDIATE }; - - WorkQueue(TaskQueueImpl* task_queue, const char* name, QueueType queue_type); + WorkQueue(TaskQueueImpl* task_queue, const char* name); ~WorkQueue(); // Associates this work queue with the given work queue sets. This must be @@ -122,7 +120,6 @@ HeapHandle heap_handle_; const char* name_; EnqueueOrder fence_; - QueueType queue_type_; DISALLOW_COPY_AND_ASSIGN(WorkQueue); };
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.cc b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.cc index 8c608b0..bec08d1 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.cc
@@ -63,8 +63,6 @@ size_t set_index = work_queue->work_queue_set_index(); DCHECK_LT(set_index, work_queue_heaps_.size()) << " set_index = " << set_index; - // |work_queue| should not be in work_queue_heaps_[set_index]. - DCHECK(!work_queue->heap_handle().IsValid()); work_queue_heaps_[set_index].insert({enqueue_order, work_queue}); } @@ -83,8 +81,6 @@ } else { // O(log n) work_queue_heaps_[set_index].pop(); - DCHECK(work_queue_heaps_[set_index].empty() || - work_queue_heaps_[set_index].min().value != work_queue); } } @@ -107,18 +103,6 @@ return true; } -bool WorkQueueSets::GetOldestQueueAndEnqueueOrderInSet( - size_t set_index, - WorkQueue** out_work_queue, - EnqueueOrder* out_enqueue_order) const { - DCHECK_LT(set_index, work_queue_heaps_.size()); - if (work_queue_heaps_[set_index].empty()) - return false; - *out_work_queue = work_queue_heaps_[set_index].min().value; - *out_enqueue_order = work_queue_heaps_[set_index].min().key; - return true; -} - bool WorkQueueSets::IsSetEmpty(size_t set_index) const { DCHECK_LT(set_index, work_queue_heaps_.size()) << " set_index = " << set_index;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.h b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.h index 23668ff..7f80725 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.h +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets.h
@@ -56,12 +56,6 @@ bool GetOldestQueueInSet(size_t set_index, WorkQueue** out_work_queue) const; // O(1) - bool GetOldestQueueAndEnqueueOrderInSet( - size_t set_index, - WorkQueue** out_work_queue, - EnqueueOrder* out_enqueue_order) const; - - // O(1) bool IsSetEmpty(size_t set_index) const; #if DCHECK_IS_ON() || !defined(NDEBUG)
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc index b340d7a..4f8b081 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue_sets_unittest.cc
@@ -35,8 +35,7 @@ }; WorkQueue* NewTaskQueue(const char* queue_name) { - WorkQueue* queue = - new WorkQueue(nullptr, "test", WorkQueue::QueueType::IMMEDIATE); + WorkQueue* queue = new WorkQueue(nullptr, "test"); work_queues_.push_back(base::WrapUnique(queue)); work_queue_sets_->AddQueue(queue, TaskQueue::CONTROL_PRIORITY); return queue;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc index 2c111e2..caff182 100644 --- a/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc +++ b/third_party/WebKit/Source/platform/scheduler/base/work_queue_unittest.cc
@@ -28,8 +28,7 @@ new TaskQueueImpl(nullptr, time_domain_.get(), TaskQueue::Spec(TaskQueue::QueueType::TEST), "", "")); - work_queue_.reset(new WorkQueue(task_queue_.get(), "test", - WorkQueue::QueueType::IMMEDIATE)); + work_queue_.reset(new WorkQueue(task_queue_.get(), "test")); work_queue_sets_.reset(new WorkQueueSets(1, "test")); work_queue_sets_->AddQueue(work_queue_.get(), 0);
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc index 0bbbcbc1..5870d2f 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc +++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
@@ -18,19 +18,6 @@ const char* tracing_category, const char* disabled_by_default_tracing_category, const char* disabled_by_default_verbose_tracing_category) - : SchedulerHelper(task_queue_manager_delegate, - tracing_category, - disabled_by_default_tracing_category, - disabled_by_default_verbose_tracing_category, - TaskQueue::Spec(TaskQueue::QueueType::DEFAULT) - .SetShouldMonitorQuiescence(true)) {} - -SchedulerHelper::SchedulerHelper( - scoped_refptr<SchedulerTqmDelegate> task_queue_manager_delegate, - const char* tracing_category, - const char* disabled_by_default_tracing_category, - const char* disabled_by_default_verbose_tracing_category, - TaskQueue::Spec default_task_queue_spec) : task_queue_manager_delegate_(task_queue_manager_delegate), task_queue_manager_( new TaskQueueManager(task_queue_manager_delegate, @@ -40,7 +27,9 @@ control_task_runner_( NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::CONTROL) .SetShouldNotifyObservers(false))), - default_task_runner_(NewTaskQueue(default_task_queue_spec)), + default_task_runner_( + NewTaskQueue(TaskQueue::Spec(TaskQueue::QueueType::DEFAULT) + .SetShouldMonitorQuiescence(true))), observer_(nullptr), tracing_category_(tracing_category), disabled_by_default_tracing_category_( @@ -66,15 +55,6 @@ task_queue_manager_delegate_->RestoreDefaultTaskRunner(); } -void SchedulerHelper::SetRecordTaskDelayHistograms( - bool record_task_delay_histograms) { - if (!task_queue_manager_) - return; - - task_queue_manager_->SetRecordTaskDelayHistograms( - record_task_delay_histograms); -} - scoped_refptr<TaskQueue> SchedulerHelper::NewTaskQueue( const TaskQueue::Spec& spec) { DCHECK(task_queue_manager_.get());
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h index 67f978b..220ab7a 100644 --- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h +++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
@@ -28,18 +28,8 @@ const char* tracing_category, const char* disabled_by_default_tracing_category, const char* disabled_by_default_verbose_tracing_category); - SchedulerHelper( - scoped_refptr<SchedulerTqmDelegate> task_queue_manager_delegate, - const char* tracing_category, - const char* disabled_by_default_tracing_category, - const char* disabled_by_default_verbose_tracing_category, - TaskQueue::Spec default_task_queue_spec); ~SchedulerHelper() override; - // There is a small overhead to recording task delay histograms, we may not - // wish to do this on all threads. - void SetRecordTaskDelayHistograms(bool record_task_delay_histograms); - // TaskQueueManager::Observer implementation: void OnUnregisterTaskQueue(const scoped_refptr<TaskQueue>& queue) override; void OnTriedToExecuteBlockedTask(const TaskQueue& queue,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc index 455a0c2d..a34edb215 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.cc
@@ -14,14 +14,13 @@ AutoAdvancingVirtualTimeDomain::~AutoAdvancingVirtualTimeDomain() {} -base::Optional<base::TimeDelta> -AutoAdvancingVirtualTimeDomain::DelayTillNextTask(LazyNow* lazy_now) { +bool AutoAdvancingVirtualTimeDomain::MaybeAdvanceTime() { base::TimeTicks run_time; - if (!can_advance_virtual_time_ || !NextScheduledRunTime(&run_time)) - return base::Optional<base::TimeDelta>(); - + if (!can_advance_virtual_time_ || !NextScheduledRunTime(&run_time)) { + return false; + } AdvanceTo(run_time); - return base::TimeDelta(); // Makes DoWork post an immediate continuation. + return true; } void AutoAdvancingVirtualTimeDomain::RequestWakeup(base::TimeTicks now,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.h b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.h index 0ca186d..ffd880e 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.h +++ b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain.h
@@ -27,7 +27,7 @@ ~AutoAdvancingVirtualTimeDomain() override; // TimeDomain implementation: - base::Optional<base::TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override; + bool MaybeAdvanceTime() override; void RequestWakeup(base::TimeTicks now, base::TimeDelta delay) override; const char* GetName() const override;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.cc b/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.cc index db1d088..8f6887c 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.cc +++ b/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.cc
@@ -23,20 +23,19 @@ // behalf. } -base::Optional<base::TimeDelta> ThrottledTimeDomain::DelayTillNextTask( - LazyNow* lazy_now) { +bool ThrottledTimeDomain::MaybeAdvanceTime() { base::TimeTicks next_run_time; if (!NextScheduledRunTime(&next_run_time)) - return base::Optional<base::TimeDelta>(); + return false; - base::TimeTicks now = lazy_now->Now(); + base::TimeTicks now = Now(); if (now >= next_run_time) - return base::TimeDelta(); // Makes DoWork post an immediate continuation. + return true; // Causes DoWork to post a continuation. - // Unlike RealTimeDomain::ContinuationNeeded we don't request a wake up here, - // we assume the owner (i.e. TaskQueueThrottler) will manage wakeups on our + // Unlike RealTimeDomain::MaybeAdvanceTime we don't request a wake up here, we + // assume the owner (i.e. TaskQueueThrottler) will manage wakeups on our // behalf. - return base::Optional<base::TimeDelta>(); + return false; } } // namespace scheduler
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.h b/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.h index c9d73fa..ba59a6c2 100644 --- a/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.h +++ b/third_party/WebKit/Source/platform/scheduler/renderer/throttled_time_domain.h
@@ -22,7 +22,7 @@ // TimeDomain implementation: const char* GetName() const override; void RequestWakeup(base::TimeTicks now, base::TimeDelta delay) override; - base::Optional<base::TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override; + bool MaybeAdvanceTime() override; using TimeDomain::WakeupReadyDelayedQueues;
diff --git a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp index 38f6beb1..fdc093e 100644 --- a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp +++ b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
@@ -334,6 +334,16 @@ STATIC_ASSERT_ENUM(WebAXStateVertical, AXVerticalState); STATIC_ASSERT_ENUM(WebAXStateVisited, AXVisitedState); +STATIC_ASSERT_ENUM(WebAXSupportedAction::None, AXSupportedAction::None); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Activate, AXSupportedAction::Activate); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Check, AXSupportedAction::Check); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Click, AXSupportedAction::Click); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Jump, AXSupportedAction::Jump); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Open, AXSupportedAction::Open); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Press, AXSupportedAction::Press); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Select, AXSupportedAction::Select); +STATIC_ASSERT_ENUM(WebAXSupportedAction::Uncheck, AXSupportedAction::Uncheck); + STATIC_ASSERT_ENUM(WebAXTextDirectionLR, AccessibilityTextDirectionLTR); STATIC_ASSERT_ENUM(WebAXTextDirectionRL, AccessibilityTextDirectionRTL); STATIC_ASSERT_ENUM(WebAXTextDirectionTB, AccessibilityTextDirectionTTB);
diff --git a/third_party/WebKit/Source/web/WebAXObject.cpp b/third_party/WebKit/Source/web/WebAXObject.cpp index b9bb16cb..ebdf64a 100644 --- a/third_party/WebKit/Source/web/WebAXObject.cpp +++ b/third_party/WebKit/Source/web/WebAXObject.cpp
@@ -133,11 +133,11 @@ return !isDetached(); } -WebString WebAXObject::actionVerb() const { +WebAXSupportedAction WebAXObject::action() const { if (isDetached()) - return WebString(); + return WebAXSupportedAction::None; - return m_private->actionVerb(); + return static_cast<WebAXSupportedAction>(m_private->action()); } bool WebAXObject::canDecrement() const {
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py index 959f1fc..888ca82 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
@@ -55,8 +55,7 @@ def _run(self, args, cwd=None, - # pylint: disable=W0622 - # redefining built-in + # pylint: disable=redefined-builtin input=None, timeout_seconds=None, error_handler=None,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/multiprocessing_bootstrap.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/multiprocessing_bootstrap.py index 663b920..8e69516 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/multiprocessing_bootstrap.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/multiprocessing_bootstrap.py
@@ -39,7 +39,7 @@ import subprocess import sys -from webkitpy.common import version_check # 'unused import' pylint: disable=W0611 +from webkitpy.common import version_check # pylint: disable=unused-import def run(*parts):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py index 492eb45..30c3a8c7 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py
@@ -292,8 +292,9 @@ def interrupt(self, pid): interrupt_signal = signal.SIGINT - # FIXME: The python docs seem to imply that platform == 'win32' may need to use signal.CTRL_C_EVENT - # http://docs.python.org/2/library/signal.html + # Note: The python docs seem to suggest that on Windows, we may want to use + # signal.CTRL_C_EVENT (http://docs.python.org/2/library/signal.html), but + # it appears that signal.SIGINT also appears to work on Windows. try: os.kill(pid, interrupt_signal) except OSError:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py index 82ea5018..d5c918a 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py
@@ -98,8 +98,7 @@ args, cwd=None, input=None, - # pylint: disable=W0613 - # unused argument + # pylint: disable=unused-argument timeout_seconds=None, error_handler=None, return_exit_code=False, @@ -206,7 +205,7 @@ assert isinstance(args, list) or isinstance(args, tuple) assert all(isinstance(arg, basestring) for arg in args) if self._exception: - raise self._exception # pylint: disable=E0702 + raise self._exception # pylint: disable=raising-bad-type if self._run_command_fn: return self._run_command_fn(args) if return_exit_code:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py index 7495623..4e0e96e 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py
@@ -42,7 +42,7 @@ class GenericFileSystemTests(object): """Tests that should pass on either a real or mock filesystem.""" - # pylint gets confused about this being a mixin: pylint: disable=E1101 + # Pylint gets confused about this being a mixin: pylint: disable=no-member def setup_generic_test_dir(self): fs = self.fs
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/lint_test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/lint_test_expectations_unittest.py index 7626442..718dd73e 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/lint_test_expectations_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/lint_test_expectations_unittest.py
@@ -78,10 +78,10 @@ for port in ports: self.ports[port.name] = port - def get(self, port_name='a', *args, **kwargs): # pylint: disable=W0613,E0202 + def get(self, port_name='a', *args, **kwargs): # pylint: disable=unused-argument,method-hidden return self.ports[port_name] - def all_port_names(self, platform=None): # pylint: disable=W0613,E0202 + def all_port_names(self, platform=None): # pylint: disable=unused-argument,method-hidden return sorted(self.ports.keys()) @@ -109,8 +109,6 @@ options = optparse.Values({'platform': 'test-mac-mac10.10'}) host = MockHost() - # pylint appears to complain incorrectly about the method overrides pylint: disable=E0202,C0322 - # FIXME: incorrect complaints about spacing pylint: disable=C0322 host.port_factory.all_port_names = lambda platform=None: [platform] logger, handler = lint_test_expectations.set_up_logging(logging_stream) @@ -124,7 +122,6 @@ options = optparse.Values({'platform': 'test', 'debug_rwt_logging': False}) host = MockHost() - # FIXME: incorrect complaints about spacing pylint: disable=C0322 port = host.port_factory.get(options.platform, options=options) port.expectations_dict = lambda: {'foo': '-- syntax error1', 'bar': '-- syntax error2'} @@ -146,7 +143,6 @@ options = optparse.Values({'platform': 'test', 'debug_rwt_logging': False}) host = MockHost() - # FIXME: incorrect complaints about spacing pylint: disable=C0322 port = host.port_factory.get(options.platform, options=options) port.expectations_dict = lambda: {'flag-specific': 'does/not/exist', 'noproblem': ''} @@ -187,7 +183,7 @@ class MainTest(unittest.TestCase): - # unused args pylint: disable=W0613 + # pylint: disable=unused-argument def setUp(self): self.orig_lint_fn = lint_test_expectations.lint
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test.py index 0ac9b69..2608f57c 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test.py
@@ -56,7 +56,7 @@ """Overridden function from the base port class. Redirects everything to src/chrome/test/data/printing/layout_tests. """ - return self.path_from_chromium_base('chrome', 'test', 'data', 'printing', 'layout_tests') # pylint: disable=E1101 + return self.path_from_chromium_base('chrome', 'test', 'data', 'printing', 'layout_tests') # pylint: disable=no-member def check_sys_deps(self, needs_http): """This function is meant to be a no-op since we don't want to actually @@ -69,7 +69,7 @@ def default_timeout_ms(self): timeout_ms = 10 * 1000 - if self.get_option('configuration') == 'Debug': # pylint: disable=E1101 + if self.get_option('configuration') == 'Debug': # pylint: disable=no-member # Debug is usually 2x-3x slower than Release. return 3 * timeout_ms return timeout_ms @@ -89,7 +89,7 @@ def default_timeout_ms(self): timeout_ms = 20 * 1000 - if self.get_option('configuration') == 'Debug': # pylint: disable=E1101 + if self.get_option('configuration') == 'Debug': # pylint: disable=no-member # Debug is usually 2x-3x slower than Release. return 3 * timeout_ms return timeout_ms @@ -99,7 +99,7 @@ def default_timeout_ms(self): timeout_ms = 20 * 1000 - if self.get_option('configuration') == 'Debug': # pylint: disable=E1101 + if self.get_option('configuration') == 'Debug': # pylint: disable=no-member # Debug is usually 2x-3x slower than Release. return 3 * timeout_ms return timeout_ms
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py index 30e2a5a8..5cbd3e1 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
@@ -310,7 +310,7 @@ port.host.filesystem.write_text_file('/tmp/foo', 'foo') port.host.filesystem.write_text_file('/tmp/bar', 'bar') ordered_dict = port.expectations_dict() - self.assertEqual(ordered_dict.keys()[-2:], options.additional_expectations) # pylint: disable=E1101 + self.assertEqual(ordered_dict.keys()[-2:], options.additional_expectations) self.assertEqual(ordered_dict.values()[-2:], ['foo', 'bar']) def test_path_to_apache_config_file(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py index 1bfd90e6..1b300d1 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_unittest.py
@@ -1165,7 +1165,7 @@ def test_exception_handling(self): orig_run_fn = run_webkit_tests._run_tests - # unused args pylint: disable=W0613 + # pylint: disable=unused-argument def interrupting_run(port, options, args, printer): raise KeyboardInterrupt
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/server_base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/server_base.py index f56da73..988d650 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/server_base.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/server_base.py
@@ -275,7 +275,7 @@ except IOError as e: if e.errno in (errno.EALREADY, errno.EADDRINUSE): raise ServerError('Port %d is already in use.' % port) - elif self._platform.is_win() and e.errno in (errno.WSAEACCES,): # pylint: disable=E1101 + elif self._platform.is_win() and e.errno in (errno.WSAEACCES,): # pylint: disable=no-member raise ServerError('Port %d is already in use.' % port) else: raise
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/abstract_local_server_command.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/abstract_local_server_command.py index 91adde1..7da1460 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/abstract_local_server_command.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/abstract_local_server_command.py
@@ -54,5 +54,5 @@ # FIXME: This seems racy. threading.Timer(0.1, lambda: tool.user.open_url(server_url)).start() - httpd = self.server(httpd_port=options.httpd_port, config=config) # pylint: disable=E1102 + httpd = self.server(httpd_port=options.httpd_port, config=config) # pylint: disable=not-callable httpd.serve_forever()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py index 5439519..31830f7 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
@@ -25,7 +25,7 @@ def setUp(self): self.tool = MockWebKitPatch() - # lint warns that command_constructor might not be set, but this is intentional; pylint: disable=E1102 + # Lint warns that command_constructor might not be set, but this is intentional; pylint: disable=not-callable self.command = self.command_constructor() self.command._tool = self.tool self.tool.builders = BuilderList({
diff --git a/third_party/WebKit/public/platform/WebLocalizedString.h b/third_party/WebKit/public/platform/WebLocalizedString.h index 13ffbbc..766bbdcd 100644 --- a/third_party/WebKit/public/platform/WebLocalizedString.h +++ b/third_party/WebKit/public/platform/WebLocalizedString.h
@@ -36,18 +36,14 @@ struct WebLocalizedString { enum Name { AXAMPMFieldText, - AXButtonActionVerb, AXCalendarShowMonthSelector, AXCalendarShowNextMonth, AXCalendarShowPreviousMonth, AXCalendarWeekDescription, - AXCheckedCheckBoxActionVerb, AXDayOfMonthFieldText, - AXDefaultActionVerb, AXHeadingText, // Deprecated. AXHourFieldText, AXImageMapText, // Deprecated. - AXLinkActionVerb, AXLinkText, // Deprecated. AXListMarkerText, // Deprecated. AXMediaAudioElement, @@ -92,11 +88,7 @@ AXMillisecondFieldText, AXMinuteFieldText, AXMonthFieldText, - AXPopUpButtonActionVerb, - AXRadioButtonActionVerb, AXSecondFieldText, - AXTextFieldActionVerb, - AXUncheckedCheckBoxActionVerb, AXWebAreaText, // Deprecated. AXWeekOfYearFieldText, AXYearFieldText,
diff --git a/third_party/WebKit/public/web/WebAXEnums.h b/third_party/WebKit/public/web/WebAXEnums.h index 2e326123..20f3e78 100644 --- a/third_party/WebKit/public/web/WebAXEnums.h +++ b/third_party/WebKit/public/web/WebAXEnums.h
@@ -225,6 +225,18 @@ WebAXStateVisited, }; +enum class WebAXSupportedAction { + None = 0, + Activate, + Check, + Click, + Jump, + Open, + Press, + Select, + Uncheck +}; + enum WebAXTextDirection { WebAXTextDirectionLR, WebAXTextDirectionRL,
diff --git a/third_party/WebKit/public/web/WebAXObject.h b/third_party/WebKit/public/web/WebAXObject.h index 3666068d..3530215 100644 --- a/third_party/WebKit/public/web/WebAXObject.h +++ b/third_party/WebKit/public/web/WebAXObject.h
@@ -243,8 +243,7 @@ WebVector<int>& ends) const; // Actions - BLINK_EXPORT WebString - actionVerb() const; // The verb corresponding to performDefaultAction. + BLINK_EXPORT WebAXSupportedAction action() const; BLINK_EXPORT bool canDecrement() const; BLINK_EXPORT bool canIncrement() const; BLINK_EXPORT bool canPress() const;
diff --git a/third_party/fips181/BUILD.gn b/third_party/fips181/BUILD.gn index ad95212..9642a327 100644 --- a/third_party/fips181/BUILD.gn +++ b/third_party/fips181/BUILD.gn
@@ -8,7 +8,6 @@ "convert.h", "fips181.cc", "fips181.h", - "owntypes.h", "randpass.cc", "randpass.h", "smbl.h",
diff --git a/third_party/fips181/README.chromium b/third_party/fips181/README.chromium index 93af1b44..83a354b 100644 --- a/third_party/fips181/README.chromium +++ b/third_party/fips181/README.chromium
@@ -12,5 +12,14 @@ Local Modifications: -pronpass.c and pronpass.h were imported as files fips181.cc and fips181.h +pronpass.c and pronpass.h were imported as files fips181.cc and fips181.h. +owntypes.h was removed and the calling code changed to use standard C99/C++ +types. (At least 1 typedef (UINT32) conflicted with the same typedef in +windows.h.) Although the upstream code is vanilla C, bool is available without +stdbool.h here because we compile the code as C++. Vanilla C users must include +that header. + +Additionally, some variables and a function (is_restricted_symbol) have had +their types changed from int to bool (they were being used as bools). This +allows us to build the code warning-free in MSVC (warning C4805).
diff --git a/third_party/fips181/convert.cc b/third_party/fips181/convert.cc index 00af6a8e..a8e0a259 100644 --- a/third_party/fips181/convert.cc +++ b/third_party/fips181/convert.cc
@@ -108,7 +108,7 @@ (void)memcpy((void *)&tmp, (void *)syllable, sizeof(tmp)); for(i=0; i < 26; i++) if ( let[i] == tmp ) - if (is_restricted_symbol(clet[i]) != TRUE) + if (!is_restricted_symbol(clet[i])) (void)memcpy ((void *)syllable, (void *)&clet[i], 1); } } @@ -225,7 +225,7 @@ {126, "TILDE"} }; int i = 0; - int flag = FALSE; + bool flag = false; if (strlen(syllable) == 1) { @@ -234,10 +234,10 @@ if(*syllable == ssn[i].symbol) { (void)memcpy((void*)h_syllable, (void*)ssn[i].name, strlen(ssn[i].name)); - flag = TRUE; + flag = true; } } - if (flag != TRUE) + if (flag != true) (void)memcpy((void*)h_syllable, (void*)syllable, strlen(syllable)); } }
diff --git a/third_party/fips181/fips181.cc b/third_party/fips181/fips181.cc index a7725cbf..826ca794 100644 --- a/third_party/fips181/fips181.cc +++ b/third_party/fips181/fips181.cc
@@ -50,7 +50,7 @@ struct unit { char unit_code[5]; - USHORT flags; + unsigned short flags; }; static struct unit rules[] = @@ -1255,7 +1255,7 @@ ** buffer word. Also, the hyphenated word will be placed into ** the buffer hyphenated_word. Both word and hyphenated_word must ** be pre-allocated. The words generated will have sizes between -** minlen and maxlen. If restrict is TRUE, words will not be generated that +** minlen and maxlen. If restrict is true, words will not be generated that ** appear as login names or as entries in the on-line dictionary. ** This algorithm was initially worded out by Morrie Gasser in 1975. ** Any changes here are minimal so that as many word combinations @@ -1266,8 +1266,8 @@ ** could not be done. */ int -gen_pron_pass (char *word, char *hyphenated_word, USHORT minlen, - USHORT maxlen, unsigned int pass_mode) +gen_pron_pass (char *word, char *hyphenated_word, unsigned short minlen, + unsigned short maxlen, unsigned int pass_mode) { int pwlen; @@ -1309,19 +1309,19 @@ * will be found if the retry limit is adequately large enough. */ int -gen_word (char *word, char *hyphenated_word, USHORT pwlen, unsigned int pass_mode) +gen_word (char *word, char *hyphenated_word, unsigned short pwlen, unsigned int pass_mode) { - USHORT word_length; - USHORT syllable_length; + unsigned short word_length; + unsigned short syllable_length; char *new_syllable; char *syllable_for_hyph; - USHORT *syllable_units; - USHORT word_size; - USHORT word_place; - USHORT *word_units; - USHORT syllable_size; - UINT tries; - int ch_flag = FALSE; + unsigned short *syllable_units; + unsigned short word_size; + unsigned short word_place; + unsigned short *word_units; + unsigned short syllable_size; + unsigned int tries; + bool ch_flag = false; int dsd = 0; /* @@ -1350,9 +1350,9 @@ * explicit rule limits the length of syllables, but digram rules and * heuristics do so indirectly. */ - if ( (word_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL || - (syllable_units = (USHORT *) calloc (sizeof (USHORT), pwlen+1))==NULL || - (new_syllable = (char *) calloc (sizeof (USHORT), pwlen+1)) ==NULL || + if ( (word_units = (unsigned short *) calloc (sizeof (unsigned short), pwlen+1))==NULL || + (syllable_units = (unsigned short *) calloc (sizeof (unsigned short), pwlen+1))==NULL || + (new_syllable = (char *) calloc (sizeof (unsigned short), pwlen+1)) ==NULL || (syllable_for_hyph = (char *) calloc (sizeof(char), 20))==NULL) return(-1); @@ -1365,7 +1365,7 @@ * Get the syllable and find its length. */ (void) gen_syllable (new_syllable, pwlen - word_length, syllable_units, &syllable_size); - syllable_length = (USHORT) strlen (new_syllable); + syllable_length = (unsigned short) strlen (new_syllable); /* * Append the syllable units to the word units. @@ -1399,16 +1399,16 @@ if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && dsd == 0) { numerize(new_syllable); - ch_flag = TRUE; + ch_flag = true; } if ( ((pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1)) { specialize(new_syllable); - ch_flag = TRUE; + ch_flag = true; } - if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE)) + if ( ( (pass_mode & S_CL) > 0) && (ch_flag != true)) capitalize(new_syllable); - ch_flag = FALSE; + ch_flag = false; /**/ (void) strcpy (word, new_syllable); if (syllable_length == 1) @@ -1420,7 +1420,7 @@ { (void) strcpy (hyphenated_word, new_syllable); } - (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1)); + (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(unsigned short)+1)); (void)memset ( (void *)syllable_for_hyph, 0, 20); } else @@ -1433,16 +1433,16 @@ if ( ((pass_mode & S_NB) > 0) && (syllable_length == 1) && (dsd == 0)) { numerize(new_syllable); - ch_flag = TRUE; + ch_flag = true; } if ( ( (pass_mode & S_SS) > 0) && (syllable_length == 1) && (dsd == 1)) { specialize(new_syllable); - ch_flag = TRUE; + ch_flag = true; } - if ( ( (pass_mode & S_CL) > 0) && (ch_flag != TRUE)) + if ( ( (pass_mode & S_CL) > 0) && (ch_flag != true)) capitalize(new_syllable); - ch_flag = FALSE; + ch_flag = false; /**/ (void) strcat (word, new_syllable); (void) strcat (hyphenated_word, "-"); @@ -1455,7 +1455,7 @@ { (void) strcat (hyphenated_word, new_syllable); } - (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(USHORT)+1)); + (void)memset ( (void *)new_syllable, 0, (size_t)(pwlen * sizeof(unsigned short)+1)); (void)memset ( (void *)syllable_for_hyph, 0, 20); } word_length += syllable_length; @@ -1503,13 +1503,13 @@ * the individual letters, so three consecutive units can have * the length of 6 at most. */ -boolean -improper_word (USHORT *units, USHORT word_size) +bool +improper_word (unsigned short *units, unsigned short word_size) { - USHORT unit_count; - boolean failure; + unsigned short unit_count; + bool failure; - failure = FALSE; + failure = false; for (unit_count = 0; !failure && (unit_count < word_size); unit_count++) @@ -1524,7 +1524,7 @@ if ((unit_count != 0) && (digram[units[unit_count - 1]][units[unit_count]] & ILLEGAL_PAIR)) - failure = TRUE; + failure = true; /* * Check for consecutive vowels or consonants. Because @@ -1551,7 +1551,7 @@ (!(rules[units[unit_count - 2]].flags & VOWEL) && !(rules[units[unit_count - 1]].flags & VOWEL) && !(rules[units[unit_count]].flags & VOWEL))) - failure = TRUE; + failure = true; } } @@ -1565,12 +1565,12 @@ * y starts a word and is the only vowel in the first syllable. * The word ycl is one example. We discard words like these. */ -boolean -have_initial_y (USHORT *units, USHORT unit_size) +bool +have_initial_y (unsigned short *units, unsigned short unit_size) { - USHORT unit_count; - USHORT vowel_count; - USHORT normal_vowel_count; + unsigned short unit_count; + unsigned short vowel_count; + unsigned short normal_vowel_count; vowel_count = 0; normal_vowel_count = 0; @@ -1603,11 +1603,11 @@ * vowel at the end of the word or syllables like ble will * be generated. */ -boolean -have_final_split (USHORT *units, USHORT unit_size) +bool +have_final_split (unsigned short *units, unsigned short unit_size) { - USHORT unit_count; - USHORT vowel_count; + unsigned short unit_count; + unsigned short vowel_count; vowel_count = 0; @@ -1619,7 +1619,7 @@ vowel_count++; /* - * Return TRUE iff the only vowel was e, found at the end if the + * Return true iff the only vowel was e, found at the end if the * word. */ return ((vowel_count == 1) && @@ -1663,21 +1663,21 @@ * first unit is "alternate_vowel". */ char * -gen_syllable (char *syllable, USHORT pwlen, USHORT *units_in_syllable, - USHORT *syllable_length) +gen_syllable (char *syllable, unsigned short pwlen, unsigned short *units_in_syllable, + unsigned short *syllable_length) { - USHORT unit = 0; - SHORT current_unit = 0; - USHORT vowel_count = 0; - boolean rule_broken; - boolean want_vowel; - boolean want_another_unit; - UINT tries = 0; - USHORT last_unit = 0; - SHORT length_left = 0; - USHORT hold_saved_unit = 0; - static USHORT saved_unit; - static USHORT saved_pair[2]; + unsigned short unit = 0; + short current_unit = 0; + unsigned short vowel_count = 0; + bool rule_broken; + bool want_vowel; + bool want_another_unit; + unsigned int tries = 0; + unsigned short last_unit = 0; + short length_left = 0; + unsigned short hold_saved_unit = 0; + static unsigned short saved_unit; + static unsigned short saved_pair[2]; /* * This is needed if the saved_unit is tries and the syllable then @@ -1701,14 +1701,14 @@ vowel_count = 0; current_unit = 0; length_left = (short int) pwlen; - want_another_unit = TRUE; + want_another_unit = true; /* * This loop finds all the units for the syllable. */ do { - want_vowel = FALSE; + want_vowel = false; /* * This loop continues until a valid unit is found for the @@ -1769,9 +1769,9 @@ * Prevent having a word longer than expected. */ if (length_left < 0) - rule_broken = TRUE; + rule_broken = true; else - rule_broken = FALSE; + rule_broken = false; /* * First unit of syllable. This is special because the @@ -1785,7 +1785,7 @@ * use it. */ if (rules[unit].flags & NOT_BEGIN_SYLLABLE) - rule_broken = TRUE; + rule_broken = true; else /* * If this is the last unit of a word, @@ -1797,9 +1797,9 @@ if (length_left == 0) { if (rules[unit].flags & VOWEL) - want_another_unit = FALSE; + want_another_unit = false; else - rule_broken = TRUE; + rule_broken = true; } } else @@ -1826,7 +1826,7 @@ */ (ALLOWED (END) && (vowel_count == 0) && !(rules[unit].flags & VOWEL))) - rule_broken = TRUE; + rule_broken = true; if (current_unit == 1) { @@ -1835,7 +1835,7 @@ * a syllable and it does not fit. */ if (ALLOWED (NOT_BEGIN)) - rule_broken = TRUE; + rule_broken = true; } else { @@ -1885,7 +1885,7 @@ !(rules[units_in_syllable [current_unit - 2]].flags & VOWEL))) - rule_broken = TRUE; + rule_broken = true; /* * The following checks occur when the current unit @@ -1905,7 +1905,7 @@ */ if ((vowel_count > 1) && (rules[last_unit].flags & VOWEL)) - rule_broken = TRUE; + rule_broken = true; else /* * Check for the case of @@ -1928,12 +1928,12 @@ [current_unit - 2]] [last_unit] & NOT_END) - rule_broken = TRUE; + rule_broken = true; else { saved_unit = 1; saved_pair[0] = unit; - want_another_unit = FALSE; + want_another_unit = false; } } } @@ -1963,7 +1963,7 @@ */ (ALLOWED (END) || (length_left == 0))) { - want_another_unit = FALSE; + want_another_unit = false; } else /* @@ -1992,20 +1992,20 @@ saved_unit = 2; saved_pair[0] = unit; saved_pair[1] = last_unit; - want_another_unit = FALSE; + want_another_unit = false; } else if (ALLOWED (BREAK)) { saved_unit = 1; saved_pair[0] = unit; - want_another_unit = FALSE; + want_another_unit = false; } } else if (ALLOWED (SUFFIX)) { - want_vowel = TRUE; + want_vowel = true; } } } @@ -2066,7 +2066,7 @@ * Whoops! Too many tries. We set rule_broken so we can * loop in the outer loop and try another syllable. */ - rule_broken = TRUE; + rule_broken = true; /* * ...and the syllable length grows. @@ -2091,15 +2091,15 @@ * consonants, or syllables with consonants between vowels (unless * one of them is the final silent e). */ -boolean -illegal_placement (USHORT *units, USHORT pwlen) +bool +illegal_placement (unsigned short *units, unsigned short pwlen) { - USHORT vowel_count; - USHORT unit_count; - boolean failure; + unsigned short vowel_count; + unsigned short unit_count; + bool failure; vowel_count = 0; - failure = FALSE; + failure = false; for (unit_count = 0; !failure && (unit_count <= pwlen); unit_count++) @@ -2143,7 +2143,7 @@ VOWEL) && (rules[units[unit_count]].flags & VOWEL))))) - failure = TRUE; + failure = true; } /* @@ -2185,7 +2185,7 @@ * in this procedure without affecting the digram table or any other * programs using the Random_word subroutine. */ -static USHORT numbers[] = +static unsigned short numbers[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, @@ -2234,7 +2234,7 @@ * use vowel_numbers will adjust to the size difference automatically. */ -static USHORT vowel_numbers[] = +static unsigned short vowel_numbers[] = { 0, 0, 4, 4, 4, 8, 8, 14, 14, 19, 19, 23 }; @@ -2245,10 +2245,10 @@ * expected, use the vowel_numbers array rather than looping through * the numbers array until a vowel is found. */ -USHORT -random_unit (USHORT type) +unsigned short +random_unit (unsigned short type) { - USHORT number; + unsigned short number; /* * Sometimes, we are asked to explicitly get a vowel (i.e., if @@ -2257,12 +2257,12 @@ */ if (type & VOWEL) number = vowel_numbers[ - base::RandInt(0, (sizeof (vowel_numbers) / sizeof (USHORT))-1)]; + base::RandInt(0, (sizeof (vowel_numbers) / sizeof (unsigned short))-1)]; else /* * Get any letter according to the English distribution. */ number = numbers[ - base::RandInt(0, (sizeof (numbers) / sizeof (USHORT))-1)]; + base::RandInt(0, (sizeof (numbers) / sizeof (unsigned short))-1)]; return (number); }
diff --git a/third_party/fips181/fips181.h b/third_party/fips181/fips181.h index 524da59..952256de 100644 --- a/third_party/fips181/fips181.h +++ b/third_party/fips181/fips181.h
@@ -34,12 +34,8 @@ */ -#ifndef APG_PRONPASS_H -#define APG_PRONPASS_H 1 - -#ifndef APG_OWN_TYPES_H -#include "owntypes.h" -#endif /* APG_OWN_TYPES_H */ +#ifndef FIPS181_H +#define FIPS181_H 1 #define RULE_SIZE (sizeof(rules)/sizeof(struct unit)) #define ALLOWED(flag) (digram[units_in_syllable[current_unit -1]][unit] & (flag)) @@ -69,16 +65,18 @@ #define S_SL 0x08 /* Small */ #define S_RS 0x10 /* Restricted Symbol*/ -extern int gen_pron_pass (char *word, char* hypenated_word, - USHORT minlen, USHORT maxlen, unsigned int pass_mode); -USHORT random_unit (USHORT type); -USHORT get_random (USHORT minlen, USHORT maxlen); -boolean have_initial_y (USHORT *units, USHORT unit_size); -boolean illegal_placement (USHORT *units, USHORT pwlen); -boolean improper_word (USHORT *units, USHORT word_size); -boolean have_final_split (USHORT *units, USHORT unit_size); -int gen_word (char *word, char *hyphenated_word, USHORT pwlen, unsigned int pass_mode); -char *gen_syllable(char *syllable, USHORT pwlen, USHORT *units_in_syllable, - USHORT *syllable_length); +#define APG_MAX_PASSWORD_LENGTH 255 -#endif /* APG_PRONPASS_H */ +extern int gen_pron_pass (char *word, char* hypenated_word, + unsigned short minlen, unsigned short maxlen, unsigned int pass_mode); +unsigned short random_unit (unsigned short type); +unsigned short get_random (unsigned short minlen, unsigned short maxlen); +bool have_initial_y (unsigned short *units, unsigned short unit_size); +bool illegal_placement (unsigned short *units, unsigned short pwlen); +bool improper_word (unsigned short *units, unsigned short word_size); +bool have_final_split (unsigned short *units, unsigned short unit_size); +int gen_word (char *word, char *hyphenated_word, unsigned short pwlen, unsigned int pass_mode); +char *gen_syllable(char *syllable, unsigned short pwlen, unsigned short *units_in_syllable, + unsigned short *syllable_length); + +#endif /* FIPS181_H */
diff --git a/third_party/fips181/owntypes.h b/third_party/fips181/owntypes.h deleted file mode 100644 index 31a34f9..0000000 --- a/third_party/fips181/owntypes.h +++ /dev/null
@@ -1,44 +0,0 @@ -/* -** Copyright (c) 1999, 2000, 2001, 2002, 2003 -** Adel I. Mirzazhanov. All rights reserved -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1.Redistributions of source code must retain the above copyright notice, -** this list of conditions and the following disclaimer. -** 2.Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3.The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -** OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef APG_OWN_TYPES_H -#define APG_OWN_TYPES_H 1 - -typedef unsigned int UINT; -typedef unsigned short USHORT; -typedef short int SHORT; -typedef int boolean; -typedef unsigned long int UINT32; - -#define TRUE 1 -#define FALSE 0 - -#define APG_MAX_PASSWORD_LENGTH 255 - -#endif /* APG_OWN_TYPES_H */
diff --git a/third_party/fips181/randpass.cc b/third_party/fips181/randpass.cc index 8aded15..68dddeea 100644 --- a/third_party/fips181/randpass.cc +++ b/third_party/fips181/randpass.cc
@@ -36,7 +36,6 @@ #include <time.h> #include "base/rand_util.h" -#include "owntypes.h" #include "randpass.h" #include "smbl.h" @@ -143,18 +142,18 @@ ** INPUT: ** char - symbol. ** OUTPUT: -** int - 0 - not restricted -** 1 - restricted +** bool - false - not restricted +** true - restricted ** NOTES: ** none. */ -int +bool is_restricted_symbol (char symbol) { int j = 0; for (j = 0; j <= 93 ; j++) if (symbol == smbl[j].ch) if ((S_RS & smbl[j].type) > 0) - return(1); - return(0); + return(true); + return(false); }
diff --git a/third_party/fips181/randpass.h b/third_party/fips181/randpass.h index ee0df62..013c572 100644 --- a/third_party/fips181/randpass.h +++ b/third_party/fips181/randpass.h
@@ -33,20 +33,16 @@ #ifndef APG_RANDPASS_H #define APG_RANDPASS_H 1 -#ifndef APG_OWN_TYPES_H -#include "owntypes.h" -#endif - struct sym { char ch; - USHORT type; + unsigned short type; }; /* char gen_symbol(unsigned short int symbol_class); */ extern int gen_rand_pass(char* password_string, int minl, int maxl, unsigned int pass_mode); extern int gen_rand_symbol (char *symbol, unsigned int mode); -extern int is_restricted_symbol (char symbol); +extern bool is_restricted_symbol (char symbol); #endif /* RANDPASS_H */
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp index 8e1cb07..97d9ebd 100644 --- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp +++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -348,14 +348,19 @@ // Given // class Foo {}; + // class DerivedFoo : class Foo; // using Bar = Foo; // Bar f1(); // <- |Bar| would be matched by hasString("Bar") below. // Bar f2(); // <- |Bar| would be matched by hasName("Foo") below. + // DerivedFoo f3(); // <- |DerivedFoo| matched by isDerivedFrom(...) below. // |type_with_same_name_as_function| matcher matches Bar and Foo return types. auto type_with_same_name_as_function = qualType(anyOf( - hasString(name), // hasString matches the type as spelled (Bar above). - hasDeclaration(namedDecl(hasName(name))))); // hasDeclaration matches - // resolved type (Foo above). + // hasString matches the type as spelled (Bar above). + hasString(name), + // hasDeclaration matches resolved type (Foo or DerivedFoo above). + hasDeclaration(namedDecl(hasName(name))), + hasDeclaration(cxxRecordDecl(isDerivedFrom(namedDecl(hasName(name))))))); + // |type_containing_same_name_as_function| matcher will match all of the // return types below: // - Foo foo() // Direct application of |type_with_same_name_as_function|.
diff --git a/tools/clang/rewrite_to_chrome_style/tests/methods-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/methods-expected.cc index 1eff05b..f770362 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/methods-expected.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/methods-expected.cc
@@ -189,6 +189,39 @@ MyRefPtr<FooBar> foobar_; }; +namespace get_prefix_vs_inheritance { + +// Regression test for https://crbug.com/673031: +// 1. |frame| accessor/method should be renamed in the same way for +// WebFrameImplBase and WebLocalFrameImpl. +// 2. Need to rename |frame| to |GetFrame| (not to |Frame|) to avoid +// a conflict with the Frame type. + +class Frame {}; +class LocalFrame : public Frame {}; + +class WebFrameImplBase { + public: + virtual Frame* GetFrame() const = 0; +}; + +class WebLocalFrameImpl : public WebFrameImplBase { + public: + LocalFrame* GetFrame() const override { return nullptr; } +}; + +// This is also a regression test for https://crbug.com/673031 +// (which can happen in a non-virtual-method case): +class LayoutObject {}; +class LayoutBoxModelObject : public LayoutObject {}; +class PaintLayerStackingNode { + public: + // |layoutObject| should be renamed to |GetLayoutObject|. + LayoutBoxModelObject* GetLayoutObject() { return nullptr; } +}; + +} // namespace get_prefix_vs_inheritance + } // namespace blink namespace WTF {
diff --git a/tools/clang/rewrite_to_chrome_style/tests/methods-original.cc b/tools/clang/rewrite_to_chrome_style/tests/methods-original.cc index 1f8f3a0..2802033 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/methods-original.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/methods-original.cc
@@ -193,6 +193,39 @@ MyRefPtr<FooBar> foobar_; }; +namespace get_prefix_vs_inheritance { + +// Regression test for https://crbug.com/673031: +// 1. |frame| accessor/method should be renamed in the same way for +// WebFrameImplBase and WebLocalFrameImpl. +// 2. Need to rename |frame| to |GetFrame| (not to |Frame|) to avoid +// a conflict with the Frame type. + +class Frame {}; +class LocalFrame : public Frame {}; + +class WebFrameImplBase { + public: + virtual Frame* frame() const = 0; +}; + +class WebLocalFrameImpl : public WebFrameImplBase { + public: + LocalFrame* frame() const override { return nullptr; } +}; + +// This is also a regression test for https://crbug.com/673031 +// (which can happen in a non-virtual-method case): +class LayoutObject {}; +class LayoutBoxModelObject : public LayoutObject {}; +class PaintLayerStackingNode { + public: + // |layoutObject| should be renamed to |GetLayoutObject|. + LayoutBoxModelObject* layoutObject() { return nullptr; } +}; + +} // namespace get_prefix_vs_inheritance + } // namespace blink namespace WTF {
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index cfe94cb..dbe0fdf 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -461,6 +461,10 @@ Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR) if sys.platform == 'win32' or use_head_revision: Checkout('LLD', LLVM_REPO_URL + '/lld/trunk', LLD_DIR) + elif os.path.exists(LLD_DIR): + # In case someone sends a tryjob that temporary adds lld to the checkout, + # make sure it's not around on future builds. + RmTree(LLD_DIR) Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR) if sys.platform == 'darwin': # clang needs a libc++ checkout, else -stdlib=libc++ won't find includes
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 8a58680..2234290 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -44819,6 +44819,7 @@ <histogram name="Platform.CrOSEvent" enum="CrosEventEnum"> <owner>dkrahn@chromium.org</owner> <owner>jwerner@chromium.org</owner> + <owner>vapier@gentoo.org</owner> <summary> Generic event of interest from Chrome OS. Intended mainly to help assess the frequency of rare error conditions. @@ -80505,6 +80506,7 @@ <int value="17" label="VeyronEmmcUpgrade.FailedDiskAccess"/> <int value="18" label="VeyronEmmcUpgrade.FailedWPEnable"/> <int value="19" label="VeyronEmmcUpgrade.SignatureDetected"/> + <int value="20" label="Watchdog.StartupFailed"/> </enum> <enum name="CrosFirstRunTutorialCompletionType" type="int"> @@ -106339,6 +106341,8 @@ <int value="3" label="Unknown (unused)"/> <int value="4" label="Online"/> <int value="5" label="Policy"/> + <int value="6" label="Third party"/> + <int value="7" label="Device policy"/> </enum> <enum name="WarmupStateOnLaunch" type="int"> @@ -114572,6 +114576,8 @@ <suffix name="Original"/> <suffix name="Experimental"/> <affected-histogram name="SoftwareReporter.FoundUwSReadError"/> + <affected-histogram name="SoftwareReporter.LogsUploadResult"/> + <affected-histogram name="SoftwareReporter.LogsUploadResultRegistryError"/> <affected-histogram name="SoftwareReporter.MajorVersion"/> <affected-histogram name="SoftwareReporter.MemoryUsed"/> <affected-histogram name="SoftwareReporter.MinorVersion"/>
diff --git a/tools/perf/docs/perf_bot_sheriffing.md b/tools/perf/docs/perf_bot_sheriffing.md index 0e64a48..419dea53f 100644 --- a/tools/perf/docs/perf_bot_sheriffing.md +++ b/tools/perf/docs/perf_bot_sheriffing.md
@@ -190,6 +190,14 @@ ensure that the bug title reflects something like "Fix and re-enable testname". 4. Investigate the failure. Some tips for investigating: + * When viewing buildbot step logs, **use the **<font color="blue">[stdout]</font>** link to view logs!**. + This will link to logdog logs which do not expire. Do not use or link + to the logs found through the <font color="blue">stdio</font> link + whenever possible as these logs will expire. + * When investigating Android, look for the logcat which is uploaded to + Google Storage at the end of the run. logcat will contain much more + detailed Android device and crash info than will be found in + Telemetry logs. * If it's a non flaky failure, indentify the first failed build so you can narrow down the range of CLs that causes the failure. You can use the
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index e903feb..4910aaa1 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -61,6 +61,7 @@ "//ui/base", "//ui/gfx", "//ui/gfx/geometry", + "//ui/strings", ] if (is_win) {
diff --git a/ui/accessibility/DEPS b/ui/accessibility/DEPS index fd3b8f0..0198e2c 100644 --- a/ui/accessibility/DEPS +++ b/ui/accessibility/DEPS
@@ -1,5 +1,7 @@ include_rules = [ "+third_party/iaccessible2", + "+ui/base/l10n", "+ui/base/win", "+ui/gfx", + "+ui/strings/grit/ui_strings.h", ]
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl index ac8b0eb..6984a17 100644 --- a/ui/accessibility/ax_enums.idl +++ b/ui/accessibility/ax_enums.idl
@@ -239,6 +239,8 @@ }; // An action to be taken on an accessibility node. + // In contrast to |AXSupportedAction|, these describe what happens to the + // object, e.g. "FOCUS". enum AXAction { blur, @@ -294,6 +296,21 @@ request_inline_text_boxes }; + // Lists the actions that can be performed on a given node. + // In contrast to |AXAction|, these describe what the user can do on the + // object, e.g. "PRESS", not what happens to the object as a result. + // Only one action is supported for now. + enum AXSupportedAction { + activate, + check, + click, + jump, + open, + press, + select, + uncheck + }; + // A change to the accessibility tree. enum AXMutation { node_created, @@ -304,7 +321,6 @@ [cpp_enum_prefix_override="ax_attr"] enum AXStringAttribute { access_key, - action, // Only used when invalid_state == invalid_state_other. aria_invalid_value, auto_complete, @@ -329,6 +345,7 @@ }; [cpp_enum_prefix_override="ax_attr"] enum AXIntAttribute { + action, // Scrollable container attributes. scroll_x, scroll_x_min,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 5d14645..5a7d6c70 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -13,6 +13,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "ui/accessibility/ax_text_utils.h" #include "ui/gfx/transform.h" using base::DoubleToString; @@ -394,6 +395,12 @@ for (size_t i = 0; i < int_attributes.size(); ++i) { std::string value = IntToString(int_attributes[i].second); switch (int_attributes[i].first) { + case AX_ATTR_ACTION: + result += + " action=" + + base::UTF16ToUTF8(ActionToUnlocalizedString( + static_cast<AXSupportedAction>(int_attributes[i].second))); + break; case AX_ATTR_SCROLL_X: result += " scroll_x=" + value; break; @@ -471,12 +478,14 @@ } break; case AX_ATTR_NAME_FROM: - result += " name_from=" + ui::ToString( - static_cast<ui::AXNameFrom>(int_attributes[i].second)); + result += + " name_from=" + + ui::ToString(static_cast<AXNameFrom>(int_attributes[i].second)); break; case AX_ATTR_DESCRIPTION_FROM: - result += " description_from=" + ui::ToString( - static_cast<ui::AXDescriptionFrom>(int_attributes[i].second)); + result += " description_from=" + + ui::ToString( + static_cast<AXDescriptionFrom>(int_attributes[i].second)); break; case AX_ATTR_ACTIVEDESCENDANT_ID: result += " activedescendant=" + value; @@ -597,9 +606,6 @@ case AX_ATTR_ACCESS_KEY: result += " access_key=" + value; break; - case AX_ATTR_ACTION: - result += " action=" + value; - break; case AX_ATTR_ARIA_INVALID_VALUE: result += " aria_invalid_value=" + value; break;
diff --git a/ui/accessibility/ax_text_utils.cc b/ui/accessibility/ax_text_utils.cc index 7c97a989..af14f97 100644 --- a/ui/accessibility/ax_text_utils.cc +++ b/ui/accessibility/ax_text_utils.cc
@@ -7,6 +7,9 @@ #include "base/i18n/break_iterator.h" #include "base/logging.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/strings/grit/ui_strings.h" namespace ui { @@ -112,4 +115,56 @@ } } +base::string16 ActionToString(const AXSupportedAction supported_action) { + switch (supported_action) { + case AX_SUPPORTED_ACTION_NONE: + return base::string16(); + case AX_SUPPORTED_ACTION_ACTIVATE: + return l10n_util::GetStringUTF16(IDS_AX_ACTIVATE_ACTION_VERB); + case AX_SUPPORTED_ACTION_CHECK: + return l10n_util::GetStringUTF16(IDS_AX_CHECK_ACTION_VERB); + case AX_SUPPORTED_ACTION_CLICK: + return l10n_util::GetStringUTF16(IDS_AX_CLICK_ACTION_VERB); + case AX_SUPPORTED_ACTION_JUMP: + return l10n_util::GetStringUTF16(IDS_AX_JUMP_ACTION_VERB); + case AX_SUPPORTED_ACTION_OPEN: + return l10n_util::GetStringUTF16(IDS_AX_OPEN_ACTION_VERB); + case AX_SUPPORTED_ACTION_PRESS: + return l10n_util::GetStringUTF16(IDS_AX_PRESS_ACTION_VERB); + case AX_SUPPORTED_ACTION_SELECT: + return l10n_util::GetStringUTF16(IDS_AX_SELECT_ACTION_VERB); + case AX_SUPPORTED_ACTION_UNCHECK: + return l10n_util::GetStringUTF16(IDS_AX_UNCHECK_ACTION_VERB); + } + NOTREACHED(); + return base::string16(); +} + +// Some APIs on Linux and Windows need to return non-localized action names. +base::string16 ActionToUnlocalizedString( + const AXSupportedAction supported_action) { + switch (supported_action) { + case ui::AX_SUPPORTED_ACTION_NONE: + return base::UTF8ToUTF16("none"); + case ui::AX_SUPPORTED_ACTION_ACTIVATE: + return base::UTF8ToUTF16("activate"); + case ui::AX_SUPPORTED_ACTION_CHECK: + return base::UTF8ToUTF16("check"); + case ui::AX_SUPPORTED_ACTION_CLICK: + return base::UTF8ToUTF16("click"); + case ui::AX_SUPPORTED_ACTION_JUMP: + return base::UTF8ToUTF16("jump"); + case ui::AX_SUPPORTED_ACTION_OPEN: + return base::UTF8ToUTF16("open"); + case ui::AX_SUPPORTED_ACTION_PRESS: + return base::UTF8ToUTF16("press"); + case ui::AX_SUPPORTED_ACTION_SELECT: + return base::UTF8ToUTF16("select"); + case ui::AX_SUPPORTED_ACTION_UNCHECK: + return base::UTF8ToUTF16("uncheck"); + } + NOTREACHED(); + return base::string16(); +} + } // namespace ui
diff --git a/ui/accessibility/ax_text_utils.h b/ui/accessibility/ax_text_utils.h index a074cfe..f760660 100644 --- a/ui/accessibility/ax_text_utils.h +++ b/ui/accessibility/ax_text_utils.h
@@ -52,6 +52,15 @@ TextBoundaryDirection direction, AXTextAffinity affinity); +// Returns a string ID that corresponds to the name of the given action. +base::string16 AX_EXPORT +ActionToString(const AXSupportedAction supported_action); + +// Returns the non-localized string representation of a supported action. +// Some APIs on Linux and Windows need to return non-localized action names. +base::string16 AX_EXPORT +ActionToUnlocalizedString(const AXSupportedAction supported_action); + } // namespace ui #endif // UI_ACCESSIBILITY_AX_TEXT_UTILS_H_
diff --git a/ui/accessibility/ax_tree_combiner.cc b/ui/accessibility/ax_tree_combiner.cc index b983e995..1186acd2 100644 --- a/ui/accessibility/ax_tree_combiner.cc +++ b/ui/accessibility/ax_tree_combiner.cc
@@ -27,6 +27,7 @@ // add a new attribute without explicitly considering whether it's // a node id attribute or not. case AX_INT_ATTRIBUTE_NONE: + case AX_ATTR_ACTION: case AX_ATTR_SCROLL_X: case AX_ATTR_SCROLL_X_MIN: case AX_ATTR_SCROLL_X_MAX:
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 17439d9..5028f2da 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -374,7 +374,22 @@ STDMETHODIMP AXPlatformNodeWin::get_accDefaultAction( VARIANT var_id, BSTR* def_action) { COM_OBJECT_VALIDATE_VAR_ID_1_ARG(var_id, def_action); - return GetStringAttributeAsBstr(ui::AX_ATTR_ACTION, def_action); + int action; + if (!GetIntAttribute(AX_ATTR_ACTION, &action)) { + *def_action = nullptr; + return S_FALSE; + } + + base::string16 action_verb = + ActionToString(static_cast<AXSupportedAction>(action)); + if (action_verb.empty()) { + *def_action = nullptr; + return S_FALSE; + } + + *def_action = SysAllocString(action_verb.c_str()); + DCHECK(def_action); + return S_OK; } STDMETHODIMP AXPlatformNodeWin::get_accDescription(
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 03c6301c..a29bf600 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -32,6 +32,7 @@ #include "ui/compositor/paint_context.h" #include "ui/gfx/animation/animation.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" @@ -183,12 +184,9 @@ // cc::Layer state. if (surface_layer_ && surface_layer_->surface_id().is_valid()) { clone->SetShowSurface( - surface_layer_->surface_id(), - surface_layer_->satisfy_callback(), - surface_layer_->require_callback(), - surface_layer_->surface_size(), - surface_layer_->surface_scale(), - frame_size_in_dip_); + surface_layer_->surface_id(), surface_layer_->satisfy_callback(), + surface_layer_->require_callback(), surface_layer_->surface_size(), + surface_layer_->surface_scale()); } else if (type_ == LAYER_SOLID_COLOR) { clone->SetColor(GetTargetColor()); } @@ -661,24 +659,23 @@ const cc::SurfaceId& surface_id, const cc::SurfaceLayer::SatisfyCallback& satisfy_callback, const cc::SurfaceLayer::RequireCallback& require_callback, - gfx::Size surface_size, - float scale, - gfx::Size frame_size_in_dip) { + const gfx::Size& surface_size_in_pixels, + float scale) { DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR); scoped_refptr<cc::SurfaceLayer> new_layer = cc::SurfaceLayer::Create(satisfy_callback, require_callback); - new_layer->SetSurfaceId(surface_id, scale, surface_size); + new_layer->SetSurfaceId(surface_id, scale, surface_size_in_pixels); SwitchToLayer(new_layer); surface_layer_ = new_layer; - frame_size_in_dip_ = frame_size_in_dip; + frame_size_in_dip_ = gfx::ConvertSizeToDIP(scale, surface_size_in_pixels); RecomputeDrawsContentAndUVRect(); for (const auto& mirror : mirrors_) { - mirror->dest()->SetShowSurface( - surface_id, satisfy_callback, require_callback, - surface_size, scale, frame_size_in_dip); + mirror->dest()->SetShowSurface(surface_id, satisfy_callback, + require_callback, surface_size_in_pixels, + scale); } }
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index 4bb77d31..6bce25e 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -296,9 +296,8 @@ void SetShowSurface(const cc::SurfaceId& surface_id, const cc::SurfaceLayer::SatisfyCallback& satisfy_callback, const cc::SurfaceLayer::RequireCallback& require_callback, - gfx::Size surface_size, - float scale, - gfx::Size frame_size_in_dip); + const gfx::Size& surface_size_in_pixels, + float scale); bool has_external_content() { return texture_layer_.get() || surface_layer_.get(); @@ -388,6 +387,10 @@ return damaged_region_; } + const gfx::Size& frame_size_in_dip_for_testing() const { + return frame_size_in_dip_; + } + private: friend class LayerOwner; class LayerMirror;
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 7638b3a0..9a55e398 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -1840,7 +1840,7 @@ before = child->cc_layer_for_testing(); child->SetShowSurface(cc::SurfaceId(), base::Bind(&FakeSatisfyCallback), base::Bind(&FakeRequireCallback), gfx::Size(10, 10), - 1.0, gfx::Size(10, 10)); + 1.0); EXPECT_TRUE(child->cc_layer_for_testing()); EXPECT_NE(before.get(), child->cc_layer_for_testing()); @@ -1861,7 +1861,7 @@ cc::FrameSinkId(0, 1), cc::LocalFrameId(2, base::UnguessableToken::Create())); layer->SetShowSurface(surface_id, satisfy_callback, require_callback, - gfx::Size(10, 10), 1.0f, gfx::Size(10, 10)); + gfx::Size(10, 10), 1.0f); const auto mirror = layer->Mirror(); auto* const cc_layer = mirror->cc_layer_for_testing(); @@ -1878,7 +1878,7 @@ cc::SurfaceId(cc::FrameSinkId(1, 2), cc::LocalFrameId(3, base::UnguessableToken::Create())); layer->SetShowSurface(surface_id, satisfy_callback, require_callback, - gfx::Size(20, 20), 2.0f, gfx::Size(20, 20)); + gfx::Size(20, 20), 2.0f); // A new cc::Layer should be created for the mirror. EXPECT_NE(cc_layer, mirror->cc_layer_for_testing()); @@ -1890,6 +1890,23 @@ EXPECT_EQ(2.0f, surface->surface_scale()); } +// Test if frame size in dip is properly calculated in SetShowSurface +TEST_F(LayerWithDelegateTest, FrameSizeInDip) { + std::unique_ptr<Layer> layer(CreateLayer(LAYER_SOLID_COLOR)); + + const auto satisfy_callback = base::Bind(&FakeSatisfyCallback); + const auto require_callback = base::Bind(&FakeRequireCallback); + + cc::SurfaceId surface_id( + cc::FrameSinkId(0, 1), + cc::LocalFrameId(2, base::UnguessableToken::Create())); + + layer->SetShowSurface(surface_id, satisfy_callback, require_callback, + gfx::Size(30, 40), 2.0f); + + EXPECT_EQ(layer->frame_size_in_dip_for_testing(), gfx::Size(15, 20)); +} + // Verifies that layer filters still attached after changing implementation // layer. TEST_F(LayerWithDelegateTest, LayerFiltersSurvival) { @@ -1906,7 +1923,7 @@ scoped_refptr<cc::Layer> before = layer->cc_layer_for_testing(); layer->SetShowSurface(cc::SurfaceId(), base::Bind(&FakeSatisfyCallback), base::Bind(&FakeRequireCallback), gfx::Size(10, 10), - 1.0, gfx::Size(10, 10)); + 1.0); EXPECT_EQ(layer->layer_grayscale(), 0.5f); EXPECT_TRUE(layer->cc_layer_for_testing()); EXPECT_NE(before.get(), layer->cc_layer_for_testing()); @@ -2229,7 +2246,7 @@ layer->set_delegate(&delegate); layer->SetShowSurface(cc::SurfaceId(), base::Bind(&FakeSatisfyCallback), base::Bind(&FakeRequireCallback), gfx::Size(10, 10), - 1.0, gfx::Size(10, 10)); + 1.0); EXPECT_FALSE(delegate.delegated_frame_damage_called()); layer->OnDelegatedFrameDamage(damage_rect);
diff --git a/ui/events/win/event_utils_win_unittest.cc b/ui/events/win/event_utils_win_unittest.cc index a4efce4f..8b99008e 100644 --- a/ui/events/win/event_utils_win_unittest.cc +++ b/ui/events/win/event_utils_win_unittest.cc
@@ -22,7 +22,10 @@ LPARAM l_param, LRESULT& result, DWORD msg_map_id = 0) override { - return true; + // Handle WM_NCCALCSIZE because the test below assumes there is no + // non-client area, affecting EventSystemLocationFromNative's client to + // screen coordinate transform. + return message == WM_NCCALCSIZE; } private:
diff --git a/ui/gfx/win/window_impl.cc b/ui/gfx/win/window_impl.cc index f774468..bf6994d 100644 --- a/ui/gfx/win/window_impl.cc +++ b/ui/gfx/win/window_impl.cc
@@ -283,19 +283,20 @@ UINT message, WPARAM w_param, LPARAM l_param) { + WindowImpl* window = nullptr; if (message == WM_NCCREATE) { CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(l_param); - WindowImpl* window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams); + window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams); DCHECK(window); gfx::SetWindowUserData(hwnd, window); window->hwnd_ = hwnd; window->got_create_ = true; if (hwnd) window->got_valid_hwnd_ = true; - return TRUE; + } else { + window = reinterpret_cast<WindowImpl*>(GetWindowUserData(hwnd)); } - WindowImpl* window = reinterpret_cast<WindowImpl*>(GetWindowUserData(hwnd)); if (!window) return 0;
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h b/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h index a4802cd9..b9c694df 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h +++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h
@@ -10,6 +10,10 @@ #include <stdint.h> #include <xf86drmMode.h> +namespace gfx { +class Rect; +} // namespace gfx + namespace ui { class CrtcController;
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 2d7ed310..1b7bceb 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -317,10 +317,33 @@ Upload </message> - <!--Accessible name/action strings--> - <message name="IDS_APP_ACCACTION_PRESS" desc="The accessible default action for a button."> - Press + <!--Accessible action strings--> + <message name="IDS_AX_ACTIVATE_ACTION_VERB" desc="Verb stating the action that will occur when an element such as a text field is selected, as used by accessibility."> + activate </message> + <message name="IDS_AX_CHECK_ACTION_VERB" desc="Verb stating the action that will occur when an unchecked checkbox is clicked, as used by accessibility."> + check + </message> + <message name="IDS_AX_CLICK_ACTION_VERB" desc="Verb stating the action that will occur when clicking on a generic clickable object, when we don't know what that action is, as used by accessibility."> + click + </message> + <message name="IDS_AX_JUMP_ACTION_VERB" desc="Verb stating the action that will occur when an element such as an in-page link is activated, as used by accessibility."> + jump + </message> + <message name="IDS_AX_OPEN_ACTION_VERB" desc="Verb stating the action that will occur when an element such as a pop-up button is pressed, as used by accessibility."> + open + </message> +<message name="IDS_AX_PRESS_ACTION_VERB" desc="Verb stating the action that will occur when an element such as a button is pressed, as used by accessibility."> + press + </message> + <message name="IDS_AX_SELECT_ACTION_VERB" desc="Verb stating the action that will occur when an element such as a radio button is selected, as used by accessibility."> + select + </message> + <message name="IDS_AX_UNCHECK_ACTION_VERB" desc="Verb stating the action that will occur when a checked checkbox is clicked, as used by accessibility."> + uncheck + </message> + + <!--Accessible name strings--> <message name="IDS_APP_ACCNAME_CLOSE" desc="The accessible name for the Close button."> Close </message>
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm index 28383b0..25df35a2 100644 --- a/ui/views/cocoa/bridged_native_widget.mm +++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -1046,6 +1046,11 @@ } void BridgedNativeWidget::ReorderChildViews() { + // Ignore layer manipulation during a Close(). This can be reached during the + // orderOut: in Close(), which notifies visibility changes to Views. + if (!bridged_view_) + return; + RankMap rank; Widget* widget = native_widget_mac_->GetWidget(); RankNSViews(widget->GetRootView(), associated_views_, &rank);
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc index 416cdf3..8adf74d 100644 --- a/ui/views/controls/button/button.cc +++ b/ui/views/controls/button/button.cc
@@ -65,6 +65,8 @@ void Button::GetAccessibleNodeData(ui::AXNodeData* node_data) { node_data->role = ui::AX_ROLE_BUTTON; node_data->SetName(accessible_name_); + if (!enabled()) + node_data->AddStateFlag(ui::AX_STATE_DISABLED); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc index f07b7484..97637e3c 100644 --- a/ui/views/controls/button/checkbox.cc +++ b/ui/views/controls/button/checkbox.cc
@@ -125,6 +125,15 @@ node_data->role = ui::AX_ROLE_CHECK_BOX; if (checked()) node_data->AddStateFlag(ui::AX_STATE_CHECKED); + if (enabled()) { + if (checked()) { + node_data->AddIntAttribute(ui::AX_ATTR_ACTION, + ui::AX_SUPPORTED_ACTION_UNCHECK); + } else { + node_data->AddIntAttribute(ui::AX_ATTR_ACTION, + ui::AX_SUPPORTED_ACTION_CHECK); + } + } } void Checkbox::OnPaint(gfx::Canvas* canvas) {
diff --git a/ui/views/controls/button/custom_button.cc b/ui/views/controls/button/custom_button.cc index 4540c1b..21ebca3d 100644 --- a/ui/views/controls/button/custom_button.cc +++ b/ui/views/controls/button/custom_button.cc
@@ -351,6 +351,10 @@ // No additional accessibility node_data set for this button node_data. break; } + if (enabled()) { + node_data->AddIntAttribute(ui::AX_ATTR_ACTION, + ui::AX_SUPPORTED_ACTION_PRESS); + } } void CustomButton::VisibilityChanged(View* starting_from, bool visible) {
diff --git a/ui/views/controls/button/menu_button.cc b/ui/views/controls/button/menu_button.cc index e98dda7..c4e986b 100644 --- a/ui/views/controls/button/menu_button.cc +++ b/ui/views/controls/button/menu_button.cc
@@ -7,7 +7,6 @@ #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/display/screen.h" #include "ui/events/event.h" @@ -17,7 +16,6 @@ #include "ui/gfx/image/image.h" #include "ui/gfx/text_constants.h" #include "ui/resources/grit/ui_resources.h" -#include "ui/strings/grit/ui_strings.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/menu_button_listener.h" #include "ui/views/mouse_constants.h" @@ -300,9 +298,11 @@ void MenuButton::GetAccessibleNodeData(ui::AXNodeData* node_data) { CustomButton::GetAccessibleNodeData(node_data); node_data->role = ui::AX_ROLE_POP_UP_BUTTON; - node_data->AddStringAttribute( - ui::AX_ATTR_ACTION, l10n_util::GetStringUTF8(IDS_APP_ACCACTION_PRESS)); node_data->AddStateFlag(ui::AX_STATE_HASPOPUP); + if (enabled()) { + node_data->AddIntAttribute(ui::AX_ATTR_ACTION, + ui::AX_SUPPORTED_ACTION_OPEN); + } } void MenuButton::PaintMenuMarker(gfx::Canvas* canvas) {
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc index 8b32edd..25304929 100644 --- a/ui/views/controls/combobox/combobox.cc +++ b/ui/views/controls/combobox/combobox.cc
@@ -740,6 +740,10 @@ node_data->role = ui::AX_ROLE_COMBO_BOX; node_data->SetName(accessible_name_); node_data->SetValue(model_->GetItemAt(selected_index_)); + if (enabled()) { + node_data->AddIntAttribute(ui::AX_ATTR_ACTION, + ui::AX_SUPPORTED_ACTION_OPEN); + } node_data->AddIntAttribute(ui::AX_ATTR_POS_IN_SET, selected_index_); node_data->AddIntAttribute(ui::AX_ATTR_SET_SIZE, model_->GetItemCount()); }
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 2bb3e82..1de38cc0 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -878,6 +878,10 @@ void Textfield::GetAccessibleNodeData(ui::AXNodeData* node_data) { node_data->role = ui::AX_ROLE_TEXT_FIELD; node_data->SetName(accessible_name_); + if (enabled()) { + node_data->AddIntAttribute(ui::AX_ATTR_ACTION, + ui::AX_SUPPORTED_ACTION_ACTIVATE); + } if (read_only()) node_data->AddStateFlag(ui::AX_STATE_READ_ONLY); else
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc index 6013c84..7567394 100644 --- a/ui/views/view_unittest.cc +++ b/ui/views/view_unittest.cc
@@ -4618,6 +4618,63 @@ EXPECT_TRUE(v->on_native_theme_changed_called()); } +// A View that removes its Layer when hidden. +class NoLayerWhenHiddenView : public View { + public: + NoLayerWhenHiddenView() { + SetPaintToLayer(true); + set_owned_by_client(); + SetBounds(0, 0, 100, 100); + } + + bool was_hidden() const { return was_hidden_; } + + // View: + void VisibilityChanged(View* starting_from, bool is_visible) override { + if (!is_visible) { + was_hidden_ = true; + SetPaintToLayer(false); + } + } + + private: + bool was_hidden_ = false; + + DISALLOW_COPY_AND_ASSIGN(NoLayerWhenHiddenView); +}; + +// Test that Views can safely manipulate Layers during Widget closure. +TEST_F(ViewTest, DestroyLayerInClose) { + NoLayerWhenHiddenView view; + Widget* widget = new Widget; + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); + widget->Init(params); + widget->SetBounds(gfx::Rect(0, 0, 100, 100)); + widget->GetContentsView()->AddChildView(&view); + widget->Show(); + + EXPECT_TRUE(view.layer()); + EXPECT_TRUE(view.GetWidget()); + EXPECT_FALSE(view.was_hidden()); + + widget->Close(); + if (IsAuraMusClient()) { + // Mus on Ozone doesn't send the visibility change during Close(). + // See http://crbug.com/674003. + EXPECT_TRUE(view.layer()); + EXPECT_FALSE(view.was_hidden()); + } else { + EXPECT_FALSE(view.layer()); + // Ensure the layer went away via VisibilityChanged(). + EXPECT_TRUE(view.was_hidden()); + } + + // Not removed from Widget until Close() completes. + EXPECT_TRUE(view.GetWidget()); + base::RunLoop().RunUntilIdle(); // Let the Close() complete. + EXPECT_FALSE(view.GetWidget()); +} + //////////////////////////////////////////////////////////////////////////////// // Observer tests. ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index 73fad04..1c6b46a 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -197,10 +197,8 @@ } void NativeWidgetMac::ReorderNativeViews() { - if (bridge_) { - bridge_->SetRootView(GetWidget()->GetRootView()); + if (bridge_) bridge_->ReorderChildViews(); - } } void NativeWidgetMac::ViewRemoved(View* view) {
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index c9eb444..54116a2f5 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -329,6 +329,7 @@ current_cursor_(NULL), previous_cursor_(NULL), dpi_(0), + called_enable_non_client_dpi_scaling_(false), active_mouse_tracking_flags_(0), is_right_mouse_pressed_on_caption_(false), lock_updates_count_(0), @@ -362,7 +363,9 @@ // Create the window. WindowImpl::Init(parent, bounds); - if (delegate_->HasFrame() && base::win::IsProcessPerMonitorDpiAware()) { + if (!called_enable_non_client_dpi_scaling_ && + delegate_->HasFrame() && + base::win::IsProcessPerMonitorDpiAware()) { static auto enable_child_window_dpi_message_func = []() { // Derived signature; not available in headers. // This call gets Windows to scale the non-client area when WM_DPICHANGED @@ -1795,6 +1798,24 @@ return mode ? WVR_REDRAW : 0; } +LRESULT HWNDMessageHandler::OnNCCreate(LPCREATESTRUCT lpCreateStruct) { + SetMsgHandled(FALSE); + if (delegate_->HasFrame() && base::win::IsProcessPerMonitorDpiAware()) { + static auto enable_non_client_dpi_scaling_func = []() { + // Signature only available in the 10.0.14393.0 API. As of this writing, + // Chrome built against 10.0.10586.0. + using EnableNonClientDpiScalingPtr = LRESULT (WINAPI*)(HWND); + return reinterpret_cast<EnableNonClientDpiScalingPtr>( + GetProcAddress(GetModuleHandle(L"user32.dll"), + "EnableNonClientDpiScaling")); + }(); + called_enable_non_client_dpi_scaling_ = + !!(enable_non_client_dpi_scaling_func && + enable_non_client_dpi_scaling_func(hwnd())); + } + return FALSE; +} + LRESULT HWNDMessageHandler::OnNCHitTest(const gfx::Point& point) { if (!delegate_->HasNonClientView()) { SetMsgHandled(FALSE);
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h index 622696f..0ae7bbf 100644 --- a/ui/views/win/hwnd_message_handler.h +++ b/ui/views/win/hwnd_message_handler.h
@@ -411,6 +411,7 @@ CR_MSG_WM_MOVE(OnMove) CR_MSG_WM_MOVING(OnMoving) CR_MSG_WM_NCCALCSIZE(OnNCCalcSize) + CR_MSG_WM_NCCREATE(OnNCCreate) CR_MSG_WM_NCHITTEST(OnNCHitTest) CR_MSG_WM_NCPAINT(OnNCPaint) CR_MSG_WM_NOTIFY(OnNotify) @@ -462,6 +463,7 @@ void OnMoving(UINT param, const RECT* new_bounds); LRESULT OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param); + LRESULT OnNCCreate(LPCREATESTRUCT lpCreateStruct); LRESULT OnNCHitTest(const gfx::Point& point); void OnNCPaint(HRGN rgn); LRESULT OnNCUAHDrawCaption(UINT message, WPARAM w_param, LPARAM l_param); @@ -577,6 +579,13 @@ // The current DPI. int dpi_; + // Whether EnableNonClientDpiScaling was called successfully with this window. + // This flag exists because EnableNonClientDpiScaling must be called during + // WM_NCCREATE and EnableChildWindowDpiMessage is called after window + // creation. We don't want to call both, so this helps us determine if a call + // to EnableChildWindowDpiMessage is necessary. + bool called_enable_non_client_dpi_scaling_; + // Event handling ------------------------------------------------------------ // The flags currently being used with TrackMouseEvent to track mouse