diff --git a/DEPS b/DEPS index 3fd23d7..9f20dda 100644 --- a/DEPS +++ b/DEPS
@@ -133,11 +133,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': 'c8a84d2b7ff98b44c42a53d1ba750a2c02f9063a', + 'skia_revision': '348880c3f67fb4422d1f66588ab87866c6ea848f', # 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': '0829f5e5e466d8078da8365602f3ea5df735cfcd', + 'v8_revision': '0ef678d942fe182261c0120adea1091d6dde1986', # 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. @@ -145,15 +145,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '01cd5697760e6df88936b0d99dee740130956d49', + 'angle_revision': 'bff32703c75b0326ca3c7e49e49c7ecdacdef41e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '3d7b7ea134d1245748a26898c40f7d078fea16d7', + 'swiftshader_revision': 'cfbe5379bf8e12168908c305ab7228bb195d19bb', # 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': '0db20e0a220b9ce2ba7d6bee980ec1bcd7a667e7', + 'pdfium_revision': 'a664b953817c9d439a71486f2c1d9cda67edb8ef', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -264,11 +264,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'shaderc_revision': '1475418902b2724370f4abf003c06f8e1f947add', + 'shaderc_revision': '08549a9c626a047e4bd1c618713a0efb75774005', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '2e56970932ec01ef2b030fe6b27f305c7733a47f', + 'dawn_revision': '0195dbf908071e7b7afaed7c9fb922910e85e5c2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -802,7 +802,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5ea0721b4537610d30bc17d95ff2298b5e932e12', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '69250bb90295f22db34c8c853e218a77a0cac787', 'condition': 'checkout_linux', }, @@ -817,7 +817,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '70f65b7ac09d1702a5819da880d5eb61589c5f0f', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '7e26488a958d4ea1392889434292bce34e459040', 'condition': 'checkout_linux', }, @@ -827,7 +827,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3d86f06bc794b457a0e1329dfd4a0b5bd0dc2a0e', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2d3b9260f3085f0ce161dbec51f131979b828474', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1389,7 +1389,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@013ffd95d645dc185e569896d40e6af9a13778be', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@66347fe2ab6c4e95cc2b7abba325f16374c41019', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/apk/BUILD.gn b/android_webview/apk/BUILD.gn index a846f82..1ceff4b 100644 --- a/android_webview/apk/BUILD.gn +++ b/android_webview/apk/BUILD.gn
@@ -8,6 +8,9 @@ # in two different targets. android_library("webview_license_provider_java") { java_files = [ "//android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java" ] + deps = [ + "//base:base_java", + ] } android_library("webview_license_activity_java") {
diff --git a/android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java b/android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java index ef2dd2f..94824a6 100644 --- a/android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java +++ b/android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java
@@ -14,6 +14,8 @@ import android.os.ParcelFileDescriptor; import android.util.Log; +import org.chromium.base.FileUtils; + import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -49,11 +51,7 @@ ParcelFileDescriptor output, Uri uri, String mimeType, Bundle opts, String filename) { try (InputStream in = getContext().getAssets().open(filename); OutputStream out = new FileOutputStream(output.getFileDescriptor());) { - byte[] buf = new byte[8192]; - int size = -1; - while ((size = in.read(buf)) != -1) { - out.write(buf, 0, size); - } + FileUtils.copyStream(in, out); } catch (IOException e) { Log.e(TAG, "Failed to read the license file", e); }
diff --git a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc index 1bde77d5..31969a5 100644 --- a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc +++ b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
@@ -123,8 +123,7 @@ std::unique_ptr<net::CertVerifier::Request> request; int error = context->cert_verifier()->Verify( net::CertVerifier::RequestParams(cert, "www.ahrn.com", flags, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &result, callback.callback(), &request, net::NetLogWithSource()); EXPECT_THAT(error, net::test::IsError(net::ERR_IO_PENDING)); EXPECT_TRUE(request); @@ -161,9 +160,7 @@ net::TestCompletionCallback callback; std::unique_ptr<net::CertVerifier::Request> request; int error = context->cert_verifier()->Verify( - net::CertVerifier::RequestParams(cert, "127.0.0.1", flags, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + net::CertVerifier::RequestParams(cert, "127.0.0.1", flags, std::string()), &result, callback.callback(), &request, net::NetLogWithSource()); EXPECT_THAT(error, net::test::IsError(net::ERR_IO_PENDING)); EXPECT_TRUE(request);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidProtocolHandlerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidProtocolHandlerTest.java index 2af044e..0182d8d4 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidProtocolHandlerTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidProtocolHandlerTest.java
@@ -12,9 +12,9 @@ import org.junit.runner.RunWith; import org.chromium.android_webview.AndroidProtocolHandler; +import org.chromium.base.FileUtils; import org.chromium.base.test.util.Feature; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -67,10 +67,10 @@ InputStream svgzStream = null; try { svgStream = assertOpen("file:///android_asset/star.svg"); - byte[] expectedData = readFully(svgStream); + byte[] expectedData = FileUtils.readStream(svgStream); svgzStream = assertOpen("file:///android_asset/star.svgz"); - byte[] actualData = readFully(svgzStream); + byte[] actualData = FileUtils.readStream(svgzStream); Assert.assertArrayEquals( "Decompressed star.svgz doesn't match star.svg", expectedData, actualData); @@ -85,15 +85,4 @@ Assert.assertNotNull("Failed top open \"" + url + "\"", stream); return stream; } - - private byte[] readFully(InputStream stream) throws IOException { - ByteArrayOutputStream data = new ByteArrayOutputStream(); - byte[] buf = new byte[4096]; - for (;;) { - int len = stream.read(buf); - if (len < 1) break; - data.write(buf, 0, len); - } - return data.toByteArray(); - } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 0d564ef..7fa6dc99 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1322,7 +1322,6 @@ "//ash/components/shortcut_viewer", "//ash/keyboard/arc", "//ash/keyboard/ui", - "//ash/keyboard/ui:mojom", "//ash/login/resources:resources_grit", "//ash/system/message_center/arc", "//base", @@ -1919,7 +1918,6 @@ "//ash/components/shortcut_viewer:unit_tests", "//ash/keyboard/arc", "//ash/keyboard/ui", - "//ash/keyboard/ui:mojom", "//ash/keyboard/ui:test_support", "//ash/public/cpp", "//ash/public/cpp:manifest",
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 01c18ca..7d071e6 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -17,12 +17,12 @@ #include "ash/app_list/views/search_box_view.h" #include "ash/app_list/views/test/apps_grid_view_test_api.h" #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_list/app_list_switches.h" #include "ash/public/cpp/ash_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shelf_item_delegate.h" #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shelf_types.h"
diff --git a/ash/app_list/presenter/OWNERS b/ash/app_list/presenter/OWNERS deleted file mode 100644 index 08850f4..0000000 --- a/ash/app_list/presenter/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index dd9ee47..ba28075 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -458,9 +458,9 @@ gfx::PointF(0, y_offset), gfx::PointF())), view_(view) { - DCHECK(view_->is_in_drag() && - view_->app_list_state() == ash::mojom::AppListViewState::kPeeking && - !view_->is_tablet_mode()); + DCHECK(view_->is_in_drag()); + DCHECK_EQ(view_->app_list_state(), ash::mojom::AppListViewState::kPeeking); + DCHECK(!view_->is_tablet_mode()); } ~PeekingResetAnimation() override = default;
diff --git a/ash/detachable_base/detachable_base_handler.cc b/ash/detachable_base/detachable_base_handler.cc index c4b8e77..84f449e 100644 --- a/ash/detachable_base/detachable_base_handler.cc +++ b/ash/detachable_base/detachable_base_handler.cc
@@ -46,14 +46,11 @@ registry->RegisterDictionaryPref(prefs::kDetachableBaseDevices); } -DetachableBaseHandler::DetachableBaseHandler(Shell* shell) - : shell_(shell), +DetachableBaseHandler::DetachableBaseHandler(PrefService* local_state) + : local_state_(local_state), hammerd_observer_(this), power_manager_observer_(this), weak_ptr_factory_(this) { - if (shell_) - shell_->AddShellObserver(this); - if (chromeos::HammerdClient::Get()) // May be null in tests hammerd_observer_.Add(chromeos::HammerdClient::Get()); chromeos::PowerManagerClient* power_manager_client = @@ -63,12 +60,12 @@ power_manager_client->GetSwitchStates( base::BindOnce(&DetachableBaseHandler::OnGotPowerManagerSwitchStates, weak_ptr_factory_.GetWeakPtr())); + + if (GetPairingStatus() != DetachableBasePairingStatus::kNone) + NotifyPairingStatusChanged(); } -DetachableBaseHandler::~DetachableBaseHandler() { - if (shell_) - shell_->RemoveShellObserver(this); -} +DetachableBaseHandler::~DetachableBaseHandler() = default; void DetachableBaseHandler::AddObserver(DetachableBaseObserver* observer) { observers_.AddObserver(observer); @@ -138,14 +135,6 @@ return true; } -void DetachableBaseHandler::OnLocalStatePrefServiceInitialized( - PrefService* pref_service) { - local_state_ = pref_service; - - if (GetPairingStatus() != DetachableBasePairingStatus::kNone) - NotifyPairingStatusChanged(); -} - void DetachableBaseHandler::BaseFirmwareUpdateNeeded() { NotifyBaseRequiresFirmwareUpdate(true /*requires_update*/); }
diff --git a/ash/detachable_base/detachable_base_handler.h b/ash/detachable_base/detachable_base_handler.h index b7a9884..ae1f0e5 100644 --- a/ash/detachable_base/detachable_base_handler.h +++ b/ash/detachable_base/detachable_base_handler.h
@@ -12,7 +12,6 @@ #include "ash/ash_export.h" #include "ash/detachable_base/detachable_base_pairing_status.h" #include "ash/public/interfaces/user_info.mojom.h" -#include "ash/shell_observer.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" @@ -27,7 +26,6 @@ namespace ash { class DetachableBaseObserver; -class Shell; // Keeps track of the state of Chrome OS device's detachable base. It tracks // whether: @@ -46,13 +44,11 @@ // DetachableBaseHandler clients are expected to determine for which users the // detachable base state should be set or retrieved. class ASH_EXPORT DetachableBaseHandler - : public ShellObserver, - public chromeos::HammerdClient::Observer, + : public chromeos::HammerdClient::Observer, public chromeos::PowerManagerClient::Observer { public: - // |shell| - the ash shell that owns the DetachableBaseHandler. May be null in - // tests. - explicit DetachableBaseHandler(ash::Shell* shell); + // |local_state| - PrefService of Local state. May be null in tests. + explicit DetachableBaseHandler(PrefService* local_state); ~DetachableBaseHandler() override; // Registers the local state prefs for detachable base devices. @@ -85,9 +81,6 @@ // paired) - setting the last used base can be retried at that point. bool SetPairedBaseAsLastUsedByUser(const mojom::UserInfo& user); - // ShellObserver: - void OnLocalStatePrefServiceInitialized(PrefService* pref_service) override; - // chromeos::HammerdClient::Observer: void BaseFirmwareUpdateNeeded() override; void BaseFirmwareUpdateStarted() override; @@ -129,9 +122,6 @@ PrefService* local_state_ = nullptr; - // The shell that owns |this| - used to listen for local state initialization. - ash::Shell* shell_; - // Tablet mode state currently reported by power manager - tablet mode getting // turned on is used as a signal that the base is detached. base::Optional<chromeos::PowerManagerClient::TabletMode> tablet_mode_;
diff --git a/ash/detachable_base/detachable_base_handler_unittest.cc b/ash/detachable_base/detachable_base_handler_unittest.cc index 3a53ee4..02602e8 100644 --- a/ash/detachable_base/detachable_base_handler_unittest.cc +++ b/ash/detachable_base/detachable_base_handler_unittest.cc
@@ -95,8 +95,7 @@ default_user_ = CreateUser("user_1@foo.bar", "111111", UserType::kNormal); DetachableBaseHandler::RegisterPrefs(local_state_.registry()); - handler_ = std::make_unique<DetachableBaseHandler>(nullptr); - handler_->OnLocalStatePrefServiceInitialized(&local_state_); + handler_ = std::make_unique<DetachableBaseHandler>(&local_state_); handler_->AddObserver(&detachable_base_observer_); } @@ -122,21 +121,10 @@ void RestartHandler() { handler_->RemoveObserver(&detachable_base_observer_); - handler_ = std::make_unique<DetachableBaseHandler>(nullptr); - handler_->OnLocalStatePrefServiceInitialized(&local_state_); + handler_ = std::make_unique<DetachableBaseHandler>(&local_state_); handler_->AddObserver(&detachable_base_observer_); } - void ResetHandlerWithNoLocalState() { - handler_->RemoveObserver(&detachable_base_observer_); - handler_ = std::make_unique<DetachableBaseHandler>(nullptr); - handler_->AddObserver(&detachable_base_observer_); - } - - void SimulateLocalStateInitialized() { - handler_->OnLocalStatePrefServiceInitialized(&local_state_); - } - chromeos::FakeHammerdClient* hammerd_client_ = nullptr; TestBaseObserver detachable_base_observer_; @@ -552,42 +540,6 @@ detachable_base_observer_.reset_pairing_status_changed_count(); } -TEST_F(DetachableBaseHandlerTest, NoLocalState) { - base::RunLoop().RunUntilIdle(); - - hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04}); - handler_->SetPairedBaseAsLastUsedByUser(*default_user_); - detachable_base_observer_.reset_pairing_status_changed_count(); - - ResetHandlerWithNoLocalState(); - base::RunLoop().RunUntilIdle(); - - ChangePairedBase({0x04, 0x05, 0x06}); - - EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated, - handler_->GetPairingStatus()); - EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count()); - detachable_base_observer_.reset_pairing_status_changed_count(); - EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_)); - - SimulateLocalStateInitialized(); - - EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count()); - detachable_base_observer_.reset_pairing_status_changed_count(); - EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated, - handler_->GetPairingStatus()); - EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_)); - - ChangePairedBase({0x01, 0x02, 0x03, 0x04}); - - EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated, - handler_->GetPairingStatus()); - EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count()); - detachable_base_observer_.reset_pairing_status_changed_count(); - EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(*default_user_)); - detachable_base_observer_.reset_pairing_status_changed_count(); -} - TEST_F(DetachableBaseHandlerTest, EphemeralUser) { base::RunLoop().RunUntilIdle();
diff --git a/ash/keyboard/ash_keyboard_controller.cc b/ash/keyboard/ash_keyboard_controller.cc index ac09cc6..1768166 100644 --- a/ash/keyboard/ash_keyboard_controller.cc +++ b/ash/keyboard/ash_keyboard_controller.cc
@@ -6,8 +6,8 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui_factory.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/virtual_keyboard_controller.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h"
diff --git a/ash/keyboard/ui/BUILD.gn b/ash/keyboard/ui/BUILD.gn index 0a85456..88bf659 100644 --- a/ash/keyboard/ui/BUILD.gn +++ b/ash/keyboard/ui/BUILD.gn
@@ -43,8 +43,6 @@ "keyboard_util.h", "notification_manager.cc", "notification_manager.h", - "public/keyboard_switches.cc", - "public/keyboard_switches.h", "queued_container_type.cc", "queued_container_type.h", "queued_display_change.cc", @@ -58,8 +56,8 @@ defines = [ "KEYBOARD_IMPLEMENTATION" ] deps = [ - ":mojom", ":resources", + "//ash/public/cpp", "//base", "//services/metrics/public/cpp:ukm_builders", "//ui/aura", @@ -145,13 +143,6 @@ path = rebase_path("//third_party/google_input_tools") } -mojom("mojom") { - sources = [ - "public/keyboard_config.mojom", - "public/keyboard_controller_types.mojom", - ] -} - test("keyboard_unittests") { sources = [ "container_floating_behavior_unittest.cc", @@ -165,9 +156,9 @@ ] deps = [ - ":mojom", ":test_support", ":ui", + "//ash/public/cpp", "//base", "//base/test:test_support", "//components/ukm:test_support",
diff --git a/ash/keyboard/ui/container_behavior.h b/ash/keyboard/ui/container_behavior.h index 4efcea7..2c8d097 100644 --- a/ash/keyboard/ui/container_behavior.h +++ b/ash/keyboard/ui/container_behavior.h
@@ -6,7 +6,7 @@ #define ASH_KEYBOARD_UI_CONTAINER_BEHAVIOR_H_ #include "ash/keyboard/ui/keyboard_export.h" -#include "ash/keyboard/ui/public/keyboard_controller_types.mojom.h" +#include "ash/public/interfaces/keyboard_controller_types.mojom.h" #include "ui/display/display.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h"
diff --git a/ash/keyboard/ui/keyboard_controller.cc b/ash/keyboard/ui/keyboard_controller.cc index f87effe..395d4dc 100644 --- a/ash/keyboard/ui/keyboard_controller.cc +++ b/ash/keyboard/ui/keyboard_controller.cc
@@ -16,10 +16,10 @@ #include "ash/keyboard/ui/keyboard_ui_factory.h" #include "ash/keyboard/ui/keyboard_util.h" #include "ash/keyboard/ui/notification_manager.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/queued_container_type.h" #include "ash/keyboard/ui/queued_display_change.h" #include "ash/keyboard/ui/shaped_window_targeter.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/bind.h" #include "base/command_line.h" #include "base/macros.h" @@ -142,16 +142,17 @@ } // An enumeration of different keyboard control events that should be logged. -enum KeyboardControlEvent { - KEYBOARD_CONTROL_SHOW = 0, - KEYBOARD_CONTROL_HIDE_AUTO, - KEYBOARD_CONTROL_HIDE_USER, - KEYBOARD_CONTROL_MAX, +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class KeyboardControlEvent { + kShow = 0, + kHideAuto = 1, + kHideUser = 2, + kMaxValue = kHideUser }; void LogKeyboardControlEvent(KeyboardControlEvent event) { - UMA_HISTOGRAM_ENUMERATION("VirtualKeyboard.KeyboardControlEvent", event, - KEYBOARD_CONTROL_MAX); + UMA_HISTOGRAM_ENUMERATION("VirtualKeyboard.KeyboardControlEvent", event); } class InputMethodKeyboardController : public ui::InputMethodKeyboardController { @@ -603,11 +604,11 @@ case HIDE_REASON_SYSTEM_EXPLICIT: case HIDE_REASON_SYSTEM_IMPLICIT: case HIDE_REASON_SYSTEM_TEMPORARY: - LogKeyboardControlEvent(KEYBOARD_CONTROL_HIDE_AUTO); + LogKeyboardControlEvent(KeyboardControlEvent::kHideAuto); break; case HIDE_REASON_USER_EXPLICIT: case HIDE_REASON_USER_IMPLICIT: - LogKeyboardControlEvent(KEYBOARD_CONTROL_HIDE_USER); + LogKeyboardControlEvent(KeyboardControlEvent::kHideUser); break; } @@ -948,7 +949,7 @@ // are at begin states for animation. container_behavior_->InitializeShowAnimationStartingState(keyboard_window); - LogKeyboardControlEvent(KEYBOARD_CONTROL_SHOW); + LogKeyboardControlEvent(KeyboardControlEvent::kShow); RecordUkmKeyboardShown(); ui::LayerAnimator* container_animator = @@ -973,8 +974,7 @@ ChangeState(KeyboardControllerState::SHOWN); UMA_HISTOGRAM_ENUMERATION("InputMethod.VirtualKeyboard.ContainerBehavior", - GetActiveContainerType(), - mojom::ContainerType::kMaxValue); + GetActiveContainerType()); } bool KeyboardController::WillHideKeyboard() const {
diff --git a/ash/keyboard/ui/keyboard_controller.h b/ash/keyboard/ui/keyboard_controller.h index c61de37..efabdb6 100644 --- a/ash/keyboard/ui/keyboard_controller.h +++ b/ash/keyboard/ui/keyboard_controller.h
@@ -16,10 +16,10 @@ #include "ash/keyboard/ui/keyboard_layout_delegate.h" #include "ash/keyboard/ui/keyboard_ukm_recorder.h" #include "ash/keyboard/ui/notification_manager.h" -#include "ash/keyboard/ui/public/keyboard_config.mojom.h" -#include "ash/keyboard/ui/public/keyboard_controller_types.mojom.h" #include "ash/keyboard/ui/queued_container_type.h" #include "ash/keyboard/ui/queued_display_change.h" +#include "ash/public/interfaces/keyboard_config.mojom.h" +#include "ash/public/interfaces/keyboard_controller_types.mojom.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/scoped_observer.h"
diff --git a/ash/keyboard/ui/keyboard_util.cc b/ash/keyboard/ui/keyboard_util.cc index 84de22e..1068975 100644 --- a/ash/keyboard/ui/keyboard_util.cc +++ b/ash/keyboard/ui/keyboard_util.cc
@@ -7,7 +7,7 @@ #include <string> #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/command_line.h" #include "base/metrics/histogram_macros.h"
diff --git a/ash/keyboard/ui/public/keyboard_switches.h b/ash/keyboard/ui/public/keyboard_switches.h deleted file mode 100644 index b5e22c2..0000000 --- a/ash/keyboard/ui/public/keyboard_switches.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_KEYBOARD_UI_PUBLIC_KEYBOARD_SWITCHES_H_ -#define ASH_KEYBOARD_UI_PUBLIC_KEYBOARD_SWITCHES_H_ - -#include "ash/keyboard/ui/keyboard_export.h" - -namespace keyboard { -namespace switches { - -// Enables the virtual keyboard. -KEYBOARD_EXPORT extern const char kEnableVirtualKeyboard[]; - -} // namespace switches -} // namespace keyboard - -#endif // ASH_KEYBOARD_UI_PUBLIC_KEYBOARD_SWITCHES_H_
diff --git a/ash/keyboard/ui/queued_container_type.h b/ash/keyboard/ui/queued_container_type.h index 56dd458..53b29d5 100644 --- a/ash/keyboard/ui/queued_container_type.h +++ b/ash/keyboard/ui/queued_container_type.h
@@ -5,7 +5,7 @@ #ifndef ASH_KEYBOARD_UI_QUEUED_CONTAINER_TYPE_H_ #define ASH_KEYBOARD_UI_QUEUED_CONTAINER_TYPE_H_ -#include "ash/keyboard/ui/public/keyboard_controller_types.mojom.h" +#include "ash/public/interfaces/keyboard_controller_types.mojom.h" #include "base/bind.h" #include "base/optional.h" #include "ui/gfx/geometry/rect.h"
diff --git a/ash/keyboard/virtual_keyboard_controller.cc b/ash/keyboard/virtual_keyboard_controller.cc index faf7a58..2f4afc9d 100644 --- a/ash/keyboard/virtual_keyboard_controller.cc +++ b/ash/keyboard/virtual_keyboard_controller.cc
@@ -11,7 +11,7 @@ #include "ash/keyboard/ash_keyboard_controller.h" #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller_impl.h"
diff --git a/ash/keyboard/virtual_keyboard_controller_unittest.cc b/ash/keyboard/virtual_keyboard_controller_unittest.cc index 8d74e4b..3ea25905 100644 --- a/ash/keyboard/virtual_keyboard_controller_unittest.cc +++ b/ash/keyboard/virtual_keyboard_controller_unittest.cc
@@ -11,8 +11,8 @@ #include "ash/ime/ime_controller.h" #include "ash/ime/test_ime_controller_client.h" #include "ash/keyboard/ash_keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/shell.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/virtual_keyboard/virtual_keyboard_observer.h"
diff --git a/ash/keyboard/virtual_keyboard_unittest.cc b/ash/keyboard/virtual_keyboard_unittest.cc index b25efc5d..8e331a6 100644 --- a/ash/keyboard/virtual_keyboard_unittest.cc +++ b/ash/keyboard/virtual_keyboard_unittest.cc
@@ -4,8 +4,8 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "base/bind_helpers.h"
diff --git a/ash/login/ui/login_keyboard_test_base.cc b/ash/login/ui/login_keyboard_test_base.cc index 098aaea..f4f87cc 100644 --- a/ash/login/ui/login_keyboard_test_base.cc +++ b/ash/login/ui/login_keyboard_test_base.cc
@@ -7,11 +7,11 @@ #include "ash/keyboard/ash_keyboard_controller.h" #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/login/mock_login_screen_client.h" #include "ash/login/ui/lock_screen.h" #include "ash/login/ui/login_test_utils.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/root_window_controller.h" #include "ash/session/test_session_controller_client.h" #include "ash/shell.h"
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index bb3ba157..828be8cb 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -17,8 +17,6 @@ "app_list/app_list_metrics.h", "app_list/app_list_switches.cc", "app_list/app_list_switches.h", - "app_list/app_list_types.cc", - "app_list/app_list_types.h", "app_list/internal_app_id_constants.h", "app_list/term_break_iterator.cc", "app_list/term_break_iterator.h", @@ -35,7 +33,6 @@ "ash_features.h", "ash_pref_names.cc", "ash_pref_names.h", - "ash_public_export.h", "ash_switches.cc", "ash_switches.h", "ash_typography.cc", @@ -78,6 +75,8 @@ "immersive/immersive_fullscreen_controller_delegate.h", "immersive/immersive_revealed_lock.cc", "immersive/immersive_revealed_lock.h", + "keyboard/keyboard_switches.cc", + "keyboard/keyboard_switches.h", "keyboard_shortcut_viewer.h", "kiosk_app_menu.cc", "kiosk_app_menu.h", @@ -168,6 +167,7 @@ ] public_deps = [ + ":base", "//ash/public/interfaces:interfaces_internal", "//base", "//components/session_manager:base", @@ -180,6 +180,23 @@ output_name = "ash_public_cpp" } +# This is listed separately because app_list.mojom type mapping depends on it +# but //ash/public/interfaces could not depend on //ash/public/cpp. +# TODO(crbug.com/958134): Move this back when app_list.mojom is gone. +source_set("base") { + sources = [ + "app_list/app_list_types.cc", + "app_list/app_list_types.h", + "ash_public_export.h", + ] + + defines = [ "ASH_PUBLIC_IMPLEMENTATION" ] + + public_deps = [ + "//ui/gfx", + ] +} + source_set("manifest") { sources = [ "manifest.cc", @@ -269,7 +286,6 @@ deps = [ ":cpp", - "//ash/keyboard/ui:mojom", "//base", "//services/service_manager/public/cpp", "//ui/aura",
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc index d21c63f..b65370b 100644 --- a/ash/public/cpp/app_list/app_list_features.cc +++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -33,6 +33,8 @@ "EnableZeroStateAppsRanker", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kEnableQueryBasedMixedTypesRanker{ "EnableQueryBasedMixedTypesRanker", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kEnableZeroStateMixedTypesRanker{ + "EnableZeroStateMixedTypesRanker", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kEnableAppReinstallZeroState{ "EnableAppReinstallZeroState", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kEnableEmbeddedAssistantUI{ @@ -90,6 +92,10 @@ return base::FeatureList::IsEnabled(kEnableQueryBasedMixedTypesRanker); } +bool IsZeroStateMixedTypesRankerEnabled() { + return base::FeatureList::IsEnabled(kEnableZeroStateMixedTypesRanker); +} + bool IsAppReinstallZeroStateEnabled() { return base::FeatureList::IsEnabled(kEnableAppReinstallZeroState); }
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h index 59682837..994ddff 100644 --- a/ash/public/cpp/app_list/app_list_features.h +++ b/ash/public/cpp/app_list/app_list_features.h
@@ -53,6 +53,9 @@ // Enable an model that ranks query based non-apps result. ASH_PUBLIC_EXPORT extern const base::Feature kEnableQueryBasedMixedTypesRanker; +// Enable a model that ranks zero-state files and recent queries. +ASH_PUBLIC_EXPORT extern const base::Feature kEnableZeroStateMixedTypesRanker; + // Enables the feature to include a single reinstallation candidate in // zero-state. ASH_PUBLIC_EXPORT extern const base::Feature kEnableAppReinstallZeroState; @@ -77,6 +80,7 @@ bool ASH_PUBLIC_EXPORT IsQueryBasedAppsRankerEnabled(); bool ASH_PUBLIC_EXPORT IsZeroStateAppsRankerEnabled(); bool ASH_PUBLIC_EXPORT IsQueryBasedMixedTypesRankerEnabled(); +bool ASH_PUBLIC_EXPORT IsZeroStateMixedTypesRankerEnabled(); bool ASH_PUBLIC_EXPORT IsAppReinstallZeroStateEnabled(); bool ASH_PUBLIC_EXPORT IsEmbeddedAssistantUIEnabled(); bool ASH_PUBLIC_EXPORT IsAppGridGhostEnabled();
diff --git a/ash/keyboard/ui/public/keyboard_switches.cc b/ash/public/cpp/keyboard/keyboard_switches.cc similarity index 85% rename from ash/keyboard/ui/public/keyboard_switches.cc rename to ash/public/cpp/keyboard/keyboard_switches.cc index df21ecd..dd3e98f 100644 --- a/ash/keyboard/ui/public/keyboard_switches.cc +++ b/ash/public/cpp/keyboard/keyboard_switches.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 "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" namespace keyboard { namespace switches {
diff --git a/ash/public/cpp/keyboard/keyboard_switches.h b/ash/public/cpp/keyboard/keyboard_switches.h new file mode 100644 index 0000000..e3a01d8 --- /dev/null +++ b/ash/public/cpp/keyboard/keyboard_switches.h
@@ -0,0 +1,19 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_SWITCHES_H_ +#define ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_SWITCHES_H_ + +#include "ash/public/cpp/ash_public_export.h" + +namespace keyboard { +namespace switches { + +// Enables the virtual keyboard. +ASH_PUBLIC_EXPORT extern const char kEnableVirtualKeyboard[]; + +} // namespace switches +} // namespace keyboard + +#endif // ASH_PUBLIC_CPP_KEYBOARD_KEYBOARD_SWITCHES_H_
diff --git a/ash/public/cpp/test/shell_test_api.h b/ash/public/cpp/test/shell_test_api.h index e23379f..9367df69 100644 --- a/ash/public/cpp/test/shell_test_api.h +++ b/ash/public/cpp/test/shell_test_api.h
@@ -12,8 +12,6 @@ #include "base/callback_forward.h" #include "base/macros.h" -class PrefService; - namespace ash { class DragDropController; class MessageCenterController; @@ -43,9 +41,6 @@ DragDropController* drag_drop_controller(); PowerPrefs* power_prefs(); - // Calls the private method. - void OnLocalStatePrefServiceInitialized(PrefService* pref_service); - // Resets |shell_->power_button_controller_| to hold a new object to simulate // Chrome starting. void ResetPowerButtonControllerForTest();
diff --git a/ash/public/cpp/test/test_keyboard_controller_observer.h b/ash/public/cpp/test/test_keyboard_controller_observer.h index 935ba98..9f9988a 100644 --- a/ash/public/cpp/test/test_keyboard_controller_observer.h +++ b/ash/public/cpp/test/test_keyboard_controller_observer.h
@@ -5,7 +5,7 @@ #ifndef ASH_PUBLIC_CPP_TEST_TEST_KEYBOARD_CONTROLLER_OBSERVER_H_ #define ASH_PUBLIC_CPP_TEST_TEST_KEYBOARD_CONTROLLER_OBSERVER_H_ -#include "ash/keyboard/ui/public/keyboard_config.mojom.h" +#include "ash/public/interfaces/keyboard_config.mojom.h" #include "ash/public/interfaces/keyboard_controller.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h"
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index fe8d646f..0ec2d2d 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -37,7 +37,9 @@ "highlighter_controller.mojom", "ime_controller.mojom", "ime_info.mojom", + "keyboard_config.mojom", "keyboard_controller.mojom", + "keyboard_controller_types.mojom", "kiosk_next_shell.mojom", "locale.mojom", "login_screen.mojom", @@ -64,7 +66,6 @@ ] public_deps = [ - "//ash/keyboard/ui:mojom", "//chromeos/components/proximity_auth/public/interfaces", "//chromeos/services/assistant/public/mojom", "//components/account_id/interfaces",
diff --git a/ash/public/interfaces/app_list.typemap b/ash/public/interfaces/app_list.typemap index 169a3c49..672d5ce 100644 --- a/ash/public/interfaces/app_list.typemap +++ b/ash/public/interfaces/app_list.typemap
@@ -8,6 +8,9 @@ sources = [ "//ash/public/cpp/app_list/app_list_struct_traits.cc", ] +deps = [ + "//ash/public/cpp:base", +] type_mappings = [ "ash.mojom.AppListState=ash::AppListState", "ash.mojom.AppListModelStatus=ash::AppListModelStatus",
diff --git a/ash/keyboard/ui/public/keyboard_config.mojom b/ash/public/interfaces/keyboard_config.mojom similarity index 100% rename from ash/keyboard/ui/public/keyboard_config.mojom rename to ash/public/interfaces/keyboard_config.mojom
diff --git a/ash/public/interfaces/keyboard_controller.mojom b/ash/public/interfaces/keyboard_controller.mojom index 8dffff4..a27418c 100644 --- a/ash/public/interfaces/keyboard_controller.mojom +++ b/ash/public/interfaces/keyboard_controller.mojom
@@ -4,8 +4,8 @@ module ash.mojom; -import "ash/keyboard/ui/public/keyboard_config.mojom"; -import "ash/keyboard/ui/public/keyboard_controller_types.mojom"; +import "ash/public/interfaces/keyboard_config.mojom"; +import "ash/public/interfaces/keyboard_controller_types.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; enum HideReason {
diff --git a/ash/keyboard/ui/public/keyboard_controller_types.mojom b/ash/public/interfaces/keyboard_controller_types.mojom similarity index 100% rename from ash/keyboard/ui/public/keyboard_controller_types.mojom rename to ash/public/interfaces/keyboard_controller_types.mojom
diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc index 025085a0..62a2d7e 100644 --- a/ash/root_window_controller_unittest.cc +++ b/ash/root_window_controller_unittest.cc
@@ -9,8 +9,8 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/session/session_controller_impl.h" #include "ash/session/test_session_controller_client.h"
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc index e37aa3c31..b57109f 100644 --- a/ash/shelf/shelf_widget_unittest.cc +++ b/ash/shelf/shelf_widget_unittest.cc
@@ -6,10 +6,10 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/root_window_controller.h" #include "ash/shelf/login_shelf_view.h" #include "ash/shelf/shelf.h"
diff --git a/ash/shell.cc b/ash/shell.cc index d6326ef..ed7be4d0 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -891,6 +891,8 @@ // Required by DetachableBaseHandler. chromeos::InitializeDBusClient<chromeos::HammerdClient>(dbus_bus.get()); + local_state_ = local_state; + // This creates the MessageCenter object which is used by some other objects // initialized here, so it needs to come early. message_center_controller_ = std::make_unique<MessageCenterController>(); @@ -898,8 +900,10 @@ // These controllers call Shell::Get() in their constructors, so they cannot // be in the member initialization list. touch_devices_controller_ = std::make_unique<TouchDevicesController>(); - bluetooth_power_controller_ = std::make_unique<BluetoothPowerController>(); - detachable_base_handler_ = std::make_unique<DetachableBaseHandler>(this); + bluetooth_power_controller_ = + std::make_unique<BluetoothPowerController>(local_state_); + detachable_base_handler_ = + std::make_unique<DetachableBaseHandler>(local_state_); detachable_base_notification_controller_ = std::make_unique<DetachableBaseNotificationController>( detachable_base_handler_.get()); @@ -930,7 +934,7 @@ // Shelf, and WallPaper could be created by the factory. views::FocusManagerFactory::Install(new AshFocusManagerFactory); - wallpaper_controller_ = std::make_unique<WallpaperController>(); + wallpaper_controller_ = std::make_unique<WallpaperController>(local_state_); window_positioner_ = std::make_unique<WindowPositioner>(); @@ -940,7 +944,7 @@ InitializeDisplayManager(); - display_prefs_ = std::make_unique<DisplayPrefs>(local_state); + display_prefs_ = std::make_unique<DisplayPrefs>(local_state_); // This will initialize aura::Env which requires |display_manager_| to // be initialized first. @@ -1033,9 +1037,9 @@ sticky_keys_controller_.reset(new StickyKeysController); screen_pinning_controller_ = std::make_unique<ScreenPinningController>(); - power_prefs_ = - std::make_unique<PowerPrefs>(chromeos::PowerPolicyController::Get(), - chromeos::PowerManagerClient::Get()); + power_prefs_ = std::make_unique<PowerPrefs>( + chromeos::PowerPolicyController::Get(), + chromeos::PowerManagerClient::Get(), local_state_); backlights_forced_off_setter_ = std::make_unique<BacklightsForcedOffSetter>(); @@ -1182,10 +1186,6 @@ // By this point ash shell should have initialized its D-Bus signal // listeners, so inform the session manager that Ash is initialized. session_controller_->EmitAshInitialized(); - - // Associates with local state. - if (local_state) - OnLocalStatePrefServiceInitialized(local_state); } void Shell::InitializeDisplayManager() { @@ -1342,14 +1342,4 @@ #endif } -void Shell::OnLocalStatePrefServiceInitialized(PrefService* pref_service) { - DCHECK(!local_state_); - DCHECK(pref_service); - - local_state_ = pref_service; - - for (auto& observer : shell_observers_) - observer.OnLocalStatePrefServiceInitialized(local_state_); -} - } // namespace ash
diff --git a/ash/shell.h b/ash/shell.h index 656c933..e926b5f1 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -548,6 +548,8 @@ return toplevel_window_event_handler_.get(); } + PrefService* local_state() { return local_state_; } + // Force the shelf to query for it's current visibility state. // TODO(jamescook): Move to Shelf. void UpdateShelfVisibility(); @@ -661,8 +663,6 @@ void OnLoginStatusChanged(LoginStatus login_status) override; void OnLockStateChanged(bool locked) override; - void OnLocalStatePrefServiceInitialized(PrefService* pref_service); - static Shell* instance_; // |owned_aura_env_| is non-null if Shell created aura::Env. Shell creates
diff --git a/ash/shell_observer.h b/ash/shell_observer.h index bea0507..ace31ebc6 100644 --- a/ash/shell_observer.h +++ b/ash/shell_observer.h
@@ -12,8 +12,6 @@ class Window; } -class PrefService; - namespace ash { class ASH_EXPORT ShellObserver { @@ -69,10 +67,6 @@ // most of Shell's state has been deleted. virtual void OnShellDestroyed() {} - // Called when local state prefs are available. This occurs an arbitrary - // amount of time after Shell initialization. Only called once. - virtual void OnLocalStatePrefServiceInitialized(PrefService* pref_service) {} - protected: virtual ~ShellObserver() {} };
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc index a4e85a2..3572f3a 100644 --- a/ash/shell_test_api.cc +++ b/ash/shell_test_api.cc
@@ -166,11 +166,6 @@ return shell_->power_prefs_.get(); } -void ShellTestApi::OnLocalStatePrefServiceInitialized( - PrefService* pref_service) { - shell_->OnLocalStatePrefServiceInitialized(pref_service); -} - void ShellTestApi::ResetPowerButtonControllerForTest() { shell_->backlights_forced_off_setter_->ResetForTest(); shell_->power_button_controller_ = std::make_unique<PowerButtonController>(
diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc index c55f035..e5cec16b 100644 --- a/ash/shell_unittest.cc +++ b/ash/shell_unittest.cc
@@ -14,9 +14,9 @@ #include "ash/drag_drop/drag_drop_controller_test_api.h" #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_prefs.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/test/shell_test_api.h" #include "ash/root_window_controller.h" @@ -182,22 +182,6 @@ DISALLOW_COPY_AND_ASSIGN(SimpleMenuDelegate); }; -class TestShellObserver : public ShellObserver { - public: - TestShellObserver() = default; - ~TestShellObserver() override = default; - - // ShellObserver: - void OnLocalStatePrefServiceInitialized(PrefService* pref_service) override { - last_local_state_ = pref_service; - } - - PrefService* last_local_state_ = nullptr; - - private: - DISALLOW_COPY_AND_ASSIGN(TestShellObserver); -}; - } // namespace class ShellTest : public AshTestBase { @@ -674,21 +658,6 @@ std::unique_ptr<TestingPrefServiceSimple> local_state_; }; -TEST_F(ShellLocalStateTest, LocalState) { - TestShellObserver observer; - Shell::Get()->AddShellObserver(&observer); - - // Prefs service wrapper code creates a PrefService. - local_state_ = std::make_unique<TestingPrefServiceSimple>(); - RegisterLocalStatePrefs(local_state_->registry(), true); - TestingPrefServiceSimple* local_state_ptr = local_state_.get(); - ShellTestApi().OnLocalStatePrefServiceInitialized(local_state_ptr); - EXPECT_EQ(local_state_ptr, observer.last_local_state_); - EXPECT_EQ(local_state_ptr, ash_test_helper()->GetLocalStatePrefService()); - - Shell::Get()->RemoveShellObserver(&observer); -} - using ShellLoginTest = NoSessionAshTestBase; TEST_F(ShellLoginTest, DragAndDropDisabledBeforeLogin) {
diff --git a/ash/system/bluetooth/bluetooth_power_controller.cc b/ash/system/bluetooth/bluetooth_power_controller.cc index 33c11f0..dcadaba 100644 --- a/ash/system/bluetooth/bluetooth_power_controller.cc +++ b/ash/system/bluetooth/bluetooth_power_controller.cc
@@ -23,18 +23,29 @@ // initialize power, so taking 1000 ms has enough time buffer for worst cases. const int kBluetoothInitializationDelay = 1000; -BluetoothPowerController::BluetoothPowerController() : weak_ptr_factory_(this) { +BluetoothPowerController::BluetoothPowerController(PrefService* local_state) + : local_state_(local_state), weak_ptr_factory_(this) { device::BluetoothAdapterFactory::GetAdapter( base::BindOnce(&BluetoothPowerController::InitializeOnAdapterReady, weak_ptr_factory_.GetWeakPtr())); - Shell::Get()->AddShellObserver(this); Shell::Get()->session_controller()->AddObserver(this); + + // AppLaunchTest.TestQuickLaunch fails under target=linux due to + // |local_state_| being nullptr. + if (local_state_) { + StartWatchingLocalStatePrefsChanges(); + + if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted()) { + // Apply the local state pref only if no user has logged in (still in + // login screen). + ApplyBluetoothLocalStatePref(); + } + } } BluetoothPowerController::~BluetoothPowerController() { if (bluetooth_adapter_) bluetooth_adapter_->RemoveObserver(this); - Shell::Get()->RemoveShellObserver(this); Shell::Get()->session_controller()->RemoveObserver(this); } @@ -42,9 +53,8 @@ if (active_user_pref_service_) { active_user_pref_service_->SetBoolean(prefs::kUserBluetoothAdapterEnabled, enabled); - } else if (local_state_pref_service_) { - local_state_pref_service_->SetBoolean(prefs::kSystemBluetoothAdapterEnabled, - enabled); + } else if (local_state_) { + local_state_->SetBoolean(prefs::kSystemBluetoothAdapterEnabled, enabled); } else { DLOG(ERROR) << "active user and local state pref service cannot both be null"; @@ -78,10 +88,10 @@ } void BluetoothPowerController::StartWatchingLocalStatePrefsChanges() { - DCHECK(local_state_pref_service_); + DCHECK(local_state_); local_state_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); - local_state_pref_change_registrar_->Init(local_state_pref_service_); + local_state_pref_change_registrar_->Init(local_state_); local_state_pref_change_registrar_->Add( prefs::kSystemBluetoothAdapterEnabled, base::Bind( @@ -101,10 +111,10 @@ } void BluetoothPowerController::OnBluetoothPowerLocalStatePrefChanged() { - DCHECK(local_state_pref_service_); + DCHECK(local_state_); BLUETOOTH_LOG(EVENT) << "Local state bluetooth power pref changed"; - SetBluetoothPower(local_state_pref_service_->GetBoolean( - prefs::kSystemBluetoothAdapterEnabled)); + SetBluetoothPower( + local_state_->GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); } void BluetoothPowerController::SetPrimaryUserBluetoothPowerSetting( @@ -149,24 +159,6 @@ } } -void BluetoothPowerController::OnLocalStatePrefServiceInitialized( - PrefService* pref_service) { - // AppLaunchTest.TestQuickLaunch fails under target=linux due to - // pref_service being nullptr. - if (!pref_service) - return; - - local_state_pref_service_ = pref_service; - - StartWatchingLocalStatePrefsChanges(); - - if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted()) { - // Apply the local state pref only if no user has logged in (still in login - // screen). - ApplyBluetoothLocalStatePref(); - } -} - void BluetoothPowerController::AdapterPresentChanged( device::BluetoothAdapter* adapter, bool present) { @@ -221,15 +213,14 @@ } void BluetoothPowerController::ApplyBluetoothLocalStatePref() { - PrefService* prefs = local_state_pref_service_; - - if (prefs->FindPreference(prefs::kSystemBluetoothAdapterEnabled) + if (local_state_->FindPreference(prefs::kSystemBluetoothAdapterEnabled) ->IsDefaultValue()) { // If the device has not had the local state bluetooth pref, set the pref // according to whatever the current bluetooth power is. - SavePrefValue(prefs, prefs::kSystemBluetoothAdapterEnabled); + SavePrefValue(local_state_, prefs::kSystemBluetoothAdapterEnabled); } else { - bool enabled = prefs->GetBoolean(prefs::kSystemBluetoothAdapterEnabled); + bool enabled = + local_state_->GetBoolean(prefs::kSystemBluetoothAdapterEnabled); BLUETOOTH_LOG(EVENT) << "Applying local state pref bluetooth power: " << enabled; SetBluetoothPower(enabled);
diff --git a/ash/system/bluetooth/bluetooth_power_controller.h b/ash/system/bluetooth/bluetooth_power_controller.h index a651990..4640ea7 100644 --- a/ash/system/bluetooth/bluetooth_power_controller.h +++ b/ash/system/bluetooth/bluetooth_power_controller.h
@@ -7,7 +7,6 @@ #include "ash/ash_export.h" #include "ash/session/session_observer.h" -#include "ash/shell_observer.h" #include "base/containers/queue.h" #include "base/logging.h" #include "base/macros.h" @@ -29,10 +28,9 @@ // setting instead. class ASH_EXPORT BluetoothPowerController : public SessionObserver, - public ShellObserver, public device::BluetoothAdapter::Observer { public: - BluetoothPowerController(); + explicit BluetoothPowerController(PrefService* local_state); ~BluetoothPowerController() override; // Changes the bluetooth power setting to |enabled|. @@ -55,9 +53,6 @@ // SessionObserver: void OnActiveUserPrefServiceChanged(PrefService* pref_service) override; - // ShellObserver: - void OnLocalStatePrefServiceInitialized(PrefService* pref_service) override; - // BluetoothAdapter::Observer: void AdapterPresentChanged(device::BluetoothAdapter* adapter, bool present) override; @@ -128,7 +123,7 @@ bool is_primary_user_bluetooth_applied_ = false; PrefService* active_user_pref_service_ = nullptr; - PrefService* local_state_pref_service_ = nullptr; + PrefService* local_state_ = nullptr; // Contains pending tasks which depend on the availability of bluetooth // adapter.
diff --git a/ash/system/bluetooth/bluetooth_power_controller_unittest.cc b/ash/system/bluetooth/bluetooth_power_controller_unittest.cc index 437d0df..cb80cac 100644 --- a/ash/system/bluetooth/bluetooth_power_controller_unittest.cc +++ b/ash/system/bluetooth/bluetooth_power_controller_unittest.cc
@@ -58,10 +58,9 @@ BluetoothPowerController::RegisterProfilePrefs( active_user_prefs_.registry()); - BluetoothPowerController::RegisterLocalStatePrefs( - local_state_prefs_.registry()); + BluetoothPowerController::RegisterLocalStatePrefs(local_state_.registry()); - GetController()->local_state_pref_service_ = &local_state_prefs_; + GetController()->local_state_ = &local_state_; SetupBluetoothAdapter(); } @@ -105,7 +104,7 @@ } TestingPrefServiceSimple active_user_prefs_; - TestingPrefServiceSimple local_state_prefs_; + TestingPrefServiceSimple local_state_; private: DISALLOW_COPY_AND_ASSIGN(BluetoothPowerControllerTest); @@ -115,14 +114,11 @@ TEST_F(BluetoothPowerControllerTest, ToggleBluetoothEnabled) { // Toggling bluetooth on/off when there is no user session should affect // local state prefs. - EXPECT_FALSE( - local_state_prefs_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); + EXPECT_FALSE(local_state_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); GetController()->SetBluetoothEnabled(true); - EXPECT_TRUE( - local_state_prefs_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); + EXPECT_TRUE(local_state_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); GetController()->SetBluetoothEnabled(false); - EXPECT_FALSE( - local_state_prefs_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); + EXPECT_FALSE(local_state_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); // Toggling bluetooth on/off when there is user session should affect // user prefs. @@ -144,15 +140,14 @@ // Makes sure we start with bluetooth power off. EXPECT_FALSE(GetBluetoothAdapter()->IsPowered()); - EXPECT_FALSE( - local_state_prefs_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); + EXPECT_FALSE(local_state_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); // Power should be turned on when pref changes to enabled. - local_state_prefs_.SetBoolean(prefs::kSystemBluetoothAdapterEnabled, true); + local_state_.SetBoolean(prefs::kSystemBluetoothAdapterEnabled, true); EXPECT_TRUE(GetBluetoothAdapter()->IsPowered()); // Power should be turned off when pref changes to disabled. - local_state_prefs_.SetBoolean(prefs::kSystemBluetoothAdapterEnabled, false); + local_state_.SetBoolean(prefs::kSystemBluetoothAdapterEnabled, false); EXPECT_FALSE(GetBluetoothAdapter()->IsPowered()); } @@ -208,7 +203,7 @@ TEST_F(BluetoothPowerControllerTest, ApplyBluetoothLocalStatePrefDefault) { // Makes sure pref hasn't been set before. EXPECT_TRUE( - local_state_prefs_.FindPreference(prefs::kSystemBluetoothAdapterEnabled) + local_state_.FindPreference(prefs::kSystemBluetoothAdapterEnabled) ->IsDefaultValue()); // Start with bluetooth power on. GetBluetoothAdapter()->SetPowered(true, base::DoNothing(), base::DoNothing()); @@ -218,19 +213,18 @@ // Pref should now contain the current bluetooth adapter state (on). EXPECT_FALSE( - local_state_prefs_.FindPreference(prefs::kSystemBluetoothAdapterEnabled) + local_state_.FindPreference(prefs::kSystemBluetoothAdapterEnabled) ->IsDefaultValue()); - EXPECT_TRUE( - local_state_prefs_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); + EXPECT_TRUE(local_state_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); } // Tests how BluetoothPowerController applies the local state pref when // the pref has been set before. TEST_F(BluetoothPowerControllerTest, ApplyBluetoothLocalStatePrefOn) { // Set the pref to true. - local_state_prefs_.SetBoolean(prefs::kSystemBluetoothAdapterEnabled, true); + local_state_.SetBoolean(prefs::kSystemBluetoothAdapterEnabled, true); EXPECT_FALSE( - local_state_prefs_.FindPreference(prefs::kSystemBluetoothAdapterEnabled) + local_state_.FindPreference(prefs::kSystemBluetoothAdapterEnabled) ->IsDefaultValue()); // Start with bluetooth power off. GetBluetoothAdapter()->SetPowered(false, base::DoNothing(), @@ -240,8 +234,7 @@ ApplyBluetoothLocalStatePref(); // Bluetooth power setting should be applied (on), and pref value unchanged. - EXPECT_TRUE( - local_state_prefs_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); + EXPECT_TRUE(local_state_.GetBoolean(prefs::kSystemBluetoothAdapterEnabled)); EXPECT_TRUE(GetBluetoothAdapter()->IsPowered()); }
diff --git a/ash/system/message_center/ash_popup_alignment_delegate_unittest.cc b/ash/system/message_center/ash_popup_alignment_delegate_unittest.cc index b4092f22..c149179 100644 --- a/ash/system/message_center/ash_popup_alignment_delegate_unittest.cc +++ b/ash/system/message_center/ash_popup_alignment_delegate_unittest.cc
@@ -10,7 +10,7 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h"
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc index 287cbc1..4331e31 100644 --- a/ash/system/palette/palette_tray.cc +++ b/ash/system/palette/palette_tray.cc
@@ -72,10 +72,19 @@ // Returns true if the |palette_tray| is on an internal display or on every // display if requested from the command line. bool ShouldShowOnDisplay(PaletteTray* palette_tray) { + if (stylus_utils::IsPaletteEnabledOnEveryDisplay()) + return true; + + // |widget| is null when this function is called from PaletteTray constructor + // before it is added to a widget. + views::Widget* const widget = palette_tray->GetWidget(); + if (!widget) + return false; + const display::Display& display = display::Screen::GetScreen()->GetDisplayNearestWindow( - palette_tray->GetWidget()->GetNativeWindow()); - return display.IsInternal() || stylus_utils::IsPaletteEnabledOnEveryDisplay(); + widget->GetNativeWindow()); + return display.IsInternal(); } class TitleView : public views::View, public views::ButtonListener { @@ -182,6 +191,8 @@ tray_container()->AddChildView(icon_); Shell::Get()->AddShellObserver(this); + + InitializeWithLocalState(); } PaletteTray::~PaletteTray() { @@ -222,8 +233,8 @@ } void PaletteTray::OnStylusEvent(const ui::TouchEvent& event) { - if (!HasSeenStylus() && local_state_pref_service_) - local_state_pref_service_->SetBoolean(prefs::kHasSeenStylus, true); + if (!HasSeenStylus() && local_state_) + local_state_->SetBoolean(prefs::kHasSeenStylus, true); // Attempt to show the welcome bubble. if (!welcome_bubble_->HasBeenShown() && active_user_pref_service_) { @@ -277,27 +288,6 @@ } } -void PaletteTray::OnLocalStatePrefServiceInitialized( - PrefService* pref_service) { - local_state_pref_service_ = pref_service; - - // If a device has an internal stylus or the flag to force stylus is set, mark - // the has seen stylus flag as true since we know the user has a stylus. - if (stylus_utils::HasInternalStylus() || - stylus_utils::HasForcedStylusInput()) { - local_state_pref_service_->SetBoolean(prefs::kHasSeenStylus, true); - } - - pref_change_registrar_local_ = std::make_unique<PrefChangeRegistrar>(); - pref_change_registrar_local_->Init(local_state_pref_service_); - pref_change_registrar_local_->Add( - prefs::kHasSeenStylus, - base::BindRepeating(&PaletteTray::OnHasSeenStylusPrefChanged, - base::Unretained(this))); - - OnHasSeenStylusPrefChanged(); -} - void PaletteTray::ClickedOutsideBubble() { if (num_actions_in_bubble_ == 0) { RecordPaletteOptionsUsage(PaletteTrayOptions::PALETTE_CLOSED_NO_ACTION, @@ -528,6 +518,30 @@ return bubble_ ? bubble_->bubble_view() : nullptr; } +void PaletteTray::InitializeWithLocalState() { + DCHECK(!local_state_); + local_state_ = Shell::Get()->local_state(); + // |local_state_| could be null in tests. + if (!local_state_) + return; + + // If a device has an internal stylus or the flag to force stylus is set, mark + // the has seen stylus flag as true since we know the user has a stylus. + if (stylus_utils::HasInternalStylus() || + stylus_utils::HasForcedStylusInput()) { + local_state_->SetBoolean(prefs::kHasSeenStylus, true); + } + + pref_change_registrar_local_ = std::make_unique<PrefChangeRegistrar>(); + pref_change_registrar_local_->Init(local_state_); + pref_change_registrar_local_->Add( + prefs::kHasSeenStylus, + base::BindRepeating(&PaletteTray::OnHasSeenStylusPrefChanged, + base::Unretained(this))); + + OnHasSeenStylusPrefChanged(); +} + void PaletteTray::UpdateTrayIcon() { icon_->SetImage(CreateVectorIcon( palette_tool_manager_->GetActiveTrayIcon( @@ -548,7 +562,7 @@ } void PaletteTray::OnHasSeenStylusPrefChanged() { - DCHECK(local_state_pref_service_); + DCHECK(local_state_); UpdateIconVisibility(); } @@ -569,8 +583,7 @@ } bool PaletteTray::HasSeenStylus() { - return local_state_pref_service_ && - local_state_pref_service_->GetBoolean(prefs::kHasSeenStylus); + return local_state_ && local_state_->GetBoolean(prefs::kHasSeenStylus); } void PaletteTray::UpdateIconVisibility() {
diff --git a/ash/system/palette/palette_tray.h b/ash/system/palette/palette_tray.h index f067c64..f2e1588 100644 --- a/ash/system/palette/palette_tray.h +++ b/ash/system/palette/palette_tray.h
@@ -69,7 +69,6 @@ // ShellObserver: void OnLockStateChanged(bool locked) override; - void OnLocalStatePrefServiceInitialized(PrefService* pref_service) override; // TrayBackgroundView: void ClickedOutsideBubble() override; @@ -106,6 +105,9 @@ void OnActiveToolChanged() override; aura::Window* GetWindow() override; + // Initializes with Shell's local state and starts to observe it. + void InitializeWithLocalState(); + // Updates the tray icon from the palette tool manager. void UpdateTrayIcon(); @@ -132,7 +134,7 @@ // A Shell pre-target handler that notifies PaletteTray of stylus events. std::unique_ptr<ui::EventHandler> stylus_event_handler_; - PrefService* local_state_pref_service_ = nullptr; // Not owned. + PrefService* local_state_ = nullptr; // Not owned. PrefService* active_user_pref_service_ = nullptr; // Not owned. std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_local_; std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_user_;
diff --git a/ash/system/power/power_prefs.cc b/ash/system/power/power_prefs.cc index ad3b5a4..e62f14c 100644 --- a/ash/system/power/power_prefs.cc +++ b/ash/system/power/power_prefs.cc
@@ -136,22 +136,25 @@ } // namespace PowerPrefs::PowerPrefs(chromeos::PowerPolicyController* power_policy_controller, - chromeos::PowerManagerClient* power_manager_client) + chromeos::PowerManagerClient* power_manager_client, + PrefService* local_state) : power_policy_controller_(power_policy_controller), power_manager_client_observer_(this), - tick_clock_(base::DefaultTickClock::GetInstance()) { + tick_clock_(base::DefaultTickClock::GetInstance()), + local_state_(local_state) { DCHECK(power_manager_client); DCHECK(power_policy_controller_); DCHECK(tick_clock_); - Shell::Get()->AddShellObserver(this); - power_manager_client_observer_.Add(power_manager_client); Shell::Get()->session_controller()->AddObserver(this); + + // |local_state_| could be null in tests. + if (local_state_) + ObserveLocalStatePrefs(local_state_); } PowerPrefs::~PowerPrefs() { - Shell::Get()->RemoveShellObserver(this); Shell::Get()->session_controller()->RemoveObserver(this); } @@ -243,16 +246,6 @@ ObservePrefs(prefs); } -void PowerPrefs::OnLocalStatePrefServiceInitialized(PrefService* prefs) { - local_state_ = prefs; - - // Pass |nullptr| in tests, because lifetime of local state prefs is shorter - // than lifetime of PowerPrefs. - if (local_state_) { - ObserveLocalStatePrefs(prefs); - } -} - void PowerPrefs::UpdatePowerPolicyFromPrefs() { PrefService* prefs = GetPrefService(); if (!prefs || !local_state_)
diff --git a/ash/system/power/power_prefs.h b/ash/system/power/power_prefs.h index 8e52e29..7671a402 100644 --- a/ash/system/power/power_prefs.h +++ b/ash/system/power/power_prefs.h
@@ -9,7 +9,6 @@ #include "ash/ash_export.h" #include "ash/session/session_observer.h" -#include "ash/shell_observer.h" #include "base/macros.h" #include "base/scoped_observer.h" #include "base/time/tick_clock.h" @@ -29,14 +28,16 @@ namespace ash { +class PowerPrefsTest; + // Sends an updated power policy to the |power_policy_controller| whenever one // of the power-related prefs changes. class ASH_EXPORT PowerPrefs : public chromeos::PowerManagerClient::Observer, - public SessionObserver, - public ShellObserver { + public SessionObserver { public: PowerPrefs(chromeos::PowerPolicyController* power_policy_controller, - chromeos::PowerManagerClient* power_manager_client); + chromeos::PowerManagerClient* power_manager_client, + PrefService* local_state); ~PowerPrefs() override; // Registers power prefs with default values applicable to the local state @@ -54,6 +55,8 @@ void set_tick_clock_for_test(base::TickClock* clock) { tick_clock_ = clock; } private: + friend class PowerPrefsTest; + // chromeos::PowerManagerClient::Observer: void ScreenIdleStateChanged( const power_manager::ScreenIdleState& proto) override; @@ -63,9 +66,6 @@ void OnSigninScreenPrefServiceInitialized(PrefService* prefs) override; void OnActiveUserPrefServiceChanged(PrefService* prefs) override; - // ShellObserver: - void OnLocalStatePrefServiceInitialized(PrefService* pref_service) override; - void UpdatePowerPolicyFromPrefs(); // Observes either the signin screen prefs or active user prefs and loads
diff --git a/ash/system/power/power_prefs_unittest.cc b/ash/system/power/power_prefs_unittest.cc index 7f4a8cb3..87c7adbc 100644 --- a/ash/system/power/power_prefs_unittest.cc +++ b/ash/system/power/power_prefs_unittest.cc
@@ -200,8 +200,7 @@ } void TearDown() override { - static_cast<ShellObserver*>(power_prefs_) - ->OnLocalStatePrefServiceInitialized(nullptr); + power_prefs_->local_state_ = nullptr; NoSessionAshTestBase::TearDown(); } @@ -220,8 +219,8 @@ PowerPrefs::RegisterLocalStatePrefs(pref_registry_.get()); - static_cast<ShellObserver*>(power_prefs_) - ->OnLocalStatePrefServiceInitialized(local_state_.get()); + power_prefs_->local_state_ = local_state_.get(); + power_prefs_->ObserveLocalStatePrefs(power_prefs_->local_state_); } std::string GetCurrentPowerPolicy() const {
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc index 10d2cd5..a20d8b3 100644 --- a/ash/system/status_area_widget_unittest.cc +++ b/ash/system/status_area_widget_unittest.cc
@@ -7,9 +7,9 @@ #include "ash/focus_cycler.h" #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/public/cpp/ash_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/system_tray_focus_observer.h" #include "ash/session/session_controller_impl.h" #include "ash/session/test_session_controller_client.h"
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h index 9b9230e..523ef01 100644 --- a/ash/system/tray/tray_constants.h +++ b/ash/system/tray/tray_constants.h
@@ -230,16 +230,14 @@ constexpr int kUnifiedFeaturePodHoverRadius = 4; constexpr int kUnifiedFeaturePodVerticalPadding = 28; constexpr int kUnifiedFeaturePodTopPadding = 24; -constexpr int kUnifiedFeaturePodBottomPadding = 5; +constexpr int kUnifiedFeaturePodBottomPadding = 20; constexpr int kUnifiedFeaturePodHorizontalSidePadding = 12; constexpr int kUnifiedFeaturePodHorizontalMiddlePadding = 0; -constexpr int kUnifiedFeaturePodCollapsedVerticalPadding = 12; +constexpr int kUnifiedFeaturePodCollapsedVerticalPadding = 16; constexpr int kUnifiedFeaturePodCollapsedHorizontalPadding = 24; constexpr int kUnifiedFeaturePodArrowSpacing = 4; constexpr int kUnifiedFeaturePodItemsInRow = 3; -constexpr int kUnifiedFeaturePodItemsRows = 3; constexpr int kUnifiedFeaturePodMaxItemsInCollapsed = 5; -constexpr int kUnifiedFeaturePodsPageSpacing = 48; constexpr int kUnifiedNotificationSeparatorThickness = 1; // Constants used in PageIndicatorView of UnifiedSystemTray.
diff --git a/ash/system/unified/feature_pods_container_view.cc b/ash/system/unified/feature_pods_container_view.cc index b6004d33..21127a8 100644 --- a/ash/system/unified/feature_pods_container_view.cc +++ b/ash/system/unified/feature_pods_container_view.cc
@@ -4,26 +4,15 @@ #include "ash/system/unified/feature_pods_container_view.h" -#include "ash/public/cpp/ash_features.h" -#include "ash/public/cpp/pagination/pagination_controller.h" -#include "ash/public/cpp/pagination/pagination_model.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/unified/feature_pod_button.h" namespace ash { -FeaturePodsContainerView::FeaturePodsContainerView( - PaginationModel* pagination_model, - bool initially_expanded) - : pagination_model_(pagination_model), - expanded_amount_(initially_expanded ? 1.0 : 0.0) { - pagination_model_->AddObserver(this); -} +FeaturePodsContainerView::FeaturePodsContainerView(bool initially_expanded) + : expanded_amount_(initially_expanded ? 1.0 : 0.0) {} -FeaturePodsContainerView::~FeaturePodsContainerView() { - DCHECK(pagination_model_); - pagination_model_->RemoveObserver(this); -} +FeaturePodsContainerView::~FeaturePodsContainerView() = default; void FeaturePodsContainerView::SetExpandedAmount(double expanded_amount) { DCHECK(0.0 <= expanded_amount && expanded_amount <= 1.0); @@ -44,10 +33,6 @@ // floor(visible_count / kUnifiedFeaturePodItemsInRow) int number_of_lines = (visible_count + kUnifiedFeaturePodItemsInRow - 1) / kUnifiedFeaturePodItemsInRow; - - if (features::IsSystemTrayFeaturePodsPaginationEnabled()) - number_of_lines = std::min(number_of_lines, kUnifiedFeaturePodItemsRows); - return kUnifiedFeaturePodBottomPadding + (kUnifiedFeaturePodVerticalPadding + kUnifiedFeaturePodSize.height()) * number_of_lines; @@ -98,10 +83,27 @@ void FeaturePodsContainerView::Layout() { UpdateCollapsedSidePadding(); - CalculateIdealBoundsForFeaturePods(); - for (int i = 0; i < visible_buttons_.view_size(); ++i) { - auto* button = visible_buttons_.view_at(i); - button->SetBoundsRect(visible_buttons_.ideal_bounds(i)); + + int visible_count = 0; + for (auto* child : children()) { + if (!child->visible()) + continue; + + gfx::Size child_size; + if (expanded_amount_ > 0.0) { + child_size = kUnifiedFeaturePodSize; + + // Flexibly give more height if the child view doesn't fit into the + // default height, so that label texts won't be broken up in the middle. + child_size.set_height(std::max( + child_size.height(), child->GetHeightForWidth(child_size.height()))); + } else { + child_size = kUnifiedFeaturePodCollapsedSize; + } + + child->SetBoundsRect( + gfx::Rect(GetButtonPosition(visible_count++), child_size)); + child->Layout(); } } @@ -112,26 +114,15 @@ int visible_count = 0; for (auto* view : children()) { auto* child = static_cast<FeaturePodButton*>(view); - bool visible = IsButtonVisible(child, visible_count); + bool visible = child->visible_preferred() && + (expanded_amount_ > 0.0 || + visible_count < kUnifiedFeaturePodMaxItemsInCollapsed); child->SetVisibleByContainer(visible); - if (visible) { - if (visible_buttons_.GetIndexOfView(child) < 0) - visible_buttons_.Add(child, visible_count); + if (visible) ++visible_count; - } else { - if (visible_buttons_.GetIndexOfView(child)) - visible_buttons_.Remove(visible_buttons_.GetIndexOfView(child)); - } } - UpdateTotalPages(); - changing_visibility_ = false; -} -bool FeaturePodsContainerView::IsButtonVisible(FeaturePodButton* button, - int index) { - return button->visible_preferred() && - (expanded_amount_ > 0.0 || - index < kUnifiedFeaturePodMaxItemsInCollapsed); + changing_visibility_ = false; } int FeaturePodsContainerView::GetVisibleCount() const { @@ -191,106 +182,4 @@ DCHECK(collapsed_side_padding_ > 0); } -void FeaturePodsContainerView::AddFeaturePodButton(FeaturePodButton* button) { - int view_size = visible_buttons_.view_size(); - if (IsButtonVisible(button, view_size)) { - visible_buttons_.Add(button, view_size); - } - AddChildView(button); - - UpdateTotalPages(); -} - -const gfx::Vector2d FeaturePodsContainerView::CalculateTransitionOffset( - int page_of_view) const { - gfx::Size grid_size = CalculatePreferredSize(); - - // If there is a transition, calculates offset for current and target page. - const int current_page = pagination_model_->selected_page(); - const PaginationModel::Transition& transition = - pagination_model_->transition(); - const bool is_valid = - pagination_model_->is_valid_page(transition.target_page); - - // Transition to previous page means negative offset. - const int direction = transition.target_page > current_page ? -1 : 1; - - int x_offset = 0; - int y_offset = 0; - - // Page size including padding pixels. A tile.x + page_width means the same - // tile slot in the next page. - const int page_width = grid_size.width() + kUnifiedFeaturePodsPageSpacing; - if (page_of_view < current_page) - x_offset = -page_width; - else if (page_of_view > current_page) - x_offset = page_width; - - if (is_valid) { - if (page_of_view == current_page || - page_of_view == transition.target_page) { - x_offset += transition.progress * page_width * direction; - } - } - - return gfx::Vector2d(x_offset, y_offset); -} - -void FeaturePodsContainerView::CalculateIdealBoundsForFeaturePods() { - for (int i = 0; i < visible_buttons_.view_size(); ++i) { - gfx::Rect tile_bounds; - gfx::Size child_size; - if (expanded_amount_ > 0.0) { - child_size = kUnifiedFeaturePodSize; - - // Flexibly give more height if the child view doesn't fit into the - // default height, so that label texts won't be broken up in the middle. - child_size.set_height(std::max( - child_size.height(), - visible_buttons_.view_at(i)->GetHeightForWidth(child_size.height()))); - - tile_bounds = - gfx::Rect(GetButtonPosition(i % GetTilesPerPage()), child_size); - // TODO(amehfooz): refactor this logic so that the ideal_bounds are set - // once when the transition starts and the actual feature pod bounds are - // interpolated using the ideal_bounds as the transition progresses. - tile_bounds.Offset(CalculateTransitionOffset(i / GetTilesPerPage())); - } else { - child_size = kUnifiedFeaturePodCollapsedSize; - tile_bounds = gfx::Rect(GetButtonPosition(i), child_size); - } - - visible_buttons_.set_ideal_bounds(i, tile_bounds); - } -} - -int FeaturePodsContainerView::GetTilesPerPage() const { - if (features::IsSystemTrayFeaturePodsPaginationEnabled()) - return kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodItemsRows; - else - return children().size(); -} - -void FeaturePodsContainerView::UpdateTotalPages() { - int total_pages = 0; - - int total_visible = visible_buttons_.view_size(); - int tiles_per_page = GetTilesPerPage(); - - if (!visible_buttons_.view_size() || !tiles_per_page) { - total_pages = 0; - } else { - total_pages = (total_visible / tiles_per_page) + - (total_visible % tiles_per_page ? 1 : 0); - } - pagination_model_->SetTotalPages(total_pages); -} - -void FeaturePodsContainerView::TransitionChanged() { - const PaginationModel::Transition& transition = - pagination_model_->transition(); - if (pagination_model_->is_valid_page(transition.target_page)) - Layout(); -} - } // namespace ash
diff --git a/ash/system/unified/feature_pods_container_view.h b/ash/system/unified/feature_pods_container_view.h index a8ade81..c93737e6 100644 --- a/ash/system/unified/feature_pods_container_view.h +++ b/ash/system/unified/feature_pods_container_view.h
@@ -6,31 +6,20 @@ #define ASH_SYSTEM_UNIFIED_FEATURE_PODS_CONTAINER_VIEW_H_ #include "ash/ash_export.h" -#include "ash/public/cpp/pagination/pagination_model_observer.h" #include "ui/views/view.h" -#include "ui/views/view_model.h" namespace ash { -class FeaturePodButton; -class PaginationModel; - // Container of feature pods buttons in the middle of UnifiedSystemTrayView. // The container has number of buttons placed in 3x3 plane at regular distances. // FeaturePodButtons implements these individual buttons. // The container also implements collapsed state where the top 5 buttons are // horizontally placed and others are hidden. -class ASH_EXPORT FeaturePodsContainerView : public views::View, - public PaginationModelObserver { +class ASH_EXPORT FeaturePodsContainerView : public views::View { public: - FeaturePodsContainerView(PaginationModel* pagination_model, - bool initially_expanded); + explicit FeaturePodsContainerView(bool initially_expanded); ~FeaturePodsContainerView() override; - // Add a FeaturePodButton as a child view and if it's visible add it to the - // view structure and update the pagination model. - void AddFeaturePodButton(FeaturePodButton* button); - // Change the expanded state. 0.0 if collapsed, and 1.0 if expanded. // Otherwise, it shows intermediate state. If collapsed, all the buttons are // horizontally placed. @@ -58,39 +47,15 @@ void Layout() override; private: - friend class FeaturePodsContainerViewTest; + void UpdateChildVisibility(); // Calculate the current position of the button from |visible_index| and // |expanded_amount_|. gfx::Point GetButtonPosition(int visible_index) const; - void UpdateChildVisibility(); - // Update |collapsed_state_padding_|. void UpdateCollapsedSidePadding(); - // Calculates the ideal bounds for all feature pods. - void CalculateIdealBoundsForFeaturePods(); - - // Calculates the offset for |page_of_view| based on current page and - // transition target page. - const gfx::Vector2d CalculateTransitionOffset(int page_of_view) const; - - // Returns true if button at provided index is visible. - bool IsButtonVisible(FeaturePodButton* button, int index); - - // Returns the number of tiles per page. - int GetTilesPerPage() const; - - // Updates page splits for feature pod buttons. - void UpdateTotalPages(); - - // PaginationModelObserver: - void TransitionChanged() override; - - // Owned by UnifiedSystemTrayModel. - PaginationModel* pagination_model_; - // The last |expanded_amount| passed to SetExpandedAmount(). double expanded_amount_; @@ -104,10 +69,6 @@ // A button that had focus at the point SaveButtonFocus is called. views::View* focused_button_ = nullptr; - // A view model that contains all visible feature pod buttons. - // Used to calculate required number of pages. - views::ViewModelT<FeaturePodButton> visible_buttons_; - DISALLOW_COPY_AND_ASSIGN(FeaturePodsContainerView); };
diff --git a/ash/system/unified/feature_pods_container_view_unittest.cc b/ash/system/unified/feature_pods_container_view_unittest.cc index 747add5..8a3ec63 100644 --- a/ash/system/unified/feature_pods_container_view_unittest.cc +++ b/ash/system/unified/feature_pods_container_view_unittest.cc
@@ -4,13 +4,10 @@ #include "ash/system/unified/feature_pods_container_view.h" -#include "ash/public/cpp/ash_features.h" -#include "ash/public/cpp/pagination/pagination_model.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/unified/feature_pod_button.h" #include "ash/system/unified/feature_pod_controller_base.h" #include "ash/test/ash_test_base.h" -#include "base/test/scoped_feature_list.h" #include "ui/views/view_observer.h" namespace ash { @@ -25,13 +22,10 @@ // AshTestBase: void SetUp() override { AshTestBase::SetUp(); - pagination_model_ = std::make_unique<PaginationModel>(); container_ = std::make_unique<FeaturePodsContainerView>( - pagination_model_.get(), true /* initially_expanded */); + true /* initially_expanded */); container_->AddObserver(this); preferred_size_changed_count_ = 0; - - scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>(); } // FeaturePodControllerBase: @@ -47,11 +41,6 @@ } protected: - void EnablePagination() { - scoped_feature_list_->InitAndEnableFeature( - features::kSystemTrayFeaturePodsPagination); - } - void AddButtons(int count) { for (int i = 0; i < count; ++i) { buttons_.push_back(new FeaturePodButton(this)); @@ -63,8 +52,6 @@ FeaturePodsContainerView* container() { return container_.get(); } - PaginationModel* pagination_model() { return pagination_model_.get(); } - int preferred_size_changed_count() const { return preferred_size_changed_count_; } @@ -72,9 +59,7 @@ std::vector<FeaturePodButton*> buttons_; private: - std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; std::unique_ptr<FeaturePodsContainerView> container_; - std::unique_ptr<PaginationModel> pagination_model_; int preferred_size_changed_count_ = 0; DISALLOW_COPY_AND_ASSIGN(FeaturePodsContainerViewTest); @@ -179,59 +164,4 @@ EXPECT_EQ(2, preferred_size_changed_count()); } -TEST_F(FeaturePodsContainerViewTest, NumberOfPagesChanged) { - const int kNumberOfPages = 8; - - EnablePagination(); - AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodItemsRows * - kNumberOfPages); - - // Adding buttons to fill kNumberOfPages should cause the the same number of - // pages to be created. - EXPECT_EQ(kNumberOfPages, pagination_model()->total_pages()); - - // Adding an additional button causes a new page to be added. - AddButtons(1); - EXPECT_EQ(pagination_model()->total_pages(), kNumberOfPages + 1); -} - -TEST_F(FeaturePodsContainerViewTest, PaginationTransition) { - const int kNumberOfPages = 8; - - EnablePagination(); - AddButtons(kUnifiedFeaturePodItemsInRow * kUnifiedFeaturePodItemsRows * - kNumberOfPages); - - // Position of a button should slide to the left during a page - // transition to the next page. - gfx::Rect current_bounds; - gfx::Rect initial_bounds = buttons_[0]->bounds(); - gfx::Rect previous_bounds = initial_bounds; - - PaginationModel::Transition transition( - pagination_model()->selected_page() + 1, 0); - - for (double i = 0.1; i <= 1.0; i += 0.1) { - transition.progress = i; - pagination_model()->SetTransition(transition); - - current_bounds = buttons_[0]->bounds(); - - EXPECT_LT(current_bounds.x(), previous_bounds.x()); - EXPECT_EQ(current_bounds.y(), previous_bounds.y()); - - previous_bounds = current_bounds; - } - - // Button Position after page switch should move to the left by a page offset. - int page_offset = container()->CalculatePreferredSize().width() + - kUnifiedFeaturePodsPageSpacing; - gfx::Rect final_bounds = - gfx::Rect(initial_bounds.x() - page_offset, initial_bounds.y(), - initial_bounds.width(), initial_bounds.height()); - pagination_model()->SelectPage(1, false); - container()->Layout(); - EXPECT_EQ(final_bounds, buttons_[0]->bounds()); -} - } // namespace ash
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc index e376ec2..a5ed7ea 100644 --- a/ash/system/unified/unified_system_tray_view.cc +++ b/ash/system/unified/unified_system_tray_view.cc
@@ -16,7 +16,6 @@ #include "ash/system/unified/feature_pod_button.h" #include "ash/system/unified/feature_pods_container_view.h" #include "ash/system/unified/notification_hidden_view.h" -#include "ash/system/unified/page_indicator_view.h" #include "ash/system/unified/top_shortcuts_view.h" #include "ash/system/unified/unified_system_info_view.h" #include "ash/system/unified/unified_system_tray_controller.h" @@ -221,11 +220,7 @@ controller_(controller), notification_hidden_view_(new NotificationHiddenView()), top_shortcuts_view_(new TopShortcutsView(controller_)), - feature_pods_container_( - new FeaturePodsContainerView(controller_->model()->pagination_model(), - initially_expanded)), - page_indicator_view_( - new PageIndicatorView(controller_, initially_expanded)), + feature_pods_container_(new FeaturePodsContainerView(initially_expanded)), sliders_container_(new UnifiedSlidersContainerView(initially_expanded)), system_info_view_(new UnifiedSystemInfoView(controller_)), system_tray_container_(new SystemTrayContainer()), @@ -260,7 +255,6 @@ system_tray_container_->AddChildView(top_shortcuts_view_); system_tray_container_->AddChildView(feature_pods_container_); - system_tray_container_->AddChildView(page_indicator_view_); system_tray_container_->AddChildView(sliders_container_); system_tray_container_->AddChildView(system_info_view_); @@ -294,7 +288,7 @@ } void UnifiedSystemTrayView::AddFeaturePodButton(FeaturePodButton* button) { - feature_pods_container_->AddFeaturePodButton(button); + feature_pods_container_->AddChildView(button); } void UnifiedSystemTrayView::AddSliderView(views::View* slider_view) { @@ -341,7 +335,6 @@ top_shortcuts_view_->SetExpandedAmount(expanded_amount); feature_pods_container_->SetExpandedAmount(expanded_amount); - page_indicator_view_->SetExpandedAmount(expanded_amount); sliders_container_->SetExpandedAmount(expanded_amount); if (!IsTransformEnabled()) { @@ -365,7 +358,6 @@ : 0) + top_shortcuts_view_->GetPreferredSize().height() + feature_pods_container_->GetExpandedHeight() + - page_indicator_view_->GetPreferredSize().height() + sliders_container_->GetExpandedHeight() + system_info_view_->GetPreferredSize().height(); }
diff --git a/ash/system/unified/unified_system_tray_view.h b/ash/system/unified/unified_system_tray_view.h index 423a5ff..fb1e556 100644 --- a/ash/system/unified/unified_system_tray_view.h +++ b/ash/system/unified/unified_system_tray_view.h
@@ -15,7 +15,6 @@ class FeaturePodsContainerView; class TopShortcutsView; class NotificationHiddenView; -class PageIndicatorView; class UnifiedMessageCenterView; class UnifiedSystemInfoView; class UnifiedSystemTrayController; @@ -148,7 +147,6 @@ NotificationHiddenView* const notification_hidden_view_; TopShortcutsView* const top_shortcuts_view_; FeaturePodsContainerView* const feature_pods_container_; - PageIndicatorView* const page_indicator_view_; UnifiedSlidersContainerView* const sliders_container_; UnifiedSystemInfoView* const system_info_view_; views::View* const system_tray_container_;
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc index 458361b..d7aa47f8 100644 --- a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc +++ b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
@@ -6,8 +6,8 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" #include "ash/test/ash_test_base.h"
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index 7a69f01d..587ea0d 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -43,6 +43,7 @@ #include "base/values.h" #include "chromeos/constants/chromeos_switches.h" #include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "services/data_decoder/public/cpp/decode_image.h" #include "ui/display/manager/display_manager.h" @@ -441,7 +442,7 @@ const char WallpaperController::kLargeWallpaperSubDir[] = "large"; const char WallpaperController::kOriginalWallpaperSubDir[] = "original"; -WallpaperController::WallpaperController() +WallpaperController::WallpaperController(PrefService* local_state) : locked_(false), wallpaper_mode_(WALLPAPER_NONE), color_profiles_(GetProminentColorProfiles()), @@ -450,6 +451,7 @@ {base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})), scoped_session_observer_(this), + local_state_(local_state), weak_factory_(this) { DCHECK(!color_profiles_.empty()); prominent_colors_ = @@ -1366,12 +1368,6 @@ InstallDesktopController(root_window); } -void WallpaperController::OnLocalStatePrefServiceInitialized( - PrefService* pref_service) { - DCHECK(!wallpaper_controller_client_); - local_state_ = pref_service; -} - void WallpaperController::OnShellInitialized() { Shell::Get()->tablet_mode_controller()->AddObserver(this); }
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h index 9b49616..1f31c1b 100644 --- a/ash/wallpaper/wallpaper_controller.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -82,7 +82,7 @@ static const char kLargeWallpaperSubDir[]; static const char kOriginalWallpaperSubDir[]; - WallpaperController(); + explicit WallpaperController(PrefService* local_state); ~WallpaperController() override; static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); @@ -295,7 +295,6 @@ // ShellObserver: void OnRootWindowAdded(aura::Window* root_window) override; - void OnLocalStatePrefServiceInitialized(PrefService* pref_service) override; void OnShellInitialized() override; void OnShellDestroying() override; @@ -661,9 +660,9 @@ // default wallpaper decoding is initiated.) std::vector<base::FilePath> decode_requests_for_testing_; - // PrefService provided by Shell::OnLocalStatePrefServiceInitialized. + // PrefService provided by Shell when constructing this. // Valid for the lifetime of ash::Shell which owns WallpaperController. - // May be null during intialization or in tests. + // May be null in tests. PrefService* local_state_ = nullptr; base::WeakPtrFactory<WallpaperController> weak_factory_;
diff --git a/ash/wm/always_on_top_controller_unittest.cc b/ash/wm/always_on_top_controller_unittest.cc index 6f954c8..8714958 100644 --- a/ash/wm/always_on_top_controller_unittest.cc +++ b/ash/wm/always_on_top_controller_unittest.cc
@@ -7,8 +7,8 @@ #include "ash/keyboard/ash_keyboard_controller.h" #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "ash/shell.h"
diff --git a/ash/wm/collision_detection/collision_detection_utils_unittest.cc b/ash/wm/collision_detection/collision_detection_utils_unittest.cc index f95a3fa..0f20f552 100644 --- a/ash/wm/collision_detection/collision_detection_utils_unittest.cc +++ b/ash/wm/collision_detection/collision_detection_utils_unittest.cc
@@ -5,8 +5,8 @@ #include "ash/wm/collision_detection/collision_detection_utils.h" #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/root_window_controller.h" #include "ash/scoped_root_window_for_new_windows.h" #include "ash/shelf/shelf.h"
diff --git a/ash/wm/lock_action_handler_layout_manager_unittest.cc b/ash/wm/lock_action_handler_layout_manager_unittest.cc index fc7f475..0d50f1e2 100644 --- a/ash/wm/lock_action_handler_layout_manager_unittest.cc +++ b/ash/wm/lock_action_handler_layout_manager_unittest.cc
@@ -11,11 +11,11 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/lock_screen_action/lock_screen_action_background_controller.h" #include "ash/lock_screen_action/lock_screen_action_background_controller_stub.h" #include "ash/lock_screen_action/test_lock_screen_action_background_controller.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/interfaces/tray_action.mojom.h" #include "ash/root_window_controller.h"
diff --git a/ash/wm/lock_layout_manager_unittest.cc b/ash/wm/lock_layout_manager_unittest.cc index 4b8d773..fbbf0e5 100644 --- a/ash/wm/lock_layout_manager_unittest.cc +++ b/ash/wm/lock_layout_manager_unittest.cc
@@ -5,8 +5,8 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "ash/screen_util.h"
diff --git a/ash/wm/overview/overview_controller_unittest.cc b/ash/wm/overview/overview_controller_unittest.cc index 54ea941..f636c68 100644 --- a/ash/wm/overview/overview_controller_unittest.cc +++ b/ash/wm/overview/overview_controller_unittest.cc
@@ -7,8 +7,8 @@ #include "ash/app_list/test/app_list_test_helper.h" #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wallpaper/wallpaper_widget_controller.h"
diff --git a/ash/wm/pip/pip_positioner_unittest.cc b/ash/wm/pip/pip_positioner_unittest.cc index d63328c..7df1911 100644 --- a/ash/wm/pip/pip_positioner_unittest.cc +++ b/ash/wm/pip/pip_positioner_unittest.cc
@@ -10,8 +10,8 @@ #include <vector> #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/root_window_controller.h" #include "ash/scoped_root_window_for_new_windows.h" #include "ash/shelf/shelf.h"
diff --git a/ash/wm/pip/pip_unittest.cc b/ash/wm/pip/pip_unittest.cc index de19aa4..82df7d88 100644 --- a/ash/wm/pip/pip_unittest.cc +++ b/ash/wm/pip/pip_unittest.cc
@@ -8,8 +8,8 @@ #include <utility> #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/root_window_controller.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_widget.h"
diff --git a/ash/wm/pip/pip_window_resizer_unittest.cc b/ash/wm/pip/pip_window_resizer_unittest.cc index 5172552..b9ec671 100644 --- a/ash/wm/pip/pip_window_resizer_unittest.cc +++ b/ash/wm/pip/pip_window_resizer_unittest.cc
@@ -9,9 +9,9 @@ #include <utility> #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/metrics/pip_uma.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/scoped_root_window_for_new_windows.h" #include "ash/shelf/shelf.h" #include "ash/shell.h"
diff --git a/ash/wm/system_modal_container_layout_manager_unittest.cc b/ash/wm/system_modal_container_layout_manager_unittest.cc index 71093e1..cf681b13 100644 --- a/ash/wm/system_modal_container_layout_manager_unittest.cc +++ b/ash/wm/system_modal_container_layout_manager_unittest.cc
@@ -9,8 +9,8 @@ #include "ash/keyboard/ash_keyboard_controller.h" #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "ash/shell.h"
diff --git a/ash/wm/window_animations_unittest.cc b/ash/wm/window_animations_unittest.cc index acdda97..a5d369a 100644 --- a/ash/wm/window_animations_unittest.cc +++ b/ash/wm/window_animations_unittest.cc
@@ -4,7 +4,7 @@ #include "ash/wm/window_animations.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_animation_types.h" #include "ash/shell.h"
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc index 5b08381..6406454 100644 --- a/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -14,10 +14,10 @@ #include "ash/keyboard/ui/keyboard_controller.h" #include "ash/keyboard/ui/keyboard_ui.h" #include "ash/keyboard/ui/keyboard_util.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_types.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/test/shell_test_api.h" #include "ash/public/cpp/window_properties.h"
diff --git a/base/android/java/src/org/chromium/base/FileUtils.java b/base/android/java/src/org/chromium/base/FileUtils.java index 5ceded4..20d3dcf 100644 --- a/base/android/java/src/org/chromium/base/FileUtils.java +++ b/base/android/java/src/org/chromium/base/FileUtils.java
@@ -9,9 +9,10 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.os.ParcelFileDescriptor; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -29,9 +30,13 @@ /** * Delete the given File and (if it's a directory) everything within it. + * @param currentFile The file or directory to delete. Does not need to exist. + * @return Whether currentFile does not exist afterwards. */ - public static void recursivelyDeleteFile(File currentFile) { - ThreadUtils.assertOnBackgroundThread(); + public static boolean recursivelyDeleteFile(File currentFile) { + if (!currentFile.exists()) { + return true; + } if (currentFile.isDirectory()) { File[] files = currentFile.listFiles(); if (files != null) { @@ -41,7 +46,11 @@ } } - if (!currentFile.delete()) Log.e(TAG, "Failed to delete: " + currentFile); + boolean ret = currentFile.delete(); + if (!ret) { + Log.e(TAG, "Failed to delete: %s", currentFile); + } + return ret; } /** @@ -50,8 +59,6 @@ * @param filePaths The file paths or content URIs to delete. */ public static void batchDeleteFiles(List<String> filePaths) { - ThreadUtils.assertOnBackgroundThread(); - for (String filePath : filePaths) { if (ContentUriUtils.isContentUri(filePath)) { ContentUriUtils.delete(filePath); @@ -66,58 +73,41 @@ * Extracts an asset from the app's APK to a file. * @param context * @param assetName Name of the asset to extract. - * @param dest File to extract the asset to. + * @param outFile File to extract the asset to. * @return true on success. */ - public static boolean extractAsset(Context context, String assetName, File dest) { - InputStream inputStream = null; - OutputStream outputStream = null; - try { - inputStream = context.getAssets().open(assetName); - outputStream = new BufferedOutputStream(new FileOutputStream(dest)); - byte[] buffer = new byte[8192]; - int c; - while ((c = inputStream.read(buffer)) != -1) { - outputStream.write(buffer, 0, c); - } - inputStream.close(); - outputStream.close(); + public static boolean extractAsset(Context context, String assetName, File outFile) { + try (InputStream inputStream = context.getAssets().open(assetName)) { + copyStreamToFile(inputStream, outFile); return true; } catch (IOException e) { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ex) { - } - } - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException ex) { - } - } + return false; } - return false; + } + + /** + * Performs a simple copy of inputStream to outputStream. + */ + public static void copyStream(InputStream inputStream, OutputStream outputStream) + throws IOException { + byte[] buffer = new byte[8192]; + int amountRead; + while ((amountRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, amountRead); + } } /** * Atomically copies the data from an input stream into an output file. * @param is Input file stream to read data from. * @param outFile Output file path. - * @param buffer Caller-provided buffer. Provided to avoid allocating the same - * buffer on each call when copying several files in sequence. * @throws IOException in case of I/O error. */ - public static void copyFileStreamAtomicWithBuffer(InputStream is, File outFile, byte[] buffer) - throws IOException { + public static void copyStreamToFile(InputStream is, File outFile) throws IOException { File tmpOutputFile = new File(outFile.getPath() + ".tmp"); try (OutputStream os = new FileOutputStream(tmpOutputFile)) { Log.i(TAG, "Writing to %s", outFile); - - int count = 0; - while ((count = is.read(buffer, 0, buffer.length)) != -1) { - os.write(buffer, 0, count); - } + copyStream(is, os); } if (!tmpOutputFile.renameTo(outFile)) { throw new IOException(); @@ -125,6 +115,16 @@ } /** + * Reads inputStream into a byte array. + */ + @NonNull + public static byte[] readStream(InputStream inputStream) throws IOException { + ByteArrayOutputStream data = new ByteArrayOutputStream(); + FileUtils.copyStream(inputStream, data); + return data.toByteArray(); + } + + /** * Returns a URI that points at the file. * @param file File to get a URI for. * @return URI that points at that file, either as a content:// URI or a file:// URI.
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index ae710cf..72d116b7 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -747,8 +747,7 @@ throw new RuntimeException("Cannot find ZipEntry" + pathWithinApk); InputStream inputStream = zipFile.getInputStream(zipEntry); - FileUtils.copyFileStreamAtomicWithBuffer( - inputStream, libraryFile, new byte[16 * 1024]); + FileUtils.copyStreamToFile(inputStream, libraryFile); libraryFile.setReadable(true, false); libraryFile.setExecutable(true, false); } catch (IOException e) {
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index a0ab2e8..73a4c48 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -57,7 +57,8 @@ } else { import("//build/config/android/sdk.gni") declare_args() { - # Android SDK release. Currently, only "o_mr1" is publicly supported. + # Android SDK release. Currently, only "o_mr1" and "p" are publicly + # supported. android_sdk_release = default_android_sdk_release } }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index f501a921..704a1db 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8913465501118992272 \ No newline at end of file +8913436241537136912 \ No newline at end of file
diff --git a/build/landmines.py b/build/landmines.py index d0f42980..c811bf9 100755 --- a/build/landmines.py +++ b/build/landmines.py
@@ -37,7 +37,7 @@ def get_build_dir(src_dir): - """ + r""" Returns output directory absolute path dependent on build and targets. Examples: r'c:\b\build\slave\win\build\src\out'
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py index 15e385e6..c226670 100755 --- a/build/vs_toolchain.py +++ b/build/vs_toolchain.py
@@ -5,6 +5,7 @@ from __future__ import print_function +import collections import glob import json import os @@ -22,9 +23,11 @@ script_dir = os.path.dirname(os.path.realpath(__file__)) json_data_file = os.path.join(script_dir, 'win_toolchain.json') - -# Use MSVS2017 as the default toolchain. -CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2017' +# VS versions are listed in descending order of priority (highest first). +MSVS_VERSIONS = collections.OrderedDict([ + ('2017', '15.0'), + ('2019', '16.0'), +]) def SetEnvironmentAndGetRuntimeDllDirs(): @@ -129,9 +132,47 @@ def GetVisualStudioVersion(): - """Return GYP_MSVS_VERSION of Visual Studio. + """Return best available version of Visual Studio. """ - return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION) + + env_version = os.environ.get('GYP_MSVS_VERSION') + supported_versions = MSVS_VERSIONS.keys() + + # VS installed in depot_tools for Googlers + if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))): + if env_version: + return env_version + else: + return supported_versions[0] + + # VS installed in system for external developers + supported_versions_str = ', '.join('{} ({})'.format(v,k) + for k,v in MSVS_VERSIONS.items()) + available_versions = [] + for version in supported_versions: + for path in ( + os.environ.get('vs%s_install' % version), + os.path.expandvars('%ProgramFiles(x86)%' + + '/Microsoft Visual Studio/%s' % version)): + if path and os.path.exists(path): + available_versions.append(version) + break + + if not available_versions: + raise Exception('No supported Visual Studio can be found.' + ' Supported versions are: %s.' % supported_versions_str) + + if env_version: + if env_version not in supported_versions: + raise Exception('Visual Studio version %s (from GYP_MSVS_VERSION)' + ' is not supported. Supported versions are: %s.' + % (env_version, supported_versions_str)) + if env_version not in available_versions: + raise Exception('Visual Studio version %s (from GYP_MSVS_VERSION)' + ' is not available.' % env_version) + return env_version + + return available_versions[0] def DetectVisualStudioPath(): @@ -141,14 +182,6 @@ # Note that this code is used from # build/toolchain/win/setup_toolchain.py as well. version_as_year = GetVisualStudioVersion() - year_to_version = { - '2017': '15.0', - '2019': '16.0', - } - if version_as_year not in year_to_version: - raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)' - ' not supported. Supported versions are: %s') % ( - version_as_year, ', '.join(year_to_version.keys()))) # The VC++ >=2017 install location needs to be located using COM instead of # the registry. For details see: @@ -171,8 +204,8 @@ if path and os.path.exists(path): return path - raise Exception(('Visual Studio Version %s (from GYP_MSVS_VERSION)' - ' not found.') % (version_as_year)) + raise Exception('Visual Studio Version %s (from GYP_MSVS_VERSION)' + ' not found.' % version_as_year) def _CopyRuntimeImpl(target, source, verbose=True): @@ -267,7 +300,7 @@ version number part changes frequently so the highest version number found is used. """ - assert GetVisualStudioVersion() in ['2017', '2019'] + SetEnvironmentAndGetRuntimeDllDirs() assert ('GYP_MSVS_OVERRIDE_PATH' in os.environ) vc_component_msvc_root = os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc index 1a7ffbb..3629d673 100644 --- a/cc/trees/proxy_main.cc +++ b/cc/trees/proxy_main.cc
@@ -547,9 +547,9 @@ void ProxyMain::SetMutator(std::unique_ptr<LayerTreeMutator> mutator) { TRACE_EVENT0("cc", "ThreadProxy::SetMutator"); ImplThreadTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&ProxyImpl::InitializeMutatorOnImpl, - base::Unretained(proxy_impl_.get()), - base::Passed(std::move(mutator)))); + FROM_HERE, + base::BindOnce(&ProxyImpl::InitializeMutatorOnImpl, + base::Unretained(proxy_impl_.get()), std::move(mutator))); } void ProxyMain::SetPaintWorkletLayerPainter( @@ -558,8 +558,7 @@ ImplThreadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&ProxyImpl::InitializePaintWorkletLayerPainterOnImpl, - base::Unretained(proxy_impl_.get()), - base::Passed(std::move(painter)))); + base::Unretained(proxy_impl_.get()), std::move(painter))); } bool ProxyMain::SupportsImplScrolling() const {
diff --git a/chrome/VERSION b/chrome/VERSION index 8db8a39..6fa27ac 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=76 MINOR=0 -BUILD=3795 +BUILD=3796 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 6816e8f6..092f9f33 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1466,7 +1466,6 @@ "java/src/org/chromium/chrome/browser/tab/TabContextMenuPopulator.java", "java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java", "java/src/org/chromium/chrome/browser/tab/TabFavicon.java", - "java/src/org/chromium/chrome/browser/tab/TabFullscreenHandler.java", "java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java", "java/src/org/chromium/chrome/browser/tab/TabIdManager.java", "java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java",
diff --git a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java index dccd860..ec83aa2e 100644 --- a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java +++ b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
@@ -127,6 +127,21 @@ private final PropertyModel mModel = mMediator.getModelForTesting(); private final UserDataHost mUserDataHost = new UserDataHost(); + private static class MockActivityTabProvider extends ActivityTabProvider { + public Tab mTab; + + public void set(Tab tab) { + mTab = tab; + } + + @Override + public Tab get() { + return mTab; + } + }; + + private final MockActivityTabProvider mActivityTabProvider = new MockActivityTabProvider(); + /** * Helper class that provides shortcuts to providing and observing AccessorySheetData and * Actions. @@ -268,7 +283,7 @@ when(mMockWindow.getActivity()).thenReturn(new WeakReference<>(mMockActivity)); when(mMockKeyboard.calculateKeyboardHeight(any())).thenReturn(0); when(mMockActivity.getTabModelSelector()).thenReturn(mMockTabModelSelector); - when(mMockActivity.getActivityTabProvider()).thenReturn(mock(ActivityTabProvider.class)); + when(mMockActivity.getActivityTabProvider()).thenReturn(mActivityTabProvider); ChromeFullscreenManager fullscreenManager = new ChromeFullscreenManager(mMockActivity, 0); when(mMockActivity.getFullscreenManager()).thenReturn(fullscreenManager); when(mMockActivity.getCompositorViewHolder()).thenReturn(mMockCompositorViewHolder); @@ -1019,8 +1034,8 @@ when(tab.getWebContents()).thenReturn(mLastMockWebContents); mCache.getStateFor(tab).getWebContentsObserverForTesting().wasShown(); when(tab.getContentView()).thenReturn(mMockContentView); - when(mMockActivity.getActivityTabProvider().get()).thenReturn(tab); when(mMockTabModelSelector.getCurrentTab()).thenReturn(tab); + mActivityTabProvider.set(tab); mediator.getTabModelObserverForTesting().didAddTab(tab, FROM_BROWSER_ACTIONS); mediator.getTabObserverForTesting().onShown(tab, FROM_NEW); mediator.getTabModelObserverForTesting().didSelectTab(tab, FROM_NEW, lastId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 8c71901..2f1d6b5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -128,7 +128,7 @@ import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.chrome.browser.sync.SyncController; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tab.TabFullscreenHandler; +import org.chromium.chrome.browser.tab.TabBrowserControlsState; import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; import org.chromium.chrome.browser.tabmodel.EmptyTabModel; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; @@ -871,7 +871,7 @@ // When resuming the activity, force an update to the fullscreen state to ensure a // subactivity did not change the fullscreen configuration of this ChromeTab's // renderer in the case where it was shared. - TabFullscreenHandler.updateEnabledState(tab); + TabBrowserControlsState.updateEnabledState(tab); } VrModuleProvider.getDelegate().onActivityShown(this); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java index 4bbe3e52..59b33d4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -41,7 +41,7 @@ import org.chromium.chrome.browser.tab.SadTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab.TabHidingType; -import org.chromium.chrome.browser.tab.TabFullscreenHandler; +import org.chromium.chrome.browser.tab.TabBrowserControlsState; import org.chromium.chrome.browser.tab.TabThemeColorHelper; import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver; import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; @@ -510,7 +510,7 @@ @Override public void releaseOverlayPanelContent() { if (getTabModelSelector() == null) return; - TabFullscreenHandler.updateEnabledState(getTabModelSelector().getCurrentTab()); + TabBrowserControlsState.updateEnabledState(getTabModelSelector().getCurrentTab()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java index 93085521..8d4aaf34f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java
@@ -9,7 +9,7 @@ import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate; -import org.chromium.chrome.browser.tab.TabFullscreenHandler; +import org.chromium.chrome.browser.tab.TabBrowserControlsState; import javax.inject.Inject; @@ -72,6 +72,6 @@ } private void updateActiveTabFullscreenEnabledState() { - TabFullscreenHandler.updateEnabledState(mTabProvider.get()); + TabBrowserControlsState.updateEnabledState(mTabProvider.get()); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java index 67b0351..00622b1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleLoader.java
@@ -384,9 +384,6 @@ * A task for creating module {@link ClassLoader}. */ private class ClassLoaderTask extends AsyncTask<ClassLoader> { - /** Buffer size to use while copying an input stream into the disk. */ - private static final int BUFFER_SIZE = 16 * 1024; - @Override @Nullable protected ClassLoader doInBackground() { @@ -453,7 +450,7 @@ private void copyDexToDisk(String dexAssetName) throws IOException { InputStream in = mDexInputStreamProvider.createInputStream(dexAssetName, mModuleContext); - FileUtils.copyFileStreamAtomicWithBuffer(in, getDexFile(), new byte[BUFFER_SIZE]); + FileUtils.copyStreamToFile(in, getDexFile()); } private ClassLoader getModuleClassLoader(boolean loadFromDex) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index 8018d43..5a71c76 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -476,7 +476,8 @@ } private void showControlsTransient(Tab tab) { - FullscreenManager fullscreenManager = tab.getFullscreenManager(); + assert mChromeActivity != null; + FullscreenManager fullscreenManager = mChromeActivity.getFullscreenManager(); if (!(fullscreenManager instanceof ChromeFullscreenManager)) return; ((ChromeFullscreenManager) fullscreenManager).getBrowserVisibilityDelegate() .showControlsTransient();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java index c434d4a..1ee5512 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -25,16 +25,22 @@ import org.chromium.chrome.browser.fullscreen.FullscreenHtmlApiHandler.FullscreenHtmlApiDelegate; import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.Tab.TabHidingType; +import org.chromium.chrome.browser.tab.TabAttributeKeys; +import org.chromium.chrome.browser.tab.TabAttributes; import org.chromium.chrome.browser.tab.TabBrowserControlsOffsetHelper; import org.chromium.chrome.browser.tab.TabBrowserControlsState; -import org.chromium.chrome.browser.tab.TabFullscreenHandler; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; +import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.vr.VrModuleProvider; import org.chromium.chrome.browser.widget.ControlContainer; +import org.chromium.content_public.browser.NavigationHandle; +import org.chromium.content_public.browser.SelectionPopupController; import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.BrowserControlsState; import java.lang.annotation.Retention; @@ -58,6 +64,7 @@ private final boolean mExitFullscreenOnStop; private final TokenHolder mHidingTokenHolder = new TokenHolder(this::scheduleVisibilityUpdate); + private TabModelSelectorTabObserver mTabFullscreenObserver; @Nullable private ControlContainer mControlContainer; private int mTopControlContainerHeight; private int mBottomControlContainerHeight; @@ -173,7 +180,7 @@ @Override public void run() { if (getTab() != null) { - TabFullscreenHandler.updateEnabledState(getTab()); + TabBrowserControlsState.updateEnabledState(getTab()); } else if (!mBrowserVisibilityDelegate.canAutoHideBrowserControls()) { setPositionsForTabToNonFullscreen(); } @@ -220,6 +227,81 @@ } }; + mTabFullscreenObserver = new TabModelSelectorTabObserver(modelSelector) { + @Override + public void onHidden(Tab tab, @TabHidingType int reason) { + // Clean up any fullscreen state that might impact other tabs. + exitPersistentFullscreenMode(); + } + + @Override + public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { + if (navigation.isInMainFrame() && !navigation.isSameDocument()) { + if (tab == getTab()) exitPersistentFullscreenMode(); + } + } + + @Override + public void onInteractabilityChanged(boolean interactable) { + if (interactable) { + Runnable enterFullscreen = getEnterFullscreenRunnable(getTab()); + if (enterFullscreen != null) enterFullscreen.run(); + } + } + + @Override + public void onEnterFullscreenMode(Tab tab, final FullscreenOptions options) { + // If enabling fullscreen while the tab is not interactable, fullscreen + // * will be delayed until the tab is interactable. + if (tab.isUserInteractable()) { + enterPersistentFullscreenMode(options); + destroySelectActionMode(tab); + } else { + setEnterFullscreenRunnable(tab, () -> { + enterPersistentFullscreenMode(options); + destroySelectActionMode(tab); + setEnterFullscreenRunnable(tab, null); + }); + } + } + + @Override + public void onExitFullscreenMode(Tab tab) { + setEnterFullscreenRunnable(tab, null); + if (tab == getTab()) exitPersistentFullscreenMode(); + } + + @Override + public void onContentViewChildrenStateUpdated(Tab tab) { + if (tab == getTab()) updateContentViewChildrenState(); + } + + @Override + public void onContentViewSystemUiVisibilityChanged(Tab tab, int visibility) { + if (tab == getTab()) onContentViewSystemUiVisibilityChange(visibility); + } + + private void setEnterFullscreenRunnable(Tab tab, Runnable runnable) { + TabAttributes attrs = TabAttributes.from(tab); + if (runnable == null) { + attrs.clear(TabAttributeKeys.ENTER_FULLSCREEN); + } else { + attrs.set(TabAttributeKeys.ENTER_FULLSCREEN, runnable); + } + } + + private Runnable getEnterFullscreenRunnable(Tab tab) { + return tab != null ? TabAttributes.from(tab).get(TabAttributeKeys.ENTER_FULLSCREEN) + : null; + } + + private void destroySelectActionMode(Tab tab) { + WebContents webContents = tab.getWebContents(); + if (webContents != null) { + SelectionPopupController.fromWebContents(webContents).destroySelectActionMode(); + } + } + }; assert controlContainer != null || mControlsPosition == ControlsPosition.NONE; mControlContainer = controlContainer; @@ -301,7 +383,7 @@ // We should hide browser controls first. mPendingFullscreenOptions = options; mIsEnteringPersistentModeState = true; - TabFullscreenHandler.updateEnabledState(tab); + TabBrowserControlsState.updateEnabledState(tab); } } @@ -711,5 +793,6 @@ public void destroy() { super.destroy(); mBrowserVisibilityDelegate.destroy(); + if (mTabFullscreenObserver != null) mTabFullscreenObserver.destroy(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java index 714618a..443c817e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java
@@ -8,10 +8,11 @@ import android.view.View; import android.view.Window; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.fullscreen.FullscreenHtmlApiHandler.FullscreenHtmlApiDelegate; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabBrowserControlsOffsetHelper; -import org.chromium.chrome.browser.tab.TabFullscreenHandler; +import org.chromium.chrome.browser.tab.TabBrowserControlsState; /** * Manages the basic fullscreen functionality required by a Tab. @@ -26,6 +27,20 @@ @Nullable private Tab mTab; /** + * @return {@link FullscreenManager} instance which a given {@link Tab} + * is associated with as the active tab; {@code null} if the tab + * is not an active one. + * TODO(jinsukim): Look into removing this method. + */ + public static FullscreenManager from(Tab tab) { + if (tab == null) return null; + ChromeActivity activity = tab.getActivity(); + if (activity == null) return null; + FullscreenManager manager = activity.getFullscreenManager(); + return manager.getTab() == tab ? manager : null; + } + + /** * Constructs the basic ChromeTab oriented FullscreenManager. * * @param window Top-level window to turn to fullscreen. @@ -121,19 +136,8 @@ public void setTab(@Nullable Tab tab) { if (mTab == tab) return; - // Remove the fullscreen manager from the old tab before setting the new tab. - setFullscreenManager(null); - mTab = tab; - - // Initialize the new tab with the correct fullscreen manager reference. - setFullscreenManager(this); - } - - private void setFullscreenManager(FullscreenManager manager) { - if (mTab == null) return; - mTab.setFullscreenManager(manager); - TabBrowserControlsOffsetHelper.from(mTab).resetPositions(); + if (mTab != null) TabBrowserControlsOffsetHelper.from(mTab).resetPositions(); } /** @@ -147,9 +151,9 @@ * Enters persistent fullscreen mode. In this mode, the browser controls will be * permanently hidden until this mode is exited. */ - public void enterPersistentFullscreenMode(FullscreenOptions options) { + protected void enterPersistentFullscreenMode(FullscreenOptions options) { mHtmlApiHandler.enterPersistentFullscreenMode(options); - TabFullscreenHandler.updateEnabledState(getTab()); + TabBrowserControlsState.updateEnabledState(getTab()); } /** @@ -158,7 +162,7 @@ */ public void exitPersistentFullscreenMode() { mHtmlApiHandler.exitPersistentFullscreenMode(); - TabFullscreenHandler.updateEnabledState(getTab()); + TabBrowserControlsState.updateEnabledState(getTab()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java index 3f73a2e..f7aacfc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
@@ -160,4 +160,10 @@ @Override public void onFindMatchRectsAvailable(FindMatchRectsDetails result) {} + + @Override + public void onContentViewChildrenStateUpdated(Tab tab) {} + + @Override + public void onContentViewSystemUiVisibilityChanged(Tab tab, int visibility) {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index b9ae39ffc..a71e840 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -42,7 +42,6 @@ import org.chromium.chrome.browser.content.ContentUtils; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.document.ChromeLauncherActivity; -import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.fullscreen.FullscreenOptions; import org.chromium.chrome.browser.native_page.FrozenNativePage; import org.chromium.chrome.browser.native_page.NativePage; @@ -251,8 +250,6 @@ */ private boolean mIsNativePageCommitPending; - private FullscreenManager mFullscreenManager; - private TabDelegateFactory mDelegateFactory; /** Listens for views related to the tab to be attached or detached. */ @@ -790,11 +787,6 @@ if (getWebContents() != null) getWebContents().onHide(); - // Clean up any fullscreen state that might impact other tabs. - if (mFullscreenManager != null) { - mFullscreenManager.exitPersistentFullscreenMode(); - } - // Allow this tab's NativePage to be frozen if it stays hidden for a while. NativePageAssassin.getInstance().tabHidden(this); @@ -1019,8 +1011,6 @@ assert isDetached(); updateWindowAndroid(activity.getWindowAndroid()); - // Update for the controllers that need the Compositor from the new Activity. - mFullscreenManager = activity.getFullscreenManager(); // Update the delegate factory, then recreate and propagate all delegates. mDelegateFactory = tabDelegateFactory; mWebContentsDelegate = mDelegateFactory.createWebContentsDelegate(this); @@ -1792,33 +1782,21 @@ } /** - * @return An instance of a {@link FullscreenManager}. - */ - public FullscreenManager getFullscreenManager() { - return mFullscreenManager; - } - - /** * Enters fullscreen mode. If enabling fullscreen while the tab is not interactable, fullscreen * will be delayed until the tab is interactable. * @param options Options to adjust fullscreen mode. */ public void enterFullscreenMode(FullscreenOptions options) { RewindableIterator<TabObserver> observers = getTabObservers(); - while (observers.hasNext()) { - observers.next().onEnterFullscreenMode(this, options); - } + while (observers.hasNext()) observers.next().onEnterFullscreenMode(this, options); } /** - * Exits fullscreen mode. If enabling fullscreen while the tab is not interactable, fullscreen - * will be delayed until the tab is interactable. + * Exits fullscreen mode. */ public void exitFullscreenMode() { RewindableIterator<TabObserver> observers = getTabObservers(); - while (observers.hasNext()) { - observers.next().onExitFullscreenMode(this); - } + while (observers.hasNext()) observers.next().onExitFullscreenMode(this); } /** @@ -1833,14 +1811,6 @@ } /** - * @param manager The fullscreen manager that should be notified of changes to this tab (if - * set to null, no more updates will come from this tab). - */ - public void setFullscreenManager(FullscreenManager manager) { - mFullscreenManager = manager; - } - - /** * Add a new navigation entry for the current URL and page title. */ void pushNativePageStateToNavigationEntry() { @@ -1851,25 +1821,28 @@ @Override public void onChildViewRemoved(View parent, View child) { - FullscreenManager fullscreenManager = getFullscreenManager(); - if (fullscreenManager != null) { - fullscreenManager.updateContentViewChildrenState(); - } + // TODO(jinsukkim): Consider updating |ContentView| to allow multiple + // OnHierarchyChangeListener and OnSystemUiVisibilityChangeListener + // to be added to not allow FullscreenManager to get the contentview + // and add its own observers as needed. + updateContentViewChildrenState(); } @Override public void onChildViewAdded(View parent, View child) { - FullscreenManager fullscreenManager = getFullscreenManager(); - if (fullscreenManager != null) { - fullscreenManager.updateContentViewChildrenState(); - } + updateContentViewChildrenState(); + } + + private void updateContentViewChildrenState() { + RewindableIterator<TabObserver> observers = getTabObservers(); + while (observers.hasNext()) observers.next().onContentViewChildrenStateUpdated(this); } @Override public void onSystemUiVisibilityChange(int visibility) { - FullscreenManager fullscreenManager = getFullscreenManager(); - if (fullscreenManager != null) { - fullscreenManager.onContentViewSystemUiVisibilityChange(visibility); + RewindableIterator<TabObserver> observers = getTabObservers(); + while (observers.hasNext()) { + observers.next().onContentViewSystemUiVisibilityChanged(this, visibility); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java index 3b0e896..5d4966d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabAttributeKeys.java
@@ -28,4 +28,7 @@ * Parent Tab Root Task Id. See ContextRecordTaskId (context_record_task_id.h) for definition */ public static final String PARENT_TAB_ROOT_TASK_ID = "ParentRootTaskId"; + + /** A runnable to delay the enabling of fullscreen mode if necessary. */ + public static final String ENTER_FULLSCREEN = "EnterFullscreen"; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsOffsetHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsOffsetHelper.java index cbe80a3..5b862ebf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsOffsetHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsOffsetHelper.java
@@ -101,9 +101,11 @@ /** * @return Whether the browser controls are fully visible on screen. + * TODO(jinsukkim): Have clients listen to ChromFullscreenManager directly + * and remove this method. */ public boolean areBrowserControlsFullyVisible() { - final FullscreenManager manager = mTab.getFullscreenManager(); + final FullscreenManager manager = FullscreenManager.from(mTab); return Float.compare(0f, manager.getBrowserControlHiddenRatio()) == 0; } @@ -137,7 +139,7 @@ mPreviousContentOffsetY = contentOffsetY; mAreOffsetsInitialized = true; - if (mTab.getFullscreenManager() == null) return; + if (FullscreenManager.from(mTab) == null) return; if (SadTab.isShowing(mTab) || mTab.isNativePage()) { showAndroidControls(false); } else { @@ -152,13 +154,13 @@ * @param animate Whether a slide-in animation should be run. */ public void showAndroidControls(boolean animate) { - if (mTab.getFullscreenManager() == null) return; + FullscreenManager manager = FullscreenManager.from(mTab); + if (manager == null) return; if (animate) { runBrowserDrivenShowAnimation(); } else { - updateFullscreenManagerOffsets( - true, 0, 0, mTab.getFullscreenManager().getContentOffset()); + updateFullscreenManagerOffsets(true, 0, 0, manager.getContentOffset()); } } @@ -167,7 +169,7 @@ */ public void resetPositions() { resetControlsOffsetOverridden(); - if (mTab.getFullscreenManager() == null) return; + if (FullscreenManager.from(mTab) == null) return; // Make sure the dominant control offsets have been set. if (mAreOffsetsInitialized) { @@ -176,7 +178,7 @@ } else { showAndroidControls(false); } - TabFullscreenHandler.updateEnabledState(mTab); + TabBrowserControlsState.updateEnabledState(mTab); } /** @@ -194,7 +196,7 @@ */ private void updateFullscreenManagerOffsets(boolean toNonFullscreen, int topControlsOffset, int bottomControlsOffset, int topContentOffset) { - final FullscreenManager manager = mTab.getFullscreenManager(); + final FullscreenManager manager = FullscreenManager.from(mTab); if (manager == null) return; if (mIsInVr) { @@ -238,7 +240,7 @@ mIsControlsOffsetOverridden = true; - final FullscreenManager manager = mTab.getFullscreenManager(); + final FullscreenManager manager = FullscreenManager.from(mTab); final float hiddenRatio = manager.getBrowserControlHiddenRatio(); final int topControlHeight = manager.getTopControlsHeight(); final int topControlOffset = manager.getTopControlOffset();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsState.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsState.java index 1bffcd3..6210f6a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsState.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBrowserControlsState.java
@@ -5,7 +5,10 @@ package org.chromium.chrome.browser.tab; import org.chromium.base.ObserverList.RewindableIterator; -import org.chromium.base.UserData; +import org.chromium.chrome.browser.fullscreen.FullscreenManager; +import org.chromium.content_public.browser.GestureListenerManager; +import org.chromium.content_public.browser.ImeAdapter; +import org.chromium.content_public.browser.ImeEventObserver; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.BrowserControlsState; @@ -13,7 +16,7 @@ * Manages the state of tab browser controls. Instantiation is done by * {@link TabDelegateFactory#createBrowserControlsState()}. */ -public class TabBrowserControlsState implements UserData { +public class TabBrowserControlsState extends TabWebContentsUserData implements ImeEventObserver { private static final Class<TabBrowserControlsState> USER_DATA_KEY = TabBrowserControlsState.class; @@ -46,6 +49,15 @@ } /** + * Push state about whether or not the browser controls can show or hide to the renderer. + * @param tab Tab object. + */ + public static void updateEnabledState(Tab tab) { + if (tab == null || get(tab) == null) return; + get(tab).updateEnabledState(); + } + + /** * Updates the browser controls state for this tab. As these values are set at the renderer * level, there is potential for this impacting other tabs that might share the same * process. @@ -63,17 +75,79 @@ /** Constructor */ private TabBrowserControlsState(Tab tab, BrowserControlsVisibilityDelegate delegate) { + super(tab); mTab = tab; mVisibilityDelegate = delegate; mNativeTabBrowserControlsState = nativeInit(); + mTab.addObserver(new EmptyTabObserver() { + @Override + public void onSSLStateUpdated(Tab tab) { + updateEnabledState(); + } + + @Override + public void onRendererResponsiveStateChanged(Tab tab, boolean isResponsive) { + if (FullscreenManager.from(mTab) == null) return; + if (isResponsive) { + updateEnabledState(); + } else { + update(BrowserControlsState.SHOWN, false); + } + } + + @Override + public void onPageLoadFinished(Tab tab, String url) { + updateEnabledState(); + } + + @Override + public void onDestroyed(Tab tab) { + tab.removeObserver(this); + } + }); } @Override - public void destroy() { + public void destroyInternal() { nativeOnDestroyed(mNativeTabBrowserControlsState); } - private void update(int current, boolean animate) { + @Override + public void initWebContents(WebContents webContents) { + ImeAdapter.fromWebContents(webContents).addEventObserver(this); + } + + @Override + public void cleanupWebContents(WebContents webContents) {} + + private void updateEnabledState() { + if (mTab.isFrozen()) return; + + update(BrowserControlsState.BOTH, getConstraints() != BrowserControlsState.HIDDEN); + + WebContents webContents = mTab.getWebContents(); + if (webContents != null) { + GestureListenerManager gestureManager = + GestureListenerManager.fromWebContents(webContents); + FullscreenManager fullscreenManager = FullscreenManager.from(mTab); + if (gestureManager != null && fullscreenManager != null) { + gestureManager.updateMultiTouchZoomSupport( + !fullscreenManager.getPersistentFullscreenMode()); + } + } + } + + /** + * Updates the browser controls state for this tab. As these values are set at the renderer + * level, there is potential for this impacting other tabs that might share the same + * process. + * + * @param current The desired current state for the controls. Pass + * {@link BrowserControlsState#BOTH} to preserve the current position. + * @param animate Whether the controls should animate to the specified ending condition or + * should jump immediately. + */ + public void update(int current, boolean animate) { int constraints = getConstraints(); // Do nothing if current and constraints conflict to avoid error in renderer. @@ -120,6 +194,14 @@ return constraints; } + // ImeEventObserver + + @Override + public void onNodeAttributeUpdated(boolean editable, boolean password) { + if (FullscreenManager.from(mTab) == null) return; + updateEnabledState(); + } + private native long nativeInit(); private native void nativeOnDestroyed(long nativeTabBrowserControlsState); private native void nativeUpdateState(long nativeTabBrowserControlsState,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFullscreenHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFullscreenHandler.java deleted file mode 100644 index b7c585e4..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabFullscreenHandler.java +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.tab; - -import org.chromium.chrome.browser.fullscreen.FullscreenManager; -import org.chromium.chrome.browser.fullscreen.FullscreenOptions; -import org.chromium.content_public.browser.GestureListenerManager; -import org.chromium.content_public.browser.ImeAdapter; -import org.chromium.content_public.browser.ImeEventObserver; -import org.chromium.content_public.browser.SelectionPopupController; -import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.common.BrowserControlsState; - -/** - * {@link TabObserver} for basic fullscreen operations for {@link Tab}. - */ -public final class TabFullscreenHandler extends TabWebContentsUserData implements ImeEventObserver { - private static final Class<TabFullscreenHandler> USER_DATA_KEY = TabFullscreenHandler.class; - - private final Tab mTab; - - /** A runnable to delay the enabling of fullscreen mode if necessary. */ - private Runnable mEnterFullscreenRunnable; - - public static void createForTab(Tab tab) { - assert get(tab) == null; - tab.getUserDataHost().setUserData(USER_DATA_KEY, new TabFullscreenHandler(tab)); - } - - /** - * Push state about whether or not the browser controls can show or hide to the renderer. - */ - public static void updateEnabledState(Tab tab) { - if (tab == null) return; - TabFullscreenHandler.get(tab).updateEnabledState(); - } - - private TabFullscreenHandler(Tab tab) { - super(tab); - mTab = tab; - mTab.addObserver(new EmptyTabObserver() { - @Override - public void onSSLStateUpdated(Tab tab) { - updateEnabledState(); - } - - @Override - public void onInteractabilityChanged(boolean interactable) { - if (interactable && mEnterFullscreenRunnable != null) - mEnterFullscreenRunnable.run(); - } - - @Override - public void onEnterFullscreenMode(Tab tab, final FullscreenOptions options) { - if (!tab.isUserInteractable()) { - mEnterFullscreenRunnable = new Runnable() { - @Override - public void run() { - enterFullscreenInternal(tab, options); - mEnterFullscreenRunnable = null; - } - }; - return; - } - - enterFullscreenInternal(tab, options); - } - - @Override - public void onExitFullscreenMode(Tab tab) { - if (mEnterFullscreenRunnable != null) { - mEnterFullscreenRunnable = null; - return; - } - - if (tab.getFullscreenManager() != null) { - tab.getFullscreenManager().exitPersistentFullscreenMode(); - } - } - - /** - * Do the actual enter of fullscreen mode. - * @param options Options adjust fullscreen mode. - */ - private void enterFullscreenInternal(Tab tab, FullscreenOptions options) { - if (tab.getFullscreenManager() != null) { - tab.getFullscreenManager().enterPersistentFullscreenMode(options); - } - - WebContents webContents = tab.getWebContents(); - if (webContents != null) { - SelectionPopupController.fromWebContents(webContents).destroySelectActionMode(); - } - } - - @Override - public void onRendererResponsiveStateChanged(Tab tab, boolean isResponsive) { - if (tab.getFullscreenManager() == null) return; - if (isResponsive) { - updateEnabledState(); - } else { - TabBrowserControlsState.update(mTab, BrowserControlsState.SHOWN, false); - } - } - - @Override - public void onPageLoadFinished(Tab tab, String url) { - updateEnabledState(); - } - - @Override - public void onDestroyed(Tab tab) { - tab.removeObserver(this); - } - }); - } - - static TabFullscreenHandler get(Tab tab) { - return tab.getUserDataHost().getUserData(USER_DATA_KEY); - } - - @Override - public void initWebContents(WebContents webContents) { - ImeAdapter.fromWebContents(webContents).addEventObserver(this); - } - - @Override - public void cleanupWebContents(WebContents webContents) {} - - // ImeEventObserver - - @Override - public void onNodeAttributeUpdated(boolean editable, boolean password) { - if (mTab.getFullscreenManager() == null) return; - updateEnabledState(); - } - - private void updateEnabledState() { - if (mTab.isFrozen()) return; - - int current = TabBrowserControlsState.getConstraints(mTab); - TabBrowserControlsState.update( - mTab, BrowserControlsState.BOTH, current != BrowserControlsState.HIDDEN); - - WebContents webContents = mTab.getWebContents(); - if (webContents != null) { - GestureListenerManager gestureManager = - GestureListenerManager.fromWebContents(webContents); - FullscreenManager fullscreenManager = mTab.getFullscreenManager(); - if (gestureManager != null && fullscreenManager != null) { - gestureManager.updateMultiTouchZoomSupport( - !fullscreenManager.getPersistentFullscreenMode()); - } - } - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java index f6485c6..2557f29 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.tab; -import org.chromium.base.Supplier; import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.content_public.browser.GestureListenerManager; import org.chromium.content_public.browser.GestureStateListener; @@ -19,25 +18,24 @@ private static final Class<TabGestureStateListener> USER_DATA_KEY = TabGestureStateListener.class; + private final Tab mTab; private GestureStateListener mGestureListener; - private Supplier<FullscreenManager> mFullscreenManager; /** * Creates TabGestureStateListener and lets the WebContentsUserData of the Tab manage it. * @param tab Tab instance that the active WebContents instance gets loaded in. */ - public static TabGestureStateListener from(Tab tab, Supplier<FullscreenManager> fullscreen) { + public static TabGestureStateListener from(Tab tab) { TabGestureStateListener listener = tab.getUserDataHost().getUserData(USER_DATA_KEY); if (listener == null) { - tab.getUserDataHost().setUserData( - USER_DATA_KEY, new TabGestureStateListener(tab, fullscreen)); + tab.getUserDataHost().setUserData(USER_DATA_KEY, new TabGestureStateListener(tab)); } return listener; } - private TabGestureStateListener(Tab tab, Supplier<FullscreenManager> fullscreenManager) { + private TabGestureStateListener(Tab tab) { super(tab); - mFullscreenManager = fullscreenManager; + mTab = tab; } @Override @@ -65,7 +63,7 @@ } private void onScrollingStateChanged() { - FullscreenManager fullscreenManager = mFullscreenManager.get(); + FullscreenManager fullscreenManager = FullscreenManager.from(mTab); if (fullscreenManager == null) return; fullscreenManager.onContentViewScrollingStateChanged(isScrollInProgress()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java index bd2429f..56a170b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabHelpers.java
@@ -33,7 +33,6 @@ static void initTabHelpers(Tab tab, Tab parentTab, @TabCreationState Integer creationState) { if (creationState != null) TabUma.create(tab, creationState); TabThemeColorHelper.createForTab(tab); - TabFullscreenHandler.createForTab(tab); InterceptNavigationDelegateImpl.createForTab(tab); ContextualSearchTabHelper.createForTab(tab); if (ChromeFeatureList.isInitialized() @@ -59,7 +58,7 @@ InfoBarContainer.from(tab); TabWebContentsObserver.from(tab); - TabGestureStateListener.from(tab, tab::getFullscreenManager); + TabGestureStateListener.from(tab); SwipeRefreshHandler.from(tab); TabFavicon.from(tab); TrustedCdn.from(tab);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java index 844dceb..0bb49c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserver.java
@@ -354,4 +354,16 @@ * @param result Detail information on the matched rects. */ void onFindMatchRectsAvailable(FindMatchRectsDetails result); + + /** + * Invoked when a child view is added or removed to Tab's content view. + */ + void onContentViewChildrenStateUpdated(Tab tab); + + /** + * Invoked when the status bar changes visibility. + * @param visibility Flags indicating the global state of the UI visibility. + * @see View#setSystemUiVisibility(int) + */ + void onContentViewSystemUiVisibilityChanged(Tab tab, int visibility); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java index a0fb17e4..243e5d9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java
@@ -11,6 +11,7 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.device.DeviceClassManager; +import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.modaldialog.TabModalPresenter; import org.chromium.chrome.browser.tab.Tab.TabHidingType; import org.chromium.chrome.browser.util.AccessibilityUtil; @@ -63,7 +64,7 @@ if (!mIsFullscreenWaitingForLoad) return; mIsFullscreenWaitingForLoad = false; - TabFullscreenHandler.updateEnabledState(mTab); + TabBrowserControlsState.updateEnabledState(mTab); } private void cancelEnableFullscreenLoadDelay() { @@ -94,13 +95,13 @@ mHandler.removeMessages(MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD); mHandler.sendEmptyMessageDelayed( MSG_ID_ENABLE_FULLSCREEN_AFTER_LOAD, getLoadDelayMs()); - TabFullscreenHandler.updateEnabledState(mTab); + TabBrowserControlsState.updateEnabledState(mTab); } @Override public void onPageLoadStarted(Tab tab, String url) { mIsFullscreenWaitingForLoad = !DomDistillerUrlUtils.isDistilledPage(url); - TabFullscreenHandler.updateEnabledState(mTab); + TabBrowserControlsState.updateEnabledState(mTab); } @Override @@ -108,13 +109,13 @@ // Handle the case where a commit or prerender swap notification failed to arrive // and the enable fullscreen message was never enqueued. scheduleEnableFullscreenLoadDelayIfNecessary(); - TabFullscreenHandler.updateEnabledState(mTab); ///? + TabBrowserControlsState.updateEnabledState(mTab); } @Override public void onPageLoadFailed(Tab tab, int errorCode) { cancelEnableFullscreenLoadDelay(); - TabFullscreenHandler.updateEnabledState(mTab); + TabBrowserControlsState.updateEnabledState(mTab); } @Override @@ -158,7 +159,7 @@ enableHidingBrowserControls &= !mTab.isShowingErrorPage(); enableHidingBrowserControls &= !webContents.isShowingInterstitialPage(); enableHidingBrowserControls &= !mTab.isRendererUnresponsive(); - enableHidingBrowserControls &= (mTab.getFullscreenManager() != null); + enableHidingBrowserControls &= (FullscreenManager.from(mTab) != null); enableHidingBrowserControls &= DeviceClassManager.enableFullscreen(); enableHidingBrowserControls &= !mIsFullscreenWaitingForLoad; enableHidingBrowserControls &= !TabModalPresenter.isDialogShowing(mTab); @@ -168,8 +169,8 @@ @Override public boolean canShowBrowserControls() { - if (mTab.getFullscreenManager() == null) return true; - return !mTab.getFullscreenManager().getPersistentFullscreenMode(); + FullscreenManager manager = FullscreenManager.from(mTab); + return manager != null ? !manager.getPersistentFullscreenMode() : true; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java index 29b5f8b..b93bbe9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
@@ -34,6 +34,7 @@ import org.chromium.chrome.browser.findinpage.FindMatchRectsDetails; import org.chromium.chrome.browser.findinpage.FindNotificationDetails; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; +import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.fullscreen.FullscreenOptions; import org.chromium.chrome.browser.media.MediaCaptureNotificationService; import org.chromium.chrome.browser.policy.PolicyAuditor; @@ -250,8 +251,8 @@ @Override public boolean isFullscreenForTabOrPending() { - return mTab.getFullscreenManager() == null - ? false : mTab.getFullscreenManager().getPersistentFullscreenMode(); + FullscreenManager manager = FullscreenManager.from(mTab); + return manager != null ? manager.getPersistentFullscreenMode() : false; } protected TabModel getTabModel() { @@ -472,30 +473,22 @@ mTab.getActivity().setOverlayMode(useOverlayMode); } - private ChromeFullscreenManager getFullscreenManager() { - // Following get* methods use this method instead of |Tab.getFullscreenManager| - // because the latter can return null if invoked while the tab is in detached state. - ChromeActivity activity = mTab.getActivity(); - return activity != null && !activity.isActivityFinishingOrDestroyed() ? - activity.getFullscreenManager() : null; - } - @Override public int getTopControlsHeight() { - ChromeFullscreenManager manager = getFullscreenManager(); + FullscreenManager manager = FullscreenManager.from(mTab); return manager != null ? manager.getTopControlsHeight() : 0; } @Override public int getBottomControlsHeight() { - ChromeFullscreenManager manager = getFullscreenManager(); + FullscreenManager manager = FullscreenManager.from(mTab); return manager != null ? manager.getBottomControlsHeight() : 0; } @Override public boolean controlsResizeView() { - ChromeFullscreenManager manager = getFullscreenManager(); - return manager != null ? manager.controlsResizeView() : false; + FullscreenManager manager = FullscreenManager.from(mTab); + return manager != null ? ((ChromeFullscreenManager) manager).controlsResizeView() : false; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java index 8d3e810..ccf96a6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -17,7 +17,6 @@ import org.chromium.chrome.browser.AppHooks; import org.chromium.chrome.browser.SwipeRefreshHandler; import org.chromium.chrome.browser.display_cutout.DisplayCutoutController; -import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.infobar.InfoBarContainer; import org.chromium.chrome.browser.media.MediaCaptureNotificationService; import org.chromium.chrome.browser.policy.PolicyAuditor; @@ -264,12 +263,6 @@ } } - FullscreenManager fullscreenManager = mTab.getFullscreenManager(); - if (navigation.isInMainFrame() && !navigation.isSameDocument() - && fullscreenManager != null) { - fullscreenManager.exitPersistentFullscreenMode(); - } - if (navigation.isInMainFrame()) { // Stop swipe-to-refresh animation. SwipeRefreshHandler handler = SwipeRefreshHandler.get(mTab); @@ -302,7 +295,7 @@ observers.next().onDidAttachInterstitialPage(mTab); } mTab.notifyLoadProgress(mTab.getProgress()); - TabFullscreenHandler.updateEnabledState(mTab); + TabBrowserControlsState.updateEnabledState(mTab); PolicyAuditor auditor = AppHooks.get().getPolicyAuditor(); auditor.notifyCertificateFailure( PolicyAuditor.nativeGetCertificateFailure(mTab.getWebContents()), @@ -318,7 +311,7 @@ observers.next().onDidDetachInterstitialPage(mTab); } mTab.notifyLoadProgress(mTab.getProgress()); - TabFullscreenHandler.updateEnabledState(mTab); + TabBrowserControlsState.updateEnabledState(mTab); if (!mTab.maybeShowNativePage(mTab.getUrl(), false)) { mTab.showRenderedPage(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java index 1dedba70..f2fd0a4a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java
@@ -8,6 +8,7 @@ import android.util.SparseArray; import org.chromium.base.ContextUtils; +import org.chromium.base.FileUtils; import org.chromium.base.Log; import org.chromium.base.StreamUtil; import org.chromium.base.task.AsyncTask; @@ -19,7 +20,6 @@ import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelInfo.DocumentEntry; import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelInfo.DocumentList; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -40,9 +40,6 @@ /** Directory to store TabState files in. */ private static final String STATE_DIRECTORY = "ChromeDocumentActivity"; - /** The buffer size to use when reading the DocumentTabModel file, set to 4k bytes. */ - private static final int BUF_SIZE = 0x1000; - /** Cached base state directory to prevent main-thread filesystem access in getStateDirectory(). */ private static AsyncTask<File> sBaseStateDirectoryFetchTask; @@ -69,15 +66,7 @@ try { String filename = getFilename(encrypted); streamIn = ContextUtils.getApplicationContext().openFileInput(filename); - - // Read the file from the file into the out stream. - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - byte[] buf = new byte[BUF_SIZE]; - int r; - while ((r = streamIn.read(buf)) != -1) { - streamOut.write(buf, 0, r); - } - bytes = streamOut.toByteArray(); + bytes = FileUtils.readStream(streamIn); } catch (FileNotFoundException e) { Log.e(TAG, "DocumentTabModel file not found."); } catch (IOException e) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java index 15b2a1c6..e8bad23 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkShareTargetUtil.java
@@ -17,12 +17,12 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; +import org.chromium.base.FileUtils; import org.chromium.base.StrictModeContext; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.net.MimeTypeFilter; import org.chromium.webapk.lib.common.WebApkMetaDataKeys; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -87,14 +87,7 @@ try (InputStream inputStream = ContextUtils.getApplicationContext().getContentResolver().openInputStream( uri)) { - ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - - int len; - while ((len = inputStream.read(buffer)) != -1) { - byteBuffer.write(buffer, 0, len); - } - return byteBuffer.toByteArray(); + return FileUtils.readStream(inputStream); } catch (IOException e) { return null; }
diff --git a/chrome/app_shim/DEPS b/chrome/app_shim/DEPS index 37a1d69..54b4483 100644 --- a/chrome/app_shim/DEPS +++ b/chrome/app_shim/DEPS
@@ -3,7 +3,7 @@ "+chrome/browser/ui/cocoa", "+chrome/installer/launcher_support", "+components/crash/content/app", - "+components/remote_cocoa/common", + "+components/remote_cocoa", "+content/public/browser", "+mojo/core/embedder", ]
diff --git a/chrome/app_shim/app_shim_controller.mm b/chrome/app_shim/app_shim_controller.mm index d117cde..4512ad1 100644 --- a/chrome/app_shim/app_shim_controller.mm +++ b/chrome/app_shim/app_shim_controller.mm
@@ -25,6 +25,8 @@ #include "chrome/browser/ui/cocoa/main_menu_builder.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/mac/app_mode_common.h" +#include "components/remote_cocoa/app_shim/bridge_factory_impl.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "components/remote_cocoa/common/bridge_factory.mojom.h" #include "content/public/browser/ns_view_bridge_factory_impl.h" #include "content/public/common/ns_view_bridge_factory.mojom.h" @@ -34,8 +36,6 @@ #include "mojo/public/cpp/platform/platform_channel.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/views_bridge_mac/bridge_factory_impl.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace { // The maximum amount of time to wait for Chrome's AppShimHostManager to be
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 95fe0ae..9757365 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -9,8 +9,8 @@ #include <set> #include <utility> -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/public/cpp/app_list/app_list_features.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/base_switches.h" #include "base/bind.h" #include "base/callback.h" @@ -1431,12 +1431,6 @@ {"enable-virtual-keyboard", flag_descriptions::kVirtualKeyboardName, flag_descriptions::kVirtualKeyboardDescription, kOsCrOS, SINGLE_VALUE_TYPE(keyboard::switches::kEnableVirtualKeyboard)}, - {"enable-physical-keyboard-autocorrect", - flag_descriptions::kPhysicalKeyboardAutocorrectName, - flag_descriptions::kPhysicalKeyboardAutocorrectDescription, kOsCrOS, - ENABLE_DISABLE_VALUE_TYPE( - chromeos::switches::kEnablePhysicalKeyboardAutocorrect, - chromeos::switches::kDisablePhysicalKeyboardAutocorrect)}, #endif // OS_CHROMEOS #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) {"device-discovery-notifications",
diff --git a/chrome/browser/android/history_report/delta_file_service.cc b/chrome/browser/android/history_report/delta_file_service.cc index ce51a73..44001b9 100644 --- a/chrome/browser/android/history_report/delta_file_service.cc +++ b/chrome/browser/android/history_report/delta_file_service.cc
@@ -89,9 +89,9 @@ DeltaFileService::~DeltaFileService() { // Unregister should happen on task runner. - task_runner_->PostTask( - FROM_HERE, base::BindOnce(&DeltaFileServiceDoUnregisterMDP, - base::Passed(std::move(delta_file_backend_)))); + task_runner_->PostTask(FROM_HERE, + base::BindOnce(&DeltaFileServiceDoUnregisterMDP, + std::move(delta_file_backend_))); } void DeltaFileService::PageAdded(const GURL& url) {
diff --git a/chrome/browser/android/history_report/usage_reports_buffer_service.cc b/chrome/browser/android/history_report/usage_reports_buffer_service.cc index 111442c6..6c36117 100644 --- a/chrome/browser/android/history_report/usage_reports_buffer_service.cc +++ b/chrome/browser/android/history_report/usage_reports_buffer_service.cc
@@ -85,7 +85,7 @@ // Unregister should happen on task runner. task_runner_->PostTask( FROM_HERE, base::BindOnce(&UsageReportsBufferServiceDoUnregisterMDP, - base::Passed(std::move(backend_)))); + std::move(backend_))); } void UsageReportsBufferService::Init() {
diff --git a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc index 4530be3..031870cf 100644 --- a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc +++ b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/apps/intent_helper/page_transition_util.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/menu_manager.h" +#include "chrome/browser/page_load_metrics/page_load_metrics_util.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -31,6 +32,16 @@ namespace { +// Returns true if |url| is a known and valid redirector that will redirect a +// navigation elsewhere. +bool IsGoogleRedirectorUrl(const GURL& url) { + // This currently only check for redirectors on the "google" domain. + if (!page_load_metrics::IsGoogleSearchHostname(url)) + return false; + + return url.path_piece() == "/url" && url.has_query(); +} + // Compares the host name of the referrer and target URL to decide whether // the navigation needs to be overridden. bool ShouldOverrideUrlLoading(const GURL& previous_url, @@ -54,6 +65,11 @@ return false; } + // Skip URL redirectors that are intermediate pages redirecting towards a + // final URL. + if (IsGoogleRedirectorUrl(current_url)) + return false; + return true; } @@ -162,6 +178,11 @@ } // static +bool AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting(const GURL& url) { + return IsGoogleRedirectorUrl(url); +} + +// static bool AppsNavigationThrottle::ShouldOverrideUrlLoadingForTesting( const GURL& previous_url, const GURL& current_url) { @@ -413,6 +434,15 @@ content::NavigationThrottle::ThrottleCheckResult AppsNavigationThrottle::HandleRequest() { content::NavigationHandle* handle = navigation_handle(); + // If the navigation is from an iframe then no intent picker check is + // required. If the navigation happened without changing document or the + // navigation resulted in an error page, don't check intent for the + // navigation. + if (!handle->IsInMainFrame() || handle->IsSameDocument() || + handle->IsErrorPage()) { + return content::NavigationThrottle::PROCEED; + } + DCHECK(!ui_displayed_); navigate_from_link_ = false;
diff --git a/chrome/browser/apps/intent_helper/apps_navigation_throttle.h b/chrome/browser/apps/intent_helper/apps_navigation_throttle.h index 9b3afd4..73c3dea 100644 --- a/chrome/browser/apps/intent_helper/apps_navigation_throttle.h +++ b/chrome/browser/apps/intent_helper/apps_navigation_throttle.h
@@ -74,6 +74,8 @@ IntentPickerCloseReason close_reason, bool should_persist); + static bool IsGoogleRedirectorUrlForTesting(const GURL& url); + static bool ShouldOverrideUrlLoadingForTesting(const GURL& previous_url, const GURL& current_url);
diff --git a/chrome/browser/apps/intent_helper/apps_navigation_throttle_unittest.cc b/chrome/browser/apps/intent_helper/apps_navigation_throttle_unittest.cc index 150a969..6465caff3 100644 --- a/chrome/browser/apps/intent_helper/apps_navigation_throttle_unittest.cc +++ b/chrome/browser/apps/intent_helper/apps_navigation_throttle_unittest.cc
@@ -9,6 +9,36 @@ namespace apps { +TEST(AppsNavigationThrottleTest, TestIsGoogleRedirectorUrl) { + // Test that redirect urls with different TLDs are still recognized. + EXPECT_TRUE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.google.com.au/url?q=wathever"))); + EXPECT_TRUE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.google.com.mx/url?q=hotpot"))); + EXPECT_TRUE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.google.co/url?q=query"))); + + // Non-google domains shouldn't be used as valid redirect links. + EXPECT_FALSE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.not-google.com/url?q=query"))); + EXPECT_FALSE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.gooogle.com/url?q=legit_query"))); + + // This method only takes "/url" as a valid path, it needs to contain a query, + // we don't analyze that query as it will expand later on in the same + // throttle. + EXPECT_TRUE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.google.com/url?q=who_dis"))); + EXPECT_TRUE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("http://www.google.com/url?q=who_dis"))); + EXPECT_FALSE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.google.com/url"))); + EXPECT_FALSE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.google.com/link?q=query"))); + EXPECT_FALSE(AppsNavigationThrottle::IsGoogleRedirectorUrlForTesting( + GURL("https://www.google.com/link"))); +} + TEST(AppsNavigationThrottleTest, TestShouldOverrideUrlLoading) { // If either of two paramters is empty, the function should return false. EXPECT_FALSE(AppsNavigationThrottle::ShouldOverrideUrlLoadingForTesting( @@ -60,6 +90,17 @@ GURL("chrome://fake_document"), GURL("https://www.a.com"))); EXPECT_TRUE(AppsNavigationThrottle::ShouldOverrideUrlLoadingForTesting( GURL("file://fake_document"), GURL("https://www.a.com"))); + + // A navigation going to a redirect url cannot be overridden, unless there's + // no query or the path is not valid. + EXPECT_FALSE(AppsNavigationThrottle::ShouldOverrideUrlLoadingForTesting( + GURL("http://www.google.com"), GURL("https://www.google.com/url?q=b"))); + EXPECT_FALSE(AppsNavigationThrottle::ShouldOverrideUrlLoadingForTesting( + GURL("https://www.a.com"), GURL("https://www.google.com/url?q=a"))); + EXPECT_TRUE(AppsNavigationThrottle::ShouldOverrideUrlLoadingForTesting( + GURL("https://www.a.com"), GURL("https://www.google.com/url"))); + EXPECT_TRUE(AppsNavigationThrottle::ShouldOverrideUrlLoadingForTesting( + GURL("https://www.a.com"), GURL("https://www.google.com/link?q=a"))); } TEST(AppsNavigationThrottleTest, TestGetPickerAction) {
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc index fd57bd8..b686009 100644 --- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc +++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -7,8 +7,8 @@ #include <algorithm> #include <utility> -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/public/cpp/ash_pref_names.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/bind.h" #include "base/logging.h" #include "base/memory/singleton.h"
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc index 86565988..b6c8216 100644 --- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc +++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -9,8 +9,8 @@ #include <utility> #include <vector> -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/public/cpp/ash_pref_names.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h"
diff --git a/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc b/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc index 814fbc3..7d240e4 100644 --- a/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc +++ b/chrome/browser/chromeos/extensions/default_keyboard_extension_browser_test.cc
@@ -7,7 +7,7 @@ #include <vector> -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/command_line.h" #include "base/run_loop.h" #include "base/threading/thread_restrictions.h"
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc index 8288f8f..a26aa86 100644 --- a/chrome/browser/chromeos/extensions/input_method_api.cc +++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/command_line.h" #include "base/lazy_instance.h" #include "base/values.h" #include "build/build_config.h" @@ -30,7 +29,6 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/extensions/api/input_method_private.h" #include "chrome/common/pref_names.h" -#include "chromeos/constants/chromeos_switches.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/sync/driver/sync_service.h" @@ -86,10 +84,7 @@ EXTENSION_FUNCTION_VALIDATE(false); #else std::unique_ptr<base::DictionaryValue> output(new base::DictionaryValue()); - output->SetBoolean( - "isPhysicalKeyboardAutocorrectEnabled", - !base::CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kDisablePhysicalKeyboardAutocorrect)); + output->SetBoolean("isPhysicalKeyboardAutocorrectEnabled", true); output->SetBoolean("isImeMenuActivated", Profile::FromBrowserContext(browser_context()) ->GetPrefs()
diff --git a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc index 5735a7e..82f76188 100644 --- a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc +++ b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc
@@ -346,9 +346,8 @@ context_id, base::BindOnce( &FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(std::move(file_definition_list)), - base::Passed(std::move(entry_definition_list)), handler_pid)); + weak_ptr_factory_.GetWeakPtr(), std::move(file_definition_list), + std::move(entry_definition_list), handler_pid)); } }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index df130c4..d6560092 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -4,7 +4,7 @@ #include <stddef.h> -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" @@ -965,7 +965,8 @@ .EnableMyFilesVolume() .DontMountVolumes(), TestCase("myFilesUpdatesChildren").EnableMyFilesVolume(), - TestCase("myFilesAutoExpandOnce").EnableMyFilesVolume())); + TestCase("myFilesAutoExpandOnce").EnableMyFilesVolume(), + TestCase("myFilesToolbarDelete").EnableMyFilesVolume())); WRAPPED_INSTANTIATE_TEST_SUITE_P( InstallLinuxPackageDialog, /* install_linux_package_dialog.js */
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc index 5e541a4..3efe605d 100644 --- a/chrome/browser/chromeos/login/kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -6,8 +6,8 @@ #include <vector> #include "apps/test/app_window_waiter.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/public/cpp/ash_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/interfaces/login_screen_test_api.test-mojom-test-utils.h" #include "ash/public/interfaces/wallpaper.mojom.h" #include "base/bind.h"
diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc b/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc index 372c4382..95f07879 100644 --- a/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc +++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller_unittest.cc
@@ -134,7 +134,6 @@ int VerifyInternal(net::X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, net::CRLSet* crl_set, const net::CertificateList& additional_trust_anchors,
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc b/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc index 1827b13..709d632 100644 --- a/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_network_configuration_updater_factory_browsertest.cc
@@ -262,9 +262,8 @@ int result = net::OK; content::BrowserContext::GetDefaultStoragePartition(profile) ->GetNetworkContext() - ->VerifyCertificateForTesting(certificate, "127.0.0.1", - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), &result); + ->VerifyCertificateForTesting(certificate, "127.0.0.1", std::string(), + &result); return result; }
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc index de8bd9e2..d4dc455 100644 --- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc +++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -9,7 +9,7 @@ #include <memory> #include <utility> -#include "ash/keyboard/ui/public/keyboard_config.mojom.h" +#include "ash/public/interfaces/keyboard_config.mojom.h" #include "base/feature_list.h" #include "base/macros.h" #include "chrome/browser/chromeos/input_method/input_method_engine.h"
diff --git a/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc b/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc index 09b9b975..b1d8957d 100644 --- a/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc +++ b/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
@@ -192,7 +192,6 @@ const int flags = 0; std::string ocsp_response; - std::string sct_list; net::CertVerifyResult* const verify_result_ptr = verify_result.get(); RequestState* request_state = new RequestState(); @@ -202,7 +201,7 @@ const int return_value = verifier->Verify( net::CertVerifier::RequestParams(std::move(cert_chain), details.hostname, - flags, ocsp_response, sct_list), + flags, ocsp_response), verify_result_ptr, bound_callback, &request_state->request, *net_log); if (return_value != net::ERR_IO_PENDING) {
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc index 0538bb1..0c1ea72 100644 --- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc +++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -8,8 +8,8 @@ #include <string> #include <utility> -#include "ash/keyboard/ui/public/keyboard_controller_types.mojom.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" +#include "ash/public/interfaces/keyboard_controller_types.mojom.h" #include "base/bind.h" #include "base/command_line.h" #include "base/feature_list.h"
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 6ee95ef..c3d4b78 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1390,11 +1390,6 @@ "expiry_milestone": -1 }, { - "name": "enable-physical-keyboard-autocorrect", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-pixel-canvas-recording", "owners": [ "malaykeshav", "oshima" ], "expiry_milestone": 77
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index a3a28de..ecb094b 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3154,11 +3154,6 @@ const char kNewZipUnpackerDescription[] = "Use the ZIP Archiver for mounting/unpacking ZIP files"; -const char kPhysicalKeyboardAutocorrectName[] = "Physical keyboard autocorrect"; -const char kPhysicalKeyboardAutocorrectDescription[] = - "Enable physical keyboard autocorrect for US keyboard, which can provide " - "suggestions as typing on physical keyboard."; - const char kPrinterProviderSearchAppName[] = "Chrome Web Store Gallery app for printer drivers"; const char kPrinterProviderSearchAppDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 036d5c5..804028f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1903,9 +1903,6 @@ extern const char kNewZipUnpackerName[]; extern const char kNewZipUnpackerDescription[]; -extern const char kPhysicalKeyboardAutocorrectName[]; -extern const char kPhysicalKeyboardAutocorrectDescription[]; - extern const char kPrinterProviderSearchAppName[]; extern const char kPrinterProviderSearchAppDescription[];
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc index 85d89493..09b97310 100644 --- a/chrome/browser/geolocation/geolocation_browsertest.cc +++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -39,7 +39,6 @@ #include "content/public/test/browser_test_utils.h" #include "net/base/escape.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/url_request/test_url_fetcher_factory.h" #include "services/device/public/cpp/test/scoped_geolocation_overrider.h" #include "services/device/public/mojom/geoposition.mojom.h" @@ -172,39 +171,6 @@ DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver); }; -// Observer that waits until a TestURLFetcher with the specified fetcher_id -// starts, after which it is made available through .fetcher(). -class TestURLFetcherObserver : public net::TestURLFetcher::DelegateForTests { - public: - explicit TestURLFetcherObserver(int expected_fetcher_id) - : expected_fetcher_id_(expected_fetcher_id) { - factory_.SetDelegateForTests(this); - } - virtual ~TestURLFetcherObserver() {} - - void Wait() { loop_.Run(); } - - net::TestURLFetcher* fetcher() { return fetcher_; } - - // net::TestURLFetcher::DelegateForTests: - void OnRequestStart(int fetcher_id) override { - if (fetcher_id == expected_fetcher_id_) { - fetcher_ = factory_.GetFetcherByID(fetcher_id); - fetcher_->SetDelegateForTests(nullptr); - factory_.SetDelegateForTests(nullptr); - loop_.Quit(); - } - } - void OnChunkUpload(int fetcher_id) override {} - void OnRequestEnd(int fetcher_id) override {} - - private: - const int expected_fetcher_id_; - net::TestURLFetcher* fetcher_ = nullptr; - net::TestURLFetcherFactory factory_; - base::RunLoop loop_; -}; - } // namespace
diff --git a/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc b/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc index c0b2d8b0..dc05e5b 100644 --- a/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc
@@ -63,8 +63,10 @@ child_process_data.metrics_name = kTestGpuProcessName; provider.BrowserChildProcessLaunchedAndConnected(child_process_data); - content::ChildProcessTerminationInfo abnormal_termination_info{ - base::TERMINATION_STATUS_ABNORMAL_TERMINATION, 1}; + content::ChildProcessTerminationInfo abnormal_termination_info; + abnormal_termination_info.status = + base::TERMINATION_STATUS_ABNORMAL_TERMINATION; + abnormal_termination_info.exit_code = 1; provider.BrowserChildProcessCrashed(child_process_data, abnormal_termination_info); provider.BrowserChildProcessCrashed(child_process_data, @@ -94,8 +96,10 @@ provider.BrowserChildProcessLaunchedAndConnected(child_process_data); const int kExitCode = 1; - content::ChildProcessTerminationInfo abnormal_termination_info{ - base::TERMINATION_STATUS_ABNORMAL_TERMINATION, kExitCode}; + content::ChildProcessTerminationInfo abnormal_termination_info; + abnormal_termination_info.status = + base::TERMINATION_STATUS_ABNORMAL_TERMINATION; + abnormal_termination_info.exit_code = kExitCode; provider.BrowserChildProcessCrashed(child_process_data, abnormal_termination_info); provider.BrowserChildProcessCrashed(child_process_data, @@ -146,31 +150,35 @@ rph_factory->CreateRenderProcessHost(profile, site_instance.get())); // Crash and abnormal termination should increment renderer crash count. - content::ChildProcessTerminationInfo crash_details{ - base::TERMINATION_STATUS_PROCESS_CRASHED, 1}; + content::ChildProcessTerminationInfo crash_details; + crash_details.status = base::TERMINATION_STATUS_PROCESS_CRASHED; + crash_details.exit_code = 1; provider.Observe( content::NOTIFICATION_RENDERER_PROCESS_CLOSED, content::Source<content::RenderProcessHost>(host), content::Details<content::ChildProcessTerminationInfo>(&crash_details)); - content::ChildProcessTerminationInfo term_details{ - base::TERMINATION_STATUS_ABNORMAL_TERMINATION, 1}; + content::ChildProcessTerminationInfo term_details; + term_details.status = base::TERMINATION_STATUS_ABNORMAL_TERMINATION; + term_details.exit_code = 1; provider.Observe( content::NOTIFICATION_RENDERER_PROCESS_CLOSED, content::Source<content::RenderProcessHost>(host), content::Details<content::ChildProcessTerminationInfo>(&term_details)); // Kill does not increment renderer crash count. - content::ChildProcessTerminationInfo kill_details{ - base::TERMINATION_STATUS_PROCESS_WAS_KILLED, 1}; + content::ChildProcessTerminationInfo kill_details; + kill_details.status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED; + kill_details.exit_code = 1; provider.Observe( content::NOTIFICATION_RENDERER_PROCESS_CLOSED, content::Source<content::RenderProcessHost>(host), content::Details<content::ChildProcessTerminationInfo>(&kill_details)); // Failed launch increments failed launch count. - content::ChildProcessTerminationInfo failed_launch_details{ - base::TERMINATION_STATUS_LAUNCH_FAILED, 1}; + content::ChildProcessTerminationInfo failed_launch_details; + failed_launch_details.status = base::TERMINATION_STATUS_LAUNCH_FAILED; + failed_launch_details.exit_code = 1; provider.Observe(content::NOTIFICATION_RENDERER_PROCESS_CLOSED, content::Source<content::RenderProcessHost>(host), content::Details<content::ChildProcessTerminationInfo>(
diff --git a/chrome/browser/metrics/plugin_metrics_provider_unittest.cc b/chrome/browser/metrics/plugin_metrics_provider_unittest.cc index 6475cbf..18702b4 100644 --- a/chrome/browser/metrics/plugin_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/plugin_metrics_provider_unittest.cc
@@ -168,8 +168,10 @@ // Increase number of process launches which should also start a delayed // task. - content::ChildProcessTerminationInfo abnormal_termination_info{ - base::TERMINATION_STATUS_ABNORMAL_TERMINATION, 1}; + content::ChildProcessTerminationInfo abnormal_termination_info; + abnormal_termination_info.status = + base::TERMINATION_STATUS_ABNORMAL_TERMINATION; + abnormal_termination_info.exit_code = 1; content::ChildProcessData child_process_data1( content::PROCESS_TYPE_PPAPI_PLUGIN); child_process_data1.name = base::UTF8ToUTF16("p1");
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc index f32ff1d..bcd1b0f 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -2979,39 +2979,3 @@ EXPECT_EQ(overlay_window->muted_state_for_testing(), OverlayWindowViews::MutedState::kNoAudio); } - -// Tests that when closing the window after the player was reset, the <video> -// element is still notified. -IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, - ResetPlayerCloseWindowNotifiesElement) { - LoadTabAndEnterPictureInPicture(browser()); - content::WebContents* active_web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - // Video should be in Picture-in-Picture. - { - bool in_picture_in_picture = false; - ASSERT_TRUE(ExecuteScriptAndExtractBool(active_web_contents, - "isInPictureInPicture();", - &in_picture_in_picture)); - EXPECT_TRUE(in_picture_in_picture); - } - - // Reset video source and wait for the notification. - ASSERT_TRUE(content::ExecuteScript(active_web_contents, "resetVideo();")); - base::string16 expected_title = base::ASCIIToUTF16("emptied"); - EXPECT_EQ(expected_title, - content::TitleWatcher(active_web_contents, expected_title) - .WaitAndGetTitle()); - - window_controller()->Close(true /* should_pause_video */); - - // Video should no longer be in Picture-in-Picture. - { - bool in_picture_in_picture = false; - ASSERT_TRUE(ExecuteScriptAndExtractBool(active_web_contents, - "isInPictureInPicture();", - &in_picture_in_picture)); - EXPECT_FALSE(in_picture_in_picture); - } -}
diff --git a/chrome/browser/resources/downloads/BUILD.gn b/chrome/browser/resources/downloads/BUILD.gn index ceb9f736..ff97df9 100644 --- a/chrome/browser/resources/downloads/BUILD.gn +++ b/chrome/browser/resources/downloads/BUILD.gn
@@ -21,7 +21,9 @@ excludes = [ "chrome://resources/js/mojo_bindings_lite.js", "chrome://downloads/downloads.mojom-lite.js", + "chrome://downloads/downloads.mojom-lite.html", ] + replace_for_html_imports_polyfill = "crisper.js" deps = [ ":unpak", @@ -92,6 +94,7 @@ ":manager", "//ui/webui/resources/js:cr", ] + externs_list = [ "$externs_path/html_imports.js" ] } js_library("icon_loader") {
diff --git a/chrome/browser/resources/downloads/browser_proxy.html b/chrome/browser/resources/downloads/browser_proxy.html index 505910d7..610c6459 100644 --- a/chrome/browser/resources/downloads/browser_proxy.html +++ b/chrome/browser/resources/downloads/browser_proxy.html
@@ -1,4 +1,4 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> -<script src="downloads.mojom-lite.js"></script> +<link rel="import" href="chrome://downloads/downloads.mojom-lite.html"> <script src="browser_proxy.js"></script>
diff --git a/chrome/browser/resources/downloads/downloads.html b/chrome/browser/resources/downloads/downloads.html index dcb81ef..a177651 100644 --- a/chrome/browser/resources/downloads/downloads.html +++ b/chrome/browser/resources/downloads/downloads.html
@@ -42,6 +42,8 @@ <command id="clear-all-command" shortcut="Alt|c"> <command id="undo-command" shortcut="Ctrl|z"> </if> + <script src="chrome://resources/polymer/v1_0/html-imports/html-imports.min.js"> + </script> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html">
diff --git a/chrome/browser/resources/downloads/downloads.js b/chrome/browser/resources/downloads/downloads.js index fe3834c0..6bad17b 100644 --- a/chrome/browser/resources/downloads/downloads.js +++ b/chrome/browser/resources/downloads/downloads.js
@@ -2,13 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -window.addEventListener('load', function() { - downloads.Manager.onLoad().then(function() { - requestIdleCallback(function() { - chrome.send( - 'metricsHandler:recordTime', - ['Download.ResultsRenderedTime', window.performance.now()]); - document.fonts.load('bold 12px Roboto'); +function loadDownloads() { + return HTMLImports.whenReady(function() { + downloads.Manager.onLoad().then(function() { + requestIdleCallback(function() { + chrome.send( + 'metricsHandler:recordTime', + ['Download.ResultsRenderedTime', window.performance.now()]); + document.fonts.load('bold 12px Roboto'); + }); }); }); -}); +} + +if (document.readyState === 'complete') { + loadDownloads(); +} else { + window.addEventListener('load', loadDownloads); +}
diff --git a/chrome/browser/resources/downloads/downloads.mojom-lite.html b/chrome/browser/resources/downloads/downloads.mojom-lite.html new file mode 100644 index 0000000..5a695dbb --- /dev/null +++ b/chrome/browser/resources/downloads/downloads.mojom-lite.html
@@ -0,0 +1 @@ +<script src="downloads.mojom-lite.js"></script>
diff --git a/chrome/browser/resources/downloads/downloads_resources.grd b/chrome/browser/resources/downloads/downloads_resources.grd index ba9c485..bbdb58c 100644 --- a/chrome/browser/resources/downloads/downloads_resources.grd +++ b/chrome/browser/resources/downloads/downloads_resources.grd
@@ -18,6 +18,9 @@ <include name="IDR_DOWNLOADS_IMAGES_NO_DOWNLOADS_SVG" file="images\no_downloads.svg" type="BINDATA" /> + <include name="IDR_DOWNLOADS_MOJO_LITE_HTML" + file="downloads.mojom-lite.html" + type="BINDATA" /> <include name="IDR_DOWNLOADS_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\downloads\downloads.mojom-lite.js" use_base_dir="false"
diff --git a/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd b/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd index 71179dc..05ad680b 100644 --- a/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd +++ b/chrome/browser/resources/downloads/downloads_resources_vulcanized.grd
@@ -18,6 +18,9 @@ <include name="IDR_DOWNLOADS_IMAGES_NO_DOWNLOADS_SVG" file="images\no_downloads.svg" type="BINDATA" /> + <include name="IDR_DOWNLOADS_MOJO_LITE_HTML" + file="downloads.mojom-lite.html" + type="BINDATA" /> <include name="IDR_DOWNLOADS_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\downloads\downloads.mojom-lite.js" use_base_dir="false"
diff --git a/chrome/browser/resources/extensions/shortcut_input.html b/chrome/browser/resources/extensions/shortcut_input.html index e7c6b44..d35415d4 100644 --- a/chrome/browser/resources/extensions/shortcut_input.html +++ b/chrome/browser/resources/extensions/shortcut_input.html
@@ -36,7 +36,8 @@ '$i18nPolymer{shortcutTooManyModifiers}', '$i18nPolymer{shortcutNeedCharacter}')]]" value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]"> - <cr-icon-button id="clear" slot="suffix" class="icon-cancel no-overlap" + <cr-icon-button id="clear" aria-label="$i18nPolymer{clear}" + slot="suffix" class="icon-cancel no-overlap" hidden$="[[computeClearHidden_(capturing_, shortcut)]]" on-click="onClearTap_"></cr-icon-button> </cr-input>
diff --git a/chrome/browser/resources/settings/device_page/device_page.html b/chrome/browser/resources/settings/device_page/device_page.html index e0ab2a8..2db1660 100644 --- a/chrome/browser/resources/settings/device_page/device_page.html +++ b/chrome/browser/resources/settings/device_page/device_page.html
@@ -81,7 +81,7 @@ </settings-storage> </settings-subpage> </template> - <template is="dom-if" if="[[androidRunning_]]"> + <template is="dom-if" if="[[androidEnabled_]]"> <template is="dom-if" route-path="/storage/externalStoragePreferences"> <settings-subpage associated-control="[[$$('#externalStoragePreferencesRow')]]"
diff --git a/chrome/browser/resources/settings/device_page/device_page.js b/chrome/browser/resources/settings/device_page/device_page.js index f009dad..bf0c44a1 100644 --- a/chrome/browser/resources/settings/device_page/device_page.js +++ b/chrome/browser/resources/settings/device_page/device_page.js
@@ -101,7 +101,7 @@ }, /** @private */ - androidRunning_: { + androidEnabled_: { type: Boolean, value: false, }, @@ -124,8 +124,8 @@ settings.DevicePageBrowserProxyImpl.getInstance().initializeStylus(); this.addWebUIListener( - 'storage-android-running-changed', - this.set.bind(this, 'androidRunning_')); + 'storage-android-enabled-changed', + this.set.bind(this, 'androidEnabled_')); }, /**
diff --git a/chrome/browser/resources/settings/device_page/storage.html b/chrome/browser/resources/settings/device_page/storage.html index 00881f1..d074d9c 100644 --- a/chrome/browser/resources/settings/device_page/storage.html +++ b/chrome/browser/resources/settings/device_page/storage.html
@@ -233,7 +233,7 @@ label="$i18n{storageItemOtherUsers}" sub-label="$i18n{storageSizeComputing}"></cr-link-row> </template> - <template is="dom-if" if="[[androidRunning_]]"> + <template is="dom-if" if="[[androidEnabled_]]"> <cr-link-row id="externalStoragePreferences" class="hr" on-click="onExternalStoragePreferencesTap_" label="$i18n{storageExternal}"></cr-link-row>
diff --git a/chrome/browser/resources/settings/device_page/storage.js b/chrome/browser/resources/settings/device_page/storage.js index 2867765..b96c768f 100644 --- a/chrome/browser/resources/settings/device_page/storage.js +++ b/chrome/browser/resources/settings/device_page/storage.js
@@ -44,6 +44,12 @@ }, /** @private */ + androidEnabled_: { + type: Boolean, + value: false, + }, + + /** @private */ androidRunning_: { type: Boolean, value: false, @@ -112,6 +118,9 @@ 'storage-drive-enabled-changed', this.handleDriveEnabledChanged_.bind(this)); this.addWebUIListener( + 'storage-android-enabled-changed', + this.handleAndroidEnabledChanged_.bind(this)); + this.addWebUIListener( 'storage-android-running-changed', this.handleAndroidRunningChanged_.bind(this)); }, @@ -277,6 +286,14 @@ }, /** + * @param {boolean} enabled True if Play Store is enabled. + * @private + */ + handleAndroidEnabledChanged_: function(enabled) { + this.androidEnabled_ = enabled; + }, + + /** * @param {boolean} running True if Android (ARC) is running. * @private */
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 1e1f6c8..bf9797c 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1809,7 +1809,6 @@ "//ash", "//ash/components/shortcut_viewer", "//ash/keyboard/ui", - "//ash/keyboard/ui:mojom", "//ash/public/cpp", "//ash/public/cpp/resources:ash_public_unscaled_resources", "//ash/public/cpp/vector_icons", @@ -3294,8 +3293,6 @@ "app_list/search/arc/arc_playstore_search_result.h", "app_list/search/chrome_search_result.cc", "app_list/search/chrome_search_result.h", - "app_list/search/common/json_response_fetcher.cc", - "app_list/search/common/json_response_fetcher.h", "app_list/search/common/url_icon_source.cc", "app_list/search/common/url_icon_source.h", "app_list/search/crostini/crostini_repository_search_provider.cc",
diff --git a/chrome/browser/ui/app_list/search/common/json_response_fetcher.cc b/chrome/browser/ui/app_list/search/common/json_response_fetcher.cc deleted file mode 100644 index 35847c2..0000000 --- a/chrome/browser/ui/app_list/search/common/json_response_fetcher.cc +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/search/common/json_response_fetcher.h" - -#include <utility> - -#include "base/bind.h" -#include "base/memory/ptr_util.h" -#include "base/values.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/storage_partition.h" -#include "content/public/common/service_manager_connection.h" -#include "net/base/load_flags.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_request_status.h" -#include "services/data_decoder/public/cpp/safe_json_parser.h" -#include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/simple_url_loader.h" -#include "url/gurl.h" - -namespace app_list { - -const char kBadResponse[] = "Bad Web Service search response"; - -JSONResponseFetcher::JSONResponseFetcher( - const Callback& callback, - content::BrowserContext* browser_context) - : callback_(callback), - browser_context_(browser_context), - weak_factory_(this) { - DCHECK(!callback_.is_null()); -} - -JSONResponseFetcher::~JSONResponseFetcher() {} - -void JSONResponseFetcher::Start(const GURL& query_url) { - Stop(); - - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("json_response_fetcher", R"( - semantics { - sender: "JSON Response Fetcher" - description: - "Chrome OS downloads data for a web store result." - trigger: - "When a user initiates a web store search and views results. " - data: - "JSON data comprising search results. " - "No user information is sent." - destination: GOOGLE_OWNED_SERVICE - } - policy { - cookies_allowed: NO - })"); - auto resource_request = std::make_unique<network::ResourceRequest>(); - resource_request->url = query_url; - resource_request->load_flags = - net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DISABLE_CACHE; - simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request), - traffic_annotation); - network::mojom::URLLoaderFactory* loader_factory = - content::BrowserContext::GetDefaultStoragePartition(browser_context_) - ->GetURLLoaderFactoryForBrowserProcess() - .get(); - simple_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( - loader_factory, - base::BindOnce(&JSONResponseFetcher::OnSimpleLoaderComplete, - base::Unretained(this))); -} - -void JSONResponseFetcher::Stop() { - simple_loader_.reset(); - weak_factory_.InvalidateWeakPtrs(); -} - -void JSONResponseFetcher::OnJsonParseSuccess( - std::unique_ptr<base::Value> parsed_json) { - if (!parsed_json->is_dict()) { - OnJsonParseError(kBadResponse); - return; - } - - callback_.Run(base::WrapUnique( - static_cast<base::DictionaryValue*>(parsed_json.release()))); -} - -void JSONResponseFetcher::OnJsonParseError(const std::string& error) { - callback_.Run(std::unique_ptr<base::DictionaryValue>()); -} - -void JSONResponseFetcher::OnSimpleLoaderComplete( - std::unique_ptr<std::string> response_body) { - if (!response_body) { - OnJsonParseError(kBadResponse); - return; - } - - // The parser will call us back via one of the callbacks. - data_decoder::SafeJsonParser::Parse( - content::ServiceManagerConnection::GetForProcess()->GetConnector(), - *response_body, - base::Bind(&JSONResponseFetcher::OnJsonParseSuccess, - weak_factory_.GetWeakPtr()), - base::Bind(&JSONResponseFetcher::OnJsonParseError, - weak_factory_.GetWeakPtr())); -} - -} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/common/json_response_fetcher.h b/chrome/browser/ui/app_list/search/common/json_response_fetcher.h deleted file mode 100644 index 8f2ddc4..0000000 --- a/chrome/browser/ui/app_list/search/common/json_response_fetcher.h +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_JSON_RESPONSE_FETCHER_H_ -#define CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_JSON_RESPONSE_FETCHER_H_ - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" - -class GURL; - -namespace base { -class DictionaryValue; -class Value; -} - -namespace content { -class BrowserContext; -} - -namespace network { -class SimpleURLLoader; -} - -namespace app_list { - -// A class that fetches a JSON formatted response from a server and uses a -// sandboxed utility process to parse it to a DictionaryValue. -// TODO(rkc): Add the ability to give control of handling http failures to -// the consumers of this class. -class JSONResponseFetcher { - public: - // Callback to pass back the parsed json dictionary returned from the server. - // Invoked with NULL if there is an error. - typedef base::Callback<void(std::unique_ptr<base::DictionaryValue>)> Callback; - - JSONResponseFetcher(const Callback& callback, - content::BrowserContext* browser_context); - ~JSONResponseFetcher(); - - // Starts to fetch results for the given |query_url|. - void Start(const GURL& query_url); - void Stop(); - - private: - // Callbacks for SafeJsonParser. - void OnJsonParseSuccess(std::unique_ptr<base::Value> parsed_json); - void OnJsonParseError(const std::string& error); - - // Invoked from SimpleURLLoader after download is complete. - void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body); - - Callback callback_; - content::BrowserContext* browser_context_; - std::unique_ptr<network::SimpleURLLoader> simple_loader_; - base::WeakPtrFactory<JSONResponseFetcher> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(JSONResponseFetcher); -}; - -} // namespace app_list - -#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_JSON_RESPONSE_FETCHER_H_
diff --git a/chrome/browser/ui/app_list/search/mixer.cc b/chrome/browser/ui/app_list/search/mixer.cc index 4a38185..ae14179 100644 --- a/chrome/browser/ui/app_list/search/mixer.cc +++ b/chrome/browser/ui/app_list/search/mixer.cc
@@ -156,19 +156,24 @@ } void Mixer::FetchResults(const base::string16& query) { - if (ranker_) - ranker_->FetchRankings(query); + if (non_app_ranker_) + non_app_ranker_->FetchRankings(query); for (const auto& group : groups_) - group->FetchResults(ranker_.get()); + group->FetchResults(non_app_ranker_.get()); } -void Mixer::SetSearchResultRanker(std::unique_ptr<SearchResultRanker> ranker) { - ranker_ = std::move(ranker); +void Mixer::SetNonAppSearchResultRanker( + std::unique_ptr<SearchResultRanker> ranker) { + non_app_ranker_ = std::move(ranker); +} + +SearchResultRanker* Mixer::GetNonAppSearchResultRanker() { + return non_app_ranker_.get(); } void Mixer::Train(const std::string& id, RankingItemType type) { - if (ranker_) - ranker_->Train(id, type); + if (non_app_ranker_) + non_app_ranker_->Train(id, type); } } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/mixer.h b/chrome/browser/ui/app_list/search/mixer.h index 777443b4..93b766bd 100644 --- a/chrome/browser/ui/app_list/search/mixer.h +++ b/chrome/browser/ui/app_list/search/mixer.h
@@ -50,9 +50,13 @@ // Collects the results, sorts and publishes them. void MixAndPublish(size_t num_max_results, const base::string16& query); - // Sets a SearchResultRanker to re-rank search results before they are + // Sets a SearchResultRanker to re-rank non-app search results before they are // published. - void SetSearchResultRanker(std::unique_ptr<SearchResultRanker> ranker); + void SetNonAppSearchResultRanker(std::unique_ptr<SearchResultRanker> ranker); + + // Get a pointer to the SearchResultRanker owned by this object used for all + // non-app ranking. + SearchResultRanker* GetNonAppSearchResultRanker(); // Handle a training signal. void Train(const std::string& id, RankingItemType type); @@ -88,7 +92,7 @@ Groups groups_; // Adaptive models used for re-ranking search results. - std::unique_ptr<SearchResultRanker> ranker_; + std::unique_ptr<SearchResultRanker> non_app_ranker_; DISALLOW_COPY_AND_ASSIGN(Mixer); };
diff --git a/chrome/browser/ui/app_list/search/search_controller.cc b/chrome/browser/ui/app_list/search/search_controller.cc index 308f13e..2a81d51 100644 --- a/chrome/browser/ui/app_list/search/search_controller.cc +++ b/chrome/browser/ui/app_list/search/search_controller.cc
@@ -51,10 +51,13 @@ AppListControllerDelegate* list_controller, Profile* profile) : mixer_(std::make_unique<Mixer>(model_updater)), - ranker_(std::make_unique<AppSearchResultRanker>( + app_ranker_(std::make_unique<AppSearchResultRanker>( profile->GetPath(), chromeos::ProfileHelper::IsEphemeralUserProfile(profile))), - list_controller_(list_controller) {} + list_controller_(list_controller) { + mixer_->SetNonAppSearchResultRanker( + std::make_unique<SearchResultRanker>(profile)); +} SearchController::~SearchController() {} @@ -150,9 +153,12 @@ return nullptr; } -void SearchController::SetSearchResultRanker( - std::unique_ptr<SearchResultRanker> ranker) { - mixer_->SetSearchResultRanker(std::move(ranker)); +AppSearchResultRanker* SearchController::GetAppSearchResultRanker() { + return app_ranker_.get(); +} + +SearchResultRanker* SearchController::GetNonAppSearchResultRanker() { + return mixer_->GetNonAppSearchResultRanker(); } void SearchController::Train(const std::string& id, RankingItemType type) { @@ -176,8 +182,4 @@ mixer_->Train(id, type); } -AppSearchResultRanker* SearchController::GetSearchResultRanker() { - return ranker_.get(); -} - } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_controller.h b/chrome/browser/ui/app_list/search/search_controller.h index 79e3ca9..a8c70ff 100644 --- a/chrome/browser/ui/app_list/search/search_controller.h +++ b/chrome/browser/ui/app_list/search/search_controller.h
@@ -54,16 +54,16 @@ ChromeSearchResult* FindSearchResult(const std::string& result_id); ChromeSearchResult* GetResultByTitleForTest(const std::string& title); - // Sets a SearchResultRanker to re-rank search results before they are - // published. The Mixer owned by the SearchController will take ownership of - // |ranker|. - void SetSearchResultRanker(std::unique_ptr<SearchResultRanker> ranker); - // Sends training signal to each |providers_| void Train(const std::string& id, RankingItemType type); - // Get the app search result ranker owned by this object. - AppSearchResultRanker* GetSearchResultRanker(); + // Gets the search result ranker owned by this object that is used for ranking + // apps. + AppSearchResultRanker* GetAppSearchResultRanker(); + + // Gets the search result ranker owned by the Mixer that is used for all + // other ranking. + SearchResultRanker* GetNonAppSearchResultRanker(); private: // Invoked when the search results are changed. @@ -77,10 +77,10 @@ // The query associated with the most recent search. base::string16 last_query_; + std::unique_ptr<Mixer> mixer_; using Providers = std::vector<std::unique_ptr<SearchProvider>>; Providers providers_; - std::unique_ptr<Mixer> mixer_; - std::unique_ptr<AppSearchResultRanker> ranker_; + std::unique_ptr<AppSearchResultRanker> app_ranker_; AppListControllerDelegate* list_controller_; DISALLOW_COPY_AND_ASSIGN(SearchController);
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index a816f91..baccde2 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -75,7 +75,8 @@ std::unique_ptr<SearchController> controller = std::make_unique<SearchController>(model_updater, list_controller, profile); - AppSearchResultRanker* ranker = controller->GetSearchResultRanker(); + + AppSearchResultRanker* app_ranker = controller->GetAppSearchResultRanker(); // Add mixer groups. There are four main groups: answer card, apps // and omnibox. Each group has a "soft" maximum number of results. However, if @@ -94,7 +95,7 @@ controller->AddProvider(apps_group_id, std::make_unique<AppSearchProvider>( profile, list_controller, base::DefaultClock::GetInstance(), - model_updater, ranker)); + model_updater, app_ranker)); controller->AddProvider(omnibox_group_id, std::make_unique<OmniboxProvider>( profile, list_controller)); if (app_list_features::IsAnswerCardEnabled()) { @@ -155,7 +156,7 @@ controller->AddProvider( app_shortcut_group_id, std::make_unique<ArcAppShortcutsSearchProvider>( - kMaxAppShortcutResults, profile, list_controller, ranker)); + kMaxAppShortcutResults, profile, list_controller, app_ranker)); } // TODO(https://crbug.com/921429): Put feature switch in ash/public/app_list/ @@ -168,9 +169,6 @@ std::make_unique<CrostiniRepositorySearchProvider>(profile)); } - controller->SetSearchResultRanker( - std::make_unique<SearchResultRanker>(profile)); - return controller; }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc index a069e7f..cdcd116 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc
@@ -49,7 +49,9 @@ } // namespace -SearchResultRanker::SearchResultRanker(Profile* profile) { +SearchResultRanker::SearchResultRanker(Profile* profile) + : enable_zero_state_mixed_types_( + app_list_features::IsZeroStateMixedTypesRankerEnabled()) { if (app_list_features::IsAdaptiveResultRankerEnabled()) { RecurrenceRankerConfigProto config; config.set_min_seconds_between_saves(240u); @@ -73,18 +75,43 @@ } profile_ = profile; - if (auto* notifier = - file_manager::file_tasks::FileTasksNotifier::GetForProfile(profile_)) - notifier->AddObserver(this); - /*file_tasks_observer_.Add( - file_manager::file_tasks::FileTasksNotifierFactory::GetInstance() - ->GetForProfile(profile));*/ + if (enable_zero_state_mixed_types_) { + if (auto* notifier = + file_manager::file_tasks::FileTasksNotifier::GetForProfile( + profile_)) { + notifier->AddObserver(this); + } + + RecurrenceRankerConfigProto config; + config.set_min_seconds_between_saves(240u); + config.set_condition_limit(0u); + config.set_condition_decay(0.5f); + + config.set_target_limit(base::GetFieldTrialParamByFeatureAsInt( + app_list_features::kEnableZeroStateMixedTypesRanker, "target_limit", + 200)); + config.set_target_decay(base::GetFieldTrialParamByFeatureAsDouble( + app_list_features::kEnableZeroStateMixedTypesRanker, "target_decay", + 0.8f)); + + // Despite not changing any fields, this sets the predictor to the default + // predictor. + config.mutable_default_predictor(); + + zero_state_mixed_types_ranker_ = std::make_unique<RecurrenceRanker>( + profile->GetPath().AppendASCII("zero_state_mixed_types_ranker.proto"), + config, chromeos::ProfileHelper::IsEphemeralUserProfile(profile)); + } } SearchResultRanker::~SearchResultRanker() { - if (auto* notifier = - file_manager::file_tasks::FileTasksNotifier::GetForProfile(profile_)) - notifier->RemoveObserver(this); + if (enable_zero_state_mixed_types_) { + if (auto* notifier = + file_manager::file_tasks::FileTasksNotifier::GetForProfile( + profile_)) { + notifier->RemoveObserver(this); + } + } } void SearchResultRanker::FetchRankings(const base::string16& query) { @@ -141,7 +168,15 @@ void SearchResultRanker::OnFilesOpened( const std::vector<FileOpenEvent>& file_opens) { - // TODO(959679): route file open events to a model as training signals. + if (enable_zero_state_mixed_types_) { + DCHECK(zero_state_mixed_types_ranker_); + for (const auto& file_open : file_opens) + zero_state_mixed_types_ranker_->Record(file_open.path.value()); + } +} + +RecurrenceRanker* SearchResultRanker::get_zero_state_mixed_types_ranker() { + return zero_state_mixed_types_ranker_.get(); } } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.h b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.h index 29a1e53..858bf65a 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.h +++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.h
@@ -51,6 +51,8 @@ // file_manager::file_tasks::FileTaskObserver: void OnFilesOpened(const std::vector<FileOpenEvent>& file_opens) override; + RecurrenceRanker* get_zero_state_mixed_types_ranker(); + private: // Records the time of the last call to FetchRankings() and is used to // limit the number of queries to the models within a short timespan. @@ -68,13 +70,15 @@ // affect apps. std::unique_ptr<RecurrenceRanker> results_list_group_ranker_; + // Ranks files and previous queries for launcher zero-state. + std::unique_ptr<RecurrenceRanker> zero_state_mixed_types_ranker_; + // TODO(931149): Move the AppSearchResultRanker instance and associated logic // to here. Profile* profile_; - /*ScopedObserver<file_manager::file_tasks::FileTasksNotifier, - file_manager::file_tasks::FileTasksObserver> - file_tasks_observer_{this};*/ + + const bool enable_zero_state_mixed_types_; }; } // namespace app_list
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc index 2c487b6c..da2c62aa 100644 --- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc +++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.cc
@@ -7,8 +7,8 @@ #include <utility> #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/resources/keyboard_resource_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h" #include "base/callback.h"
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h index 43359a8b..2912fde 100644 --- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h +++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h
@@ -9,7 +9,7 @@ #include <set> #include <vector> -#include "ash/keyboard/ui/public/keyboard_config.mojom.h" +#include "ash/public/interfaces/keyboard_config.mojom.h" #include "ash/public/interfaces/keyboard_controller.mojom.h" #include "base/callback_forward.h" #include "base/macros.h"
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc index 326cdee..9c5401d43 100644 --- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -3,8 +3,8 @@ // found in the LICENSE file. #include "ash/keyboard/ui/keyboard_controller.h" -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/resources/keyboard_resource_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/macros.h"
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc index 9d497cf..4b009f2 100644 --- a/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/keyboard/ui/public/keyboard_switches.h" #include "ash/keyboard/ui/resources/keyboard_resource_util.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "base/command_line.h" #include "base/files/file.h" #include "base/run_loop.h"
diff --git a/chrome/browser/ui/cocoa/browser_window_command_handler.mm b/chrome/browser/ui/cocoa/browser_window_command_handler.mm index a32d7ff..f470b1d 100644 --- a/chrome/browser/ui/cocoa/browser_window_command_handler.mm +++ b/chrome/browser/ui/cocoa/browser_window_command_handler.mm
@@ -13,10 +13,10 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #include "content/public/browser/web_contents.h" #import "ui/base/cocoa/cocoa_base_utils.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace {
diff --git a/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm b/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm index 8a7192c..ce8f820 100644 --- a/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm +++ b/chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm
@@ -6,12 +6,12 @@ #include "base/logging.h" #include "chrome/browser/global_keyboard_shortcuts_mac.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #include "content/public/browser/native_web_keyboard_event.h" #include "ui/base/accelerators/accelerator_manager.h" #include "ui/content_accelerators/accelerator_util.h" #include "ui/views/widget/widget.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" @implementation ChromeCommandDispatcherDelegate
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm index 69456e6..833e0837 100644 --- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm +++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.mm
@@ -5,8 +5,8 @@ #import "chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller_views.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "ui/views/cocoa/bridged_native_widget_host_impl.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" @implementation FullscreenToolbarControllerViews
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h index a5b0e85..a6cb956b 100644 --- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h +++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.h
@@ -12,8 +12,8 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "components/app_modal/native_app_modal_dialog.h" +#include "components/remote_cocoa/app_shim/alert.h" #include "components/remote_cocoa/common/alert.mojom.h" -#include "ui/views_bridge_mac/alert.h" class PopunderPreventer;
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm index e739556..29cc502 100644 --- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm +++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
@@ -17,6 +17,7 @@ #include "components/app_modal/javascript_app_modal_dialog.h" #include "components/app_modal/javascript_dialog_manager.h" #include "components/app_modal/javascript_native_dialog_factory.h" +#include "components/remote_cocoa/app_shim/alert.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" @@ -26,7 +27,6 @@ #include "ui/strings/grit/ui_strings.h" #include "ui/views/cocoa/bridge_factory_host.h" #include "ui/views/cocoa/bridged_native_widget_host_impl.h" -#include "ui/views_bridge_mac/alert.h" using views_bridge_mac::mojom::AlertDisposition;
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm index 0c6c6bf..2610388 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller_browsertest.mm
@@ -14,6 +14,7 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/prefs/pref_service.h" +#include "components/remote_cocoa/app_shim/window_touch_bar_delegate.h" #include "components/search_engines/default_search_manager.h" #include "components/search_engines/search_engines_test_util.h" #include "components/search_engines/template_url_data.h" @@ -21,7 +22,6 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "testing/gtest_mac.h" -#include "ui/views_bridge_mac/window_touch_bar_delegate.h" // TODO(spqchan): Write tests that will check for page load and bookmark // updates.
diff --git a/chrome/browser/ui/extensions/OWNERS b/chrome/browser/ui/extensions/OWNERS index b8cca04d..dd0cbe0 100644 --- a/chrome/browser/ui/extensions/OWNERS +++ b/chrome/browser/ui/extensions/OWNERS
@@ -1,8 +1,15 @@ # App-y stuff benwells@chromium.org + +per-file bookmark_app_*=alancutter@chromium.org +per-file bookmark_app_*=mgiuca@chromium.org +per-file bookmark_app_*=ortuno@chromium.org per-file hosted_app_*=alancutter@chromium.org per-file hosted_app_*=mgiuca@chromium.org per-file hosted_app_*=ortuno@chromium.org +per-file pwa_*=alancutter@chromium.org +per-file pwa_*=mgiuca@chromium.org +per-file pwa_*=ortuno@chromium.org # Extension-y stuff finnur@chromium.org
diff --git a/chrome/browser/ui/views/apps/app_window_native_widget_mac.mm b/chrome/browser/ui/views/apps/app_window_native_widget_mac.mm index 2df0332..2f9db3846 100644 --- a/chrome/browser/ui/views/apps/app_window_native_widget_mac.mm +++ b/chrome/browser/ui/views/apps/app_window_native_widget_mac.mm
@@ -7,10 +7,10 @@ #import <Cocoa/Cocoa.h> #import "chrome/browser/ui/cocoa/apps/titlebar_background_view.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" #include "components/remote_cocoa/common/bridged_native_widget.mojom.h" #include "extensions/browser/app_window/native_app_window.h" #import "ui/base/cocoa/window_size_constants.h" -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" AppWindowNativeWidgetMac::AppWindowNativeWidgetMac( views::Widget* widget,
diff --git a/chrome/browser/ui/views/extensions/OWNERS b/chrome/browser/ui/views/extensions/OWNERS index 061ecf1..87bcf12 100644 --- a/chrome/browser/ui/views/extensions/OWNERS +++ b/chrome/browser/ui/views/extensions/OWNERS
@@ -1,6 +1,4 @@ -benwells@chromium.org -finnur@chromium.org -rdevlin.cronin@chromium.org +file://chrome/browser/ui/extensions/OWNERS # TEAM: extensions-dev@chromium.org # COMPONENT: Platform>Extensions
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.mm b/chrome/browser/ui/views/frame/browser_frame_mac.mm index 418ad1db..fb6fb15 100644 --- a/chrome/browser/ui/views/frame/browser_frame_mac.mm +++ b/chrome/browser/ui/views/frame/browser_frame_mac.mm
@@ -23,6 +23,9 @@ #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/bookmarks/common/bookmark_pref_names.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" +#import "components/remote_cocoa/app_shim/window_touch_bar_delegate.h" #include "components/remote_cocoa/common/bridge_factory.mojom.h" #include "components/remote_cocoa/common/bridged_native_widget.mojom.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" @@ -31,9 +34,6 @@ #import "ui/base/cocoa/window_size_constants.h" #include "ui/base/l10n/l10n_util.h" #import "ui/views/cocoa/bridged_native_widget_host_impl.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" -#import "ui/views_bridge_mac/window_touch_bar_delegate.h" namespace {
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc index 03bfe52..21966cd 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc +++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -6,7 +6,7 @@ #include <memory> -#include "ash/keyboard/ui/public/keyboard_switches.h" +#include "ash/public/cpp/keyboard/keyboard_switches.h" #include "ash/public/cpp/test/shell_test_api.h" #include "base/bind_helpers.h" #include "base/files/file_util.h"
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc index d0518761..1e17ab3 100644 --- a/chrome/browser/ui/webui/downloads/downloads_ui.cc +++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -39,6 +39,7 @@ #include "ui/base/accelerators/accelerator.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/resources/grit/webui_resources.h" using content::BrowserContext; using content::DownloadManager; @@ -138,8 +139,9 @@ IDR_DOWNLOADS_IMAGES_NO_DOWNLOADS_SVG); source->AddResourcePath("downloads.mojom-lite.js", IDR_DOWNLOADS_MOJO_LITE_JS); - #if BUILDFLAG(OPTIMIZE_WEBUI) + source->AddResourcePath("downloads.mojom-lite.html", + IDR_DOWNLOADS_MOJO_LITE_HTML); source->AddResourcePath("crisper.js", IDR_DOWNLOADS_CRISPER_JS); source->SetDefaultResource(IDR_DOWNLOADS_VULCANIZED_HTML); #else @@ -147,6 +149,9 @@ source->AddResourcePath(kDownloadsResources[i].name, kDownloadsResources[i].value); } + // Add the subpage loader, to load subpages in non-optimized builds. + source->AddResourcePath("subpage_loader.html", IDR_WEBUI_HTML_SUBPAGE_LOADER); + source->AddResourcePath("subpage_loader.js", IDR_WEBUI_JS_SUBPAGE_LOADER); source->SetDefaultResource(IDR_DOWNLOADS_DOWNLOADS_HTML); #endif
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 2a6e521..48427bf0 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -118,6 +118,7 @@ {"back", IDS_ACCNAME_BACK}, {"cancel", IDS_CANCEL}, {"close", IDS_CLOSE}, + {"clear", IDS_CLEAR}, {"confirm", IDS_CONFIRM}, {"controlledSettingPolicy", IDS_CONTROLLED_SETTING_POLICY}, {"done", IDS_DONE},
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc index eec0877..522ef6b 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -34,6 +34,7 @@ #include "chromeos/cryptohome/cryptohome_util.h" #include "chromeos/dbus/cryptohome/cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "components/arc/arc_prefs.h" #include "components/arc/arc_service_manager.h" #include "components/arc/arc_util.h" #include "components/arc/session/arc_bridge_service.h" @@ -111,6 +112,13 @@ } void StorageHandler::OnJavascriptAllowed() { + pref_change_registrar_.Init(profile_->GetPrefs()); + pref_change_registrar_.Add( + arc::prefs::kArcEnabled, + base::BindRepeating(&StorageHandler::OnArcEnabledChanged, + // |this| always outlives |pref_change_registrar_|. + base::Unretained(this))); + // Start observing the mojo connection UpdateAndroidSize() relies on. Note // that OnConnectionReady() will be called immediately if the connection has // already been established. @@ -131,6 +139,9 @@ ->arc_bridge_service() ->storage_manager() ->RemoveObserver(this); + + // Stop observing the pref changes for the same reason. + pref_change_registrar_.RemoveAll(); } void StorageHandler::HandleUpdateStorageInfo(const base::ListValue* args) { @@ -143,6 +154,7 @@ UpdateAndroidSize(); UpdateCrostiniSize(); UpdateOtherUsersSize(); + OnArcEnabledChanged(); } void StorageHandler::HandleOpenDownloads( @@ -428,5 +440,11 @@ FireWebUIListener("storage-android-running-changed", base::Value(false)); } +void StorageHandler::OnArcEnabledChanged() { + FireWebUIListener( + "storage-android-enabled-changed", + base::Value(arc::IsArcPlayStoreEnabledForProfile(profile_))); +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h index b8ac8464..423c7fc 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
@@ -19,6 +19,7 @@ #include "components/arc/common/storage_manager.mojom.h" #include "components/arc/session/connection_observer.h" #include "components/arc/storage_manager/arc_storage_manager.h" +#include "components/prefs/pref_change_registrar.h" #include "components/user_manager/user.h" class Profile; @@ -110,6 +111,9 @@ // Callback to save the fetched user sizes and update the UI. void OnGetOtherUserSize(base::Optional<cryptohome::BaseReply> reply); + // Callback to update ARC related UI. + void OnArcEnabledChanged(); + // Total size of cache data in browsing data. int64_t browser_cache_size_; @@ -145,6 +149,10 @@ bool is_android_running_; Profile* const profile_; + + // Used to watch ARC prefs for changes so the UI can be notified. + PrefChangeRegistrar pref_change_registrar_; + base::WeakPtrFactory<StorageHandler> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(StorageHandler);
diff --git a/chrome/browser/web_applications/components/install_finalizer.h b/chrome/browser/web_applications/components/install_finalizer.h index 78eeffe..8235135 100644 --- a/chrome/browser/web_applications/components/install_finalizer.h +++ b/chrome/browser/web_applications/components/install_finalizer.h
@@ -28,6 +28,8 @@ public: using InstallFinalizedCallback = base::OnceCallback<void(const AppId& app_id, InstallResultCode code)>; + using UninstallExternalWebAppCallback = + base::OnceCallback<void(bool uninstalled)>; using CreateOsShortcutsCallback = base::OnceCallback<void(bool shortcuts_created)>; @@ -46,6 +48,11 @@ const FinalizeOptions& options, InstallFinalizedCallback callback) = 0; + // Removes the external app for |app_url| from disk and registrar. Fails if + // there is no installed external app for |app_url|. + virtual void UninstallExternalWebApp(const GURL& app_url, + UninstallExternalWebAppCallback) = 0; + virtual bool CanCreateOsShortcuts() const = 0; virtual void CreateOsShortcuts(const AppId& app_id, bool add_to_desktop,
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn index bea8a41..b523ab8 100644 --- a/chrome/browser/web_applications/extensions/BUILD.gn +++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -16,8 +16,6 @@ "bookmark_app_registrar.h", "bookmark_app_tab_helper.cc", "bookmark_app_tab_helper.h", - "bookmark_app_uninstaller.cc", - "bookmark_app_uninstaller.h", "bookmark_app_util.cc", "bookmark_app_util.h", "pending_bookmark_app_manager.cc", @@ -46,7 +44,6 @@ sources = [ "bookmark_app_install_finalizer_unittest.cc", "bookmark_app_installation_task_unittest.cc", - "bookmark_app_uninstaller_unittest.cc", "bookmark_app_util_unittest.cc", "externally_installed_web_app_prefs_unittest.cc", "install_manager_bookmark_app_unittest.cc",
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc index f71447f8..5c1875f 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
@@ -23,6 +23,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/install/crx_install_error.h" +#include "extensions/browser/uninstall_reason.h" #include "extensions/common/extension.h" #include "extensions/common/extension_id.h" #include "extensions/common/extension_set.h" @@ -70,7 +71,7 @@ } // namespace BookmarkAppInstallFinalizer::BookmarkAppInstallFinalizer(Profile* profile) - : profile_(profile) { + : profile_(profile), externally_installed_app_prefs_(profile->GetPrefs()) { crx_installer_factory_ = base::BindRepeating([](Profile* profile) { ExtensionService* extension_service = ExtensionSystem::Get(profile)->extension_service(); @@ -124,6 +125,41 @@ crx_installer->InstallWebApp(web_app_info); } +void BookmarkAppInstallFinalizer::UninstallExternalWebApp( + const GURL& app_url, + UninstallExternalWebAppCallback callback) { + base::Optional<web_app::AppId> app_id = + externally_installed_app_prefs_.LookupAppId(app_url); + if (!app_id.has_value()) { + LOG(WARNING) << "Couldn't uninstall app with url " << app_url + << "; No corresponding extension for url."; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), false)); + return; + } + + if (!ExtensionRegistry::Get(profile_)->enabled_extensions().GetByID( + app_id.value())) { + LOG(WARNING) << "Couldn't uninstall app with url " << app_url + << "; Extension not installed."; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), false)); + return; + } + + base::string16 error; + bool uninstalled = + ExtensionSystem::Get(profile_)->extension_service()->UninstallExtension( + app_id.value(), UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION, &error); + + if (!uninstalled) { + LOG(WARNING) << "Couldn't uninstall app with url " << app_url << ". " + << error; + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), uninstalled)); +} + bool BookmarkAppInstallFinalizer::CanCreateOsShortcuts() const { return CanBookmarkAppCreateOsShortcuts(); }
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h index 42685c5..7956bd80 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "chrome/browser/web_applications/components/externally_installed_web_app_prefs.h" #include "chrome/browser/web_applications/components/install_finalizer.h" class Profile; @@ -29,6 +30,9 @@ void FinalizeInstall(const WebApplicationInfo& web_app_info, const FinalizeOptions& options, InstallFinalizedCallback callback) override; + void UninstallExternalWebApp( + const GURL& app_url, + UninstallExternalWebAppCallback callback) override; bool CanCreateOsShortcuts() const override; void CreateOsShortcuts(const web_app::AppId& app_id, bool add_to_desktop, @@ -53,6 +57,7 @@ private: CrxInstallerFactory crx_installer_factory_; Profile* profile_; + web_app::ExternallyInstalledWebAppPrefs externally_installed_app_prefs_; DISALLOW_COPY_AND_ASSIGN(BookmarkAppInstallFinalizer); };
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc index 2852cd8..f2644fe 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer_unittest.cc
@@ -24,6 +24,7 @@ #include "chrome/test/base/testing_profile.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_registry_observer.h" #include "extensions/browser/install/crx_install_error.h" #include "extensions/common/constants.h" #include "extensions/common/extension_id.h" @@ -34,6 +35,7 @@ namespace { const GURL kWebAppUrl("https://foo.example"); +const GURL kAlternateWebAppUrl("https://bar.example"); const char kWebAppTitle[] = "Foo Title"; } // namespace @@ -91,6 +93,45 @@ false /* autoupdate_enabled */); } + web_app::AppId InstallExternalApp(BookmarkAppInstallFinalizer* finalizer, + const GURL& app_url) { + auto info = std::make_unique<WebApplicationInfo>(); + info->app_url = app_url; + info->title = base::ASCIIToUTF16(kWebAppTitle); + + web_app::InstallFinalizer::FinalizeOptions options; + options.policy_installed = true; + + web_app::AppId app_id; + base::RunLoop run_loop; + finalizer->FinalizeInstall( + *info, options, + base::BindLambdaForTesting([&](const web_app::AppId& installed_app_id, + web_app::InstallResultCode code) { + ASSERT_EQ(web_app::InstallResultCode::kSuccess, code); + app_id = installed_app_id; + run_loop.Quit(); + })); + run_loop.Run(); + + web_app::ExternallyInstalledWebAppPrefs(profile()->GetPrefs()) + .Insert(app_url, app_id, web_app::InstallSource::kExternalPolicy); + + return app_id; + } + + void SimulateExternalAppUninstalledByUser(const web_app::AppId& app_id) { + ExtensionRegistry::Get(profile())->RemoveEnabled(app_id); + auto* extension_prefs = ExtensionPrefs::Get(profile()); + extension_prefs->OnExtensionUninstalled(app_id, Manifest::EXTERNAL_POLICY, + false /* external_uninstall */); + DCHECK(extension_prefs->IsExternalExtensionUninstalled(app_id)); + } + + const ExtensionSet& enabled_extensions() { + return ExtensionRegistry::Get(profile())->enabled_extensions(); + } + private: DISALLOW_COPY_AND_ASSIGN(BookmarkAppInstallFinalizerTest); }; @@ -336,6 +377,113 @@ installer.CanSkipAppUpdateForSync(app_id, info_with_diff_description)); } +TEST_F(BookmarkAppInstallFinalizerTest, UninstallExternalWebApp_Successful) { + BookmarkAppInstallFinalizer finalizer(profile()); + + InstallExternalApp(&finalizer, kWebAppUrl); + ASSERT_EQ(1u, enabled_extensions().size()); + + base::RunLoop run_loop; + finalizer.UninstallExternalWebApp( + kWebAppUrl, base::BindLambdaForTesting([&](bool uninstalled) { + EXPECT_TRUE(uninstalled); + EXPECT_EQ(0u, enabled_extensions().size()); + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_F(BookmarkAppInstallFinalizerTest, UninstallExternalWebApp_Multiple) { + BookmarkAppInstallFinalizer finalizer(profile()); + + auto foo_app_id = InstallExternalApp(&finalizer, kWebAppUrl); + auto bar_app_id = InstallExternalApp(&finalizer, kAlternateWebAppUrl); + ASSERT_EQ(2u, enabled_extensions().size()); + + // Uninstall one app. + { + base::RunLoop run_loop; + finalizer.UninstallExternalWebApp( + kWebAppUrl, base::BindLambdaForTesting([&](bool uninstalled) { + EXPECT_TRUE(uninstalled); + run_loop.Quit(); + })); + run_loop.Run(); + } + + EXPECT_EQ(1u, enabled_extensions().size()); + EXPECT_TRUE(enabled_extensions().Contains(bar_app_id)); + + // Uninstall the second app. + { + base::RunLoop run_loop; + finalizer.UninstallExternalWebApp( + kAlternateWebAppUrl, base::BindLambdaForTesting([&](bool uninstalled) { + EXPECT_TRUE(uninstalled); + run_loop.Quit(); + })); + run_loop.Run(); + } + EXPECT_EQ(0u, enabled_extensions().size()); +} + +TEST_F(BookmarkAppInstallFinalizerTest, + UninstallExternalWebApp_UninstalledExternalApp) { + BookmarkAppInstallFinalizer finalizer(profile()); + + auto app_id = InstallExternalApp(&finalizer, kWebAppUrl); + SimulateExternalAppUninstalledByUser(app_id); + + base::RunLoop run_loop; + finalizer.UninstallExternalWebApp( + kWebAppUrl, base::BindLambdaForTesting([&](bool uninstalled) { + EXPECT_FALSE(uninstalled); + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_F(BookmarkAppInstallFinalizerTest, + UninstallExternalWebApp_FailsNeverInstalled) { + BookmarkAppInstallFinalizer finalizer(profile()); + base::RunLoop run_loop; + finalizer.UninstallExternalWebApp( + kWebAppUrl, base::BindLambdaForTesting([&](bool uninstalled) { + EXPECT_FALSE(uninstalled); + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_F(BookmarkAppInstallFinalizerTest, + UninstallExternalWebApp_FailsAlreadyUninstalled) { + BookmarkAppInstallFinalizer finalizer(profile()); + + InstallExternalApp(&finalizer, kWebAppUrl); + + // Uninstall the app. + { + base::RunLoop run_loop; + finalizer.UninstallExternalWebApp( + kWebAppUrl, base::BindLambdaForTesting([&](bool uninstalled) { + EXPECT_TRUE(uninstalled); + run_loop.Quit(); + })); + run_loop.Run(); + } + + // Try to uninstall it again. + { + base::RunLoop run_loop; + finalizer.UninstallExternalWebApp( + kWebAppUrl, base::BindLambdaForTesting([&](bool uninstalled) { + EXPECT_FALSE(uninstalled); + run_loop.Quit(); + })); + run_loop.Run(); + } +} + TEST_F(BookmarkAppInstallFinalizerTest, NotLocallyInstalled) { BookmarkAppInstallFinalizer installer(profile());
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc index 3454417..5005acb 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
@@ -178,6 +178,12 @@ std::move(callback))); } + void UninstallExternalWebApp( + const GURL& app_url, + UninstallExternalWebAppCallback callback) override { + NOTREACHED(); + } + bool CanCreateOsShortcuts() const override { return true; } void CreateOsShortcuts(const web_app::AppId& app_id,
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.cc b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.cc deleted file mode 100644 index 74e9021..0000000 --- a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h" - -#include "base/optional.h" -#include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/web_applications/components/app_registrar.h" -#include "extensions/browser/extension_system.h" -#include "extensions/browser/uninstall_reason.h" - -namespace extensions { - -BookmarkAppUninstaller::BookmarkAppUninstaller(Profile* profile, - web_app::AppRegistrar* registrar) - : profile_(profile), - registrar_(registrar), - externally_installed_app_prefs_(profile->GetPrefs()) {} - -BookmarkAppUninstaller::~BookmarkAppUninstaller() = default; - -void BookmarkAppUninstaller::UninstallApp(const GURL& app_url, - UninstallCallback callback) { - base::Optional<web_app::AppId> app_id = - externally_installed_app_prefs_.LookupAppId(app_url); - if (!app_id.has_value()) { - LOG(WARNING) << "Couldn't uninstall app with url " << app_url - << "; No corresponding extension for url."; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), false)); - return; - } - - if (!registrar_->IsInstalled(app_id.value())) { - LOG(WARNING) << "Couldn't uninstall app with url " << app_url - << "; Extension not installed."; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), false)); - return; - } - - base::string16 error; - bool uninstalled = - ExtensionSystem::Get(profile_)->extension_service()->UninstallExtension( - app_id.value(), UNINSTALL_REASON_ORPHANED_EXTERNAL_EXTENSION, &error); - - if (!uninstalled) { - LOG(WARNING) << "Couldn't uninstall app with url " << app_url << ". " - << error; - } - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), uninstalled)); -} - -} // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h deleted file mode 100644 index a8ee388..0000000 --- a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_UNINSTALLER_H_ -#define CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_UNINSTALLER_H_ - -#include "chrome/browser/web_applications/components/externally_installed_web_app_prefs.h" - -class Profile; -class GURL; - -namespace web_app { -class AppRegistrar; -} - -namespace extensions { - -class BookmarkAppUninstaller { - public: - using UninstallCallback = base::OnceCallback<void(bool uninstalled)>; - - BookmarkAppUninstaller(Profile* profile, web_app::AppRegistrar* registrar); - virtual ~BookmarkAppUninstaller(); - - // Runs |callback| with true if the app with |app_url| was successfully - // uninstalled. Runs callback with false if the app doesn't not exist, or the - // app failed to be uninstalled. - virtual void UninstallApp(const GURL& app_url, UninstallCallback callback); - - private: - Profile* profile_; - web_app::AppRegistrar* registrar_; - web_app::ExternallyInstalledWebAppPrefs externally_installed_app_prefs_; -}; - -} // namespace extensions - -#endif // CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_UNINSTALLER_H_
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc deleted file mode 100644 index 754ba12c..0000000 --- a/chrome/browser/web_applications/extensions/bookmark_app_uninstaller_unittest.cc +++ /dev/null
@@ -1,216 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/scoped_observer.h" -#include "base/test/bind_test_util.h" -#include "chrome/browser/extensions/test_extension_system.h" -#include "chrome/browser/web_applications/components/web_app_constants.h" -#include "chrome/browser/web_applications/extensions/bookmark_app_registrar.h" -#include "chrome/browser/web_applications/test/test_app_registrar.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "chrome/test/base/testing_profile.h" -#include "components/crx_file/id_util.h" -#include "content/public/test/test_utils.h" -#include "extensions/browser/extension_prefs.h" -#include "extensions/browser/extension_registry.h" -#include "extensions/browser/extension_registry_observer.h" -#include "extensions/common/extension_builder.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace extensions { - -namespace { - -const GURL kFooWebAppUrl("https://foo.example"); -const GURL kBarWebAppUrl("https://bar.example"); - -class TestExtensionRegistryObserver : public ExtensionRegistryObserver { - public: - explicit TestExtensionRegistryObserver(ExtensionRegistry* registry) { - extension_registry_observer_.Add(registry); - } - - ~TestExtensionRegistryObserver() override = default; - - const std::vector<std::string>& uninstalled_extension_ids() { - return uninstalled_extension_ids_; - } - - void ResetResults() { uninstalled_extension_ids_.clear(); } - - // ExtensionRegistryObserver - void OnExtensionUninstalled(content::BrowserContext* browser_context, - const Extension* extension, - UninstallReason reason) override { - uninstalled_extension_ids_.push_back(extension->id()); - } - - private: - std::vector<std::string> uninstalled_extension_ids_; - - ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> - extension_registry_observer_{this}; - - DISALLOW_COPY_AND_ASSIGN(TestExtensionRegistryObserver); -}; - -std::string GenerateFakeAppId(const GURL& url) { - return crx_file::id_util::GenerateId("fake_app_id_for:" + url.spec()); -} - -} // namespace - -class BookmarkAppUninstallerTest : public ChromeRenderViewHostTestHarness { - public: - BookmarkAppUninstallerTest() = default; - ~BookmarkAppUninstallerTest() override = default; - - void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - - TestExtensionSystem* test_system = - static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile())); - test_system->CreateExtensionService(base::CommandLine::ForCurrentProcess(), - profile()->GetPath(), - false /* autoupdate_enabled */); - test_extension_registry_observer_ = - std::make_unique<TestExtensionRegistryObserver>( - ExtensionRegistry::Get(profile())); - - registrar_ = std::make_unique<BookmarkAppRegistrar>(profile()); - - uninstaller_ = - std::make_unique<BookmarkAppUninstaller>(profile(), registrar_.get()); - } - - void TearDown() override { - // Delete the observer before ExtensionRegistry is deleted. - test_extension_registry_observer_.reset(); - ChromeRenderViewHostTestHarness::TearDown(); - } - - std::string SimulateInstalledApp(const GURL& app_url) { - std::string app_id = GenerateFakeAppId(app_url); - - auto extension = ExtensionBuilder("FooBar") - .SetLocation(Manifest::EXTERNAL_POLICY) - .SetID(app_id) - .Build(); - ExtensionRegistry::Get(profile())->AddEnabled(extension); - web_app::ExternallyInstalledWebAppPrefs(profile()->GetPrefs()) - .Insert(app_url, app_id, web_app::InstallSource::kExternalPolicy); - return app_id; - } - - void SimulateExternalAppUninstalledByUser(const GURL& app_url) { - const std::string app_id = GenerateFakeAppId(app_url); - ExtensionRegistry::Get(profile())->RemoveEnabled(app_id); - ExtensionPrefs::Get(profile())->OnExtensionUninstalled( - app_id, Manifest::EXTERNAL_POLICY, false /* external_uninstall */); - } - - bool UninstallAppAndWait(const GURL& app_url) { - base::RunLoop run_loop; - base::Optional<bool> result; - uninstaller().UninstallApp( - app_url, base::BindLambdaForTesting([&](bool uninstalled) { - result = uninstalled; - run_loop.Quit(); - })); - run_loop.Run(); - return result.value(); - } - - void ResetResults() { test_extension_registry_observer_->ResetResults(); } - - BookmarkAppUninstaller& uninstaller() { return *uninstaller_; } - - const std::vector<std::string>& uninstalled_extension_ids() { - return test_extension_registry_observer_->uninstalled_extension_ids(); - } - - const ExtensionSet& enabled_extensions() { - return ExtensionRegistry::Get(profile())->enabled_extensions(); - } - - private: - std::unique_ptr<TestExtensionRegistryObserver> - test_extension_registry_observer_; - - std::unique_ptr<BookmarkAppRegistrar> registrar_; - std::unique_ptr<BookmarkAppUninstaller> uninstaller_; - - DISALLOW_COPY_AND_ASSIGN(BookmarkAppUninstallerTest); -}; - -TEST_F(BookmarkAppUninstallerTest, Uninstall_Successful) { - SimulateInstalledApp(kFooWebAppUrl); - ASSERT_EQ(1u, enabled_extensions().size()); - - EXPECT_TRUE(UninstallAppAndWait(kFooWebAppUrl)); - content::RunAllTasksUntilIdle(); - - EXPECT_EQ(1u, uninstalled_extension_ids().size()); - EXPECT_EQ(0u, enabled_extensions().size()); -} - -TEST_F(BookmarkAppUninstallerTest, Uninstall_Multiple) { - auto foo_app_id = SimulateInstalledApp(kFooWebAppUrl); - auto bar_app_id = SimulateInstalledApp(kBarWebAppUrl); - ASSERT_EQ(2u, enabled_extensions().size()); - - EXPECT_TRUE(UninstallAppAndWait(kBarWebAppUrl)); - content::RunAllTasksUntilIdle(); - - EXPECT_EQ(1u, uninstalled_extension_ids().size()); - EXPECT_EQ(1u, enabled_extensions().size()); - EXPECT_FALSE(enabled_extensions().Contains(bar_app_id)); - EXPECT_TRUE(enabled_extensions().Contains(foo_app_id)); - - ResetResults(); - - EXPECT_TRUE(UninstallAppAndWait(kFooWebAppUrl)); - content::RunAllTasksUntilIdle(); - - EXPECT_EQ(1u, uninstalled_extension_ids().size()); - EXPECT_TRUE(enabled_extensions().is_empty()); -} - -TEST_F(BookmarkAppUninstallerTest, Uninstall_UninstalledExternalApp) { - SimulateInstalledApp(kFooWebAppUrl); - SimulateExternalAppUninstalledByUser(kFooWebAppUrl); - - EXPECT_FALSE(UninstallAppAndWait(kFooWebAppUrl)); -} - -// Tests trying to uninstall an app that was never installed. -TEST_F(BookmarkAppUninstallerTest, Uninstall_FailsNeverInstalled) { - EXPECT_FALSE(UninstallAppAndWait(kFooWebAppUrl)); -} - -// Tests trying to uninstall an app that was previously uninstalled. -TEST_F(BookmarkAppUninstallerTest, Uninstall_FailsAlreadyUninstalled) { - SimulateInstalledApp(kFooWebAppUrl); - - EXPECT_TRUE(UninstallAppAndWait(kFooWebAppUrl)); - content::RunAllTasksUntilIdle(); - - EXPECT_EQ(1u, uninstalled_extension_ids().size()); - EXPECT_TRUE(enabled_extensions().is_empty()); - - ResetResults(); - - EXPECT_FALSE(UninstallAppAndWait(kFooWebAppUrl)); - content::RunAllTasksUntilIdle(); - - EXPECT_EQ(0u, uninstalled_extension_ids().size()); -} - -} // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc index 3be7d49..27045fe5 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
@@ -52,8 +52,6 @@ : profile_(profile), registrar_(registrar), install_finalizer_(install_finalizer), - uninstaller_( - std::make_unique<BookmarkAppUninstaller>(profile_, registrar_)), externally_installed_app_prefs_(profile->GetPrefs()), url_loader_(std::make_unique<web_app::WebAppUrlLoader>()), task_factory_(base::BindRepeating(&InstallationTaskCreateWrapper)) {} @@ -93,7 +91,7 @@ std::vector<GURL> uninstall_urls, const UninstallCallback& callback) { for (auto& url : uninstall_urls) { - uninstaller_->UninstallApp( + install_finalizer_->UninstallExternalWebApp( url, base::BindOnce( [](const UninstallCallback& callback, const GURL& app_url, bool uninstalled) { callback.Run(app_url, uninstalled); }, @@ -124,11 +122,6 @@ task_factory_ = std::move(task_factory); } -void PendingBookmarkAppManager::SetUninstallerForTesting( - std::unique_ptr<BookmarkAppUninstaller> uninstaller) { - uninstaller_ = std::move(uninstaller); -} - void PendingBookmarkAppManager::SetUrlLoaderForTesting( std::unique_ptr<web_app::WebAppUrlLoader> url_loader) { url_loader_ = std::move(url_loader); @@ -272,7 +265,7 @@ install_options.url); if (app_id.has_value() && registrar_->IsInstalled(app_id.value())) { - uninstaller_->UninstallApp( + install_finalizer_->UninstallExternalWebApp( install_options.url, base::BindOnce(&PendingBookmarkAppManager::OnPlaceholderUninstalled, weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h index 428978f3..ef0361b 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h
@@ -19,7 +19,6 @@ #include "chrome/browser/web_applications/components/pending_app_manager.h" #include "chrome/browser/web_applications/components/web_app_url_loader.h" #include "chrome/browser/web_applications/extensions/bookmark_app_installation_task.h" -#include "chrome/browser/web_applications/extensions/bookmark_app_uninstaller.h" class GURL; class Profile; @@ -73,8 +72,6 @@ web_app::InstallSource install_source) const override; void SetTaskFactoryForTesting(TaskFactory task_factory); - void SetUninstallerForTesting( - std::unique_ptr<BookmarkAppUninstaller> uninstaller); void SetUrlLoaderForTesting( std::unique_ptr<web_app::WebAppUrlLoader> url_loader); @@ -102,7 +99,6 @@ Profile* profile_; web_app::AppRegistrar* registrar_; web_app::InstallFinalizer* install_finalizer_; - std::unique_ptr<BookmarkAppUninstaller> uninstaller_; web_app::ExternallyInstalledWebAppPrefs externally_installed_app_prefs_; // unique_ptr so that it can be replaced in tests.
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc index 711b92bc..69300c2 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
@@ -146,58 +146,6 @@ DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppInstallationTask); }; -class TestBookmarkAppUninstaller : public BookmarkAppUninstaller { - public: - TestBookmarkAppUninstaller(Profile* profile, - web_app::TestAppRegistrar* registrar) - : BookmarkAppUninstaller(profile, registrar), registrar_(registrar) {} - - ~TestBookmarkAppUninstaller() override = default; - - size_t uninstall_call_count() { return uninstall_call_count_; } - - const std::vector<GURL>& uninstalled_app_urls() { - return uninstalled_app_urls_; - } - - const GURL& last_uninstalled_app_url() { return uninstalled_app_urls_[0]; } - - void SetNextResultForTesting(const GURL& app_url, bool result) { - DCHECK(!base::ContainsKey(next_result_map_, app_url)); - next_result_map_[app_url] = result; - } - - // BookmarkAppUninstaller - void UninstallApp(const GURL& app_url, UninstallCallback callback) override { - DCHECK(base::ContainsKey(next_result_map_, app_url)); - - ++uninstall_call_count_; - uninstalled_app_urls_.push_back(app_url); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(base::BindLambdaForTesting( - [&, app_url](UninstallCallback callback) { - bool result = next_result_map_[app_url]; - next_result_map_.erase(app_url); - - if (result) - registrar_->RemoveAsInstalled( - GenerateFakeAppId(app_url)); - std::move(callback).Run(result); - }), - std::move(callback))); - } - - private: - std::map<GURL, bool> next_result_map_; - web_app::TestAppRegistrar* registrar_; - - size_t uninstall_call_count_ = 0; - std::vector<GURL> uninstalled_app_urls_; - - DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppUninstaller); -}; - } // namespace class PendingBookmarkAppManagerTest : public ChromeRenderViewHostTestHarness { @@ -223,7 +171,6 @@ } void TearDown() override { - uninstaller_ = nullptr; ChromeRenderViewHostTestHarness::TearDown(); } @@ -349,14 +296,6 @@ profile(), registrar_.get(), install_finalizer_.get()); manager->SetTaskFactoryForTesting(successful_installation_task_creator()); - // The test suite doesn't support multiple uninstallers. - DCHECK_EQ(nullptr, uninstaller_); - - auto uninstaller = std::make_unique<TestBookmarkAppUninstaller>( - profile(), registrar_.get()); - uninstaller_ = uninstaller.get(); - manager->SetUninstallerForTesting(std::move(uninstaller)); - // The test suite doesn't support multiple loaders. DCHECK_EQ(nullptr, url_loader_); @@ -382,24 +321,28 @@ return install_placeholder_run_count_; } - size_t uninstall_call_count() { return uninstaller_->uninstall_call_count(); } + size_t uninstall_call_count() { + return install_finalizer_->uninstall_external_web_app_urls().size(); + } const std::vector<GURL>& uninstalled_app_urls() { - return uninstaller_->uninstalled_app_urls(); + return install_finalizer_->uninstall_external_web_app_urls(); } const GURL& last_uninstalled_app_url() { - return uninstaller_->last_uninstalled_app_url(); + return install_finalizer_->uninstall_external_web_app_urls().back(); } web_app::TestAppRegistrar* registrar() { return registrar_.get(); } web_app::TestWebAppUiDelegate* ui_delegate() { return ui_delegate_.get(); } - TestBookmarkAppUninstaller* uninstaller() { return uninstaller_; } - web_app::TestWebAppUrlLoader* url_loader() { return url_loader_; } + web_app::TestInstallFinalizer* install_finalizer() { + return install_finalizer_.get(); + } + private: base::Optional<web_app::InstallOptions> last_app_info_; size_t install_run_count_ = 0; @@ -412,7 +355,6 @@ std::unique_ptr<web_app::TestWebAppUiDelegate> ui_delegate_; std::unique_ptr<web_app::TestInstallFinalizer> install_finalizer_; - TestBookmarkAppUninstaller* uninstaller_ = nullptr; web_app::TestWebAppUrlLoader* url_loader_ = nullptr; DISALLOW_COPY_AND_ASSIGN(PendingBookmarkAppManagerTest); @@ -1125,7 +1067,8 @@ auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories(); registrar()->AddAsInstalled(GenerateFakeAppId(kFooWebAppUrl)); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + true); UninstallAppsResults results = UninstallAppsAndWait( pending_app_manager.get(), std::vector<GURL>{kFooWebAppUrl}); @@ -1138,7 +1081,8 @@ TEST_F(PendingBookmarkAppManagerTest, UninstallApps_Fails) { auto pending_app_manager = GetPendingBookmarkAppManagerWithTestFactories(); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, false); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + false); UninstallAppsResults results = UninstallAppsAndWait( pending_app_manager.get(), std::vector<GURL>{kFooWebAppUrl}); EXPECT_EQ(results, UninstallAppsResults({{kFooWebAppUrl, false}})); @@ -1152,8 +1096,10 @@ registrar()->AddAsInstalled(GenerateFakeAppId(kFooWebAppUrl)); registrar()->AddAsInstalled(GenerateFakeAppId(kBarWebAppUrl)); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true); - uninstaller()->SetNextResultForTesting(kBarWebAppUrl, true); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + true); + install_finalizer()->SetNextUninstallExternalWebAppResult(kBarWebAppUrl, + true); UninstallAppsResults results = UninstallAppsAndWait(pending_app_manager.get(), std::vector<GURL>{kFooWebAppUrl, kBarWebAppUrl}); @@ -1180,7 +1126,8 @@ run_loop.Quit(); })); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, false); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + false); UninstallAppsResults uninstall_results = UninstallAppsAndWait( pending_app_manager.get(), std::vector<GURL>{kFooWebAppUrl}); EXPECT_EQ(uninstall_results, UninstallAppsResults({{kFooWebAppUrl, false}})); @@ -1212,7 +1159,8 @@ install_options.reinstall_placeholder = true; url_loader()->SetNextLoadUrlResult( kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + true); base::Optional<GURL> url; base::Optional<web_app::InstallResultCode> code; @@ -1255,7 +1203,8 @@ install_options.reinstall_placeholder = true; url_loader()->SetNextLoadUrlResult( kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, false); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + false); base::Optional<GURL> url; base::Optional<web_app::InstallResultCode> code; @@ -1298,7 +1247,8 @@ install_options.reinstall_placeholder = true; url_loader()->SetNextLoadUrlResult( kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + true); base::Optional<GURL> url; base::Optional<web_app::InstallResultCode> code; @@ -1346,7 +1296,8 @@ ui_delegate()->SetNumWindowsForApp(GenerateFakeAppId(kFooWebAppUrl), 0); url_loader()->SetNextLoadUrlResult( kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + true); base::Optional<GURL> url; base::Optional<web_app::InstallResultCode> code; @@ -1391,7 +1342,8 @@ ui_delegate()->SetNumWindowsForApp(GenerateFakeAppId(kFooWebAppUrl), 1); url_loader()->SetNextLoadUrlResult( kFooWebAppUrl, web_app::WebAppUrlLoader::Result::kUrlLoaded); - uninstaller()->SetNextResultForTesting(kFooWebAppUrl, true); + install_finalizer()->SetNextUninstallExternalWebAppResult(kFooWebAppUrl, + true); base::Optional<GURL> url; base::Optional<web_app::InstallResultCode> code;
diff --git a/chrome/browser/web_applications/test/test_install_finalizer.cc b/chrome/browser/web_applications/test/test_install_finalizer.cc index 8889f65..ddc52a2 100644 --- a/chrome/browser/web_applications/test/test_install_finalizer.cc +++ b/chrome/browser/web_applications/test/test_install_finalizer.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/web_applications/test/test_install_finalizer.h" #include "base/callback.h" +#include "base/test/bind_test_util.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" @@ -42,6 +43,24 @@ FROM_HERE, base::BindOnce(std::move(callback), app_id, code)); } +void TestInstallFinalizer::UninstallExternalWebApp( + const GURL& app_url, + UninstallExternalWebAppCallback callback) { + DCHECK(base::ContainsKey(next_uninstall_external_web_app_results_, app_url)); + uninstall_external_web_app_urls_.push_back(app_url); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + base::BindLambdaForTesting( + [this, app_url](UninstallExternalWebAppCallback callback) { + bool result = next_uninstall_external_web_app_results_[app_url]; + next_uninstall_external_web_app_results_.erase(app_url); + std::move(callback).Run(result); + }), + std::move(callback))); +} + bool TestInstallFinalizer::CanCreateOsShortcuts() const { return true; } @@ -95,4 +114,11 @@ next_result_code_ = code; } +void TestInstallFinalizer::SetNextUninstallExternalWebAppResult( + const GURL& app_url, + bool uninstalled) { + DCHECK(!base::ContainsKey(next_uninstall_external_web_app_results_, app_url)); + next_uninstall_external_web_app_results_[app_url] = uninstalled; +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/test/test_install_finalizer.h b/chrome/browser/web_applications/test/test_install_finalizer.h index 0251eb5..ddff3d6 100644 --- a/chrome/browser/web_applications/test/test_install_finalizer.h +++ b/chrome/browser/web_applications/test/test_install_finalizer.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_INSTALL_FINALIZER_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_TEST_TEST_INSTALL_FINALIZER_H_ +#include <map> #include <memory> #include "base/macros.h" @@ -24,6 +25,9 @@ void FinalizeInstall(const WebApplicationInfo& web_app_info, const FinalizeOptions& options, InstallFinalizedCallback callback) override; + void UninstallExternalWebApp( + const GURL& app_url, + UninstallExternalWebAppCallback callback) override; bool CanCreateOsShortcuts() const override; void CreateOsShortcuts(const AppId& app_id, bool add_to_desktop, @@ -42,6 +46,8 @@ void SetNextFinalizeInstallResult(const AppId& app_id, InstallResultCode code); + void SetNextUninstallExternalWebAppResult(const GURL& app_url, + bool uninstalled); std::unique_ptr<WebApplicationInfo> web_app_info() { return std::move(web_app_info_copy_); @@ -51,6 +57,10 @@ return finalize_options_list_; } + const std::vector<GURL>& uninstall_external_web_app_urls() const { + return uninstall_external_web_app_urls_; + } + int num_create_os_shortcuts_calls() { return num_create_os_shortcuts_calls_; } int num_reparent_tab_calls() { return num_reparent_tab_calls_; } int num_reveal_appshim_calls() { return num_reveal_appshim_calls_; } @@ -59,9 +69,11 @@ private: std::unique_ptr<WebApplicationInfo> web_app_info_copy_; std::vector<FinalizeOptions> finalize_options_list_; + std::vector<GURL> uninstall_external_web_app_urls_; base::Optional<AppId> next_app_id_; base::Optional<InstallResultCode> next_result_code_; + std::map<GURL, bool> next_uninstall_external_web_app_results_; int num_create_os_shortcuts_calls_ = 0; int num_reparent_tab_calls_ = 0;
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc index 91da2b0..5bc64fbc 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.cc +++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -81,6 +81,12 @@ std::move(web_app))); } +void WebAppInstallFinalizer::UninstallExternalWebApp( + const GURL& app_url, + UninstallExternalWebAppCallback callback) { + NOTIMPLEMENTED(); +} + void WebAppInstallFinalizer::OnDataWritten(InstallFinalizedCallback callback, std::unique_ptr<WebApp> web_app, bool success) {
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h index e1a8bb4..06a450af 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.h +++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -29,6 +29,9 @@ void FinalizeInstall(const WebApplicationInfo& web_app_info, const FinalizeOptions& options, InstallFinalizedCallback callback) override; + void UninstallExternalWebApp( + const GURL& app_url, + UninstallExternalWebAppCallback callback) override; bool CanCreateOsShortcuts() const override; void CreateOsShortcuts(const AppId& app_id, bool add_to_desktop,
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 3a710a6..0d6ed14 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1603,7 +1603,8 @@ // Imports Polyfill so that they will not require native imports. Return true // for only pages that have not been updated yet. See // https://crbug.com/937747. - bool canUsePolyfill = url.host() == chrome::kChromeUIExtensionsHost; + bool canUsePolyfill = url.host() == chrome::kChromeUIExtensionsHost || + url.host() == chrome::kChromeUIDownloadsHost; #if BUILDFLAG(ENABLE_PRINT_PREVIEW) canUsePolyfill |= url.host() == chrome::kChromeUIPrintHost; #endif
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationData.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationData.java index 53cf717..cc544f1 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationData.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ApplicationData.java
@@ -6,10 +6,10 @@ import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; -import android.annotation.SuppressLint; import android.content.Context; import android.support.v4.content.ContextCompat; +import org.chromium.base.FileUtils; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -42,17 +42,11 @@ public static void clearAppData(final Context targetContext) { CriteriaHelper.pollInstrumentationThread( new Criteria() { - private boolean mDataRemoved; - - // The lint check for calling apply() rather than commit() on a shared pref - // was recently renamed. - @SuppressLint({"ApplySharedPref", "CommitPrefEdits"}) @Override public boolean isSatisfied() { - if (!mDataRemoved && !removeAppData(targetContext)) { + if (!removeAppData(targetContext)) { return false; } - mDataRemoved = true; // We have to make sure the cache directory still exists, as the framework // will try to create it otherwise and will fail for sandbox processes with // a NullPointerException. @@ -65,8 +59,6 @@ /** * Remove all files and directories under the given application directory, except 'lib'. - * - * @return whether removal succeeded. */ private static boolean removeAppData(final Context targetContext) { File dataDir = ContextCompat.getDataDir(targetContext); @@ -90,7 +82,7 @@ removeSharedPrefs(file); continue; } - if (!removeFile(file)) { + if (!FileUtils.recursivelyDeleteFile(file)) { return false; } } @@ -105,22 +97,4 @@ } } } - - /** - * Remove the given file or directory. - * - * @param file the file or directory to remove. - * - * @return whether removal succeeded. - */ - private static boolean removeFile(File file) { - if (file.isDirectory()) { - File[] files = file.listFiles(); - if (files == null) return true; - for (File sub_file : files) { - if (!removeFile(sub_file)) return false; - } - } - return file.delete(); - } }
diff --git a/chrome/test/base/mojo_web_ui_browser_test.cc b/chrome/test/base/mojo_web_ui_browser_test.cc index 764ff7e..d244a150 100644 --- a/chrome/test/base/mojo_web_ui_browser_test.cc +++ b/chrome/test/base/mojo_web_ui_browser_test.cc
@@ -8,6 +8,7 @@ #include "base/bind_helpers.h" #include "base/macros.h" #include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/webui/web_ui_test_handler.h" #include "chrome/common/chrome_paths.h" @@ -104,9 +105,22 @@ content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); if (use_mojo_lite_bindings_) { + base::string16 file_content = + l10n_util::GetStringUTF16(IDR_WEB_UI_TEST_MOJO_LITE_JS); + // The generated script assumes that mojo has already been imported by the + // page. This is not the case when native HTML imports are disabled. If + // the polyfill is in place, wait for HTMLImports.whenReady(). + base::string16 wrapped_file_content = + base::UTF8ToUTF16( + "const promise = typeof HTMLImports === 'undefined' ? " + "Promise.resolve() : " + "new Promise(resolve => { " + "HTMLImports.whenReady(resolve); " + "}); " + "promise.then(() => {") + + file_content + base::UTF8ToUTF16("});"); web_contents->GetMainFrame()->ExecuteJavaScriptForTests( - l10n_util::GetStringUTF16(IDR_WEB_UI_TEST_MOJO_LITE_JS), - base::NullCallback()); + wrapped_file_content, base::NullCallback()); } else { web_contents->GetMainFrame()->ExecuteJavaScriptForTests( l10n_util::GetStringUTF16(IDR_WEB_UI_TEST_MOJO_JS),
diff --git a/chrome/test/data/media/picture-in-picture/window-size.html b/chrome/test/data/media/picture-in-picture/window-size.html index 1443db9..50c954c 100644 --- a/chrome/test/data/media/picture-in-picture/window-size.html +++ b/chrome/test/data/media/picture-in-picture/window-size.html
@@ -145,12 +145,5 @@ .catch(e => { document.title = 'failed to enter Picture-in-Picture after leaving'; }); }); } - - function resetVideo() { - video.addEventListener('emptied', () => { - document.title = 'emptied'; - }, { once: true }); - video.src = ''; - } </script> </html>
diff --git a/chrome/test/data/webui/downloads/downloads_browsertest.js b/chrome/test/data/webui/downloads/downloads_browsertest.js index ceb5557..5c082e7 100644 --- a/chrome/test/data/webui/downloads/downloads_browsertest.js +++ b/chrome/test/data/webui/downloads/downloads_browsertest.js
@@ -23,6 +23,21 @@ }, /** @override */ + loaderFile: 'subpage_loader.html', + + // The name of the custom element under test. Should be overridden by + // subclasses that are loading the URL of a non-element. + get customElementName() { + const r = /chrome\:\/\/downloads\/([a-zA-Z-_]+)\.html/; + const result = r.exec(this.browsePreload); + if (!result || result.length < 1) { + // Loading the main page, so wait for downloads manager. + return 'downloads-manager'; + } + return 'downloads-' + result[1].replace(/_/gi, '-'); + }, + + /** @override */ runAccessibilityChecks: true, }; @@ -110,6 +125,14 @@ /** @override */ browsePreload: 'chrome://downloads/a/b/', + + /** @override */ + loaderFile: '', + + /** @override */ + get customElementName() { + return null; + } }; TEST_F('DownloadsUrlTest', 'All', function() {
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc index f2c32b8..6ed0877 100644 --- a/chromeos/constants/chromeos_switches.cc +++ b/chromeos/constants/chromeos_switches.cc
@@ -237,10 +237,6 @@ // Disables per-user timezone. const char kDisablePerUserTimezone[] = "disable-per-user-timezone"; -// Disables suggestions while typing on a physical keyboard. -const char kDisablePhysicalKeyboardAutocorrect[] = - "disable-physical-keyboard-autocorrect"; - // Disables rollback option on reset screen. const char kDisableRollbackOption[] = "disable-rollback-option"; @@ -295,10 +291,6 @@ // Enables the marketing opt-in screen in OOBE. const char kEnableMarketingOptInScreen[] = "enable-market-opt-in"; -// Enables suggestions while typing on a physical keyboard. -const char kEnablePhysicalKeyboardAutocorrect[] = - "enable-physical-keyboard-autocorrect"; - // Enables request of tablet site (via user agent override). const char kEnableRequestTabletSite[] = "enable-request-tablet-site";
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h index d28d89d..e6a900b 100644 --- a/chromeos/constants/chromeos_switches.h +++ b/chromeos/constants/chromeos_switches.h
@@ -85,8 +85,6 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kDisableNewZIPUnpacker[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kDisablePerUserTimezone[]; -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) -extern const char kDisablePhysicalKeyboardAutocorrect[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kDisableRollbackOption[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kDisableSigninFrameClientCerts[]; @@ -112,8 +110,6 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kEnableMarketingOptInScreen[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) -extern const char kEnablePhysicalKeyboardAutocorrect[]; -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kEnableRequestTabletSite[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kEnableTouchCalibrationSetting[];
diff --git a/components/components_strings.grd b/components/components_strings.grd index 33c5baf..3b165b2 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd
@@ -238,6 +238,9 @@ <message name="IDS_CLOSE" desc="A generic term for Close on buttons and menus."> Close </message> + <message name="IDS_CLEAR" desc="A generic term for Clearing input fields."> + Clear + </message> <message name="IDS_DONE" desc="A generic term for Done on buttons and menus."> Done </message>
diff --git a/components/crash/content/browser/child_exit_observer_android.cc b/components/crash/content/browser/child_exit_observer_android.cc index 595a52744..dd252440 100644 --- a/components/crash/content/browser/child_exit_observer_android.cc +++ b/components/crash/content/browser/child_exit_observer_android.cc
@@ -38,6 +38,7 @@ content_info.remaining_process_with_moderate_binding; info->remaining_process_with_waived_binding = content_info.remaining_process_with_waived_binding; + info->best_effort_reverse_rank = content_info.best_effort_reverse_rank; info->was_oom_protected_status = content_info.status == base::TERMINATION_STATUS_OOM_PROTECTED; }
diff --git a/components/crash/content/browser/child_exit_observer_android.h b/components/crash/content/browser/child_exit_observer_android.h index 1059f0c4..ae292f6 100644 --- a/components/crash/content/browser/child_exit_observer_android.h +++ b/components/crash/content/browser/child_exit_observer_android.h
@@ -70,6 +70,7 @@ int remaining_process_with_strong_binding = 0; int remaining_process_with_moderate_binding = 0; int remaining_process_with_waived_binding = 0; + int best_effort_reverse_rank = -1; // Note this is slightly different |has_oom_protection_bindings|. // This is equivalent to status == TERMINATION_STATUS_NORMAL_TERMINATION,
diff --git a/components/crash/content/browser/crash_metrics_reporter_android.cc b/components/crash/content/browser/crash_metrics_reporter_android.cc index 9ddeee9f..38af0400 100644 --- a/components/crash/content/browser/crash_metrics_reporter_android.cc +++ b/components/crash/content/browser/crash_metrics_reporter_android.cc
@@ -287,6 +287,17 @@ info.remaining_process_with_strong_binding, 20); } + if (android_oom_kill) { + if (info.best_effort_reverse_rank >= 0) { + UMA_HISTOGRAM_EXACT_LINEAR("Stability.Android.OomKillReverseRank", + info.best_effort_reverse_rank, 50); + } + if (info.best_effort_reverse_rank != -2) { + UMA_HISTOGRAM_BOOLEAN("Stability.Android.OomKillReverseRankSuccess", + info.best_effort_reverse_rank != -1); + } + } + ReportLegacyCrashUma(info, crashed); NotifyObservers(info.process_host_id, reported_counts); }
diff --git a/components/drive/chromeos/file_system.cc b/components/drive/chromeos/file_system.cc index 39a57ed..e760eb8 100644 --- a/components/drive/chromeos/file_system.cc +++ b/components/drive/chromeos/file_system.cc
@@ -953,7 +953,7 @@ base::RepeatingClosure closure = base::BarrierClosure( num_callbacks, base::BindOnce(&FileSystem::OnGetMetadata, weak_ptr_factory_.GetWeakPtr(), - base::Passed(std::move(callback)), base::Owned(metadata), + std::move(callback), base::Owned(metadata), base::Owned(team_drive_metadata))); metadata->refreshing = default_corpus_change_list_loader_->IsRefreshing();
diff --git a/components/drive/chromeos/file_system/get_file_for_saving_operation.cc b/components/drive/chromeos/file_system/get_file_for_saving_operation.cc index 21d010367..3c2a7fe5 100644 --- a/components/drive/chromeos/file_system/get_file_for_saving_operation.cc +++ b/components/drive/chromeos/file_system/get_file_for_saving_operation.cc
@@ -123,8 +123,8 @@ file_closer, entry_ptr), base::BindOnce( &GetFileForSavingOperation::GetFileForSavingAfterOpenForWrite, - weak_ptr_factory_.GetWeakPtr(), base::Passed(std::move(callback)), - cache_path, std::move(entry), base::Owned(file_closer))); + weak_ptr_factory_.GetWeakPtr(), std::move(callback), cache_path, + std::move(entry), base::Owned(file_closer))); } void GetFileForSavingOperation::GetFileForSavingAfterOpenForWrite(
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 1bd0221..c36b09b 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -86,7 +86,6 @@ if (is_chromeos) { deps += [ "//ash/keyboard/ui", - "//ash/keyboard/ui:mojom", "//ash/public/cpp", ] sources += [
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 2cd7455a..6d2fdaa 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -7,7 +7,6 @@ #include <alpha-compositing-unstable-v1-server-protocol.h> #include <aura-shell-server-protocol.h> #include <cursor-shapes-unstable-v1-server-protocol.h> -#include <gaming-input-unstable-v1-server-protocol.h> #include <gaming-input-unstable-v2-server-protocol.h> #include <grp.h> #include <input-timestamps-unstable-v1-server-protocol.h>
diff --git a/components/exo/wayland/zcr_gaming_input.cc b/components/exo/wayland/zcr_gaming_input.cc index 5d5ba65f..ecdecc0 100644 --- a/components/exo/wayland/zcr_gaming_input.cc +++ b/components/exo/wayland/zcr_gaming_input.cc
@@ -4,7 +4,6 @@ #include "components/exo/wayland/zcr_gaming_input.h" -#include <gaming-input-unstable-v1-server-protocol.h> #include <gaming-input-unstable-v2-server-protocol.h> #include <wayland-server-core.h> #include <wayland-server-protocol-core.h>
diff --git a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java index 2b43ebf..f7038cb3 100644 --- a/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java +++ b/components/minidump_uploader/android/java/src/org/chromium/components/minidump_uploader/MinidumpUploadCallable.java
@@ -8,6 +8,7 @@ import android.support.annotation.IntDef; import org.chromium.base.ContextUtils; +import org.chromium.base.FileUtils; import org.chromium.base.Log; import org.chromium.base.StreamUtil; import org.chromium.base.VisibleForTesting; @@ -16,14 +17,11 @@ import org.chromium.components.minidump_uploader.util.HttpURLConnectionFactoryImpl; import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.HttpURLConnection; @@ -119,7 +117,8 @@ return MinidumpUploadStatus.FAILURE; } minidumpInputStream = new FileInputStream(mFileToUpload); - streamCopy(minidumpInputStream, new GZIPOutputStream(connection.getOutputStream())); + FileUtils.copyStream( + minidumpInputStream, new GZIPOutputStream(connection.getOutputStream())); boolean success = handleExecutionResponse(connection); return success ? MinidumpUploadStatus.SUCCESS : MinidumpUploadStatus.FAILURE; @@ -127,14 +126,11 @@ // ArrayIndexOutOfBoundsException due to bad GZIPOutputStream implementation on some // old sony devices. // For now just log the stack trace. - Log.w(TAG, "Error while uploading " + mFileToUpload.getName(), e); + Log.w(TAG, "Error while uploading %s", mFileToUpload.getName(), e); return MinidumpUploadStatus.FAILURE; } finally { connection.disconnect(); - - if (minidumpInputStream != null) { - StreamUtil.closeQuietly(minidumpInputStream); - } + StreamUtil.closeQuietly(minidumpInputStream); } } @@ -174,9 +170,9 @@ if (isSuccessful(responseCode)) { String responseContent = getResponseContentAsString(connection); // The crash server returns the crash ID. - String uploadId = responseContent != null ? responseContent : "unknown"; + String uploadId = responseContent.isEmpty() ? "unknown" : responseContent; String crashFileName = mFileToUpload.getName(); - Log.i(TAG, "Minidump " + crashFileName + " uploaded successfully, id: " + uploadId); + Log.i(TAG, "Minidump %s uploaded successfully, id: %s", crashFileName, uploadId); // TODO(acleung): MinidumpUploadService is in charge of renaming while this class is // in charge of deleting. We should move all the file system operations into @@ -284,33 +280,8 @@ */ private static String getResponseContentAsString(HttpURLConnection connection) throws IOException { - String responseContent = null; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - streamCopy(connection.getInputStream(), baos); - if (baos.size() > 0) { - responseContent = baos.toString(); - } - return responseContent; - } - - /** - * Copies all available data from |inStream| to |outStream|. Closes both - * streams when done. - * - * @param inStream the stream to read - * @param outStream the stream to write to - * @throws IOException - */ - private static void streamCopy(InputStream inStream, OutputStream outStream) - throws IOException { - byte[] temp = new byte[4096]; - int bytesRead = inStream.read(temp); - while (bytesRead >= 0) { - outStream.write(temp, 0, bytesRead); - bytesRead = inStream.read(temp); - } - inStream.close(); - outStream.close(); + byte[] bytes = FileUtils.readStream(connection.getInputStream()); + return new String(bytes); } // TODO(gayane): Remove this function and unused prefs in M51. crbug.com/555022
diff --git a/components/remote_cocoa/app_shim/BUILD.gn b/components/remote_cocoa/app_shim/BUILD.gn index 72fa7f8..46cbd19 100644 --- a/components/remote_cocoa/app_shim/BUILD.gn +++ b/components/remote_cocoa/app_shim/BUILD.gn
@@ -17,34 +17,34 @@ configs += [ ":app_shim_warnings" ] sources = [ - "//ui/views_bridge_mac/alert.h", - "//ui/views_bridge_mac/alert.mm", - "//ui/views_bridge_mac/bridge_factory_impl.h", - "//ui/views_bridge_mac/bridge_factory_impl.mm", - "//ui/views_bridge_mac/bridged_content_view.h", - "//ui/views_bridge_mac/bridged_content_view.mm", - "//ui/views_bridge_mac/bridged_content_view_touch_bar.mm", - "//ui/views_bridge_mac/bridged_native_widget_host_helper.h", - "//ui/views_bridge_mac/bridged_native_widget_impl.h", - "//ui/views_bridge_mac/bridged_native_widget_impl.mm", - "//ui/views_bridge_mac/browser_native_widget_window_mac.h", - "//ui/views_bridge_mac/browser_native_widget_window_mac.mm", - "//ui/views_bridge_mac/cocoa_mouse_capture.h", - "//ui/views_bridge_mac/cocoa_mouse_capture.mm", - "//ui/views_bridge_mac/cocoa_mouse_capture_delegate.h", - "//ui/views_bridge_mac/cocoa_window_move_loop.h", - "//ui/views_bridge_mac/cocoa_window_move_loop.mm", - "//ui/views_bridge_mac/drag_drop_client.h", - "//ui/views_bridge_mac/native_widget_mac_frameless_nswindow.h", - "//ui/views_bridge_mac/native_widget_mac_frameless_nswindow.mm", - "//ui/views_bridge_mac/native_widget_mac_nswindow.h", - "//ui/views_bridge_mac/native_widget_mac_nswindow.mm", - "//ui/views_bridge_mac/views_bridge_mac_export.h", - "//ui/views_bridge_mac/views_nswindow_delegate.h", - "//ui/views_bridge_mac/views_nswindow_delegate.mm", - "//ui/views_bridge_mac/views_scrollbar_bridge.h", - "//ui/views_bridge_mac/views_scrollbar_bridge.mm", - "//ui/views_bridge_mac/window_touch_bar_delegate.h", + "alert.h", + "alert.mm", + "bridge_factory_impl.h", + "bridge_factory_impl.mm", + "bridged_content_view.h", + "bridged_content_view.mm", + "bridged_content_view_touch_bar.mm", + "bridged_native_widget_host_helper.h", + "bridged_native_widget_impl.h", + "bridged_native_widget_impl.mm", + "browser_native_widget_window_mac.h", + "browser_native_widget_window_mac.mm", + "drag_drop_client.h", + "mouse_capture.h", + "mouse_capture.mm", + "mouse_capture_delegate.h", + "native_widget_mac_frameless_nswindow.h", + "native_widget_mac_frameless_nswindow.mm", + "native_widget_mac_nswindow.h", + "native_widget_mac_nswindow.mm", + "remote_cocoa_app_shim_export.h", + "views_nswindow_delegate.h", + "views_nswindow_delegate.mm", + "views_scrollbar_bridge.h", + "views_scrollbar_bridge.mm", + "window_move_loop.h", + "window_move_loop.mm", + "window_touch_bar_delegate.h", ] defines = [ "VIEWS_BRIDGE_MAC_IMPLEMENTATION" ] deps = [
diff --git a/ui/views_bridge_mac/alert.h b/components/remote_cocoa/app_shim/alert.h similarity index 87% rename from ui/views_bridge_mac/alert.h rename to components/remote_cocoa/app_shim/alert.h index c2f2205..0f0cf9d 100644 --- a/ui/views_bridge_mac/alert.h +++ b/components/remote_cocoa/app_shim/alert.h
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_ALERT_H_ -#define UI_VIEWS_BRIDGE_MAC_ALERT_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_ALERT_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_ALERT_H_ #import <Cocoa/Cocoa.h> #include "base/mac/scoped_nsobject.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" #include "components/remote_cocoa/common/alert.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/gfx/text_elider.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" @class AlertBridgeHelper; @@ -19,7 +19,7 @@ // Class that displays an NSAlert with associated UI as described by the mojo // AlertBridge interface. -class VIEWS_BRIDGE_MAC_EXPORT AlertBridge +class REMOTE_COCOA_APP_SHIM_EXPORT AlertBridge : public views_bridge_mac::mojom::AlertBridge { public: // Creates a new alert which controls its own lifetime. It will destroy itself @@ -62,4 +62,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_BRIDGE_MAC_ALERT_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_ALERT_H_
diff --git a/ui/views_bridge_mac/alert.mm b/components/remote_cocoa/app_shim/alert.mm similarity index 99% rename from ui/views_bridge_mac/alert.mm rename to components/remote_cocoa/app_shim/alert.mm index 9b7310a9..0169e235 100644 --- a/ui/views_bridge_mac/alert.mm +++ b/components/remote_cocoa/app_shim/alert.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/views_bridge_mac/alert.h" +#include "components/remote_cocoa/app_shim/alert.h" #include "base/bind.h" #include "base/i18n/rtl.h"
diff --git a/ui/views_bridge_mac/bridge_factory_impl.h b/components/remote_cocoa/app_shim/bridge_factory_impl.h similarity index 72% rename from ui/views_bridge_mac/bridge_factory_impl.h rename to components/remote_cocoa/app_shim/bridge_factory_impl.h index ca22fc4..18702bac7 100644 --- a/ui/views_bridge_mac/bridge_factory_impl.h +++ b/components/remote_cocoa/app_shim/bridge_factory_impl.h
@@ -2,23 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_ -#define UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGE_FACTORY_IMPL_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGE_FACTORY_IMPL_H_ +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" #include "components/remote_cocoa/common/alert.mojom.h" #include "components/remote_cocoa/common/bridge_factory.mojom.h" #include "components/remote_cocoa/common/bridged_native_widget.mojom.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" -// TODO(ccameron): This file is to be moved to /ui/views_bridge_mac when -// possible. For now, put it in the namespace of that path. +// TODO(ccameron): This file is to be moved to /components/remote_cocoa/app_shim +// when possible. For now, put it in the namespace of that path. namespace views_bridge_mac { // The factory that creates BridgedNativeWidget instances. This object is to // be instantiated in app shim processes. -class VIEWS_BRIDGE_MAC_EXPORT BridgeFactoryImpl : public mojom::BridgeFactory { +class REMOTE_COCOA_APP_SHIM_EXPORT BridgeFactoryImpl + : public mojom::BridgeFactory { public: static BridgeFactoryImpl* Get(); void BindRequest(mojom::BridgeFactoryAssociatedRequest request); @@ -41,4 +42,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGE_FACTORY_IMPL_H_
diff --git a/ui/views_bridge_mac/bridge_factory_impl.mm b/components/remote_cocoa/app_shim/bridge_factory_impl.mm similarity index 93% rename from ui/views_bridge_mac/bridge_factory_impl.mm rename to components/remote_cocoa/app_shim/bridge_factory_impl.mm index 3f2a92c..bc9efda 100644 --- a/ui/views_bridge_mac/bridge_factory_impl.mm +++ b/components/remote_cocoa/app_shim/bridge_factory_impl.mm
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/views_bridge_mac/bridge_factory_impl.h" +#include "components/remote_cocoa/app_shim/bridge_factory_impl.h" #include "base/bind.h" #include "base/no_destructor.h" +#include "components/remote_cocoa/app_shim/alert.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/cocoa/remote_accessibility_api.h" -#include "ui/views_bridge_mac/alert.h" -#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views_bridge_mac {
diff --git a/ui/views_bridge_mac/bridged_content_view.h b/components/remote_cocoa/app_shim/bridged_content_view.h similarity index 81% rename from ui/views_bridge_mac/bridged_content_view.h rename to components/remote_cocoa/app_shim/bridged_content_view.h index ab25f8a..af42e05 100644 --- a/ui/views_bridge_mac/bridged_content_view.h +++ b/components/remote_cocoa/app_shim/bridged_content_view.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_ -#define UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_CONTENT_VIEW_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_CONTENT_VIEW_H_ #import <Cocoa/Cocoa.h> #include "base/strings/string16.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" #import "ui/base/cocoa/tool_tip_base_view.h" #import "ui/base/cocoa/tracking_area.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" namespace ui { class TextInputClient; @@ -23,11 +23,11 @@ // The NSView that sits as the root contentView of the NSWindow, whilst it has // a views::RootView present. Bridges requests from Cocoa to the hosted // views::View. -VIEWS_BRIDGE_MAC_EXPORT -@interface BridgedContentView : ToolTipBaseView<NSTextInputClient, - NSUserInterfaceValidations, - NSDraggingSource, - NSServicesMenuRequestor> { +REMOTE_COCOA_APP_SHIM_EXPORT +@interface BridgedContentView : ToolTipBaseView <NSTextInputClient, + NSUserInterfaceValidations, + NSDraggingSource, + NSServicesMenuRequestor> { @private // Weak, reset by clearView. views::BridgedNativeWidgetImpl* bridge_; @@ -83,4 +83,4 @@ @end -#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_CONTENT_VIEW_H_
diff --git a/ui/views_bridge_mac/bridged_content_view.mm b/components/remote_cocoa/app_shim/bridged_content_view.mm similarity index 98% rename from ui/views_bridge_mac/bridged_content_view.mm rename to components/remote_cocoa/app_shim/bridged_content_view.mm index c8082beb..53c71de 100644 --- a/ui/views_bridge_mac/bridged_content_view.mm +++ b/components/remote_cocoa/app_shim/bridged_content_view.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" #include "base/logging.h" #import "base/mac/foundation_util.h" @@ -11,6 +11,9 @@ #import "base/mac/sdk_forward_declarations.h" #include "base/metrics/histogram_macros.h" #include "base/strings/sys_string_conversions.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/drag_drop_client.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #import "ui/base/cocoa/appkit_utils.h" #include "ui/base/cocoa/cocoa_base_utils.h" @@ -30,9 +33,6 @@ #import "ui/gfx/mac/coordinate_conversion.h" #import "ui/gfx/path_mac.h" #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" -#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" -#import "ui/views_bridge_mac/drag_drop_client.h" namespace { @@ -1248,8 +1248,8 @@ } - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard { - NSArray* objects = - [pboard readObjectsForClasses:@[ [NSString class] ] options:0]; + NSArray* objects = [pboard readObjectsForClasses:@ [[NSString class]] + options:0]; DCHECK([objects count] == 1); [self insertText:[objects lastObject]]; return YES; @@ -1468,7 +1468,7 @@ if (!bridge_) return nil; return [bridge_->host_helper()->GetNativeViewAccessible() - accessibilityFocusedUIElement]; + accessibilityFocusedUIElement]; } @end
diff --git a/ui/views_bridge_mac/bridged_content_view_touch_bar.mm b/components/remote_cocoa/app_shim/bridged_content_view_touch_bar.mm similarity index 94% rename from ui/views_bridge_mac/bridged_content_view_touch_bar.mm rename to components/remote_cocoa/app_shim/bridged_content_view_touch_bar.mm index 5deafda..ebc9f2a 100644 --- a/ui/views_bridge_mac/bridged_content_view_touch_bar.mm +++ b/components/remote_cocoa/app_shim/bridged_content_view_touch_bar.mm
@@ -6,10 +6,10 @@ #import "base/mac/scoped_nsobject.h" #import "base/mac/sdk_forward_declarations.h" #include "base/strings/sys_string_conversions.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #import "ui/base/cocoa/touch_bar_forward_declarations.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace { @@ -20,7 +20,7 @@ } // namespace -@interface BridgedContentView (TouchBarAdditions)<NSTouchBarDelegate> +@interface BridgedContentView (TouchBarAdditions) <NSTouchBarDelegate> - (void)touchBarButtonAction:(id)sender; @end
diff --git a/ui/views_bridge_mac/bridged_native_widget_host_helper.h b/components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h similarity index 85% rename from ui/views_bridge_mac/bridged_native_widget_host_helper.h rename to components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h index cfb144c..c7e19c64 100644 --- a/ui/views_bridge_mac/bridged_native_widget_host_helper.h +++ b/components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_ -#define UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_ +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" #include "ui/base/ui_base_types.h" #include "ui/events/event_utils.h" #include "ui/gfx/decorated_text.h" #include "ui/gfx/geometry/point.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" @class NSView; @@ -25,7 +25,7 @@ // This provides an easier-to-use interface than the mojo for selected // functions. It also is temporarily exposing functionality that is not yet // implemented over mojo. -class VIEWS_BRIDGE_MAC_EXPORT BridgedNativeWidgetHostHelper { +class REMOTE_COCOA_APP_SHIM_EXPORT BridgedNativeWidgetHostHelper { public: virtual ~BridgedNativeWidgetHostHelper() = default; @@ -63,4 +63,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_
diff --git a/ui/views_bridge_mac/bridged_native_widget_impl.h b/components/remote_cocoa/app_shim/bridged_native_widget_impl.h similarity index 96% rename from ui/views_bridge_mac/bridged_native_widget_impl.h rename to components/remote_cocoa/app_shim/bridged_native_widget_impl.h index 57047cf..14d966bf3 100644 --- a/ui/views_bridge_mac/bridged_native_widget_impl.h +++ b/components/remote_cocoa/app_shim/bridged_native_widget_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_ -#define UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_NATIVE_WIDGET_IMPL_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_NATIVE_WIDGET_IMPL_H_ #import <Cocoa/Cocoa.h> @@ -12,6 +12,8 @@ #import "base/mac/scoped_nsobject.h" #include "base/macros.h" +#import "components/remote_cocoa/app_shim/mouse_capture_delegate.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" #include "components/remote_cocoa/common/bridged_native_widget.mojom.h" #include "components/remote_cocoa/common/text_input_host.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h" @@ -21,8 +23,6 @@ #include "ui/base/cocoa/ns_view_ids.h" #include "ui/base/ime/text_input_client.h" #include "ui/display/display_observer.h" -#import "ui/views_bridge_mac/cocoa_mouse_capture_delegate.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" @class BridgedContentView; @class ModalShowAnimationWithLayer; @@ -57,7 +57,7 @@ // A bridge to an NSWindow managed by an instance of NativeWidgetMac or // DesktopNativeWidgetMac. Serves as a helper class to bridge requests from the // NativeWidgetMac to the Cocoa window. Behaves a bit like an aura::Window. -class VIEWS_BRIDGE_MAC_EXPORT BridgedNativeWidgetImpl +class REMOTE_COCOA_APP_SHIM_EXPORT BridgedNativeWidgetImpl : public views_bridge_mac::mojom::BridgedNativeWidget, public display::DisplayObserver, public ui::CATransactionCoordinator::PreCommitObserver, @@ -376,4 +376,4 @@ } // namespace views -#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_BRIDGED_NATIVE_WIDGET_IMPL_H_
diff --git a/ui/views_bridge_mac/bridged_native_widget_impl.mm b/components/remote_cocoa/app_shim/bridged_native_widget_impl.mm similarity index 97% rename from ui/views_bridge_mac/bridged_native_widget_impl.mm rename to components/remote_cocoa/app_shim/bridged_native_widget_impl.mm index a8d39db..24142bf 100644 --- a/ui/views_bridge_mac/bridged_native_widget_impl.mm +++ b/components/remote_cocoa/app_shim/bridged_native_widget_impl.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #import <objc/runtime.h> #include <stddef.h> @@ -18,6 +18,14 @@ #include "base/no_destructor.h" #include "base/single_thread_task_runner.h" #include "base/strings/sys_string_conversions.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h" +#import "components/remote_cocoa/app_shim/browser_native_widget_window_mac.h" +#import "components/remote_cocoa/app_shim/mouse_capture.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" +#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h" +#import "components/remote_cocoa/app_shim/window_move_loop.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/cocoa/cocoa_base_utils.h" @@ -32,14 +40,6 @@ #include "ui/gfx/geometry/dip_util.h" #import "ui/gfx/mac/coordinate_conversion.h" #import "ui/gfx/mac/nswindow_frame_controls.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#import "ui/views_bridge_mac/bridged_native_widget_host_helper.h" -#import "ui/views_bridge_mac/browser_native_widget_window_mac.h" -#import "ui/views_bridge_mac/cocoa_mouse_capture.h" -#import "ui/views_bridge_mac/cocoa_window_move_loop.h" -#import "ui/views_bridge_mac/native_widget_mac_frameless_nswindow.h" -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" -#import "ui/views_bridge_mac/views_nswindow_delegate.h" using views_bridge_mac::mojom::VisibilityTransition; using views_bridge_mac::mojom::WindowVisibilityState; @@ -62,7 +62,7 @@ // Self-owning animation delegate that starts a hide animation, then calls // -[NSWindow close] when the animation ends, releasing itself. -@interface ViewsNSWindowCloseAnimator : NSObject<NSAnimationDelegate> { +@interface ViewsNSWindowCloseAnimator : NSObject <NSAnimationDelegate> { @private base::scoped_nsobject<NSWindow> window_; base::scoped_nsobject<NSAnimation> animation_; @@ -106,7 +106,7 @@ // animation: in that case, the shadow is never invalidated so retains the // shadow calculated before a translate is applied. @interface ModalShowAnimationWithLayer - : ConstrainedWindowAnimationShow<NSAnimationDelegate> + : ConstrainedWindowAnimationShow <NSAnimationDelegate> @end @implementation ModalShowAnimationWithLayer { @@ -533,8 +533,8 @@ const gfx::Rect& bounds) { DCHECK(!bridged_view_); - bridged_view_.reset( - [[BridgedContentView alloc] initWithBridge:this bounds:bounds]); + bridged_view_.reset([[BridgedContentView alloc] initWithBridge:this + bounds:bounds]); bridged_view_id_mapping_ = std::make_unique<ui::ScopedNSViewIdMapping>( ns_view_id, bridged_view_.get());
diff --git a/components/remote_cocoa/app_shim/browser_native_widget_window_mac.h b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.h new file mode 100644 index 0000000..26045e9 --- /dev/null +++ b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.h
@@ -0,0 +1,13 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_ + +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" + +@interface BrowserNativeWidgetWindow : NativeWidgetMacNSWindow +@end + +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_
diff --git a/ui/views_bridge_mac/browser_native_widget_window_mac.mm b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm similarity index 94% rename from ui/views_bridge_mac/browser_native_widget_window_mac.mm rename to components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm index 1d5e9102..67727935 100644 --- a/ui/views_bridge_mac/browser_native_widget_window_mac.mm +++ b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/browser_native_widget_window_mac.h" +#import "components/remote_cocoa/app_shim/browser_native_widget_window_mac.h" #import <AppKit/AppKit.h> +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" @interface NSWindow (PrivateBrowserNativeWidgetAPI) + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
diff --git a/ui/views_bridge_mac/drag_drop_client.h b/components/remote_cocoa/app_shim/drag_drop_client.h similarity index 75% rename from ui/views_bridge_mac/drag_drop_client.h rename to components/remote_cocoa/app_shim/drag_drop_client.h index 3efa842..b725faa 100644 --- a/ui/views_bridge_mac/drag_drop_client.h +++ b/components/remote_cocoa/app_shim/drag_drop_client.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_DRAG_DROP_CLIENT_H_ -#define UI_VIEWS_BRIDGE_MAC_DRAG_DROP_CLIENT_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_DRAG_DROP_CLIENT_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_DRAG_DROP_CLIENT_H_ #import <Cocoa/Cocoa.h> -#include "ui/views_bridge_mac/views_bridge_mac_export.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" namespace views_bridge_mac { @@ -15,7 +15,7 @@ // DragDropClientMac in the browser process. This interface should eventually // become mojo-ified, but at the moment only passes raw pointers (consequently, // drag-drop behavior does not work in RemoteMacViews). -class VIEWS_BRIDGE_MAC_EXPORT DragDropClient { +class REMOTE_COCOA_APP_SHIM_EXPORT DragDropClient { public: virtual ~DragDropClient() {} @@ -34,4 +34,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_BRIDGE_MAC_DRAG_DROP_CLIENT_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_DRAG_DROP_CLIENT_H_
diff --git a/ui/views_bridge_mac/cocoa_mouse_capture.h b/components/remote_cocoa/app_shim/mouse_capture.h similarity index 82% rename from ui/views_bridge_mac/cocoa_mouse_capture.h rename to components/remote_cocoa/app_shim/mouse_capture.h index b7dedad..1742913 100644 --- a/ui/views_bridge_mac/cocoa_mouse_capture.h +++ b/components/remote_cocoa/app_shim/mouse_capture.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_H_ -#define UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_H_ #include <memory> #include "base/macros.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" @class NSWindow; @@ -21,7 +21,7 @@ // menu should dismiss the menu and "swallow" the mouse event. All events are // forwarded, but only events to the same application are "swallowed", which is // consistent with how native NSMenus behave. -class VIEWS_BRIDGE_MAC_EXPORT CocoaMouseCapture { +class REMOTE_COCOA_APP_SHIM_EXPORT CocoaMouseCapture { public: explicit CocoaMouseCapture(CocoaMouseCaptureDelegate* delegate); ~CocoaMouseCapture(); @@ -50,4 +50,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_H_
diff --git a/ui/views_bridge_mac/cocoa_mouse_capture.mm b/components/remote_cocoa/app_shim/mouse_capture.mm similarity index 96% rename from ui/views_bridge_mac/cocoa_mouse_capture.mm rename to components/remote_cocoa/app_shim/mouse_capture.mm index 21f538b..a61a341 100644 --- a/ui/views_bridge_mac/cocoa_mouse_capture.mm +++ b/components/remote_cocoa/app_shim/mouse_capture.mm
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/cocoa_mouse_capture.h" +#import "components/remote_cocoa/app_shim/mouse_capture.h" #import <Cocoa/Cocoa.h> #include "base/logging.h" #include "base/macros.h" +#import "components/remote_cocoa/app_shim/mouse_capture_delegate.h" #include "ui/base/cocoa/weak_ptr_nsobject.h" -#import "ui/views_bridge_mac/cocoa_mouse_capture_delegate.h" namespace views_bridge_mac {
diff --git a/ui/views_bridge_mac/cocoa_mouse_capture_delegate.h b/components/remote_cocoa/app_shim/mouse_capture_delegate.h similarity index 80% rename from ui/views_bridge_mac/cocoa_mouse_capture_delegate.h rename to components/remote_cocoa/app_shim/mouse_capture_delegate.h index 41093fa..89a1f297 100644 --- a/ui/views_bridge_mac/cocoa_mouse_capture_delegate.h +++ b/components/remote_cocoa/app_shim/mouse_capture_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_DELEGATE_H_ -#define UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_DELEGATE_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_DELEGATE_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_DELEGATE_H_ @class NSEvent; @class NSWindow; @@ -28,4 +28,4 @@ } // namespace views_bridge_mac -#endif // UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_DELEGATE_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_DELEGATE_H_
diff --git a/ui/views_bridge_mac/native_widget_mac_frameless_nswindow.h b/components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.h similarity index 61% rename from ui/views_bridge_mac/native_widget_mac_frameless_nswindow.h rename to components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.h index afe3482..805f4ef 100644 --- a/ui/views_bridge_mac/native_widget_mac_frameless_nswindow.h +++ b/components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_ -#define UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_ -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" // Overrides contentRect <-> frameRect conversion methods to keep them equal to // each other, even for windows that do not use NSBorderlessWindowMask. This @@ -14,4 +14,4 @@ @interface NativeWidgetMacFramelessNSWindow : NativeWidgetMacNSWindow @end -#endif // UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_MAC_FRAMELESS_NSWINDOW_H_
diff --git a/ui/views_bridge_mac/native_widget_mac_frameless_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.mm similarity index 89% rename from ui/views_bridge_mac/native_widget_mac_frameless_nswindow.mm rename to components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.mm index 583003b9..8416c7c 100644 --- a/ui/views_bridge_mac/native_widget_mac_frameless_nswindow.mm +++ b/components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/native_widget_mac_frameless_nswindow.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_frameless_nswindow.h" @interface NSWindow (PrivateAPI) + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
diff --git a/ui/views_bridge_mac/native_widget_mac_nswindow.h b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h similarity index 80% rename from ui/views_bridge_mac/native_widget_mac_nswindow.h rename to components/remote_cocoa/app_shim/native_widget_mac_nswindow.h index 04636461..5b481e48 100644 --- a/ui/views_bridge_mac/native_widget_mac_nswindow.h +++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_ -#define UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_MAC_NSWINDOW_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_MAC_NSWINDOW_H_ #import <Cocoa/Cocoa.h> #include "base/mac/foundation_util.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" #import "ui/base/cocoa/command_dispatcher.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" namespace views { class BridgedNativeWidgetImpl; @@ -26,18 +26,18 @@ @interface NSThemeFrame : NSView @end -VIEWS_BRIDGE_MAC_EXPORT +REMOTE_COCOA_APP_SHIM_EXPORT @interface NativeWidgetMacNSWindowBorderlessFrame : NSNextStepFrame @end -VIEWS_BRIDGE_MAC_EXPORT +REMOTE_COCOA_APP_SHIM_EXPORT @interface NativeWidgetMacNSWindowTitledFrame : NSThemeFrame @end // The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that // can only be accomplished by overriding methods. -VIEWS_BRIDGE_MAC_EXPORT -@interface NativeWidgetMacNSWindow : NSWindow<CommandDispatchingWindow> +REMOTE_COCOA_APP_SHIM_EXPORT +@interface NativeWidgetMacNSWindow : NSWindow <CommandDispatchingWindow> // Set a CommandDispatcherDelegate, i.e. to implement key event handling. - (void)setCommandDispatcherDelegate:(id<CommandDispatcherDelegate>)delegate; @@ -61,4 +61,4 @@ @property(assign, nonatomic) views::BridgedNativeWidgetImpl* bridgeImpl; @end -#endif // UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_MAC_NSWINDOW_H_
diff --git a/ui/views_bridge_mac/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm similarity index 96% rename from ui/views_bridge_mac/native_widget_mac_nswindow.mm rename to components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm index ef634ee..aa2bb3a 100644 --- a/ui/views_bridge_mac/native_widget_mac_nswindow.mm +++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" #include "base/mac/foundation_util.h" #import "base/mac/sdk_forward_declarations.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h" +#import "components/remote_cocoa/app_shim/window_touch_bar_delegate.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #import "ui/base/cocoa/user_interface_item_command_handler.h" #import "ui/base/cocoa/window_size_constants.h" -#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" -#import "ui/views_bridge_mac/views_nswindow_delegate.h" -#import "ui/views_bridge_mac/window_touch_bar_delegate.h" @interface NSWindow (Private) + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle;
diff --git a/components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h b/components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h new file mode 100644 index 0000000..ccc66f2 --- /dev/null +++ b/components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h
@@ -0,0 +1,32 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_REMOTE_COCOA_APP_SHIM_EXPORT_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_REMOTE_COCOA_APP_SHIM_EXPORT_H_ + +// Defines REMOTE_COCOA_APP_SHIM_EXPORT so that functionality implemented by the +// RemoteMacViews module can be exported to consumers. + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION) +#define REMOTE_COCOA_APP_SHIM_EXPORT __declspec(dllexport) +#else +#define REMOTE_COCOA_APP_SHIM_EXPORT __declspec(dllimport) +#endif // defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION) +#define REMOTE_COCOA_APP_SHIM_EXPORT __attribute__((visibility("default"))) +#else +#define REMOTE_COCOA_APP_SHIM_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define REMOTE_COCOA_APP_SHIM_EXPORT +#endif + +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_REMOTE_COCOA_APP_SHIM_EXPORT_H_
diff --git a/ui/views_bridge_mac/views_nswindow_delegate.h b/components/remote_cocoa/app_shim/views_nswindow_delegate.h similarity index 79% rename from ui/views_bridge_mac/views_nswindow_delegate.h rename to components/remote_cocoa/app_shim/views_nswindow_delegate.h index 247ee4a..29761e4 100644 --- a/ui/views_bridge_mac/views_nswindow_delegate.h +++ b/components/remote_cocoa/app_shim/views_nswindow_delegate.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_ -#define UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_VIEWS_NSWINDOW_DELEGATE_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_VIEWS_NSWINDOW_DELEGATE_H_ #import <Cocoa/Cocoa.h> #import "base/mac/scoped_nsobject.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" namespace views { class BridgedNativeWidgetImpl; @@ -16,8 +16,8 @@ // The delegate set on the NSWindow when a views::BridgedNativeWidgetImpl is // initialized. -VIEWS_BRIDGE_MAC_EXPORT -@interface ViewsNSWindowDelegate : NSObject<NSWindowDelegate> { +REMOTE_COCOA_APP_SHIM_EXPORT +@interface ViewsNSWindowDelegate : NSObject <NSWindowDelegate> { @private views::BridgedNativeWidgetImpl* parent_; // Weak. Owns this. base::scoped_nsobject<NSCursor> cursor_; @@ -48,4 +48,4 @@ @end -#endif // UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_VIEWS_NSWINDOW_DELEGATE_H_
diff --git a/ui/views_bridge_mac/views_nswindow_delegate.mm b/components/remote_cocoa/app_shim/views_nswindow_delegate.mm similarity index 94% rename from ui/views_bridge_mac/views_nswindow_delegate.mm rename to components/remote_cocoa/app_shim/views_nswindow_delegate.mm index 3fbbec3..39e05b8 100644 --- a/ui/views_bridge_mac/views_nswindow_delegate.mm +++ b/components/remote_cocoa/app_shim/views_nswindow_delegate.mm
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/views_nswindow_delegate.h" +#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h" #include "base/bind.h" #include "base/logging.h" #include "base/mac/mac_util.h" #include "base/threading/thread_task_runner_handle.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" @implementation ViewsNSWindowDelegate @@ -62,7 +62,7 @@ break; currentWindow = parentWindow; if ([currentWindow isKeyWindow]) { - [(newCursor ? newCursor : [NSCursor arrowCursor])set]; + [(newCursor ? newCursor : [NSCursor arrowCursor]) set]; break; } } @@ -211,8 +211,7 @@ int32_t sheetPositionY = 0; parent_->host()->GetSheetOffsetY(&sheetPositionY); NSView* view = [window contentView]; - NSPoint pointInView = - NSMakePoint(0, NSMaxY([view bounds]) - sheetPositionY); + NSPoint pointInView = NSMakePoint(0, NSMaxY([view bounds]) - sheetPositionY); NSPoint pointInWindow = [view convertPoint:pointInView toView:nil]; // As per NSWindowDelegate documentation, the origin indicates the top left
diff --git a/ui/views_bridge_mac/views_scrollbar_bridge.h b/components/remote_cocoa/app_shim/views_scrollbar_bridge.h similarity index 77% rename from ui/views_bridge_mac/views_scrollbar_bridge.h rename to components/remote_cocoa/app_shim/views_scrollbar_bridge.h index 11d4fdb..a58f7fe 100644 --- a/ui/views_bridge_mac/views_scrollbar_bridge.h +++ b/components/remote_cocoa/app_shim/views_scrollbar_bridge.h
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_VIEWS_SCROLLBAR_BRIDGE_H_ -#define UI_VIEWS_BRIDGE_MAC_VIEWS_SCROLLBAR_BRIDGE_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_VIEWS_SCROLLBAR_BRIDGE_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_VIEWS_SCROLLBAR_BRIDGE_H_ #import <Cocoa/Cocoa.h> #import "base/mac/scoped_nsobject.h" -#include "ui/views_bridge_mac/views_bridge_mac_export.h" +#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" // The delegate set to ViewsScrollbarBridge. -class VIEWS_BRIDGE_MAC_EXPORT ViewsScrollbarBridgeDelegate { +class REMOTE_COCOA_APP_SHIM_EXPORT ViewsScrollbarBridgeDelegate { public: // Invoked by ViewsScrollbarBridge when the system informs the process that // the preferred scroller style has changed @@ -20,7 +20,7 @@ // A bridge to NSScroller managed by NativeCocoaScrollbar. Serves as a helper // class to bridge NSScroller notifications and functions to CocoaScrollbar. -VIEWS_BRIDGE_MAC_EXPORT +REMOTE_COCOA_APP_SHIM_EXPORT @interface ViewsScrollbarBridge : NSObject { @private ViewsScrollbarBridgeDelegate* delegate_; // Weak. Owns this.
diff --git a/ui/views_bridge_mac/views_scrollbar_bridge.mm b/components/remote_cocoa/app_shim/views_scrollbar_bridge.mm similarity index 94% rename from ui/views_bridge_mac/views_scrollbar_bridge.mm rename to components/remote_cocoa/app_shim/views_scrollbar_bridge.mm index 2e7eea3..6efbd9d 100644 --- a/ui/views_bridge_mac/views_scrollbar_bridge.mm +++ b/components/remote_cocoa/app_shim/views_scrollbar_bridge.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/views_scrollbar_bridge.h" +#import "components/remote_cocoa/app_shim/views_scrollbar_bridge.h" #import "base/mac/sdk_forward_declarations.h"
diff --git a/ui/views_bridge_mac/cocoa_window_move_loop.h b/components/remote_cocoa/app_shim/window_move_loop.h similarity index 87% rename from ui/views_bridge_mac/cocoa_window_move_loop.h rename to components/remote_cocoa/app_shim/window_move_loop.h index ff074d8..5f50adf 100644 --- a/ui/views_bridge_mac/cocoa_window_move_loop.h +++ b/components/remote_cocoa/app_shim/window_move_loop.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_ -#define UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_MOVE_LOOP_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_MOVE_LOOP_H_ #import <Cocoa/Cocoa.h> @@ -50,4 +50,4 @@ } // namespace views -#endif // UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_MOVE_LOOP_H_
diff --git a/ui/views_bridge_mac/cocoa_window_move_loop.mm b/components/remote_cocoa/app_shim/window_move_loop.mm similarity index 93% rename from ui/views_bridge_mac/cocoa_window_move_loop.mm rename to components/remote_cocoa/app_shim/window_move_loop.mm index f35e625..61159a8 100644 --- a/ui/views_bridge_mac/cocoa_window_move_loop.mm +++ b/components/remote_cocoa/app_shim/window_move_loop.mm
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/views_bridge_mac/cocoa_window_move_loop.h" +#include "components/remote_cocoa/app_shim/window_move_loop.h" #include "base/debug/stack_trace.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "components/crash/core/common/crash_key.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "ui/display/screen.h" #import "ui/gfx/mac/coordinate_conversion.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" // When event monitors process the events the full list of monitors is cached, // and if we unregister the event monitor that's at the end of the list while @@ -113,8 +113,8 @@ strong->quit_closure_.Run(); return event; // Process the MouseUp. }; - id monitor = - [NSEvent addLocalMonitorForEventsMatchingMask:mask handler:handler]; + id monitor = [NSEvent addLocalMonitorForEventsMatchingMask:mask + handler:handler]; run_loop.Run(); [NSEvent removeMonitor:monitor];
diff --git a/ui/views_bridge_mac/window_touch_bar_delegate.h b/components/remote_cocoa/app_shim/window_touch_bar_delegate.h similarity index 62% rename from ui/views_bridge_mac/window_touch_bar_delegate.h rename to components/remote_cocoa/app_shim/window_touch_bar_delegate.h index 9de8671..d222c524 100644 --- a/ui/views_bridge_mac/window_touch_bar_delegate.h +++ b/components/remote_cocoa/app_shim/window_touch_bar_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_ -#define UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_ +#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_TOUCH_BAR_DELEGATE_H_ +#define COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_TOUCH_BAR_DELEGATE_H_ #import <Cocoa/Cocoa.h> @@ -11,11 +11,11 @@ // Bridge delegate class for NativeWidgetMacNSWindow and // BrowserWindowTouchBarMac. -@protocol WindowTouchBarDelegate<NSObject> +@protocol WindowTouchBarDelegate <NSObject> // Creates and returns a touch bar for the browser window. - (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2)); @end -#endif // UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_ +#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_TOUCH_BAR_DELEGATE_H_
diff --git a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java index 01054b7..12314097 100644 --- a/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java +++ b/components/variations/android/java/src/org/chromium/components/variations/firstrun/VariationsSeedFetcher.java
@@ -9,13 +9,13 @@ import android.support.annotation.IntDef; import org.chromium.base.ContextUtils; +import org.chromium.base.FileUtils; import org.chromium.base.Log; import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.CachedMetrics.SparseHistogramSample; import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Retention; @@ -47,7 +47,6 @@ private static final String VARIATIONS_SERVER_URL = "https://clientservices.googleapis.com/chrome-variations/seed?osname="; - private static final int BUFFER_SIZE = 4096; private static final int READ_TIMEOUT = 3000; // time in ms private static final int REQUEST_TIMEOUT = 1000; // time in ms @@ -272,22 +271,6 @@ } } - /** - * Convert a input stream into a byte array. - * @param inputStream the input stream - * @return the byte array which holds the data from the input stream - * @throws IOException if I/O error occurs when reading data from the input stream - */ - public static byte[] convertInputStreamToByteArray(InputStream inputStream) throws IOException { - ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); - byte[] buffer = new byte[BUFFER_SIZE]; - int charactersReadCount = 0; - while ((charactersReadCount = inputStream.read(buffer)) != -1) { - byteBuffer.write(buffer, 0, charactersReadCount); - } - return byteBuffer.toByteArray(); - } - private String getHeaderFieldOrEmpty(HttpURLConnection connection, String name) { String headerField = connection.getHeaderField(name); if (headerField == null) { @@ -300,7 +283,7 @@ InputStream inputStream = null; try { inputStream = connection.getInputStream(); - return convertInputStreamToByteArray(inputStream); + return FileUtils.readStream(inputStream); } finally { if (inputStream != null) { inputStream.close();
diff --git a/content/browser/child_process_launcher_helper_android.cc b/content/browser/child_process_launcher_helper_android.cc index 50f5ee1..bed56cf 100644 --- a/content/browser/child_process_launcher_helper_android.cc +++ b/content/browser/child_process_launcher_helper_android.cc
@@ -190,7 +190,8 @@ jboolean clean_exit, jint remaining_process_with_strong_binding, jint remaining_process_with_moderate_binding, - jint remaining_process_with_waived_binding) { + jint remaining_process_with_waived_binding, + jint reverse_rank) { ChildProcessTerminationInfo* info = reinterpret_cast<ChildProcessTerminationInfo*>(termination_info_ptr); info->binding_state = @@ -203,6 +204,7 @@ remaining_process_with_moderate_binding; info->remaining_process_with_waived_binding = remaining_process_with_waived_binding; + info->best_effort_reverse_rank = reverse_rank; } // static
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc index 5c029100..b5dfc64 100644 --- a/content/browser/media/media_web_contents_observer.cc +++ b/content/browser/media/media_web_contents_observer.cc
@@ -9,8 +9,10 @@ #include "build/build_config.h" #include "content/browser/media/audible_metrics.h" #include "content/browser/media/audio_stream_monitor.h" +#include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/media/media_player_delegate_messages.h" +#include "content/public/browser/picture_in_picture_window_controller.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "ipc/ipc_message_macros.h"
diff --git a/content/browser/picture_in_picture/picture_in_picture_session.cc b/content/browser/picture_in_picture/picture_in_picture_session.cc index 0e6c05f..641f514e2 100644 --- a/content/browser/picture_in_picture/picture_in_picture_session.cc +++ b/content/browser/picture_in_picture/picture_in_picture_session.cc
@@ -7,6 +7,7 @@ #include "content/browser/picture_in_picture/picture_in_picture_service_impl.h" #include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/media/media_player_delegate_messages.h" namespace content { @@ -76,7 +77,7 @@ if (is_stopping_) return; - StopInternal(base::NullCallback()); + StopInternal(base::DoNothing()); } void PictureInPictureSession::StopInternal(StopCallback callback) { @@ -86,12 +87,13 @@ GetWebContentsImpl()->ExitPictureInPicture(); - // `OnStopped()` should only be called if there is no callback to run, as a - // contract in the API. - if (callback) - std::move(callback).Run(); - else - observer_->OnStopped(); + std::move(callback).Run(); + + // TODO(mlamouri): move to observer_->Stop(); + player_id_->render_frame_host->Send( + new MediaPlayerDelegateMsg_EndPictureInPictureMode( + player_id_->render_frame_host->GetRoutingID(), + player_id_->delegate_id)); if (auto* controller = GetController()) controller->SetActiveSession(nullptr); @@ -102,7 +104,7 @@ void PictureInPictureSession::OnConnectionError() { // StopInternal() will self destruct which will close the bindings. - StopInternal(base::NullCallback()); + StopInternal(base::DoNothing()); } WebContentsImpl* PictureInPictureSession::GetWebContentsImpl() {
diff --git a/content/browser/service_worker/fake_service_worker.cc b/content/browser/service_worker/fake_service_worker.cc index bbc0a43..12ea329 100644 --- a/content/browser/service_worker/fake_service_worker.cc +++ b/content/browser/service_worker/fake_service_worker.cc
@@ -150,7 +150,7 @@ void FakeServiceWorker::DispatchPeriodicSyncEvent( const std::string& tag, base::TimeDelta timeout, - DispatchSyncEventCallback callback) { + DispatchPeriodicSyncEventCallback callback) { NOTIMPLEMENTED(); }
diff --git a/content/browser/service_worker/fake_service_worker.h b/content/browser/service_worker/fake_service_worker.h index e565c4f..ed00f5e1 100644 --- a/content/browser/service_worker/fake_service_worker.h +++ b/content/browser/service_worker/fake_service_worker.h
@@ -86,9 +86,10 @@ bool last_chance, base::TimeDelta timeout, DispatchSyncEventCallback callback) override; - void DispatchPeriodicSyncEvent(const std::string& tag, - base::TimeDelta timeout, - DispatchSyncEventCallback callback) override; + void DispatchPeriodicSyncEvent( + const std::string& tag, + base::TimeDelta timeout, + DispatchPeriodicSyncEventCallback callback) override; void DispatchAbortPaymentEvent( payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchAbortPaymentEventCallback callback) override;
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 34d96aa8..7a09b30 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -50,7 +50,6 @@ #include "third_party/blink/public/resources/grit/blink_resources.h" #include "third_party/zlib/google/compression_utils.h" #include "ui/base/layout.h" -#include "ui/base/ui_base_features.h" #include "ui/events/gestures/blink/web_gesture_curve_impl.h" #if defined(OS_ANDROID) @@ -78,8 +77,6 @@ #if defined(OS_ANDROID) return std::make_unique<WebThemeEngineAndroid>(); #elif defined(OS_MACOSX) - if (features::IsFormControlsRefreshEnabled()) - return std::make_unique<WebThemeEngineDefault>(); return std::make_unique<WebThemeEngineMac>(); #else return std::make_unique<WebThemeEngineDefault>();
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 160d89d..b6a8d8a 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -23,7 +23,6 @@ #include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/platform/web_runtime_features.h" -#include "ui/base/ui_base_features.h" #include "ui/events/blink/blink_features.h" #include "ui/gfx/switches.h" #include "ui/gl/gl_switches.h" @@ -502,9 +501,6 @@ WebRuntimeFeatures::EnableDisplayLocking( base::FeatureList::IsEnabled(blink::features::kDisplayLocking)); - - WebRuntimeFeatures::EnableFormControlsRefresh( - features::IsFormControlsRefreshEnabled()); } } // namespace
diff --git a/content/common/media/media_player_delegate_messages.h b/content/common/media/media_player_delegate_messages.h index e9219e9..706adc9 100644 --- a/content/common/media/media_player_delegate_messages.h +++ b/content/common/media/media_player_delegate_messages.h
@@ -13,6 +13,7 @@ #include <stdint.h> +#include "components/viz/common/surfaces/surface_id.h" #include "content/common/content_export.h" #include "ipc/ipc_message_macros.h" #include "media/base/media_content_type.h" @@ -60,6 +61,9 @@ int /* delegate_id, distinguishes instances */, double /* is_persistent */) +IPC_MESSAGE_ROUTED1(MediaPlayerDelegateMsg_EndPictureInPictureMode, + int /* delegate_id, distinguishes instances */) + // ---------------------------------------------------------------------------- // Messages from the renderer notifying the browser of playback state changes. // ----------------------------------------------------------------------------
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java index 6d5e262..3d30bd0 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java
@@ -168,6 +168,7 @@ sLauncherByPid.remove(connection.getPid()); if (mBindingManager != null) mBindingManager.removeConnection(connection); if (mRanking != null) { + setReverseRankWhenConnectionLost(mRanking.getReverseRank(connection)); mRanking.removeConnection(connection); if (mBindingManager != null) mBindingManager.rankingChanged(); } @@ -183,6 +184,10 @@ private @ChildProcessImportance int mEffectiveImportance = ChildProcessImportance.MODERATE; private boolean mVisible; + // Protects fields below that are accessed on client thread as well. + private final Object mLock = new Object(); + private int mReverseRankWhenConnectionLost; + @CalledByNative private static FileDescriptorInfo makeFdInfo( int id, int fd, boolean autoClose, long offset, long size) { @@ -423,9 +428,12 @@ if (sandboxed) { mRanking = sSandboxedChildConnectionRanking; mBindingManager = sBindingManager; + mReverseRankWhenConnectionLost = -1; } else { mRanking = null; mBindingManager = null; + // -2 means not applicable. + mReverseRankWhenConnectionLost = -2; } } @@ -441,6 +449,18 @@ return TextUtils.isEmpty(mProcessType) ? "" : mProcessType; } + private void setReverseRankWhenConnectionLost(int reverseRank) { + synchronized (mLock) { + mReverseRankWhenConnectionLost = reverseRank; + } + } + + private int getReverseRankWhenConnectionLost() { + synchronized (mLock) { + return mReverseRankWhenConnectionLost; + } + } + // Called on client (UI or IO) thread. @CalledByNative private void getTerminationInfoAndStop(long terminationInfoPtr) { @@ -450,11 +470,14 @@ // access it afterwards. if (connection == null) return; + // Note there is no guarantee that connection lost has happened. However ChildProcessRanking + // is not thread safe, so this is the best we can do. + int reverseRank = getReverseRankWhenConnectionLost(); int bindingCounts[] = connection.remainingBindingStateCountsCurrentOrWhenDied(); nativeSetTerminationInfo(terminationInfoPtr, connection.bindingStateCurrentOrWhenDied(), connection.isKilledByUs(), connection.hasCleanExit(), bindingCounts[ChildBindingState.STRONG], bindingCounts[ChildBindingState.MODERATE], - bindingCounts[ChildBindingState.WAIVED]); + bindingCounts[ChildBindingState.WAIVED], reverseRank); LauncherThread.post(() -> mLauncher.stop()); } @@ -700,5 +723,5 @@ private static native void nativeSetTerminationInfo(long termiantionInfoPtr, @ChildBindingState int bindingState, boolean killedByUs, boolean cleanExit, - int remainingStrong, int remainingModerate, int remainingWaived); + int remainingStrong, int remainingModerate, int remainingWaived, int reverseRank); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java index 2e48e5b..e3e19879 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java
@@ -66,7 +66,7 @@ return 1; } - return (int) (o1.frameDepth - o2.frameDepth); + return Long.signum(o1.frameDepth - o2.frameDepth); } @Override @@ -241,6 +241,17 @@ return mRankings.get(mRankings.size() - 1).connection; } + /** + * @return reverse rank. Eg lowest ranked connection will have value 0. + */ + public int getReverseRank(ChildProcessConnection connection) { + assert connection != null; + assert mRankings.size() > 0; + int i = indexOf(connection); + assert i != -1; + return mRankings.size() - 1 - i; + } + private int indexOf(ChildProcessConnection connection) { for (int i = 0; i < mRankings.size(); ++i) { if (mRankings.get(i).connection == connection) return i;
diff --git a/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java b/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java index 172171c0..4bbcb10f 100644 --- a/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java +++ b/content/public/android/junit/src/org/chromium/content/browser/ChildProcessRankingTest.java
@@ -230,6 +230,25 @@ } @Test + public void testFrameDepthIntOverflow() { + ChildProcessConnection c1 = createConnection(); + ChildProcessConnection c2 = createConnection(); + ChildProcessConnection c3 = createConnection(); + ChildProcessRanking ranking = new ChildProcessRanking(); + + // Native can pass up the maximum value of unsigned int. + long intOverflow = ((long) Integer.MAX_VALUE) * 2; + ranking.addConnection(c3, true /* foreground */, intOverflow - 1 /* frameDepth */, + true /* intersectsViewport */, ChildProcessImportance.NORMAL); + ranking.addConnection(c2, true /* foreground */, 10 /* frameDepth */, + true /* intersectsViewport */, ChildProcessImportance.NORMAL); + ranking.addConnection(c1, true /* foreground */, intOverflow /* frameDepth */, + true /* intersectsViewport */, ChildProcessImportance.NORMAL); + + assertRankingAndRemoveAll(ranking, new ChildProcessConnection[] {c2, c3, c1}); + } + + @Test public void testThrowExceptionWhenGoingOverLimit() { ChildProcessRanking ranking = new ChildProcessRanking(2);
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index ba9451b..ca52787 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -101,6 +101,7 @@ "child_process_data.h", "child_process_launcher_utils.h", "child_process_security_policy.h", + "child_process_termination_info.cc", "child_process_termination_info.h", "clear_site_data_utils.h", "client_certificate_delegate.h",
diff --git a/content/public/browser/child_process_termination_info.cc b/content/public/browser/child_process_termination_info.cc new file mode 100644 index 0000000..753880c --- /dev/null +++ b/content/public/browser/child_process_termination_info.cc
@@ -0,0 +1,14 @@ +// Copyright 2019 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 "content/public/browser/child_process_termination_info.h" + +namespace content { + +ChildProcessTerminationInfo::ChildProcessTerminationInfo() = default; +ChildProcessTerminationInfo::ChildProcessTerminationInfo( + const ChildProcessTerminationInfo& other) = default; +ChildProcessTerminationInfo::~ChildProcessTerminationInfo() = default; + +} // namespace content
diff --git a/content/public/browser/child_process_termination_info.h b/content/public/browser/child_process_termination_info.h index 0331f00..5087bb4 100644 --- a/content/public/browser/child_process_termination_info.h +++ b/content/public/browser/child_process_termination_info.h
@@ -8,6 +8,7 @@ #include "base/process/kill.h" #include "base/time/time.h" #include "build/build_config.h" +#include "content/common/content_export.h" #include "content/public/common/result_codes.h" #if defined(OS_ANDROID) @@ -16,7 +17,11 @@ namespace content { -struct ChildProcessTerminationInfo { +struct CONTENT_EXPORT ChildProcessTerminationInfo { + ChildProcessTerminationInfo(); + ChildProcessTerminationInfo(const ChildProcessTerminationInfo& other); + ~ChildProcessTerminationInfo(); + base::TerminationStatus status = base::TERMINATION_STATUS_NORMAL_TERMINATION; // If |status| is TERMINATION_STATUS_LAUNCH_FAILED then |exit_code| will @@ -44,6 +49,12 @@ int remaining_process_with_strong_binding = 0; int remaining_process_with_moderate_binding = 0; int remaining_process_with_waived_binding = 0; + + // Eg lowest ranked process at time of death should have value 0. + // Valid values are non-negative. + // -1 means could not be obtained due to threading restrictions. + // -2 means not applicable because process is not ranked. + int best_effort_reverse_rank = -1; #endif };
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 0d4450b..f4ccca7 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -93,7 +93,9 @@ base::TerminationStatus status, int exit_code) { has_connection_ = false; - ChildProcessTerminationInfo termination_info{status, exit_code}; + ChildProcessTerminationInfo termination_info; + termination_info.status = status; + termination_info.exit_code = exit_code; NotificationService::current()->Notify( NOTIFICATION_RENDERER_PROCESS_CLOSED, Source<RenderProcessHost>(this), Details<ChildProcessTerminationInfo>(&termination_info));
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.cc b/content/renderer/media/renderer_webmediaplayer_delegate.cc index d8cbaf1..4b8faa4 100644 --- a/content/renderer/media/renderer_webmediaplayer_delegate.cc +++ b/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -238,6 +238,8 @@ OnMediaDelegateVolumeMultiplierUpdate) IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_BecamePersistentVideo, OnMediaDelegateBecamePersistentVideo) + IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_EndPictureInPictureMode, + OnPictureInPictureModeEnded) IPC_MESSAGE_UNHANDLED(return false) IPC_END_MESSAGE_MAP() return true; @@ -353,6 +355,13 @@ observer->OnBecamePersistentVideo(value); } +void RendererWebMediaPlayerDelegate::OnPictureInPictureModeEnded( + int player_id) { + Observer* observer = id_map_.Lookup(player_id); + if (observer) + observer->OnPictureInPictureModeEnded(); +} + void RendererWebMediaPlayerDelegate::ScheduleUpdateTask() { if (!pending_update_task_) { base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.h b/content/renderer/media/renderer_webmediaplayer_delegate.h index fc39ff3..3e3921e 100644 --- a/content/renderer/media/renderer_webmediaplayer_delegate.h +++ b/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -95,6 +95,7 @@ void OnMediaDelegateSuspendAllMediaPlayers(); void OnMediaDelegateVolumeMultiplierUpdate(int player_id, double multiplier); void OnMediaDelegateBecamePersistentVideo(int player_id, bool value); + void OnPictureInPictureModeEnded(int player_id); // Schedules UpdateTask() to run soon. void ScheduleUpdateTask();
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc index 5aece72..a91b08c 100644 --- a/content/renderer/media/stream/webmediaplayer_ms.cc +++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -921,6 +921,15 @@ get_client()->OnBecamePersistentVideo(value); } +void WebMediaPlayerMS::OnPictureInPictureModeEnded() { + // It is possible for this method to be called when the player is no longer in + // Picture-in-Picture mode. + if (!client_ || !IsInPictureInPicture()) + return; + + client_->PictureInPictureStopped(); +} + bool WebMediaPlayerMS::CopyVideoTextureToPlatformTexture( gpu::gles2::GLES2Interface* gl, unsigned target,
diff --git a/content/renderer/media/stream/webmediaplayer_ms.h b/content/renderer/media/stream/webmediaplayer_ms.h index 4e29246a..138c138 100644 --- a/content/renderer/media/stream/webmediaplayer_ms.h +++ b/content/renderer/media/stream/webmediaplayer_ms.h
@@ -182,6 +182,7 @@ void OnSeekBackward(double seconds) override; void OnVolumeMultiplierUpdate(double multiplier) override; void OnBecamePersistentVideo(bool value) override; + void OnPictureInPictureModeEnded() override; void OnFirstFrameReceived(media::VideoRotation video_rotation, bool is_opaque);
diff --git a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc index 11aa5d4..6a58bcb7 100644 --- a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc +++ b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -578,6 +578,7 @@ const blink::WebString& remote_device_friendly_name) override {} void MediaRemotingStopped( blink::WebLocalizedString::Name error_msg) override {} + void PictureInPictureStopped() override {} void RequestPlay() override {} void RequestPause() override {} void RequestMuted(bool muted) override {}
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index c4f8e8b..22e1e2a 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -1148,7 +1148,7 @@ void ServiceWorkerContextClient::DispatchPeriodicSyncEvent( const std::string& tag, base::TimeDelta timeout, - DispatchSyncEventCallback callback) { + DispatchPeriodicSyncEventCallback callback) { DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); // |context_| is valid because the Mojo binding is on |worker_task_runner_|. DCHECK(context_);
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h index e777e18..7d88bb58 100644 --- a/content/renderer/service_worker/service_worker_context_client.h +++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -317,9 +317,10 @@ bool last_chance, base::TimeDelta timeout, DispatchSyncEventCallback callback) override; - void DispatchPeriodicSyncEvent(const std::string& tag, - base::TimeDelta timeout, - DispatchSyncEventCallback callback) override; + void DispatchPeriodicSyncEvent( + const std::string& tag, + base::TimeDelta timeout, + DispatchPeriodicSyncEventCallback callback) override; void DispatchAbortPaymentEvent( payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchAbortPaymentEventCallback callback) override;
diff --git a/docs/gpu/gpu_testing_bot_details.md b/docs/gpu/gpu_testing_bot_details.md index b4174e00..d90d3ed 100644 --- a/docs/gpu/gpu_testing_bot_details.md +++ b/docs/gpu/gpu_testing_bot_details.md
@@ -227,8 +227,8 @@ [infradata/config]: https://chrome-internal.googlesource.com/infradata/config [bot_config.py]: https://chrome-internal.googlesource.com/infradata/config/+/master/configs/chromium-swarm/scripts/bot_config.py -[gen.star]: https://chrome-internal.googlesource.com/infradata/config/+/master/configs/chromium-swarm/gen.star [gpu.star]: https://chrome-internal.googlesource.com/infradata/config/+/master/configs/chromium-swarm/starlark/bots/chromium/gpu.star +[main.star]: https://chrome-internal.googlesource.com/infradata/config/+/master/main.star [vms.cfg]: https://chrome-internal.googlesource.com/infradata/config/+/master/configs/gce-provider/vms.cfg ## Walkthroughs of various maintenance scenarios @@ -299,7 +299,7 @@ [zones](https://cloud.google.com/compute/docs/regions-zones/) has available capacity. - 1. Run [gen.star] to regenerate `configs/chromium-swarm/bots.cfg`. + 1. Run [main.star] to regenerate `configs/chromium-swarm/bots.cfg`. Double-check your work there. 1. Get this reviewed and landed. This step associates the VM or pool of VMs with the bot's name on the waterfall. @@ -340,7 +340,7 @@ [second example](https://chrome-internal-review.googlesource.com/1111456). - 1. Run [gen.star] to regenerate `configs/chromium-swarm/bots.cfg`. + 1. Run [main.star] to regenerate `configs/chromium-swarm/bots.cfg`. Double-check your work there. 1. Allocate new virtual machines for the bots as described in [How to set up
diff --git a/extensions/browser/api/alarms/alarm_manager.cc b/extensions/browser/api/alarms/alarm_manager.cc index 3de0227e..4129bb3 100644 --- a/extensions/browser/api/alarms/alarm_manager.cc +++ b/extensions/browser/api/alarms/alarm_manager.cc
@@ -129,10 +129,9 @@ void AlarmManager::AddAlarm(const std::string& extension_id, std::unique_ptr<Alarm> alarm, AddAlarmCallback callback) { - RunWhenReady( - extension_id, - base::BindOnce(&AlarmManager::AddAlarmWhenReady, AsWeakPtr(), - base::Passed(std::move(alarm)), std::move(callback))); + RunWhenReady(extension_id, + base::BindOnce(&AlarmManager::AddAlarmWhenReady, AsWeakPtr(), + std::move(alarm), std::move(callback))); } void AlarmManager::GetAlarm(const std::string& extension_id,
diff --git a/extensions/browser/api/execute_code_function.cc b/extensions/browser/api/execute_code_function.cc index 0e77ada9..26854ab 100644 --- a/extensions/browser/api/execute_code_function.cc +++ b/extensions/browser/api/execute_code_function.cc
@@ -250,9 +250,8 @@ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::BindOnce(&ExecuteCodeFunction:: GetFileURLAndLocalizeComponentResourceInBackground, - this, base::Passed(std::move(data)), extension_id, - extension_path, extension_default_locale, - might_require_localization), + this, std::move(data), extension_id, extension_path, + extension_default_locale, might_require_localization), base::BindOnce(&ExecuteCodeFunction::DidLoadAndLocalizeFile, this, resource_.relative_path().AsUTF8Unsafe(), true /* We assume this call always succeeds */));
diff --git a/gpu/vulkan/android/vulkan_implementation_android.cc b/gpu/vulkan/android/vulkan_implementation_android.cc index 4a40c40..bbc80413 100644 --- a/gpu/vulkan/android/vulkan_implementation_android.cc +++ b/gpu/vulkan/android/vulkan_implementation_android.cc
@@ -20,6 +20,55 @@ namespace gpu { +namespace { +bool GetAhbProps( + const VkDevice& vk_device, + AHardwareBuffer* hardware_buffer, + VkAndroidHardwareBufferFormatPropertiesANDROID* ahb_format_props, + VkAndroidHardwareBufferPropertiesANDROID* ahb_props) { + DCHECK(ahb_format_props); + DCHECK(ahb_props); + + // To obtain format properties of an Android hardware buffer, include an + // instance of VkAndroidHardwareBufferFormatPropertiesANDROID in the pNext + // chain of the VkAndroidHardwareBufferPropertiesANDROID instance passed to + // vkGetAndroidHardwareBufferPropertiesANDROID. + ahb_format_props->sType = + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; + ahb_format_props->pNext = nullptr; + + ahb_props->sType = + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; + ahb_props->pNext = ahb_format_props; + + bool result = vkGetAndroidHardwareBufferPropertiesANDROID( + vk_device, hardware_buffer, ahb_props); + if (result != VK_SUCCESS) { + LOG(ERROR) + << "GetAhbProps: vkGetAndroidHardwareBufferPropertiesANDROID failed : " + << result; + return false; + } + return true; +} + +void PopulateYcbcrInfo( + const VkAndroidHardwareBufferFormatPropertiesANDROID& ahb_format_props, + VulkanYCbCrInfo* ycbcr_info) { + DCHECK(ycbcr_info); + + ycbcr_info->suggested_ycbcr_model = ahb_format_props.suggestedYcbcrModel; + ycbcr_info->suggested_ycbcr_range = ahb_format_props.suggestedYcbcrRange; + ycbcr_info->suggested_xchroma_offset = + ahb_format_props.suggestedXChromaOffset; + ycbcr_info->suggested_ychroma_offset = + ahb_format_props.suggestedYChromaOffset; + ycbcr_info->external_format = ahb_format_props.externalFormat; + ycbcr_info->format_features = ahb_format_props.formatFeatures; +} + +} // namespace + VulkanImplementationAndroid::VulkanImplementationAndroid() = default; VulkanImplementationAndroid::~VulkanImplementationAndroid() = default; @@ -171,26 +220,11 @@ DCHECK(vk_device_memory); DCHECK(mem_allocation_size); - // To obtain format properties of an Android hardware buffer, include an - // instance of VkAndroidHardwareBufferFormatPropertiesANDROID in the pNext - // chain of the VkAndroidHardwareBufferPropertiesANDROID instance passed to - // vkGetAndroidHardwareBufferPropertiesANDROID. - VkAndroidHardwareBufferFormatPropertiesANDROID ahb_format_props; - ahb_format_props.sType = - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; - ahb_format_props.pNext = nullptr; - - VkAndroidHardwareBufferPropertiesANDROID ahb_props; - ahb_props.sType = - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; - ahb_props.pNext = &ahb_format_props; - - bool result = vkGetAndroidHardwareBufferPropertiesANDROID( - vk_device, ahb_handle.get(), &ahb_props); - if (result != VK_SUCCESS) { - LOG(ERROR) << "GetAndroidHardwareBufferProperties failed : " << result; + // Get the image format properties of an Android hardware buffer. + VkAndroidHardwareBufferFormatPropertiesANDROID ahb_format_props = {}; + VkAndroidHardwareBufferPropertiesANDROID ahb_props = {}; + if (!GetAhbProps(vk_device, ahb_handle.get(), &ahb_format_props, &ahb_props)) return false; - } // To create an image with an external format, include an instance of // VkExternalFormatANDROID in the pNext chain of VkImageCreateInfo. @@ -284,7 +318,7 @@ vk_image_info->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Create Vk Image. - result = vkCreateImage(vk_device, vk_image_info, nullptr, vk_image); + bool result = vkCreateImage(vk_device, vk_image_info, nullptr, vk_image); if (result != VK_SUCCESS) { LOG(ERROR) << "vkCreateImage failed : " << result; return false; @@ -344,16 +378,24 @@ } *mem_allocation_size = mem_alloc_info.allocationSize; - if (ycbcr_info) { - ycbcr_info->suggested_ycbcr_model = ahb_format_props.suggestedYcbcrModel; - ycbcr_info->suggested_ycbcr_range = ahb_format_props.suggestedYcbcrRange; - ycbcr_info->suggested_xchroma_offset = - ahb_format_props.suggestedXChromaOffset; - ycbcr_info->suggested_ychroma_offset = - ahb_format_props.suggestedYChromaOffset; - ycbcr_info->external_format = ahb_format_props.externalFormat; - ycbcr_info->format_features = ahb_format_props.formatFeatures; - } + if (ycbcr_info) + PopulateYcbcrInfo(ahb_format_props, ycbcr_info); + return true; +} + +bool VulkanImplementationAndroid::GetSamplerYcbcrConversionInfo( + const VkDevice& vk_device, + base::android::ScopedHardwareBufferHandle ahb_handle, + VulkanYCbCrInfo* ycbcr_info) { + DCHECK(ycbcr_info); + + // Get the image format properties of an Android hardware buffer. + VkAndroidHardwareBufferFormatPropertiesANDROID ahb_format_props = {}; + VkAndroidHardwareBufferPropertiesANDROID ahb_props = {}; + if (!GetAhbProps(vk_device, ahb_handle.get(), &ahb_format_props, &ahb_props)) + return false; + + PopulateYcbcrInfo(ahb_format_props, ycbcr_info); return true; }
diff --git a/gpu/vulkan/android/vulkan_implementation_android.h b/gpu/vulkan/android/vulkan_implementation_android.h index 8d3c29a7..f1f316e 100644 --- a/gpu/vulkan/android/vulkan_implementation_android.h +++ b/gpu/vulkan/android/vulkan_implementation_android.h
@@ -61,6 +61,10 @@ VkDeviceMemory* vk_device_memory, VkDeviceSize* mem_allocation_size, VulkanYCbCrInfo* ycbcr_info) override; + bool GetSamplerYcbcrConversionInfo( + const VkDevice& vk_device, + base::android::ScopedHardwareBufferHandle ahb_handle, + VulkanYCbCrInfo* ycbcr_info) override; private: VulkanInstance vulkan_instance_;
diff --git a/gpu/vulkan/vulkan_implementation.h b/gpu/vulkan/vulkan_implementation.h index 5e676e9..0420b31 100644 --- a/gpu/vulkan/vulkan_implementation.h +++ b/gpu/vulkan/vulkan_implementation.h
@@ -122,6 +122,12 @@ VkDeviceMemory* vk_device_memory, VkDeviceSize* mem_allocation_size, VulkanYCbCrInfo* ycbcr_info = nullptr) = 0; + + // Get the sampler ycbcr conversion information from the AHB. + virtual bool GetSamplerYcbcrConversionInfo( + const VkDevice& vk_device, + base::android::ScopedHardwareBufferHandle ahb_handle, + VulkanYCbCrInfo* ycbcr_info) = 0; #endif private:
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index 763fd973..461c1a05 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -1343,12 +1343,14 @@ builders { name: "Linux Builder" mixins: "linux-ci" + mixins: "linux-xenial" dimensions: "cores:32" } builders { name: "Linux Tests" mixins: "linux-ci" + mixins: "linux-xenial" } builders { @@ -3830,6 +3832,7 @@ } builders { mixins: "linux-try" + mixins: "linux-xenial" mixins: "goma-j150" name: "linux-rel" }
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index 511e558..86a1a2e 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -295,6 +295,7 @@ "navigation/navigation_manager_impl_unittest.mm", "navigation/navigation_manager_util_unittest.mm", "navigation/nscoder_util_unittest.mm", + "navigation/wk_back_forward_list_item_holder_unittest.mm", "navigation/wk_based_navigation_manager_impl_unittest.mm", "navigation/wk_navigation_action_policy_util_unittest.mm", "navigation/wk_navigation_action_util_unittest.mm", @@ -545,7 +546,6 @@ "web_state/ui/favicon_util_unittest.mm", "web_state/ui/html_element_fetch_request_unittest.mm", "web_state/ui/web_view_js_utils_unittest.mm", - "web_state/ui/wk_back_forward_list_item_holder_unittest.mm", "web_state/ui/wk_web_view_configuration_provider_unittest.mm", ] }
diff --git a/ios/web/navigation/BUILD.gn b/ios/web/navigation/BUILD.gn index 684ac74..816b5c8e 100644 --- a/ios/web/navigation/BUILD.gn +++ b/ios/web/navigation/BUILD.gn
@@ -53,6 +53,8 @@ "session_storage_builder.mm", "time_smoother.cc", "time_smoother.h", + "wk_back_forward_list_item_holder.h", + "wk_back_forward_list_item_holder.mm", "wk_based_navigation_manager_impl.h", "wk_based_navigation_manager_impl.mm", "wk_navigation_action_policy_util.h",
diff --git a/ios/web/web_state/ui/wk_back_forward_list_item_holder.h b/ios/web/navigation/wk_back_forward_list_item_holder.h similarity index 92% rename from ios/web/web_state/ui/wk_back_forward_list_item_holder.h rename to ios/web/navigation/wk_back_forward_list_item_holder.h index 390d781..4fc84ed 100644 --- a/ios/web/web_state/ui/wk_back_forward_list_item_holder.h +++ b/ios/web/navigation/wk_back_forward_list_item_holder.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 IOS_WEB_WEB_STATE_UI_WK_BACK_FORWARD_LIST_ITEM_HOLDER_H_ -#define IOS_WEB_WEB_STATE_UI_WK_BACK_FORWARD_LIST_ITEM_HOLDER_H_ +#ifndef IOS_WEB_NAVIGATION_WK_BACK_FORWARD_LIST_ITEM_HOLDER_H_ +#define IOS_WEB_NAVIGATION_WK_BACK_FORWARD_LIST_ITEM_HOLDER_H_ #import <WebKit/WebKit.h> @@ -71,4 +71,4 @@ } // namespace web -#endif // IOS_WEB_WEB_STATE_UI_WK_BACK_FORWARD_LIST_ITEM_HOLDER_H_ +#endif // IOS_WEB_NAVIGATION_WK_BACK_FORWARD_LIST_ITEM_HOLDER_H_
diff --git a/ios/web/web_state/ui/wk_back_forward_list_item_holder.mm b/ios/web/navigation/wk_back_forward_list_item_holder.mm similarity index 94% rename from ios/web/web_state/ui/wk_back_forward_list_item_holder.mm rename to ios/web/navigation/wk_back_forward_list_item_holder.mm index aaec35d..b072b665 100644 --- a/ios/web/web_state/ui/wk_back_forward_list_item_holder.mm +++ b/ios/web/navigation/wk_back_forward_list_item_holder.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h" +#import "ios/web/navigation/wk_back_forward_list_item_holder.h" #include "base/memory/ptr_util.h" #import "ios/web/public/navigation_item.h"
diff --git a/ios/web/web_state/ui/wk_back_forward_list_item_holder_unittest.mm b/ios/web/navigation/wk_back_forward_list_item_holder_unittest.mm similarity index 98% rename from ios/web/web_state/ui/wk_back_forward_list_item_holder_unittest.mm rename to ios/web/navigation/wk_back_forward_list_item_holder_unittest.mm index 48c1465..848b088 100644 --- a/ios/web/web_state/ui/wk_back_forward_list_item_holder_unittest.mm +++ b/ios/web/navigation/wk_back_forward_list_item_holder_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h" +#import "ios/web/navigation/wk_back_forward_list_item_holder.h" #import <WebKit/WebKit.h>
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn index a384550..40adc19 100644 --- a/ios/web/web_state/ui/BUILD.gn +++ b/ios/web/web_state/ui/BUILD.gn
@@ -54,8 +54,6 @@ "crw_web_view_scroll_view_proxy.mm", "web_kit_constants.cc", "web_kit_constants.h", - "wk_back_forward_list_item_holder.h", - "wk_back_forward_list_item_holder.mm", "wk_security_origin_util.h", "wk_security_origin_util.mm", ]
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index e4c4494..82fb494 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -60,6 +60,7 @@ #import "ios/web/navigation/navigation_item_impl.h" #import "ios/web/navigation/navigation_manager_impl.h" #include "ios/web/navigation/navigation_manager_util.h" +#import "ios/web/navigation/wk_back_forward_list_item_holder.h" #import "ios/web/navigation/wk_navigation_action_policy_util.h" #import "ios/web/navigation/wk_navigation_action_util.h" #import "ios/web/navigation/wk_navigation_util.h" @@ -104,7 +105,6 @@ #import "ios/web/web_state/ui/crw_wk_script_message_router.h" #import "ios/web/web_state/ui/favicon_util.h" #include "ios/web/web_state/ui/web_kit_constants.h" -#import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h" #import "ios/web/web_state/ui/wk_security_origin_util.h" #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" #import "ios/web/web_state/web_frame_impl.h"
diff --git a/media/blink/webmediaplayer_delegate.h b/media/blink/webmediaplayer_delegate.h index b592b21..021af49 100644 --- a/media/blink/webmediaplayer_delegate.h +++ b/media/blink/webmediaplayer_delegate.h
@@ -69,6 +69,10 @@ // Called to set as the persistent video. A persistent video should hide its // controls and go fullscreen. virtual void OnBecamePersistentVideo(bool value) = 0; + + // Called when Picture-in-Picture mode is terminated from the + // Picture-in-Picture window. + virtual void OnPictureInPictureModeEnded() = 0; }; // Returns true if the host frame is hidden or closed.
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index c8016a6..8caa8dac 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -2357,6 +2357,15 @@ MaybeSendOverlayInfoToDecoder(); } +void WebMediaPlayerImpl::OnPictureInPictureModeEnded() { + // It is possible for this method to be called when the player is no longer in + // Picture-in-Picture mode. + if (!client_ || !IsInPictureInPicture()) + return; + + client_->PictureInPictureStopped(); +} + void WebMediaPlayerImpl::SendBytesReceivedUpdate() { media_metrics_provider_->AddBytesReceived(bytes_received_since_last_update_); bytes_received_since_last_update_ = 0;
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 96723c8..f7ad9ce 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -235,6 +235,7 @@ void OnSeekBackward(double seconds) override; void OnVolumeMultiplierUpdate(double multiplier) override; void OnBecamePersistentVideo(bool value) override; + void OnPictureInPictureModeEnded() override; // Callback for when bytes are received by |chunk_demuxer_| or the UrlData // being loaded.
diff --git a/media/gpu/libyuv_image_processor.cc b/media/gpu/libyuv_image_processor.cc index 3be31ae..09c053f 100644 --- a/media/gpu/libyuv_image_processor.cc +++ b/media/gpu/libyuv_image_processor.cc
@@ -205,7 +205,7 @@ DVLOGF(4); #if defined(OS_LINUX) if (input_frame->storage_type() == VideoFrame::STORAGE_DMABUFS) { - DCHECK_NE(video_frame_mapper_, nullptr); + DCHECK_NE(video_frame_mapper_.get(), nullptr); input_frame = video_frame_mapper_->Map(std::move(input_frame)); if (!input_frame) { VLOGF(1) << "Failed to map input VideoFrame";
diff --git a/media/gpu/linux/generic_dmabuf_video_frame_mapper.cc b/media/gpu/linux/generic_dmabuf_video_frame_mapper.cc index 50028c6..def9dec 100644 --- a/media/gpu/linux/generic_dmabuf_video_frame_mapper.cc +++ b/media/gpu/linux/generic_dmabuf_video_frame_mapper.cc
@@ -132,9 +132,9 @@ std::vector<std::pair<uint8_t*, size_t>> chunks; const auto& buffer_sizes = layout.buffer_sizes(); std::vector<uint8_t*> buffer_addrs(buffer_sizes.size(), nullptr); - DCHECK_EQ(buffer_addrs.size(), dmabuf_fds.size()); + DCHECK_LE(buffer_addrs.size(), dmabuf_fds.size()); DCHECK_LE(buffer_addrs.size(), VideoFrame::kMaxPlanes); - for (size_t i = 0; i < dmabuf_fds.size(); i++) { + for (size_t i = 0; i < buffer_sizes.size(); i++) { buffer_addrs[i] = Mmap(buffer_sizes[i], dmabuf_fds[i].get()); if (!buffer_addrs[i]) { MunmapBuffers(chunks, std::move(video_frame)); @@ -149,14 +149,10 @@ const auto& planes = layout.planes(); const size_t num_of_planes = layout.num_planes(); uint8_t* plane_addrs[VideoFrame::kMaxPlanes] = {}; - if (dmabuf_fds.size() == 1) { - for (size_t i = 0; i < num_of_planes; i++) { - plane_addrs[i] = buffer_addrs[0] + planes[i].offset; - } - } else { - for (size_t i = 0; i < num_of_planes; i++) { - plane_addrs[i] = buffer_addrs[i] + planes[i].offset; - } + for (size_t i = 0; i < num_of_planes; i++) { + uint8_t* buffer = + i < buffer_addrs.size() ? buffer_addrs[i] : buffer_addrs.back(); + plane_addrs[i] = buffer + planes[i].offset; } return CreateMappedVideoFrame(std::move(video_frame), plane_addrs, chunks); }
diff --git a/mojo/public/cpp/bindings/tests/connector_unittest.cc b/mojo/public/cpp/bindings/tests/connector_unittest.cc index 9da624e..b5690c5 100644 --- a/mojo/public/cpp/bindings/tests/connector_unittest.cc +++ b/mojo/public/cpp/bindings/tests/connector_unittest.cc
@@ -543,9 +543,9 @@ base::RunLoop run_loop; another_thread.task_runner()->PostTaskAndReply( FROM_HERE, - base::Bind( + base::BindOnce( [](std::unique_ptr<Connector> connector) { connector.reset(); }, - base::Passed(std::move(connector))), + std::move(connector)), run_loop.QuitClosure()); run_loop.Run();
diff --git a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h index 17c29b09..e7da7b68 100644 --- a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h +++ b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
@@ -233,8 +233,7 @@ caller_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ForwardToCallingThread::CallAcceptAndDeleteResponder, - base::Passed(std::move(responder_)), - base::Passed(std::move(*message)))); + std::move(responder_), std::move(*message))); return true; }
diff --git a/net/BUILD.gn b/net/BUILD.gn index 5e93f8d..fa62002 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -958,6 +958,7 @@ "proxy_resolution/proxy_resolver_winhttp.cc", "proxy_resolution/proxy_resolver_winhttp.h", "proxy_resolution/proxy_retry_info.h", + "quic/address_utils.h", "quic/bidirectional_stream_quic_impl.cc", "quic/bidirectional_stream_quic_impl.h", "quic/crypto/proof_source_chromium.cc", @@ -2643,8 +2644,6 @@ "data/ssl/certificates/subjectAltName_www_example_com.pem", "data/ssl/certificates/thawte.single.pem", "data/ssl/certificates/tls_feature_extension.pem", - "data/ssl/certificates/treadclimber.pem", - "data/ssl/certificates/treadclimber.sctlist", "data/ssl/certificates/unescaped.pem", "data/ssl/certificates/unittest.key.bin", "data/ssl/certificates/unittest.originbound.der",
diff --git a/net/base/ip_endpoint.cc b/net/base/ip_endpoint.cc index b3866b9..e6115c4 100644 --- a/net/base/ip_endpoint.cc +++ b/net/base/ip_endpoint.cc
@@ -181,4 +181,8 @@ return address_ == other.address_ && port_ == other.port_; } +bool IPEndPoint::operator!=(const IPEndPoint& that) const { + return !(*this == that); +} + } // namespace net
diff --git a/net/base/ip_endpoint.h b/net/base/ip_endpoint.h index f7bb248f..fd635b6 100644 --- a/net/base/ip_endpoint.h +++ b/net/base/ip_endpoint.h
@@ -65,6 +65,7 @@ bool operator<(const IPEndPoint& that) const; bool operator==(const IPEndPoint& that) const; + bool operator!=(const IPEndPoint& that) const; private: IPAddress address_;
diff --git a/net/cert/caching_cert_verifier_unittest.cc b/net/cert/caching_cert_verifier_unittest.cc index ccdba07..4ad7e8d 100644 --- a/net/cert/caching_cert_verifier_unittest.cc +++ b/net/cert/caching_cert_verifier_unittest.cc
@@ -52,19 +52,17 @@ error = callback.GetResult(verifier_.Verify( CertVerifier::RequestParams(test_cert, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &verify_result, callback.callback(), &request, NetLogWithSource())); ASSERT_TRUE(IsCertificateError(error)); ASSERT_EQ(1u, verifier_.requests()); ASSERT_EQ(0u, verifier_.cache_hits()); ASSERT_EQ(1u, verifier_.GetCacheSize()); - error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), - &verify_result, callback.callback(), &request, NetLogWithSource()); + error = verifier_.Verify(CertVerifier::RequestParams( + test_cert, "www.example.com", 0, std::string()), + &verify_result, callback.callback(), &request, + NetLogWithSource()); // Synchronous completion. ASSERT_NE(ERR_IO_PENDING, error); ASSERT_TRUE(IsCertificateError(error)); @@ -113,8 +111,7 @@ error = callback.GetResult(verifier_.Verify( CertVerifier::RequestParams(cert_chain1, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &verify_result, callback.callback(), &request, NetLogWithSource())); ASSERT_TRUE(IsCertificateError(error)); ASSERT_EQ(1u, verifier_.requests()); @@ -123,8 +120,7 @@ error = callback.GetResult(verifier_.Verify( CertVerifier::RequestParams(cert_chain2, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &verify_result, callback.callback(), &request, NetLogWithSource())); ASSERT_TRUE(IsCertificateError(error)); ASSERT_EQ(2u, verifier_.requests());
diff --git a/net/cert/cert_verifier.cc b/net/cert/cert_verifier.cc index d29b77d..97e6721 100644 --- a/net/cert/cert_verifier.cc +++ b/net/cert/cert_verifier.cc
@@ -33,13 +33,11 @@ scoped_refptr<X509Certificate> certificate, const std::string& hostname, int flags, - const std::string& ocsp_response, - const std::string& sct_list) + const std::string& ocsp_response) : certificate_(std::move(certificate)), hostname_(hostname), flags_(flags), - ocsp_response_(ocsp_response), - sct_list_(sct_list) { + ocsp_response_(ocsp_response) { // For efficiency sake, rather than compare all of the fields for each // comparison, compute a hash of their values. This is done directly in // this class, rather than as an overloaded hash operator, for efficiency's @@ -55,7 +53,6 @@ SHA256_Update(&ctx, hostname_.data(), hostname.size()); SHA256_Update(&ctx, &flags, sizeof(flags)); SHA256_Update(&ctx, ocsp_response.data(), ocsp_response.size()); - SHA256_Update(&ctx, sct_list.data(), sct_list.size()); SHA256_Final(reinterpret_cast<uint8_t*>( base::WriteInto(&key_, SHA256_DIGEST_LENGTH + 1)), &ctx);
diff --git a/net/cert/cert_verifier.h b/net/cert/cert_verifier.h index 8ea6fac14..517dd24 100644 --- a/net/cert/cert_verifier.h +++ b/net/cert/cert_verifier.h
@@ -107,17 +107,12 @@ // |ocsp_response| is optional, but if non-empty, should contain an OCSP // response obtained via OCSP stapling. It may be ignored by the // CertVerifier. - // - // |sct_list| is optional, but if non-empty, should contain a - // SignedCertificateTimestampList from the TLS extension as described in - // RFC6962 section 3.3.1. It may be ignored by the CertVerifier. class NET_EXPORT RequestParams { public: RequestParams(scoped_refptr<X509Certificate> certificate, const std::string& hostname, int flags, - const std::string& ocsp_response, - const std::string& sct_list); + const std::string& ocsp_response); RequestParams(const RequestParams& other); ~RequestParams(); @@ -127,7 +122,6 @@ const std::string& hostname() const { return hostname_; } int flags() const { return flags_; } const std::string& ocsp_response() const { return ocsp_response_; } - const std::string& sct_list() const { return sct_list_; } bool operator==(const RequestParams& other) const; bool operator<(const RequestParams& other) const; @@ -137,7 +131,6 @@ std::string hostname_; int flags_; std::string ocsp_response_; - std::string sct_list_; // Used to optimize sorting/indexing comparisons. std::string key_;
diff --git a/net/cert/cert_verifier_unittest.cc b/net/cert/cert_verifier_unittest.cc index 9a996fb8..6bc31314 100644 --- a/net/cert/cert_verifier_unittest.cc +++ b/net/cert/cert_verifier_unittest.cc
@@ -47,44 +47,36 @@ { // Test for basic equivalence. CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), true, }, { // Test that different certificates but with the same CA and for // the same host are different validation keys. CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), CertVerifier::RequestParams(expired_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), false, }, { // Test that the same EE certificate for the same host, but with // different chains are different validation keys. CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), CertVerifier::RequestParams(combined_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), false, }, { // The same certificate, with the same chain, but for different // hosts are different validation keys. CertVerifier::RequestParams(ok_cert, "www1.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), CertVerifier::RequestParams(ok_cert, "www2.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), false, }, { @@ -92,32 +84,17 @@ // are different validation keys. CertVerifier::RequestParams( ok_cert, "www.example.test", - CertVerifier::VERIFY_DISABLE_NETWORK_FETCHES, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + CertVerifier::VERIFY_DISABLE_NETWORK_FETCHES, std::string()), CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), false, }, { // Different OCSP responses. CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - "ocsp response", - /*sct_list=*/std::string()), + "ocsp response"), CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), - false, - }, - { - // Different SignedCertificateTimestampList. - CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - "sct list"), - CertVerifier::RequestParams(ok_cert, "www.example.test", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), false, }, };
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc index 1fb2c2c5..b8ae1e99 100644 --- a/net/cert/cert_verify_proc.cc +++ b/net/cert/cert_verify_proc.cc
@@ -477,7 +477,6 @@ int CertVerifyProc::Verify(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -495,8 +494,8 @@ verify_result->verified_cert = cert; DCHECK(crl_set); - int rv = VerifyInternal(cert, hostname, ocsp_response, sct_list, flags, - crl_set, additional_trust_anchors, verify_result); + int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set, + additional_trust_anchors, verify_result); // Check for mismatched signature algorithms and unknown signature algorithms // in the chain. Also fills in the has_* booleans for the digest algorithms
diff --git a/net/cert/cert_verify_proc.h b/net/cert/cert_verify_proc.h index af2219d8..8ab3bf5 100644 --- a/net/cert/cert_verify_proc.h +++ b/net/cert/cert_verify_proc.h
@@ -80,9 +80,6 @@ // // |ocsp_response|, if non-empty, is a stapled OCSP response to use. // - // |sct_list|, if non-empty, is a SignedCertificateTimestampList from the TLS - // extension as described in RFC6962 section 3.3.1. - // // |flags| is bitwise OR'd of VerifyFlags: // // If VERIFY_REV_CHECKING_ENABLED is set in |flags|, online certificate @@ -100,7 +97,6 @@ int Verify(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -157,7 +153,6 @@ virtual int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_android.cc b/net/cert/cert_verify_proc_android.cc index 06b00ea..7bae0d2 100644 --- a/net/cert/cert_verify_proc_android.cc +++ b/net/cert/cert_verify_proc_android.cc
@@ -354,7 +354,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_android.h b/net/cert/cert_verify_proc_android.h index 9868219..eab50a7b 100644 --- a/net/cert/cert_verify_proc_android.h +++ b/net/cert/cert_verify_proc_android.h
@@ -28,7 +28,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_android_unittest.cc b/net/cert/cert_verify_proc_android_unittest.cc index 19d79a5e..6f903b3 100644 --- a/net/cert/cert_verify_proc_android_unittest.cc +++ b/net/cert/cert_verify_proc_android_unittest.cc
@@ -181,11 +181,9 @@ ASSERT_TRUE( CreateCertificateChainFromFiles({"target_one_aia.pem", "i.pem"}, &leaf)); CertVerifyResult verify_result; - EXPECT_EQ( - OK, - proc->Verify(leaf.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(OK, proc->Verify(leaf.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if the certificate does not contain an AIA URL, no AIA fetch @@ -197,11 +195,10 @@ scoped_refptr<X509Certificate> cert; ASSERT_TRUE(ReadTestCert("target_no_aia.pem", &cert)); CertVerifyResult verify_result; - EXPECT_EQ( - ERR_CERT_AUTHORITY_INVALID, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, + proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if a certificate contains one file:// URL and one http:// URL, @@ -229,11 +226,9 @@ ByMove(CreateMockRequestFromX509Certificate(OK, intermediate)))); CertVerifyResult verify_result; - EXPECT_EQ( - OK, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(OK, proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if an AIA request returns the wrong intermediate, certificate @@ -253,11 +248,10 @@ ByMove(CreateMockRequestFromX509Certificate(OK, bad_intermediate)))); CertVerifyResult verify_result; - EXPECT_EQ( - ERR_CERT_AUTHORITY_INVALID, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, + proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if an AIA request returns an error, certificate verification @@ -274,11 +268,10 @@ .WillOnce(Return(ByMove(CreateMockRequestWithError(ERR_FAILED)))); CertVerifyResult verify_result; - EXPECT_EQ( - ERR_CERT_AUTHORITY_INVALID, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, + proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if an AIA request returns an unparseable cert, certificate @@ -295,11 +288,10 @@ .WillOnce(Return(ByMove(CreateMockRequestWithInvalidCertificate()))); CertVerifyResult verify_result; - EXPECT_EQ( - ERR_CERT_AUTHORITY_INVALID, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, + proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if a certificate has two HTTP AIA URLs, they are both fetched. If @@ -330,11 +322,9 @@ ByMove(CreateMockRequestFromX509Certificate(OK, intermediate)))); CertVerifyResult verify_result; - EXPECT_EQ( - OK, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(OK, proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if an intermediate is fetched via AIA, and the intermediate itself @@ -365,11 +355,10 @@ CertVerifyResult verify_result; // This chain results in an AUTHORITY_INVALID root because |root_| is not // trusted. - EXPECT_EQ( - ERR_CERT_AUTHORITY_INVALID, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, + proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if a certificate contains six AIA URLs, only the first five are @@ -389,11 +378,10 @@ .WillOnce(Return(ByMove(CreateMockRequestWithError(ERR_FAILED)))); CertVerifyResult verify_result; - EXPECT_EQ( - ERR_CERT_AUTHORITY_INVALID, - proc->Verify(cert.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, + proc->Verify(cert.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } // Tests that if the supplied chain contains an intermediate with an AIA URL, @@ -417,11 +405,10 @@ CertVerifyResult verify_result; // This chain results in an AUTHORITY_INVALID root because |root_| is not // trusted. - EXPECT_EQ( - ERR_CERT_AUTHORITY_INVALID, - proc->Verify(leaf.get(), "target", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - empty_cert_list_, &verify_result)); + EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, + proc->Verify(leaf.get(), "target", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), empty_cert_list_, + &verify_result)); } } // namespace net
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc index b9f29ba..8f2fec34 100644 --- a/net/cert/cert_verify_proc_builtin.cc +++ b/net/cert/cert_verify_proc_builtin.cc
@@ -269,7 +269,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -563,7 +562,6 @@ X509Certificate* input_cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_ios.cc b/net/cert/cert_verify_proc_ios.cc index 1ff9410..88b6ca71 100644 --- a/net/cert/cert_verify_proc_ios.cc +++ b/net/cert/cert_verify_proc_ios.cc
@@ -12,7 +12,6 @@ #include "net/base/net_errors.h" #include "net/cert/asn1_util.h" #include "net/cert/cert_verify_result.h" -#include "net/cert/ct_serialization.h" #include "net/cert/known_roots.h" #include "net/cert/test_root_certs.h" #include "net/cert/x509_certificate.h" @@ -21,14 +20,6 @@ using base::ScopedCFTypeRef; -extern "C" { -// Declared in <Security/SecTrust.h>, available in iOS 12.1.1+ -// TODO(mattm): Remove this weak_import once chromium requires a new enough -// iOS SDK. -OSStatus SecTrustSetSignedCertificateTimestamps(SecTrustRef, CFArrayRef) - __attribute__((weak_import)); -} // extern "C" - namespace net { namespace { @@ -78,7 +69,6 @@ int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array, CFArrayRef trust_policies, CFDataRef ocsp_response_ref, - CFArrayRef sct_array_ref, ScopedCFTypeRef<SecTrustRef>* trust_ref, ScopedCFTypeRef<CFArrayRef>* verified_chain, SecTrustResultType* trust_result) { @@ -101,14 +91,6 @@ return NetErrorFromOSStatus(status); } - if (sct_array_ref) { - if (__builtin_available(iOS 12.1.1, *)) { - status = SecTrustSetSignedCertificateTimestamps(tmp_trust, sct_array_ref); - if (status) - return NetErrorFromOSStatus(status); - } - } - SecTrustResultType tmp_trust_result; status = SecTrustEvaluate(tmp_trust, &tmp_trust_result); if (status) @@ -279,7 +261,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -307,35 +288,13 @@ return ERR_OUT_OF_MEMORY; } - ScopedCFTypeRef<CFMutableArrayRef> sct_array_ref; - if (!sct_list.empty()) { - if (__builtin_available(iOS 12.1.1, *)) { - std::vector<base::StringPiece> decoded_sct_list; - if (ct::DecodeSCTList(sct_list, &decoded_sct_list)) { - sct_array_ref.reset(CFArrayCreateMutable(kCFAllocatorDefault, - decoded_sct_list.size(), - &kCFTypeArrayCallBacks)); - if (!sct_array_ref) - return ERR_OUT_OF_MEMORY; - for (const auto& sct : decoded_sct_list) { - ScopedCFTypeRef<CFDataRef> sct_ref(CFDataCreate( - kCFAllocatorDefault, reinterpret_cast<const UInt8*>(sct.data()), - base::checked_cast<CFIndex>(sct.size()))); - if (!sct_ref) - return ERR_OUT_OF_MEMORY; - CFArrayAppendValue(sct_array_ref.get(), sct_ref.get()); - } - } - } - } - ScopedCFTypeRef<SecTrustRef> trust_ref; SecTrustResultType trust_result = kSecTrustResultDeny; ScopedCFTypeRef<CFArrayRef> final_chain; - status = BuildAndEvaluateSecTrustRef( - cert_array, trust_policies, ocsp_response_ref.get(), sct_array_ref.get(), - &trust_ref, &final_chain, &trust_result); + status = BuildAndEvaluateSecTrustRef(cert_array, trust_policies, + ocsp_response_ref.get(), &trust_ref, + &final_chain, &trust_result); if (status) return NetErrorFromOSStatus(status);
diff --git a/net/cert/cert_verify_proc_ios.h b/net/cert/cert_verify_proc_ios.h index ef889be0..b2048c81 100644 --- a/net/cert/cert_verify_proc_ios.h +++ b/net/cert/cert_verify_proc_ios.h
@@ -30,7 +30,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc index fe275ec..548ce4f 100644 --- a/net/cert/cert_verify_proc_mac.cc +++ b/net/cert/cert_verify_proc_mac.cc
@@ -27,7 +27,6 @@ #include "net/cert/cert_verifier.h" #include "net/cert/cert_verify_result.h" #include "net/cert/crl_set.h" -#include "net/cert/ct_serialization.h" #include "net/cert/ev_root_ca_metadata.h" #include "net/cert/internal/certificate_policies.h" #include "net/cert/internal/parsed_certificate.h" @@ -47,14 +46,6 @@ using base::ScopedCFTypeRef; -extern "C" { -// Declared in <Security/SecTrust.h>, available in 10.14.2+ -// TODO(mattm): Remove this weak_import once chromium compiles against the -// macOS 10.14 SDK. -OSStatus SecTrustSetSignedCertificateTimestamps(SecTrustRef, CFArrayRef) - __attribute__((weak_import)); -} // extern "C" - namespace net { namespace { @@ -521,7 +512,6 @@ int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array, CFArrayRef trust_policies, CFDataRef ocsp_response_ref, - CFArrayRef sct_array_ref, int flags, CFArrayRef keychain_search_list, ScopedCFTypeRef<SecTrustRef>* trust_ref, @@ -553,14 +543,6 @@ return NetErrorFromOSStatus(status); } - if (sct_array_ref && SecTrustSetSignedCertificateTimestamps) { - if (__builtin_available(macOS 10.14.2, *)) { - status = SecTrustSetSignedCertificateTimestamps(tmp_trust, sct_array_ref); - if (status) - return NetErrorFromOSStatus(status); - } - } - CSSM_APPLE_TP_ACTION_DATA tp_action_data; memset(&tp_action_data, 0, sizeof(tp_action_data)); tp_action_data.Version = CSSM_APPLE_TP_ACTION_VERSION; @@ -633,7 +615,6 @@ int VerifyWithGivenFlags(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, const int flags, CRLSet* crl_set, CertVerifyResult* verify_result, @@ -655,28 +636,6 @@ return ERR_OUT_OF_MEMORY; } - ScopedCFTypeRef<CFMutableArrayRef> sct_array_ref; - if (!sct_list.empty()) { - if (__builtin_available(macOS 10.14.2, *)) { - std::vector<base::StringPiece> decoded_sct_list; - if (ct::DecodeSCTList(sct_list, &decoded_sct_list)) { - sct_array_ref.reset(CFArrayCreateMutable(kCFAllocatorDefault, - decoded_sct_list.size(), - &kCFTypeArrayCallBacks)); - if (!sct_array_ref) - return ERR_OUT_OF_MEMORY; - for (const auto& sct : decoded_sct_list) { - ScopedCFTypeRef<CFDataRef> sct_ref(CFDataCreate( - kCFAllocatorDefault, reinterpret_cast<const UInt8*>(sct.data()), - base::checked_cast<CFIndex>(sct.size()))); - if (!sct_ref) - return ERR_OUT_OF_MEMORY; - CFArrayAppendValue(sct_array_ref.get(), sct_ref.get()); - } - } - } - } - // Serialize all calls that may use the Keychain, to work around various // issues in OS X 10.6+ with multi-threaded access to Security.framework. base::AutoLock lock(crypto::GetMacSecurityServicesLock()); @@ -813,8 +772,7 @@ CSSM_TP_APPLE_EVIDENCE_INFO* temp_chain_info = NULL; int rv = BuildAndEvaluateSecTrustRef( - cert_array, trust_policies, ocsp_response_ref.get(), - sct_array_ref.get(), flags, + cert_array, trust_policies, ocsp_response_ref.get(), flags, scoped_alternate_keychain_search_list.get(), &temp_ref, &temp_trust_result, &temp_chain, &temp_chain_info); if (rv != OK) @@ -1045,7 +1003,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -1059,9 +1016,8 @@ GetCandidateEVPolicy(cert, &candidate_ev_policy_oid); CRLSetResult completed_chain_crl_result; - int rv = - VerifyWithGivenFlags(cert, hostname, ocsp_response, sct_list, flags, - crl_set, verify_result, &completed_chain_crl_result); + int rv = VerifyWithGivenFlags(cert, hostname, ocsp_response, flags, crl_set, + verify_result, &completed_chain_crl_result); if (rv != OK) return rv; @@ -1079,7 +1035,7 @@ // re-verification starts with a clean slate. *verify_result = input_verify_result; int tmp_rv = VerifyWithGivenFlags( - verify_result->verified_cert.get(), hostname, ocsp_response, sct_list, + verify_result->verified_cert.get(), hostname, ocsp_response, flags | VERIFY_REV_CHECKING_ENABLED, crl_set, verify_result, &completed_chain_crl_result); // If re-verification failed, return those results without setting EV
diff --git a/net/cert/cert_verify_proc_mac.h b/net/cert/cert_verify_proc_mac.h index ee4a64a6..b9bce00 100644 --- a/net/cert/cert_verify_proc_mac.h +++ b/net/cert/cert_verify_proc_mac.h
@@ -25,7 +25,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_mac_unittest.cc b/net/cert/cert_verify_proc_mac_unittest.cc index 6b2572a51..5a6044e 100644 --- a/net/cert/cert_verify_proc_mac_unittest.cc +++ b/net/cert/cert_verify_proc_mac_unittest.cc
@@ -107,10 +107,9 @@ CertVerifyResult verify_result; scoped_refptr<CertVerifyProc> verify_proc = new CertVerifyProcMac; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, crl_set.get(), CertificateList(), - &verify_result); + int error = + verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + crl_set.get(), CertificateList(), &verify_result); ASSERT_EQ(OK, error); ASSERT_EQ(0U, verify_result.cert_status); @@ -167,9 +166,8 @@ CertVerifyResult verify_result; scoped_refptr<CertVerifyProc> verify_proc = new CertVerifyProcMac; int error = verify_proc->Verify( - cert.get(), "gms.hongleong.com.my", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + cert.get(), "gms.hongleong.com.my", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), CertificateList(), &verify_result); ASSERT_EQ(OK, error); EXPECT_FALSE(verify_result.has_sha1); @@ -214,10 +212,9 @@ int flags = 0; CertVerifyResult verify_result; scoped_refptr<CertVerifyProc> verify_proc = new CertVerifyProcMac; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); }
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc index 9b430bf..7bb58da 100644 --- a/net/cert/cert_verify_proc_nss.cc +++ b/net/cert/cert_verify_proc_nss.cc
@@ -1006,7 +1006,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_nss.h b/net/cert/cert_verify_proc_nss.h index 022d675..417c4cd6 100644 --- a/net/cert/cert_verify_proc_nss.h +++ b/net/cert/cert_verify_proc_nss.h
@@ -38,7 +38,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index 8d07f0d..463073d 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -110,7 +110,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -125,7 +124,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -716,8 +714,7 @@ CRLSet* crl_set, const CertificateList& additional_trust_anchors, CertVerifyResult* verify_result) { - return verify_proc_->Verify(cert, hostname, /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, crl_set, + return verify_proc_->Verify(cert, hostname, std::string(), flags, crl_set, additional_trust_anchors, verify_result); } @@ -1356,10 +1353,9 @@ scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(dummy_result); - return verify_proc->Verify( - chain.get(), "test.example.com", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + return verify_proc->Verify(chain.get(), "test.example.com", std::string(), + flags, CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); } private: @@ -1913,10 +1909,9 @@ dummy_result.is_issued_by_known_root = true; scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(dummy_result); - error = verify_proc->Verify( - cert.get(), "webmail", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + error = verify_proc->Verify(cert.get(), "webmail", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), CertificateList(), + &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); @@ -1924,10 +1919,9 @@ dummy_result.Reset(); dummy_result.is_issued_by_known_root = false; verify_proc = base::MakeRefCounted<MockCertVerifyProc>(dummy_result); - error = verify_proc->Verify( - cert.get(), "webmail", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + error = verify_proc->Verify(cert.get(), "webmail", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), CertificateList(), + &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); } @@ -1968,10 +1962,9 @@ verify_proc = base::MakeRefCounted<MockCertVerifyProc>(symantec_result); CertVerifyResult test_result_1; - error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &test_result_1); + error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &test_result_1); EXPECT_THAT(error, IsError(ERR_CERT_SYMANTEC_LEGACY)); EXPECT_TRUE(test_result_1.cert_status & CERT_STATUS_SYMANTEC_LEGACY); @@ -1985,18 +1978,16 @@ verify_proc = base::MakeRefCounted<MockCertVerifyProc>(whitelisted_result); CertVerifyResult test_result_2; - error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &test_result_2); + error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &test_result_2); EXPECT_THAT(error, IsOk()); EXPECT_FALSE(test_result_2.cert_status & CERT_STATUS_AUTHORITY_INVALID); // ... Or the caller disabled enforcement of Symantec policies. CertVerifyResult test_result_3; error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), + cert.get(), "127.0.0.1", std::string(), CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, CRLSet::BuiltinCRLSet().get(), CertificateList(), &test_result_3); EXPECT_THAT(error, IsOk()); @@ -2028,10 +2019,9 @@ verify_proc = base::MakeRefCounted<MockCertVerifyProc>(symantec_result); CertVerifyResult test_result_1; - error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &test_result_1); + error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &test_result_1); if (feature_flag_enabled) { EXPECT_THAT(error, IsError(ERR_CERT_SYMANTEC_LEGACY)); EXPECT_TRUE(test_result_1.cert_status & CERT_STATUS_SYMANTEC_LEGACY); @@ -2050,18 +2040,16 @@ verify_proc = base::MakeRefCounted<MockCertVerifyProc>(whitelisted_result); CertVerifyResult test_result_2; - error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &test_result_2); + error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), 0, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &test_result_2); EXPECT_THAT(error, IsOk()); EXPECT_FALSE(test_result_2.cert_status & CERT_STATUS_AUTHORITY_INVALID); // ... Or the caller disabled enforcement of Symantec policies. CertVerifyResult test_result_3; error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), + cert.get(), "127.0.0.1", std::string(), CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, CRLSet::BuiltinCRLSet().get(), CertificateList(), &test_result_3); EXPECT_THAT(error, IsOk()); @@ -2246,93 +2234,6 @@ EXPECT_FALSE(verify_result.is_issued_by_known_root); } -// Test verification with a leaf that does not contain embedded SCTs, and which -// has a notBefore date after 2018/10/15, and with no |sct_list|. -// On recent macOS and iOS versions this should fail to verify. -// The iOS simulator has different verifier behavior than a real device, and -// verification succeeds on all currently available versions. If this test -// fails on iossim in the future, disable the test on TARGET_IPHONE_SIMULATOR -// and file a bug against mattm. -TEST_P(CertVerifyProcInternalTest, LeafNewerThan20181015NoScts) { - scoped_refptr<X509Certificate> chain = CreateCertificateChainFromFile( - GetTestCertsDirectory(), "treadclimber.pem", - X509Certificate::FORMAT_PEM_CERT_SEQUENCE); - ASSERT_TRUE(chain); - if (base::Time::Now() > chain->valid_expiry()) { - FAIL() << "This test uses a certificate chain which is now expired. Please " - "disable and file a bug against mattm."; - return; - } - - // Verification should pass, except on recent macOS / iOS systems. - int flags = 0; - CertVerifyResult verify_result; - int error = verify_proc()->Verify( - chain.get(), "treadclimber.com", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); - -#if defined(OS_IOS) && !TARGET_IPHONE_SIMULATOR - if (verify_proc_type() == CERT_VERIFY_PROC_IOS) { - if (__builtin_available(iOS 12.1.1, *)) { - // TODO(mattm): Check if this can this be mapped to some better error. - EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); - EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); - return; - } - } -#elif defined(OS_MACOSX) - if (verify_proc_type() == CERT_VERIFY_PROC_MAC) { - if (__builtin_available(macOS 10.14.2, *)) { - // TODO(mattm): SecTrustEvaluate just gives a generic - // CSSMERR_TP_VERIFY_ACTION_FAILED error. Not sure there's much that - // could be done about that. - EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); - EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); - return; - } - } -#endif - // On older macOS and iOS versions, and all other verifiers, verification - // should succeed: - EXPECT_THAT(error, IsOk()); - EXPECT_EQ(0U, verify_result.cert_status); - EXPECT_TRUE(verify_result.is_issued_by_known_root); -} - -// Test verification with a leaf that does not contain embedded SCTs, and which -// has a notBefore date after 2018/10/15, and passing a valid |sct_list| to -// Verify(). Verification should succeed on all platforms. (Assuming the -// verifier trusts the SCT Logs used in |sct_list|.) -TEST_P(CertVerifyProcInternalTest, LeafNewerThan20181015WithTlsSctList) { - scoped_refptr<X509Certificate> chain = CreateCertificateChainFromFile( - GetTestCertsDirectory(), "treadclimber.pem", - X509Certificate::FORMAT_PEM_CERT_SEQUENCE); - ASSERT_TRUE(chain); - if (base::Time::Now() > chain->valid_expiry()) { - FAIL() << "This test uses a certificate chain which is now expired. Please " - "disable and file a bug against mattm."; - return; - } - - std::string sct_list; - ASSERT_TRUE(base::ReadFileToString( - GetTestCertsDirectory().AppendASCII("treadclimber.sctlist"), &sct_list)); - - int flags = 0; - CertVerifyResult verify_result; - int error = verify_proc()->Verify(chain.get(), "treadclimber.com", - /*ocsp_response=*/std::string(), sct_list, - flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); - - // Since the valid |sct_list| was passed to Verify, verification should - // succeed on all verifiers and OS versions. - EXPECT_THAT(error, IsOk()); - EXPECT_EQ(0U, verify_result.cert_status); - EXPECT_TRUE(verify_result.is_issued_by_known_root); -} - // Test that CRLSets are effective in making a certificate appear to be // revoked. TEST_P(CertVerifyProcInternalTest, CRLSet) { @@ -3255,10 +3156,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); } @@ -3274,10 +3174,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); } @@ -3293,10 +3192,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); } @@ -3314,10 +3212,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); } @@ -3335,10 +3232,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); if (AreSHA1IntermediatesAllowed()) { EXPECT_THAT(error, IsOk()); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); @@ -3363,20 +3259,18 @@ // SHA-1 should be rejected by default for private roots... int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); // ... unless VERIFY_ENABLE_SHA1_LOCAL_ANCHORS was supplied. flags = CertVerifyProc::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS; verify_result.Reset(); - error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), CertificateList(), + &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); } @@ -3461,9 +3355,9 @@ // hash algorithms is done by CertVerifyProc::Verify(). scoped_refptr<CertVerifyProc> proc = new MockCertVerifyProc(CertVerifyResult()); - proc->Verify(ee_chain.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + proc->Verify(ee_chain.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), CertificateList(), + &verify_result); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD2), verify_result.has_md2); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD4), verify_result.has_md4); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD5), verify_result.has_md5); @@ -3590,10 +3484,9 @@ scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result); CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), hostname, /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), 0, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), hostname, std::string(), 0, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); if (valid) { EXPECT_THAT(error, IsOk()); EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_COMMON_NAME_INVALID); @@ -3686,10 +3579,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_EQ(OK, error); histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1); @@ -3714,9 +3606,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", "dummy response", /*sct_list=*/std::string(), - flags, CRLSet::BuiltinCRLSet().get(), CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", "dummy response", + flags, CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_EQ(OK, error); histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1); @@ -3741,10 +3633,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_EQ(OK, error); histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, false, 1); @@ -3767,10 +3658,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_EQ(OK, error); histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); @@ -3809,10 +3699,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_EQ(OK, error); histograms.ExpectUniqueSample(kTrustAnchorVerifyHistogram, kGTSRootR4HistogramID, 1); @@ -3857,10 +3746,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_EQ(OK, error); // Only GTS Root R3 should be recorded. @@ -3896,10 +3784,9 @@ int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &verify_result); + int error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), + CertificateList(), &verify_result); EXPECT_EQ(OK, error); const base::HistogramBase::Sample kUnknownRootHistogramID = 0; histograms.ExpectUniqueSample(kTrustAnchorVerifyHistogram,
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc index 2847990c..9fdb3b4 100644 --- a/net/cert/cert_verify_proc_win.cc +++ b/net/cert/cert_verify_proc_win.cc
@@ -847,7 +847,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_win.h b/net/cert/cert_verify_proc_win.h index e584906..666fa95 100644 --- a/net/cert/cert_verify_proc_win.h +++ b/net/cert/cert_verify_proc_win.h
@@ -24,7 +24,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc index 531aa0e..c578a473 100644 --- a/net/cert/multi_threaded_cert_verifier.cc +++ b/net/cert/multi_threaded_cert_verifier.cc
@@ -196,7 +196,6 @@ const scoped_refptr<X509Certificate>& cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, const scoped_refptr<CRLSet>& crl_set, const CertificateList& additional_trust_anchors) { @@ -205,7 +204,7 @@ MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives allow_base_sync_primitives; verify_result->error = verify_proc->Verify( - cert.get(), hostname, ocsp_response, sct_list, flags, crl_set.get(), + cert.get(), hostname, ocsp_response, flags, crl_set.get(), additional_trust_anchors, &verify_result->result); return verify_result; } @@ -249,8 +248,8 @@ FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&DoVerifyOnWorkerThread, verify_proc, key_.certificate(), - key_.hostname(), key_.ocsp_response(), key_.sct_list(), - flags, config.crl_set, config.additional_trust_anchors), + key_.hostname(), key_.ocsp_response(), flags, + config.crl_set, config.additional_trust_anchors), base::BindOnce(&CertVerifierJob::OnJobCompleted, weak_ptr_factory_.GetWeakPtr(), config_id)); }
diff --git a/net/cert/multi_threaded_cert_verifier_unittest.cc b/net/cert/multi_threaded_cert_verifier_unittest.cc index fac1994..5506984 100644 --- a/net/cert/multi_threaded_cert_verifier_unittest.cc +++ b/net/cert/multi_threaded_cert_verifier_unittest.cc
@@ -39,11 +39,10 @@ class MockCertVerifyProc : public CertVerifyProc { public: - MOCK_METHOD8(VerifyInternal, + MOCK_METHOD7(VerifyInternal, int(X509Certificate*, const std::string&, const std::string&, - const std::string&, int, CRLSet*, const CertificateList&, @@ -56,7 +55,7 @@ ACTION(SetCertVerifyResult) { X509Certificate* cert = arg0; - CertVerifyResult* result = arg7; + CertVerifyResult* result = arg6; result->Reset(); result->verified_cert = cert; result->cert_status = CERT_STATUS_COMMON_NAME_INVALID; @@ -64,7 +63,7 @@ ACTION(SetCertVerifyRevokedResult) { X509Certificate* cert = arg0; - CertVerifyResult* result = arg7; + CertVerifyResult* result = arg6; result->Reset(); result->verified_cert = cert; result->cert_status = CERT_STATUS_REVOKED; @@ -79,7 +78,7 @@ verifier_(mock_verify_proc_) { EXPECT_CALL(*mock_verify_proc_, SupportsAdditionalTrustAnchors()) .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_verify_proc_, VerifyInternal(_, _, _, _, _, _, _, _)) + EXPECT_CALL(*mock_verify_proc_, VerifyInternal(_, _, _, _, _, _, _)) .WillRepeatedly( DoAll(SetCertVerifyResult(), Return(ERR_CERT_COMMON_NAME_INVALID))); } @@ -105,18 +104,16 @@ TestCompletionCallback callback2; std::unique_ptr<CertVerifier::Request> request2; - error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), - &verify_result, callback.callback(), &request, NetLogWithSource()); + error = verifier_.Verify(CertVerifier::RequestParams( + test_cert, "www.example.com", 0, std::string()), + &verify_result, callback.callback(), &request, + NetLogWithSource()); ASSERT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request); - error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), - &verify_result2, callback2.callback(), &request2, NetLogWithSource()); + error = verifier_.Verify(CertVerifier::RequestParams( + test_cert, "www.example.com", 0, std::string()), + &verify_result2, callback2.callback(), &request2, + NetLogWithSource()); EXPECT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request2); error = callback.WaitForResult(); @@ -138,11 +135,10 @@ CertVerifyResult verify_result; std::unique_ptr<CertVerifier::Request> request; - error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), - &verify_result, base::BindOnce(&FailTest), &request, NetLogWithSource()); + error = verifier_.Verify(CertVerifier::RequestParams( + test_cert, "www.example.com", 0, std::string()), + &verify_result, base::BindOnce(&FailTest), &request, + NetLogWithSource()); ASSERT_THAT(error, IsError(ERR_IO_PENDING)); ASSERT_TRUE(request); request.reset(); @@ -154,8 +150,7 @@ for (int i = 0; i < 5; ++i) { error = verifier_.Verify( CertVerifier::RequestParams(test_cert, "www2.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &verify_result, callback.callback(), &request, NetLogWithSource()); ASSERT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request); @@ -185,8 +180,7 @@ ANNOTATE_SCOPED_MEMORY_LEAK; error = verifier_.Verify( CertVerifier::RequestParams(test_cert, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &verify_result, callback.callback(), &request, NetLogWithSource()); } ASSERT_THAT(error, IsError(ERR_IO_PENDING)); @@ -226,42 +220,32 @@ // Start 3 unique requests. error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, domain2, 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + CertVerifier::RequestParams(test_cert, domain2, 0, std::string()), &verify_result1, callback1.callback(), &request1, NetLogWithSource()); ASSERT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request1); error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, domain2, 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + CertVerifier::RequestParams(test_cert, domain2, 0, std::string()), &verify_result2, callback2.callback(), &request2, NetLogWithSource()); EXPECT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request2); error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, domain3, 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + CertVerifier::RequestParams(test_cert, domain3, 0, std::string()), &verify_result3, callback3.callback(), &request3, NetLogWithSource()); EXPECT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request3); // Start duplicate requests (which should join to existing jobs). error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, domain1, 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + CertVerifier::RequestParams(test_cert, domain1, 0, std::string()), &verify_result4, callback4.callback(), &request4, NetLogWithSource()); EXPECT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request4); error = verifier_.Verify( - CertVerifier::RequestParams(test_cert, domain2, 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + CertVerifier::RequestParams(test_cert, domain2, 0, std::string()), &verify_result5, callback5.callback(), &request5, NetLogWithSource()); EXPECT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request5); @@ -305,7 +289,7 @@ verifier_.SetConfig(config); EXPECT_CALL(*mock_verify_proc_, - VerifyInternal(_, _, _, _, test_config.expected_flag, _, _, _)) + VerifyInternal(_, _, _, test_config.expected_flag, _, _, _)) .WillRepeatedly( DoAll(SetCertVerifyRevokedResult(), Return(ERR_CERT_REVOKED))); @@ -314,8 +298,7 @@ std::unique_ptr<CertVerifier::Request> request; int error = verifier_.Verify( CertVerifier::RequestParams(test_cert, "www.example.com", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &verify_result, callback.callback(), &request, NetLogWithSource()); ASSERT_THAT(error, IsError(ERR_IO_PENDING)); EXPECT_TRUE(request);
diff --git a/net/cert/nss_cert_database_unittest.cc b/net/cert/nss_cert_database_unittest.cc index d2480dd..367ca2574 100644 --- a/net/cert/nss_cert_database_unittest.cc +++ b/net/cert/nss_cert_database_unittest.cc
@@ -573,10 +573,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_found_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_found_server_cert.get(), "127.0.0.1", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); } @@ -605,10 +604,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_puny_cert.get(), "xn--wgv71a119e.com", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_puny_cert.get(), "xn--wgv71a119e.com", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); } @@ -638,10 +636,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_puny_cert.get(), "xn--wgv71a119e.com", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_puny_cert.get(), "xn--wgv71a119e.com", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_EQ(0U, verify_result.cert_status); } @@ -674,10 +671,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_EQ(0U, verify_result.cert_status); } @@ -715,10 +711,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_REVOKED)); EXPECT_EQ(CERT_STATUS_REVOKED, verify_result.cert_status); } @@ -765,10 +760,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_EQ(0U, verify_result.cert_status); @@ -792,8 +786,7 @@ // Server cert should fail to verify. CertVerifyResult verify_result2; error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, crl_set_.get(), + std::string(), flags, crl_set_.get(), empty_cert_list_, &verify_result2); EXPECT_THAT(error, IsError(ERR_CERT_REVOKED)); EXPECT_EQ(CERT_STATUS_REVOKED, verify_result2.cert_status); @@ -832,10 +825,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_EQ(0U, verify_result.cert_status); @@ -846,8 +838,7 @@ // Server cert should fail to verify. CertVerifyResult verify_result2; error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, crl_set_.get(), + std::string(), flags, crl_set_.get(), empty_cert_list_, &verify_result2); EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result2.cert_status); @@ -896,10 +887,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsOk()); EXPECT_EQ(0U, verify_result.cert_status); @@ -910,8 +900,7 @@ // Server cert should fail to verify. CertVerifyResult verify_result2; error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, crl_set_.get(), + std::string(), flags, crl_set_.get(), empty_cert_list_, &verify_result2); EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result2.cert_status); @@ -960,10 +949,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify( - x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), flags, - crl_set_.get(), empty_cert_list_, &verify_result); + int error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", + std::string(), flags, crl_set_.get(), + empty_cert_list_, &verify_result); EXPECT_THAT(error, IsError(ERR_CERT_REVOKED)); EXPECT_EQ(CERT_STATUS_REVOKED, verify_result.cert_status); @@ -974,8 +962,7 @@ // Server cert should verify. CertVerifyResult verify_result2; error = verify_proc->Verify(x509_server_cert.get(), "127.0.0.1", - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, crl_set_.get(), + std::string(), flags, crl_set_.get(), empty_cert_list_, &verify_result2); EXPECT_THAT(error, IsOk()); EXPECT_EQ(0U, verify_result2.cert_status);
diff --git a/net/cert/test_root_certs_unittest.cc b/net/cert/test_root_certs_unittest.cc index 62e2365..8c2a5c0 100644 --- a/net/cert/test_root_certs_unittest.cc +++ b/net/cert/test_root_certs_unittest.cc
@@ -91,10 +91,10 @@ CertVerifyResult bad_verify_result; scoped_refptr<CertVerifyProc> verify_proc( CertVerifyProc::CreateDefault(/*cert_net_fetcher=*/nullptr)); - int bad_status = verify_proc->Verify( - test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, net::CRLSet::BuiltinCRLSet().get(), - CertificateList(), &bad_verify_result); + int bad_status = + verify_proc->Verify(test_cert.get(), "127.0.0.1", std::string(), flags, + net::CRLSet::BuiltinCRLSet().get(), CertificateList(), + &bad_verify_result); EXPECT_NE(OK, bad_status); EXPECT_NE(0u, bad_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); @@ -107,9 +107,8 @@ // TestRootCerts is successfully imbuing trust. CertVerifyResult good_verify_result; int good_status = verify_proc->Verify( - test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &good_verify_result); + test_cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), CertificateList(), &good_verify_result); EXPECT_THAT(good_status, IsOk()); EXPECT_EQ(0u, good_verify_result.cert_status); @@ -120,10 +119,10 @@ // revert to their original state, and don't linger. If trust status // lingers, it will likely break other tests in net_unittests. CertVerifyResult restored_verify_result; - int restored_status = verify_proc->Verify( - test_cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(), - CertificateList(), &restored_verify_result); + int restored_status = + verify_proc->Verify(test_cert.get(), "127.0.0.1", std::string(), flags, + CRLSet::BuiltinCRLSet().get(), CertificateList(), + &restored_verify_result); EXPECT_NE(OK, restored_status); EXPECT_NE(0u, restored_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
diff --git a/net/cert/trial_comparison_cert_verifier.cc b/net/cert/trial_comparison_cert_verifier.cc index 7f96f29..c3e71d2 100644 --- a/net/cert/trial_comparison_cert_verifier.cc +++ b/net/cert/trial_comparison_cert_verifier.cc
@@ -262,9 +262,9 @@ } // Chains were different, reverify the trial_result_.verified_cert chain // using the platform verifier and compare results again. - RequestParams reverification_params( - trial_result_.verified_cert, params_.hostname(), params_.flags(), - params_.ocsp_response(), params_.sct_list()); + RequestParams reverification_params(trial_result_.verified_cert, + params_.hostname(), params_.flags(), + params_.ocsp_response()); int rv = cert_verifier_->primary_reverifier()->Verify( reverification_params, &reverification_result_,
diff --git a/net/cert/trial_comparison_cert_verifier_unittest.cc b/net/cert/trial_comparison_cert_verifier_unittest.cc index 4d2c3a4..946523b 100644 --- a/net/cert/trial_comparison_cert_verifier_unittest.cc +++ b/net/cert/trial_comparison_cert_verifier_unittest.cc
@@ -120,7 +120,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -138,7 +137,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -163,7 +161,6 @@ int VerifyInternal(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -176,7 +173,6 @@ X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -194,11 +190,10 @@ MockCertVerifyProc() = default; // CertVerifyProc implementation: bool SupportsAdditionalTrustAnchors() const override { return false; } - MOCK_METHOD8(VerifyInternal, + MOCK_METHOD7(VerifyInternal, int(X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -288,9 +283,8 @@ base::MakeRefCounted<FakeCertVerifyProc>(OK, dummy_result), base::MakeRefCounted<NotCalledCertVerifyProc>(), base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -350,9 +344,8 @@ false /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf, "t0.test", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf, "t0.test", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -365,9 +358,8 @@ // Enable the trial and do another verification. verifier.set_trial_allowed(true); - CertVerifier::RequestParams params2(leaf, "t1.test", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params2(leaf, "t1.test", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result2; TestCompletionCallback callback2; std::unique_ptr<CertVerifier::Request> request2; @@ -432,9 +424,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf, "t0.test", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf, "t0.test", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -447,9 +438,8 @@ // Disable the trial and do another verification. verifier.set_trial_allowed(false); - CertVerifier::RequestParams params2(leaf, "t1.test", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params2(leaf, "t1.test", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result2; TestCompletionCallback callback2; std::unique_ptr<CertVerifier::Request> request2; @@ -492,9 +482,8 @@ base::MakeRefCounted<NotCalledCertVerifyProc>(), base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -543,9 +532,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -598,9 +586,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -645,9 +632,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -708,9 +694,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -769,9 +754,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -827,9 +811,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -881,12 +864,12 @@ base::MakeRefCounted<MockCertVerifyProc>(); // Primary verifier returns ok status and chain1 if verifying the leaf alone. EXPECT_CALL(*verify_proc1, - VerifyInternal(leaf_cert_1_.get(), _, _, _, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<7>(chain1_result), Return(OK))); + VerifyInternal(leaf_cert_1_.get(), _, _, _, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<6>(chain1_result), Return(OK))); // Primary verifier returns ok status and chain2 if verifying chain2. EXPECT_CALL(*verify_proc1, - VerifyInternal(cert_chain_2_.get(), _, _, _, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<7>(chain2_result), Return(OK))); + VerifyInternal(cert_chain_2_.get(), _, _, _, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<6>(chain2_result), Return(OK))); // Trial verifier returns ok status and chain2. scoped_refptr<FakeCertVerifyProc> verify_proc2 = @@ -897,9 +880,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -983,14 +965,13 @@ base::MakeRefCounted<MockCertVerifyProc>(); // Primary verifier returns ok status and different_chain if verifying leaf // alone. - EXPECT_CALL(*verify_proc1, VerifyInternal(leaf.get(), _, _, _, _, _, _, _)) + EXPECT_CALL(*verify_proc1, VerifyInternal(leaf.get(), _, _, _, _, _, _)) .WillRepeatedly( - DoAll(SetArgPointee<7>(different_chain_result), Return(OK))); + DoAll(SetArgPointee<6>(different_chain_result), Return(OK))); // Primary verifier returns ok status and nonev_chain_result if verifying // cert_chain. - EXPECT_CALL(*verify_proc1, - VerifyInternal(cert_chain.get(), _, _, _, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<7>(nonev_chain_result), Return(OK))); + EXPECT_CALL(*verify_proc1, VerifyInternal(cert_chain.get(), _, _, _, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<6>(nonev_chain_result), Return(OK))); // Trial verifier returns ok status and ev_chain_result. scoped_refptr<FakeCertVerifyProc> verify_proc2 = @@ -1001,9 +982,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf, "test.example", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf, "test.example", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1060,8 +1040,7 @@ verifier.SetConfig(config); CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1124,9 +1103,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); // Start first verification request. CertVerifyResult result_1; @@ -1200,9 +1178,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; std::unique_ptr<CertVerifier::Request> request; int error = @@ -1258,9 +1235,8 @@ base::MakeRefCounted<NotCalledCertVerifyProc>(), base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; std::unique_ptr<CertVerifier::Request> request; int error = @@ -1310,9 +1286,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1364,24 +1339,23 @@ scoped_refptr<MockCertVerifyProc> verify_proc2 = base::MakeRefCounted<MockCertVerifyProc>(); // Secondary verifier returns ok status... - EXPECT_CALL(*verify_proc2, VerifyInternal(_, _, _, _, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<7>(ok_result), Return(OK))); + EXPECT_CALL(*verify_proc2, VerifyInternal(_, _, _, _, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<6>(ok_result), Return(OK))); // ...unless it was called with REV_CHECKING_ENABLED. EXPECT_CALL( *verify_proc2, - VerifyInternal(_, _, _, _, CertVerifyProc::VERIFY_REV_CHECKING_ENABLED, _, - _, _)) + VerifyInternal(_, _, _, CertVerifyProc::VERIFY_REV_CHECKING_ENABLED, _, _, + _)) .WillRepeatedly( - DoAll(SetArgPointee<7>(revoked_result), Return(ERR_CERT_REVOKED))); + DoAll(SetArgPointee<6>(revoked_result), Return(ERR_CERT_REVOKED))); std::vector<TrialReportInfo> reports; TrialComparisonCertVerifier verifier( true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1436,17 +1410,16 @@ // REV_CHECKING_ENABLED was passed. scoped_refptr<MockCertVerifyProc> verify_proc2 = base::MakeRefCounted<MockCertVerifyProc>(); - EXPECT_CALL(*verify_proc2, VerifyInternal(_, _, _, _, _, _, _, _)) - .WillRepeatedly(DoAll(SetArgPointee<7>(ok_result), Return(OK))); + EXPECT_CALL(*verify_proc2, VerifyInternal(_, _, _, _, _, _, _)) + .WillRepeatedly(DoAll(SetArgPointee<6>(ok_result), Return(OK))); std::vector<TrialReportInfo> reports; TrialComparisonCertVerifier verifier( true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1521,9 +1494,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1585,9 +1557,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1652,9 +1623,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request; @@ -1701,9 +1671,8 @@ true /* initial_allowed */, verify_proc1, verify_proc2, base::BindRepeating(&RecordTrialReport, &reports)); - CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */); CertVerifyResult result; TestCompletionCallback callback; std::unique_ptr<CertVerifier::Request> request;
diff --git a/net/cert_net/nss_ocsp_unittest.cc b/net/cert_net/nss_ocsp_unittest.cc index 79984fff..9c42f2f 100644 --- a/net/cert_net/nss_ocsp_unittest.cc +++ b/net/cert_net/nss_ocsp_unittest.cc
@@ -150,8 +150,7 @@ int flags = 0; int error = verifier()->Verify( CertVerifier::RequestParams(test_cert, "aia-host.invalid", flags, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + std::string()), &verify_result, test_callback.callback(), &request, NetLogWithSource()); ASSERT_THAT(error, IsError(ERR_IO_PENDING));
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README index 32c7d287..a33a5bf 100644 --- a/net/data/ssl/certificates/README +++ b/net/data/ssl/certificates/README
@@ -69,11 +69,6 @@ - www.ahrn.com.pem: A certificate issued by the Legacy Symantec PKI in 2014, expires on 2019-10-27. -- treadclimber.pem: A chain where the leaf does not contain embedded SCTs, - and which has a notBefore date after 2018/10/15. Expires 2020/02/07. -- treadclimber.sctlist: The TLS encoded SignedCertificateTimestampList for the - treadclimber.pem leaf certificate. - ===== Manually generated certificates - client.p12 : A PKCS #12 file containing a client certificate and a private key created for testing. The password is "12345".
diff --git a/net/data/ssl/certificates/treadclimber.pem b/net/data/ssl/certificates/treadclimber.pem deleted file mode 100644 index bfbf8594..0000000 --- a/net/data/ssl/certificates/treadclimber.pem +++ /dev/null
@@ -1,227 +0,0 @@ -=========================================== -Certificate0: 2f3d743c3627324a11549a9e5cfd1845e6dfdd63771509f0903456411c60bda8 -=========================================== -Certificate: - Data: - Version: 3 (0x2) - Serial Number: - 8c:7f:32:24:e1:a7:ab:96:00:00:00:00:50:ed:50:f3 - Signature Algorithm: sha256WithRSAEncryption - Issuer: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2012 Entrust, Inc. - for authorized use only", CN = Entrust Certification Authority - L1K - Validity - Not Before: Feb 7 17:50:22 2019 GMT - Not After : Feb 7 18:20:21 2020 GMT - Subject: C = US, ST = Washington, L = Vancouver, O = "Nautilus, Inc.", CN = Treadclimber.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public-Key: (2048 bit) - Modulus: - 00:c5:4a:d9:1b:cb:70:54:d7:7d:57:83:53:8e:22: - ad:aa:d2:41:4a:b7:39:4e:7f:99:66:a9:7e:4f:2b: - a7:ed:17:4c:da:3b:8d:07:bd:f1:90:0b:8d:05:4d: - e0:dc:3c:19:ef:2e:fe:a3:38:30:c4:9e:8d:56:34: - 91:fe:25:65:8d:ad:46:a2:f1:fb:d0:5f:63:73:8d: - 29:f8:09:f6:9c:4d:10:5e:63:5e:bf:66:24:0c:70: - 3b:88:8f:f4:c6:ee:8f:31:68:05:0e:89:7a:7a:96: - 3a:2b:50:71:97:d3:a0:f1:95:49:11:e2:f9:c8:78: - 54:63:e8:6a:db:96:87:2d:de:18:ea:f2:43:4c:8d: - 3f:a5:76:27:fa:d9:e3:25:ba:96:60:9c:9a:9a:a9: - d3:37:3c:9c:49:28:f4:54:ce:c0:2a:e1:ce:9f:de: - f8:b5:3f:d9:1c:aa:9c:3c:9c:d0:f7:67:84:3a:3a: - bf:19:bf:e2:44:b3:13:3a:d5:94:f3:db:eb:67:7e: - da:50:9a:4a:40:e9:46:f6:5f:65:b5:21:ae:e2:4e: - 4d:02:fe:33:7f:b3:aa:0c:9c:cf:97:44:fe:28:15: - 64:26:ca:fb:07:8c:4f:40:b9:df:f5:fb:7b:e4:81: - 0e:85:16:4b:7e:80:74:df:62:3a:dd:1e:30:e8:11: - 3a:bf - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Key Usage: critical - Digital Signature, Key Encipherment - X509v3 Extended Key Usage: - TLS Web Server Authentication, TLS Web Client Authentication - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.entrust.net/level1k.crl - - X509v3 Certificate Policies: - Policy: 2.16.840.1.114028.10.1.5 - CPS: http://www.entrust.net/rpa - Policy: 2.23.140.1.2.2 - - Authority Information Access: - OCSP - URI:http://ocsp.entrust.net - CA Issuers - URI:http://aia.entrust.net/l1k-chain256.cer - - X509v3 Subject Alternative Name: - DNS:Treadclimber.com, DNS:www.Treadclimber.com, DNS:bowflexcatalog.com, DNS:www.bowflexcatalog.com, DNS:bowflexhomegyms.com, DNS:www.bowflexhomegyms.com, DNS:bowflexmaxtrainer.com, DNS:www.bowflexmaxtrainer.com, DNS:bowflexselecttech.com, DNS:www.bowflexselecttech.com, DNS:bowflexhvt.com, DNS:www.bowflexhvt.com, DNS:meethvt.com, DNS:www.meethvt.com, DNS:universalhomefitness.com, DNS:www.universalhomefitness.com, DNS:bowflexmaxtrainer.ca, DNS:www.bowflexmaxtrainer.ca, DNS:treadclimber.ca, DNS:www.treadclimber.ca - X509v3 Authority Key Identifier: - keyid:82:A2:70:74:DD:BC:53:3F:CF:7B:D4:F7:CD:7F:A7:60:C6:0A:4C:BF - - X509v3 Subject Key Identifier: - DB:F8:04:79:71:73:4C:9D:47:E0:52:C2:8A:24:7E:C4:A6:14:D2:90 - X509v3 Basic Constraints: - CA:FALSE - Signature Algorithm: sha256WithRSAEncryption - 29:86:2a:a0:6f:bf:b7:3b:7e:9e:c3:e1:bb:28:9f:45:9f:0d: - 97:fc:24:a0:9c:28:6e:7c:50:3d:c2:ee:24:50:d1:c3:55:79: - 7b:10:94:50:4c:47:91:f5:f7:b3:d9:05:62:73:26:6f:8d:8e: - 18:b5:44:ae:55:32:0d:9d:12:36:a5:3b:df:d0:c1:07:7b:f4: - a5:8b:7a:64:b6:8b:d1:de:4f:fb:6e:64:a1:e8:95:f4:69:d7: - d3:f3:5c:75:ff:24:da:4e:e5:94:4d:e2:06:dc:87:de:2f:48: - fe:69:8e:77:ac:7f:3c:6b:cc:57:08:a7:9a:c7:9d:b3:37:9b: - 0a:a6:54:0c:a4:08:e8:95:63:73:95:c5:d5:5a:7e:41:57:d2: - a7:ca:45:ba:2c:4d:46:00:2d:3d:95:02:e2:34:08:91:43:7b: - c5:aa:e1:af:cd:f1:f4:f4:b6:e2:43:f6:8d:ff:2d:7a:26:13: - f8:99:be:77:92:90:b9:86:5f:93:2c:c6:61:37:56:0f:2a:1b: - ed:ad:68:fc:16:aa:ef:b6:3e:3e:3c:97:b6:8e:e2:72:ef:cc: - 47:9a:4c:e6:55:ea:b7:81:60:bf:d7:c4:23:a8:06:6e:02:0f: - 85:2b:70:8c:0a:3d:fc:5c:be:21:46:e8:33:0f:dd:18:d3:ad: - 8b:d0:b6:6a - ------BEGIN CERTIFICATE----- -MIIG4zCCBcugAwIBAgIRAIx/MiThp6uWAAAAAFDtUPMwDQYJKoZIhvcNAQELBQAw -gboxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL -Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg -MjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxLjAs -BgNVBAMTJUVudHJ1c3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBMMUswHhcN -MTkwMjA3MTc1MDIyWhcNMjAwMjA3MTgyMDIxWjBqMQswCQYDVQQGEwJVUzETMBEG -A1UECBMKV2FzaGluZ3RvbjESMBAGA1UEBxMJVmFuY291dmVyMRcwFQYDVQQKEw5O -YXV0aWx1cywgSW5jLjEZMBcGA1UEAxMQVHJlYWRjbGltYmVyLmNvbTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVK2RvLcFTXfVeDU44irarSQUq3OU5/ -mWapfk8rp+0XTNo7jQe98ZALjQVN4Nw8Ge8u/qM4MMSejVY0kf4lZY2tRqLx+9Bf -Y3ONKfgJ9pxNEF5jXr9mJAxwO4iP9MbujzFoBQ6JenqWOitQcZfToPGVSRHi+ch4 -VGPoatuWhy3eGOryQ0yNP6V2J/rZ4yW6lmCcmpqp0zc8nEko9FTOwCrhzp/e+LU/ -2RyqnDyc0PdnhDo6vxm/4kSzEzrVlPPb62d+2lCaSkDpRvZfZbUhruJOTQL+M3+z -qgycz5dE/igVZCbK+weMT0C53/X7e+SBDoUWS36AdN9iOt0eMOgROr8CAwEAAaOC -AzEwggMtMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB -BQUHAwIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9s -ZXZlbDFrLmNybDBLBgNVHSAERDBCMDYGCmCGSAGG+mwKAQUwKDAmBggrBgEFBQcC -ARYaaHR0cDovL3d3dy5lbnRydXN0Lm5ldC9ycGEwCAYGZ4EMAQICMGgGCCsGAQUF -BwEBBFwwWjAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYI -KwYBBQUHMAKGJ2h0dHA6Ly9haWEuZW50cnVzdC5uZXQvbDFrLWNoYWluMjU2LmNl -cjCCAcMGA1UdEQSCAbowggG2ghBUcmVhZGNsaW1iZXIuY29tghR3d3cuVHJlYWRj -bGltYmVyLmNvbYISYm93ZmxleGNhdGFsb2cuY29tghZ3d3cuYm93ZmxleGNhdGFs -b2cuY29tghNib3dmbGV4aG9tZWd5bXMuY29tghd3d3cuYm93ZmxleGhvbWVneW1z -LmNvbYIVYm93ZmxleG1heHRyYWluZXIuY29tghl3d3cuYm93ZmxleG1heHRyYWlu -ZXIuY29tghVib3dmbGV4c2VsZWN0dGVjaC5jb22CGXd3dy5ib3dmbGV4c2VsZWN0 -dGVjaC5jb22CDmJvd2ZsZXhodnQuY29tghJ3d3cuYm93ZmxleGh2dC5jb22CC21l -ZXRodnQuY29tgg93d3cubWVldGh2dC5jb22CGHVuaXZlcnNhbGhvbWVmaXRuZXNz -LmNvbYIcd3d3LnVuaXZlcnNhbGhvbWVmaXRuZXNzLmNvbYIUYm93ZmxleG1heHRy -YWluZXIuY2GCGHd3dy5ib3dmbGV4bWF4dHJhaW5lci5jYYIPdHJlYWRjbGltYmVy -LmNhghN3d3cudHJlYWRjbGltYmVyLmNhMB8GA1UdIwQYMBaAFIKicHTdvFM/z3vU -981/p2DGCky/MB0GA1UdDgQWBBTb+AR5cXNMnUfgUsKKJH7EphTSkDAJBgNVHRME -AjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAphiqgb7+3O36ew+G7KJ9Fnw2X/CSgnChu -fFA9wu4kUNHDVXl7EJRQTEeR9fez2QVicyZvjY4YtUSuVTINnRI2pTvf0MEHe/Sl -i3pktovR3k/7bmSh6JX0adfT81x1/yTaTuWUTeIG3IfeL0j+aY53rH88a8xXCKea -x52zN5sKplQMpAjolWNzlcXVWn5BV9KnykW6LE1GAC09lQLiNAiRQ3vFquGvzfH0 -9LbiQ/aN/y16JhP4mb53kpC5hl+TLMZhN1YPKhvtrWj8Fqrvtj4+PJe2juJy78xH -mkzmVeq3gWC/18QjqAZuAg+FK3CMCj38XL4hRugzD90Y062L0LZq ------END CERTIFICATE----- - -=========================================== -Certificate1: d6c3fc493bacd1df8a1ba30f4ae26254b2a4528e4876081eacc6a16a090aa36a -=========================================== -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1372455166 (0x51ce00fe) - Signature Algorithm: sha256WithRSAEncryption - Issuer: O = Entrust.net, OU = www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU = (c) 1999 Entrust.net Limited, CN = Entrust.net Certification Authority (2048) - Validity - Not Before: Oct 10 15:23:17 2014 GMT - Not After : Oct 11 06:22:47 2024 GMT - Subject: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2012 Entrust, Inc. - for authorized use only", CN = Entrust Certification Authority - L1K - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public-Key: (2048 bit) - Modulus: - 00:da:3f:96:d0:4d:b9:2f:44:e7:db:39:5e:9b:50: - ee:5c:a5:61:da:41:67:53:09:aa:00:9a:8e:57:7f: - 29:6b:db:c7:e1:21:24:aa:3a:d0:8d:47:23:d2:ed: - 72:16:f0:91:21:d2:5d:b7:b8:4b:a8:83:8f:b7:91: - 32:68:cf:ce:25:93:2c:b2:7d:97:c8:fe:c1:b4:17: - ba:09:9e:03:90:93:7b:7c:49:83:22:68:8a:9b:de: - 47:c3:31:98:7a:2e:7d:40:0b:d2:ef:3e:d3:b2:8c: - aa:8f:48:a9:ff:00:e8:29:58:06:f7:b6:93:5a:94: - 73:26:26:ad:58:0e:e5:42:b8:d5:ea:73:79:64:68: - 53:25:b8:84:cf:94:7a:ae:06:45:0c:a3:6b:4d:d0: - c6:be:ea:18:a4:36:f0:92:b2:ba:1c:88:8f:3a:52: - 7f:f7:5e:6d:83:1c:9d:f0:1f:e5:c3:d6:dd:a5:78: - 92:3d:b0:6d:2c:ea:c9:cf:94:41:19:71:44:68:ba: - 47:3c:04:e9:5d:ba:3e:f0:35:f7:15:b6:9e:f2:2e: - 15:1e:3f:47:c8:c8:38:a7:73:45:5d:4d:b0:3b:b1: - 8e:17:29:37:ea:dd:05:01:22:bb:94:36:2a:8d:5b: - 35:fe:53:19:2f:08:46:c1:2a:b3:1a:62:1d:4e:2b: - d9:1b - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Key Usage: critical - Certificate Sign, CRL Sign - X509v3 Basic Constraints: critical - CA:TRUE, pathlen:0 - Authority Information Access: - OCSP - URI:http://ocsp.entrust.net - - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.entrust.net/2048ca.crl - - X509v3 Certificate Policies: - Policy: X509v3 Any Policy - CPS: http://www.entrust.net/rpa - - X509v3 Subject Key Identifier: - 82:A2:70:74:DD:BC:53:3F:CF:7B:D4:F7:CD:7F:A7:60:C6:0A:4C:BF - X509v3 Authority Key Identifier: - keyid:55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 - - Signature Algorithm: sha256WithRSAEncryption - 58:42:71:c1:3e:29:16:6e:75:58:77:b5:65:4d:9e:29:f5:ae: - 0b:1c:18:f9:a3:08:43:75:ef:7d:6d:f1:92:ea:fe:ce:68:5c: - e2:1f:be:a5:af:1a:4c:aa:83:3b:5f:a2:47:46:f7:7c:9e:c1: - 83:c4:7a:24:b0:e9:cc:e9:a2:9a:07:09:e8:1e:1d:77:56:49: - fc:53:73:a8:47:cc:c9:2d:5a:60:34:a7:1a:0b:e5:2b:b8:df: - ef:82:4a:dd:70:5e:10:18:08:3b:5d:dc:8a:84:3d:68:d8:00: - b4:c4:9e:43:78:4b:5e:f0:62:6a:8c:90:66:53:8a:ac:c5:7d: - 58:ff:4e:a9:ad:d7:a4:ca:12:47:29:e5:f3:22:21:40:32:60: - da:3a:fe:92:54:1e:43:a1:0d:a9:52:37:60:bf:87:c4:a1:c7: - 78:d5:87:1e:e5:77:e3:5f:5b:dc:71:6d:ba:44:87:31:05:80: - 58:0b:c5:de:74:28:81:83:08:84:d0:c8:46:5a:fe:8a:c6:bd: - a9:0e:3b:64:78:6d:26:dc:3c:4c:f7:81:5c:3c:11:7f:25:3a: - 93:62:a5:a3:91:05:25:23:73:b4:cd:ce:cc:39:a4:03:78:30: - 66:46:5e:a9:75:b0:b4:67:03:a9:b1:9f:57:f0:d3:76:cf:e1: - 93:e8:80:a2 - ------BEGIN CERTIFICATE----- -MIIE/jCCA+agAwIBAgIEUc4A/jANBgkqhkiG9w0BAQsFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw0xNDEwMTAxNTIzMTdaFw0yNDEw -MTEwNjIyNDdaMIG6MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5j -LjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcG -A1UECxMwKGMpIDIwMTIgRW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVz -ZSBvbmx5MS4wLAYDVQQDEyVFbnRydXN0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gTDFLMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2j+W0E25L0Tn -2zlem1DuXKVh2kFnUwmqAJqOV38pa9vH4SEkqjrQjUcj0u1yFvCRIdJdt7hLqIOP -t5EyaM/OJZMssn2XyP7BtBe6CZ4DkJN7fEmDImiKm95HwzGYei59QAvS7z7Tsoyq -j0ip/wDoKVgG97aTWpRzJiatWA7lQrjV6nN5ZGhTJbiEz5R6rgZFDKNrTdDGvuoY -pDbwkrK6HIiPOlJ/915tgxyd8B/lw9bdpXiSPbBtLOrJz5RBGXFEaLpHPATpXbo+ -8DX3Fbae8i4VHj9HyMg4p3NFXU2wO7GOFyk36t0FASK7lDYqjVs1/lMZLwhGwSqz -GmIdTivZGwIDAQABo4IBDjCCAQowDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI -MAYBAf8CAQAwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8vb2Nz -cC5lbnRydXN0Lm5ldDAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLmVudHJ1 -c3QubmV0LzIwNDhjYS5jcmwwOwYDVR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUH -AgEWGmh0dHA6Ly93d3cuZW50cnVzdC5uZXQvcnBhMB0GA1UdDgQWBBSConB03bxT -P8971PfNf6dgxgpMvzAfBgNVHSMEGDAWgBRV5IHREYC+2Im5CKMx+aEkCRa5cDAN -BgkqhkiG9w0BAQsFAAOCAQEAWEJxwT4pFm51WHe1ZU2eKfWuCxwY+aMIQ3XvfW3x -kur+zmhc4h++pa8aTKqDO1+iR0b3fJ7Bg8R6JLDpzOmimgcJ6B4dd1ZJ/FNzqEfM -yS1aYDSnGgvlK7jf74JK3XBeEBgIO13cioQ9aNgAtMSeQ3hLXvBiaoyQZlOKrMV9 -WP9Oqa3XpMoSRynl8yIhQDJg2jr+klQeQ6ENqVI3YL+HxKHHeNWHHuV3419b3HFt -ukSHMQWAWAvF3nQogYMIhNDIRlr+isa9qQ47ZHhtJtw8TPeBXDwRfyU6k2Klo5EF -JSNztM3OzDmkA3gwZkZeqXWwtGcDqbGfV/DTds/hk+iAog== ------END CERTIFICATE----- -
diff --git a/net/data/ssl/certificates/treadclimber.sctlist b/net/data/ssl/certificates/treadclimber.sctlist deleted file mode 100644 index 268a0ac..0000000 --- a/net/data/ssl/certificates/treadclimber.sctlist +++ /dev/null Binary files differ
diff --git a/net/quic/address_utils.h b/net/quic/address_utils.h new file mode 100644 index 0000000..f067db7 --- /dev/null +++ b/net/quic/address_utils.h
@@ -0,0 +1,48 @@ +#ifndef NET_QUIC_ADDRESS_UTILS_H_ +#define NET_QUIC_ADDRESS_UTILS_H_ + +#include "net/base/ip_address.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address_family.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" + +namespace net { + +inline IPEndPoint ToIPEndPoint(quic::QuicSocketAddress address) { + if (!address.IsInitialized()) { + return IPEndPoint(); + } + + IPEndPoint result; + sockaddr_storage storage = address.generic_address(); + const bool success = result.FromSockAddr( + reinterpret_cast<const sockaddr*>(&storage), sizeof(storage)); + DCHECK(success); + return result; +} + +inline IPAddress ToIPAddress(quic::QuicIpAddress address) { + if (!address.IsInitialized()) { + return IPAddress(); + } + + switch (address.address_family()) { + case quic::IpAddressFamily::IP_V4: { + in_addr raw_address = address.GetIPv4(); + return IPAddress(reinterpret_cast<const uint8_t*>(&raw_address), + sizeof(raw_address)); + } + case quic::IpAddressFamily::IP_V6: { + in6_addr raw_address = address.GetIPv6(); + return IPAddress(reinterpret_cast<const uint8_t*>(&raw_address), + sizeof(raw_address)); + } + default: + DCHECK_EQ(address.address_family(), quic::IpAddressFamily::IP_UNSPEC); + return IPAddress(); + } +} + +} // namespace net + +#endif // NET_QUIC_ADDRESS_UTILS_H_
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc index e222a7e..366894c 100644 --- a/net/quic/crypto/proof_verifier_chromium.cc +++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -80,8 +80,6 @@ quic::QuicAsyncStatus VerifyCertChain( const std::string& hostname, const std::vector<std::string>& certs, - const std::string& ocsp_response, - const std::string& cert_sct, std::string* error_details, std::unique_ptr<quic::ProofVerifyDetails>* verify_details, std::unique_ptr<quic::ProofVerifierCallback> callback); @@ -103,8 +101,6 @@ quic::QuicAsyncStatus VerifyCert( const string& hostname, const uint16_t port, - const std::string& ocsp_response, - const std::string& cert_sct, std::string* error_details, std::unique_ptr<quic::ProofVerifyDetails>* verify_details, std::unique_ptr<quic::ProofVerifierCallback> callback); @@ -137,10 +133,6 @@ std::string hostname_; // |port| specifies the target port for the connection. uint16_t port_; - // Encoded stapled OCSP response for |certs|. - std::string ocsp_response_; - // Encoded SignedCertificateTimestampList for |certs|. - std::string cert_sct_; std::unique_ptr<quic::ProofVerifierCallback> callback_; std::unique_ptr<ProofVerifyDetailsChromium> verify_details_; @@ -250,15 +242,13 @@ } DCHECK(enforce_policy_checking_); - return VerifyCert(hostname, port, /*ocsp_response=*/std::string(), cert_sct, - error_details, verify_details, std::move(callback)); + return VerifyCert(hostname, port, error_details, verify_details, + std::move(callback)); } quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyCertChain( const string& hostname, const std::vector<string>& certs, - const std::string& ocsp_response, - const std::string& cert_sct, std::string* error_details, std::unique_ptr<quic::ProofVerifyDetails>* verify_details, std::unique_ptr<quic::ProofVerifierCallback> callback) { @@ -282,8 +272,8 @@ enforce_policy_checking_ = false; // |port| is not needed because |enforce_policy_checking_| is false. - return VerifyCert(hostname, /*port=*/0, ocsp_response, cert_sct, - error_details, verify_details, std::move(callback)); + return VerifyCert(hostname, /*port=*/0, error_details, verify_details, + std::move(callback)); } bool ProofVerifierChromium::Job::GetX509Certificate( @@ -317,15 +307,11 @@ quic::QuicAsyncStatus ProofVerifierChromium::Job::VerifyCert( const string& hostname, const uint16_t port, - const std::string& ocsp_response, - const std::string& cert_sct, std::string* error_details, std::unique_ptr<quic::ProofVerifyDetails>* verify_details, std::unique_ptr<quic::ProofVerifierCallback> callback) { hostname_ = hostname; port_ = port; - ocsp_response_ = ocsp_response; - cert_sct_ = cert_sct; next_state_ = STATE_VERIFY_CERT; switch (DoLoop(OK)) { @@ -383,7 +369,7 @@ return verifier_->Verify( CertVerifier::RequestParams(cert_, hostname_, cert_verify_flags_, - ocsp_response_, cert_sct_), + std::string()), &verify_details_->cert_verify_result, base::Bind(&ProofVerifierChromium::Job::OnIOComplete, base::Unretained(this)), @@ -630,15 +616,15 @@ *error_details = "Missing context"; return quic::QUIC_FAILURE; } + // TODO(mattm): use |ocsp_response| and |cert_sct|. const ProofVerifyContextChromium* chromium_context = reinterpret_cast<const ProofVerifyContextChromium*>(verify_context); std::unique_ptr<Job> job = std::make_unique<Job>( this, cert_verifier_, ct_policy_enforcer_, transport_security_state_, cert_transparency_verifier_, chromium_context->cert_verify_flags, chromium_context->net_log); - quic::QuicAsyncStatus status = - job->VerifyCertChain(hostname, certs, ocsp_response, cert_sct, - error_details, verify_details, std::move(callback)); + quic::QuicAsyncStatus status = job->VerifyCertChain( + hostname, certs, error_details, verify_details, std::move(callback)); if (status == quic::QUIC_PENDING) { Job* job_ptr = job.get(); active_jobs_[job_ptr] = std::move(job);
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 8afe739..fdeda72 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -27,6 +27,7 @@ #include "net/http/transport_security_state.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_source_type.h" +#include "net/quic/address_utils.h" #include "net/quic/crypto/proof_verifier_chromium.h" #include "net/quic/quic_chromium_connection_helper.h" #include "net/quic/quic_chromium_packet_writer.h" @@ -491,7 +492,7 @@ if (!session_) return ERR_CONNECTION_CLOSED; - *address = session_->peer_address().impl().socket_address(); + *address = ToIPEndPoint(session_->peer_address()); return OK; } @@ -500,7 +501,7 @@ if (!session_) return ERR_CONNECTION_CLOSED; - *address = session_->self_address().impl().socket_address(); + *address = ToIPEndPoint(session_->self_address()); return OK; } @@ -829,17 +830,17 @@ net_log_.EndEvent(NetLogEventType::QUIC_SESSION); DCHECK(waiting_for_confirmation_callbacks_.empty()); - if (!dynamic_streams().empty()) + if (HasActiveRequestStreams()) RecordUnexpectedOpenStreams(DESTRUCTOR); if (!handles_.empty()) RecordUnexpectedObservers(DESTRUCTOR); if (!going_away_) RecordUnexpectedNotGoingAway(DESTRUCTOR); - while (!dynamic_streams().empty() || !handles_.empty() || + while (HasActiveRequestStreams() || !handles_.empty() || !stream_requests_.empty()) { // The session must be closed before it is destroyed. - DCHECK(dynamic_streams().empty()); + DCHECK(!HasActiveRequestStreams()); CloseAllStreams(ERR_UNEXPECTED); DCHECK(handles_.empty()); CloseAllHandles(ERR_UNEXPECTED); @@ -1173,7 +1174,7 @@ } bool QuicChromiumClientSession::GetRemoteEndpoint(IPEndPoint* endpoint) { - *endpoint = peer_address().impl().socket_address(); + *endpoint = ToIPEndPoint(peer_address()); return true; } @@ -1472,7 +1473,7 @@ // Server has sent an alternate address to connect to. IPEndPoint new_address = - config()->ReceivedAlternateServerAddress().impl().socket_address(); + ToIPEndPoint(config()->ReceivedAlternateServerAddress()); IPEndPoint old_address; GetDefaultSocket()->GetPeerAddress(&old_address); @@ -1715,7 +1716,7 @@ for (auto& socket : sockets_) { socket->Close(); } - DCHECK(dynamic_streams().empty()); + DCHECK(!HasActiveRequestStreams()); CloseAllStreams(ERR_UNEXPECTED); CloseAllHandles(ERR_UNEXPECTED); CancelAllRequests(ERR_CONNECTION_CLOSED); @@ -1864,7 +1865,7 @@ NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, NetLogQuicConnectionMigrationTriggerCallback("WriteError")); MigrationResult result = - Migrate(new_network, connection()->peer_address().impl().socket_address(), + Migrate(new_network, ToIPEndPoint(connection()->peer_address()), /*close_session_on_error=*/false, migration_net_log); migration_net_log.EndEvent( NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED); @@ -2203,7 +2204,7 @@ probing_manager_.CancelProbing(network, peer_address()); MigrationResult result = - Migrate(network, connection()->peer_address().impl().socket_address(), + Migrate(network, ToIPEndPoint(connection()->peer_address()), /*close_session_on_error=*/true, net_log_); if (result == MigrationResult::FAILURE) return; @@ -2415,11 +2416,26 @@ } void QuicChromiumClientSession::CloseAllStreams(int net_error) { - while (!dynamic_streams().empty()) { - quic::QuicStream* stream = dynamic_streams().begin()->second.get(); - quic::QuicStreamId id = stream->id(); - static_cast<QuicChromiumClientStream*>(stream)->OnError(net_error); - CloseStream(id); + if (!eliminate_static_stream_map()) { + while (!dynamic_streams().empty()) { + quic::QuicStream* stream = dynamic_streams().begin()->second.get(); + quic::QuicStreamId id = stream->id(); + static_cast<QuicChromiumClientStream*>(stream)->OnError(net_error); + CloseStream(id); + } + } else { + quic::QuicSmallMap<quic::QuicStreamId, quic::QuicStream*, 10> + non_static_streams; + for (const auto& stream : dynamic_streams()) { + if (!stream.second->is_static()) { + non_static_streams[stream.first] = stream.second.get(); + } + } + for (const auto& stream : non_static_streams) { + quic::QuicStreamId id = stream.first; + static_cast<QuicChromiumClientStream*>(stream.second)->OnError(net_error); + CloseStream(id); + } } } @@ -2494,9 +2510,9 @@ // Create and configure socket on |network|. std::unique_ptr<DatagramClientSocket> probing_socket = stream_factory_->CreateSocket(net_log_.net_log(), net_log_.source()); - if (stream_factory_->ConfigureSocket( - probing_socket.get(), peer_address.impl().socket_address(), network, - session_key_.socket_tag()) != OK) { + if (stream_factory_->ConfigureSocket(probing_socket.get(), + ToIPEndPoint(peer_address), network, + session_key_.socket_tag()) != OK) { HistogramAndLogMigrationFailure( migration_net_log, MIGRATION_STATUS_INTERNAL_ERROR, connection_id(), "Socket configuration failed"); @@ -2628,6 +2644,10 @@ auto it = dynamic_streams().begin(); // Stream may be deleted when iterating through the map. while (it != dynamic_streams().end()) { + if (eliminate_static_stream_map() && it->second->is_static()) { + it++; + continue; + } QuicChromiumClientStream* stream = static_cast<QuicChromiumClientStream*>(it->second.get()); if (!stream->can_migrate_to_cellular_network()) { @@ -2749,6 +2769,8 @@ std::unique_ptr<base::ListValue> stream_list(new base::ListValue()); for (DynamicStreamMap::const_iterator it = dynamic_streams().begin(); it != dynamic_streams().end(); ++it) { + if (eliminate_static_stream_map() && it->second->is_static()) + continue; stream_list->AppendString(base::NumberToString(it->second->id())); } dict.Set("active_streams", std::move(stream_list)); @@ -2833,7 +2855,7 @@ } void QuicChromiumClientSession::NotifyFactoryOfSessionClosedLater() { - if (!dynamic_streams().empty()) + if (HasActiveRequestStreams()) RecordUnexpectedOpenStreams(NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER); if (!going_away_) @@ -2849,7 +2871,7 @@ } void QuicChromiumClientSession::NotifyFactoryOfSessionClosed() { - if (!dynamic_streams().empty()) + if (HasActiveRequestStreams()) RecordUnexpectedOpenStreams(NOTIFY_FACTORY_OF_SESSION_CLOSED); if (!going_away_)
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index 833a3b9..79ae9d9 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc
@@ -22,6 +22,7 @@ #include "net/log/net_log.h" #include "net/log/net_log_capture_mode.h" #include "net/log/net_log_event_type.h" +#include "net/quic/address_utils.h" #include "net/quic/quic_address_mismatch.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h" @@ -38,10 +39,11 @@ namespace { -base::Value NetLogQuicPacketCallback(const IPEndPoint* self_address, - const IPEndPoint* peer_address, - size_t packet_size, - NetLogCaptureMode /* capture_mode */) { +base::Value NetLogQuicPacketCallback( + const quic::QuicSocketAddress* self_address, + const quic::QuicSocketAddress* peer_address, + size_t packet_size, + NetLogCaptureMode /* capture_mode */) { base::DictionaryValue dict; dict.SetString("self_address", self_address->ToString()); dict.SetString("peer_address", peer_address->ToString()); @@ -223,7 +225,7 @@ base::Value NetLogQuicPublicResetPacketCallback( const IPEndPoint* server_hello_address, - const IPEndPoint* public_reset_address, + const quic::QuicSocketAddress* public_reset_address, NetLogCaptureMode /* capture_mode */) { base::DictionaryValue dict; dict.SetString("server_hello_address", server_hello_address->ToString()); @@ -540,10 +542,10 @@ const quic::QuicSocketAddress& peer_address, const quic::QuicEncryptedPacket& packet) { if (local_address_from_self_.GetFamily() == ADDRESS_FAMILY_UNSPECIFIED) { - local_address_from_self_ = self_address.impl().socket_address(); + local_address_from_self_ = ToIPEndPoint(self_address); UMA_HISTOGRAM_ENUMERATION( "Net.QuicSession.ConnectionTypeFromSelf", - GetRealAddressFamily(self_address.impl().socket_address().address()), + GetRealAddressFamily(ToIPEndPoint(self_address).address()), ADDRESS_FAMILY_LAST); } @@ -551,11 +553,9 @@ last_received_packet_size_ = packet.length(); if (!net_log_is_capturing_) return; - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_PACKET_RECEIVED, - base::Bind(&NetLogQuicPacketCallback, - &self_address.impl().socket_address(), - &peer_address.impl().socket_address(), packet.length())); + net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PACKET_RECEIVED, + base::Bind(&NetLogQuicPacketCallback, &self_address, + &peer_address, packet.length())); } void QuicConnectionLogger::OnUnauthenticatedHeader( @@ -737,13 +737,13 @@ void QuicConnectionLogger::OnPublicResetPacket( const quic::QuicPublicResetPacket& packet) { UpdatePublicResetAddressMismatchHistogram( - local_address_from_shlo_, packet.client_address.impl().socket_address()); + local_address_from_shlo_, ToIPEndPoint(packet.client_address)); if (!net_log_is_capturing_) return; - net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PUBLIC_RESET_PACKET_RECEIVED, - base::Bind(&NetLogQuicPublicResetPacketCallback, - &local_address_from_shlo_, - &packet.client_address.impl().socket_address())); + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_PUBLIC_RESET_PACKET_RECEIVED, + base::Bind(&NetLogQuicPublicResetPacketCallback, + &local_address_from_shlo_, &packet.client_address)); } void QuicConnectionLogger::OnVersionNegotiationPacket( @@ -763,7 +763,7 @@ if (message.GetStringPiece(quic::kCADR, &address) && decoder.Decode(address.data(), address.size())) { local_address_from_shlo_ = - IPEndPoint(decoder.ip().impl().ip_address(), decoder.port()); + IPEndPoint(ToIPAddress(decoder.ip()), decoder.port()); UMA_HISTOGRAM_ENUMERATION( "Net.QuicSession.ConnectionTypeFromPeer", GetRealAddressFamily(local_address_from_shlo_.address()),
diff --git a/net/quic/quic_connectivity_probing_manager.cc b/net/quic/quic_connectivity_probing_manager.cc index 5ce272a..7f33513 100644 --- a/net/quic/quic_connectivity_probing_manager.cc +++ b/net/quic/quic_connectivity_probing_manager.cc
@@ -9,6 +9,7 @@ #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "net/log/net_log.h" +#include "net/quic/address_utils.h" namespace net { @@ -173,7 +174,7 @@ << local_address.ToString() << ", to peer ip:port " << peer_address_.ToString(); - if (quic::QuicSocketAddressImpl(local_address) != self_address.impl() || + if (local_address != ToIPEndPoint(self_address) || peer_address_ != peer_address) { DVLOG(1) << "Received probing response from peer ip:port " << peer_address.ToString() << ", to self ip:port "
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index b5c361f..d4df7d3e 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -36,6 +36,7 @@ #include "net/log/net_log_capture_mode.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_source_type.h" +#include "net/quic/address_utils.h" #include "net/quic/crypto/proof_verifier_chromium.h" #include "net/quic/properties_based_quic_server_info.h" #include "net/quic/quic_chromium_alarm_factory.h" @@ -264,6 +265,7 @@ verify_callback_->Cancel(); } + // TODO(mattm): pass |ocsp_response| and |cert_sct|. // Starts verification of certs cached in the |crypto_config|. quic::QuicAsyncStatus Run(quic::QuicCryptoClientConfig* crypto_config, CompletionOnceCallback callback) { @@ -274,8 +276,9 @@ quic::QuicAsyncStatus status = crypto_config->proof_verifier()->VerifyCertChain( server_id_.host(), cached->certs(), - /*ocsp_response=*/std::string(), cached->cert_sct(), - verify_context_.get(), &verify_error_details_, &verify_details_, + /*ocsp_response=*/std::string(), + /*cert_sct=*/std::string(), verify_context_.get(), + &verify_error_details_, &verify_details_, std::move(verify_callback)); if (status == quic::QUIC_PENDING) { verify_callback_ = verify_callback_ptr; @@ -412,7 +415,7 @@ bool DoesPeerAddressMatchWithFreshAddressList() { std::vector<net::IPEndPoint> endpoints = fresh_resolve_host_request_->GetAddressResults().value().endpoints(); - IPEndPoint stale_address = session_->peer_address().impl().socket_address(); + IPEndPoint stale_address = ToIPEndPoint(session_->peer_address()); if (std::find(endpoints.begin(), endpoints.end(), stale_address) != endpoints.end()) { @@ -889,8 +892,7 @@ DCHECK(!factory_->HasActiveSession(key_.session_key())); // There may well now be an active session for this IP. If so, use the // existing session instead. - AddressList address( - session_->connection()->peer_address().impl().socket_address()); + AddressList address(ToIPEndPoint(session_->connection()->peer_address())); if (factory_->HasMatchingIpSession(key_, address)) { LogConnectionIpPooling(true); session_->connection()->CloseConnection( @@ -1898,7 +1900,7 @@ active_sessions_[key.session_key()] = session; session_aliases_[session].insert(key); const IPEndPoint peer_address = - session->connection()->peer_address().impl().socket_address(); + ToIPEndPoint(session->connection()->peer_address()); DCHECK(!base::ContainsKey(ip_aliases_[peer_address], session)); ip_aliases_[peer_address].insert(session); DCHECK(!base::ContainsKey(session_peer_ip_, session));
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 00821bda..6de7e444 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -27,6 +27,7 @@ #include "net/http/http_util.h" #include "net/http/transport_security_state.h" #include "net/http/transport_security_state_test_util.h" +#include "net/quic/address_utils.h" #include "net/quic/crypto/proof_verifier_chromium.h" #include "net/quic/mock_crypto_client_stream_factory.h" #include "net/quic/mock_quic_data.h" @@ -9324,9 +9325,7 @@ std::unique_ptr<HttpStream> stream = CreateStream(&request); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kNonCachedIPAddress); + EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -9373,9 +9372,7 @@ EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kNonCachedIPAddress); + EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -9431,9 +9428,8 @@ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kCachedIPAddress.ToString()); + EXPECT_EQ(session->peer_address().host().ToString(), + kCachedIPAddress.ToString()); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -9499,9 +9495,8 @@ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kCachedIPAddress.ToString()); + EXPECT_EQ(session->peer_address().host().ToString(), + kCachedIPAddress.ToString()); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -9563,9 +9558,8 @@ EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kCachedIPAddress.ToString()); + EXPECT_EQ(session->peer_address().host().ToString(), + kCachedIPAddress.ToString()); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -9634,9 +9628,7 @@ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kNonCachedIPAddress); + EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -9708,9 +9700,7 @@ EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kNonCachedIPAddress); + EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -9779,9 +9769,7 @@ EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kNonCachedIPAddress); + EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress); EXPECT_TRUE(quic_data.AllReadDataConsumed()); EXPECT_TRUE(quic_data.AllWriteDataConsumed()); @@ -10002,9 +9990,7 @@ QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); - EXPECT_EQ( - session->peer_address().impl().socket_address().ToStringWithoutPort(), - kNonCachedIPAddress); + EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress); EXPECT_TRUE(quic_data2.AllReadDataConsumed()); EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 857dc8a0..71fdb600 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -1138,16 +1138,10 @@ base::StringPiece ocsp_response( reinterpret_cast<const char*>(ocsp_response_raw), ocsp_response_len); - const uint8_t* sct_list_raw; - size_t sct_list_len; - SSL_get0_signed_cert_timestamp_list(ssl_.get(), &sct_list_raw, &sct_list_len); - base::StringPiece sct_list(reinterpret_cast<const char*>(sct_list_raw), - sct_list_len); - cert_verification_result_ = cert_verifier_->Verify( - CertVerifier::RequestParams( - server_cert_, host_and_port_.host(), ssl_config_.GetCertVerifyFlags(), - ocsp_response.as_string(), sct_list.as_string()), + CertVerifier::RequestParams(server_cert_, host_and_port_.host(), + ssl_config_.GetCertVerifyFlags(), + ocsp_response.as_string()), &server_cert_verify_result_, base::BindOnce(&SSLClientSocketImpl::OnVerifyComplete, base::Unretained(this)),
diff --git a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc index 787f123..11e9e9a 100644 --- a/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc +++ b/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
@@ -173,9 +173,8 @@ net::CertVerifyResult result; int rv = cert_verify_proc->Verify(x509_target_and_intermediates.get(), hostname, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, crl_set, - x509_additional_trust_anchors, &result); + std::string() /* ocsp_response */, flags, + crl_set, x509_additional_trust_anchors, &result); // Remove any temporary trust anchors. test_root_certs->Clear();
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.cc b/net/tools/quic/quic_client_message_loop_network_helper.cc index 72cf547e..486aab9 100644 --- a/net/tools/quic/quic_client_message_loop_network_helper.cc +++ b/net/tools/quic/quic_client_message_loop_network_helper.cc
@@ -14,6 +14,7 @@ #include "net/http/http_response_info.h" #include "net/log/net_log_source.h" #include "net/log/net_log_with_source.h" +#include "net/quic/address_utils.h" #include "net/quic/quic_chromium_alarm_factory.h" #include "net/quic/quic_chromium_connection_helper.h" #include "net/quic/quic_chromium_packet_reader.h" @@ -60,7 +61,7 @@ quic::QuicSocketAddress(quic::QuicIpAddress::Any6(), bind_to_port); } - int rc = socket->Connect(server_address.impl().socket_address()); + int rc = socket->Connect(ToIPEndPoint(server_address)); if (rc != OK) { LOG(ERROR) << "Connect failed: " << ErrorToShortString(rc); return false;
diff --git a/net/tools/quic/quic_simple_server_packet_writer.cc b/net/tools/quic/quic_simple_server_packet_writer.cc index ac952d7..6e71a9d 100644 --- a/net/tools/quic/quic_simple_server_packet_writer.cc +++ b/net/tools/quic/quic_simple_server_packet_writer.cc
@@ -12,6 +12,7 @@ #include "base/metrics/histogram_functions.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" +#include "net/quic/address_utils.h" #include "net/socket/udp_server_socket.h" #include "net/third_party/quiche/src/quic/core/quic_dispatcher.h" @@ -58,8 +59,7 @@ int rv; if (buf_len <= static_cast<size_t>(std::numeric_limits<int>::max())) { rv = socket_->SendTo( - buf.get(), static_cast<int>(buf_len), - peer_address.impl().socket_address(), + buf.get(), static_cast<int>(buf_len), ToIPEndPoint(peer_address), base::Bind(&QuicSimpleServerPacketWriter::OnWriteComplete, weak_factory_.GetWeakPtr())); } else {
diff --git a/services/network/cert_verifier_with_trust_anchors_unittest.cc b/services/network/cert_verifier_with_trust_anchors_unittest.cc index e7e1d6f1..c808a8e 100644 --- a/services/network/cert_verifier_with_trust_anchors_unittest.cc +++ b/services/network/cert_verifier_with_trust_anchors_unittest.cc
@@ -81,12 +81,11 @@ net::CompletionOnceCallback test_callback, net::CertVerifyResult* verify_result, std::unique_ptr<net::CertVerifier::Request>* request) { - return cert_verifier_->Verify(net::CertVerifier::RequestParams( - test_server_cert_.get(), "127.0.0.1", 0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), - verify_result, std::move(test_callback), - request, net::NetLogWithSource()); + return cert_verifier_->Verify( + net::CertVerifier::RequestParams(test_server_cert_.get(), "127.0.0.1", + 0, std::string()), + verify_result, std::move(test_callback), request, + net::NetLogWithSource()); } bool SupportsAdditionalTrustAnchors() {
diff --git a/services/network/cert_verify_proc_chromeos.cc b/services/network/cert_verify_proc_chromeos.cc index d559a2a..5eac37c 100644 --- a/services/network/cert_verify_proc_chromeos.cc +++ b/services/network/cert_verify_proc_chromeos.cc
@@ -44,7 +44,6 @@ net::X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, net::CRLSet* crl_set, const net::CertificateList& additional_trust_anchors,
diff --git a/services/network/cert_verify_proc_chromeos.h b/services/network/cert_verify_proc_chromeos.h index dcbfac5..45ee9fb 100644 --- a/services/network/cert_verify_proc_chromeos.h +++ b/services/network/cert_verify_proc_chromeos.h
@@ -37,7 +37,6 @@ int VerifyInternal(net::X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, int flags, net::CRLSet* crl_set, const net::CertificateList& additional_trust_anchors,
diff --git a/services/network/cert_verify_proc_chromeos_unittest.cc b/services/network/cert_verify_proc_chromeos_unittest.cc index fef1da5a..6c5934c 100644 --- a/services/network/cert_verify_proc_chromeos_unittest.cc +++ b/services/network/cert_verify_proc_chromeos_unittest.cc
@@ -107,9 +107,7 @@ std::string* root_subject_name) { int flags = 0; net::CertVerifyResult verify_result; - int error = verify_proc->Verify(cert, "127.0.0.1", - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string(), flags, + int error = verify_proc->Verify(cert, "127.0.0.1", std::string(), flags, net::CRLSet::BuiltinCRLSet().get(), additional_trust_anchors, &verify_result); if (!verify_result.verified_cert->intermediate_buffers().empty()) {
diff --git a/services/network/ignore_errors_cert_verifier_unittest.cc b/services/network/ignore_errors_cert_verifier_unittest.cc index afd4c3d01..d29015f 100644 --- a/services/network/ignore_errors_cert_verifier_unittest.cc +++ b/services/network/ignore_errors_cert_verifier_unittest.cc
@@ -94,9 +94,7 @@ static CertVerifier::RequestParams MakeRequestParams( const scoped_refptr<X509Certificate>& cert) { - return CertVerifier::RequestParams(cert, "example.com", /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()); + return CertVerifier::RequestParams(cert, "example.com", 0, ""); } static void GetWhitelistedTestCert(scoped_refptr<X509Certificate>* out) {
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index f19e147..b5771b7e 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -1357,8 +1357,7 @@ : url_request_context_->cert_verifier(); int result = cert_verifier->Verify( net::CertVerifier::RequestParams(certificate, url.host(), - 0 /* cert_verify_flags */, ocsp_result, - sct_list), + 0 /* cert_verify_flags */, ocsp_result), pending_cert_verify->result.get(), base::BindOnce(&NetworkContext::OnCertVerifyForSignedExchangeComplete, base::Unretained(this), cert_verify_id), @@ -1547,7 +1546,6 @@ const scoped_refptr<net::X509Certificate>& certificate, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, VerifyCertificateForTestingCallback callback) { net::CertVerifier* cert_verifier = url_request_context_->cert_verifier(); @@ -1555,13 +1553,12 @@ auto* request = &state->request; auto* result = &state->result; - cert_verifier->Verify( - net::CertVerifier::RequestParams(certificate.get(), hostname, 0, - ocsp_response, sct_list), - result, - base::BindOnce(TestVerifyCertCallback, std::move(state), - std::move(callback)), - request, net::NetLogWithSource()); + cert_verifier->Verify(net::CertVerifier::RequestParams( + certificate.get(), hostname, 0, ocsp_response), + result, + base::BindOnce(TestVerifyCertCallback, std::move(state), + std::move(callback)), + request, net::NetLogWithSource()); } void NetworkContext::PreconnectSockets(uint32_t num_streams,
diff --git a/services/network/network_context.h b/services/network/network_context.h index 99d81077..315ce8a 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -318,7 +318,6 @@ const scoped_refptr<net::X509Certificate>& certificate, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, VerifyCertificateForTestingCallback callback) override; void PreconnectSockets(uint32_t num_streams, const GURL& url,
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 60966ed..aa628f12 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -910,8 +910,7 @@ // Verifies the given certificate using the context's CertVerifier. VerifyCertificateForTesting(X509Certificate certificate, string hostname, - string ocsp_response, - string sct_list) => (int32 error_code); + string ocsp_response) => (int32 error_code); [Sync] // Adds a Domain Reliability Context.
diff --git a/services/network/ssl_config_service_mojo_unittest.cc b/services/network/ssl_config_service_mojo_unittest.cc index f8e0686..6af9826 100644 --- a/services/network/ssl_config_service_mojo_unittest.cc +++ b/services/network/ssl_config_service_mojo_unittest.cc
@@ -501,10 +501,7 @@ net::CertVerifyResult cert_verify_result1; std::unique_ptr<net::CertVerifier::Request> request1; int result = network_context_->url_request_context()->cert_verifier()->Verify( - net::CertVerifier::RequestParams(cert, "127.0.0.1", - /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + net::CertVerifier::RequestParams(cert, "127.0.0.1", 0, std::string()), &cert_verify_result1, callback1.callback(), &request1, net::NetLogWithSource()); ASSERT_THAT(callback1.GetResult(result), net::test::IsOk()); @@ -525,10 +522,7 @@ net::CertVerifyResult cert_verify_result2; std::unique_ptr<net::CertVerifier::Request> request2; result = network_context_->url_request_context()->cert_verifier()->Verify( - net::CertVerifier::RequestParams(cert, "127.0.0.1", - /*flags=*/0, - /*ocsp_response=*/std::string(), - /*sct_list=*/std::string()), + net::CertVerifier::RequestParams(cert, "127.0.0.1", 0, std::string()), &cert_verify_result2, callback2.callback(), &request2, net::NetLogWithSource()); ASSERT_THAT(callback2.GetResult(result),
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h index fa8bb72..bf688427 100644 --- a/services/network/test/test_network_context.h +++ b/services/network/test/test_network_context.h
@@ -182,7 +182,6 @@ const scoped_refptr<net::X509Certificate>& certificate, const std::string& hostname, const std::string& ocsp_response, - const std::string& sct_list, VerifyCertificateForTestingCallback callback) override {} void PreconnectSockets(uint32_t num_streams, const GURL& url,
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 5304f488..55f29f41 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -2129,7 +2129,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2144,7 +2144,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2159,7 +2159,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2174,7 +2174,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2189,7 +2189,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2204,7 +2204,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2219,7 +2219,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2234,7 +2234,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2249,7 +2249,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2264,7 +2264,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2280,7 +2280,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2295,7 +2295,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2310,7 +2310,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2325,7 +2325,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "shards": 10 @@ -2346,7 +2346,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2361,7 +2361,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2379,7 +2379,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2394,7 +2394,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2409,7 +2409,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2424,7 +2424,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2439,7 +2439,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2454,7 +2454,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2469,7 +2469,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2484,7 +2484,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2499,7 +2499,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "shards": 6 @@ -2520,7 +2520,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2540,7 +2540,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2555,7 +2555,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2570,7 +2570,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2585,7 +2585,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2600,7 +2600,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2615,7 +2615,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2630,7 +2630,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2645,7 +2645,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2660,7 +2660,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2675,7 +2675,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2690,7 +2690,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2705,7 +2705,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2720,7 +2720,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2735,7 +2735,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2750,7 +2750,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2765,7 +2765,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2780,7 +2780,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2795,7 +2795,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2810,7 +2810,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2825,7 +2825,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "shards": 3 @@ -2846,7 +2846,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2861,7 +2861,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2876,7 +2876,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2891,7 +2891,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2906,7 +2906,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2921,7 +2921,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2936,7 +2936,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2951,7 +2951,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2966,7 +2966,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2981,7 +2981,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -2996,7 +2996,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3011,7 +3011,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3026,7 +3026,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3041,7 +3041,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3056,7 +3056,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3071,7 +3071,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3086,7 +3086,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3101,7 +3101,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3116,7 +3116,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3131,7 +3131,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3146,7 +3146,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3161,7 +3161,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3176,7 +3176,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3191,7 +3191,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3206,7 +3206,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3221,7 +3221,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3236,7 +3236,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3251,7 +3251,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3266,7 +3266,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3281,7 +3281,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3296,7 +3296,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3311,7 +3311,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3326,7 +3326,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3341,7 +3341,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3356,7 +3356,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3371,7 +3371,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3386,7 +3386,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3401,7 +3401,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3416,7 +3416,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3431,7 +3431,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3446,7 +3446,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3461,7 +3461,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3477,7 +3477,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] }, @@ -3496,7 +3496,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3515,7 +3515,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3531,7 +3531,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3547,7 +3547,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3563,7 +3563,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3579,7 +3579,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3595,7 +3595,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3611,7 +3611,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3637,7 +3637,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "shards": 10 @@ -3654,7 +3654,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "idempotent": false @@ -3675,7 +3675,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "idempotent": false, @@ -3697,7 +3697,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "idempotent": false, @@ -3720,7 +3720,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ] } @@ -3742,7 +3742,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-14.04" + "os": "Ubuntu-16.04" } ], "shards": 6
diff --git a/testing/buildbot/filters/webui_html_imports_polyfill_browser_tests.filter b/testing/buildbot/filters/webui_html_imports_polyfill_browser_tests.filter index 7a5753b..0d113ecc8 100644 --- a/testing/buildbot/filters/webui_html_imports_polyfill_browser_tests.filter +++ b/testing/buildbot/filters/webui_html_imports_polyfill_browser_tests.filter
@@ -32,6 +32,11 @@ CrExtensionsRuntimeHostPermissionsTest.* CrExtensionsHostPermissionsToggleListTest.* +DownloadsItemTest.* +DownloadsManagerTest.* +DownloadsToolbarTest.* +DownloadsUrlTest.* + PDFAnnotationsTest.* PDFExtensionClipboardTest.* PDFExtensionHitTestTest.*
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 1767969f..de68f03 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -239,6 +239,13 @@ }, }, }, + 'linux-xenial': { + 'swarming': { + 'dimensions': { + 'os': 'Ubuntu-16.04', + }, + }, + }, 'linux_amd_r7_240': { 'swarming': { 'dimensions': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 9eab929..3e16ceb 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3423,7 +3423,7 @@ }, 'Linux Tests': { 'mixins': [ - 'linux-trusty', + 'linux-xenial', ], 'test_suites': { 'gtest_tests': 'chromium_linux_gtests',
diff --git a/third_party/blink/public/platform/web_media_player_client.h b/third_party/blink/public/platform/web_media_player_client.h index 9811f0f5..74227c82 100644 --- a/third_party/blink/public/platform/web_media_player_client.h +++ b/third_party/blink/public/platform/web_media_player_client.h
@@ -124,6 +124,9 @@ // to a localized string that explains the reason as user-readable text. virtual void MediaRemotingStopped(WebLocalizedString::Name error_msg) = 0; + // Informs that Picture-in-Picture mode has stopped for the media element. + virtual void PictureInPictureStopped() = 0; + // Returns whether the media element has native controls. It does not mean // that the controls are currently visible. virtual bool HasNativeControls() = 0;
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 8dc52ea..35c2034d 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -103,7 +103,6 @@ BLINK_PLATFORM_EXPORT static void EnableFirstContentfulPaintPlusPlus(bool); BLINK_PLATFORM_EXPORT static void EnableForceSynchronousHTMLParsing(bool); BLINK_PLATFORM_EXPORT static void EnableForceTallerSelectPopup(bool); - BLINK_PLATFORM_EXPORT static void EnableFormControlsRefresh(bool); BLINK_PLATFORM_EXPORT static void EnableGenericSensor(bool); BLINK_PLATFORM_EXPORT static void EnableGenericSensorExtraClasses(bool); BLINK_PLATFORM_EXPORT static void EnableHeapCompaction(bool);
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc index 762889f7..ce95d11 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -111,9 +111,9 @@ loading_task_runner_(platform_->test_task_runner()) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, loading_task_runner_, - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, loading_task_runner_, + MakeGarbageCollected<NoopLoaderFactory>())); ResourceRequest request(url_); request.SetRequestContext(mojom::RequestContextType::SCRIPT);
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc index 223d1cb..234a29c 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -45,6 +45,7 @@ #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h" +#include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h" #include "third_party/blink/renderer/core/paint/filter_effect_builder.h" #include "third_party/blink/renderer/core/paint/object_paint_properties.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" @@ -192,6 +193,16 @@ if (!layout_object || !layout_object->UniqueId()) { reasons |= kTargetHasInvalidCompositingState; } + + // Elements with subtrees containing will-change: contents are not + // composited for animations as if the contents change the tiles + // would need to be rerastered anyways. + // TODO(crbug.com/961686): Remove Style() check once unit tests create + // fully styled Elements. + if (layout_object && layout_object->Style() && + layout_object->Style()->SubtreeWillChangeContents()) { + reasons |= kTargetHasInvalidCompositingState; + } } PropertyHandleSet properties = keyframe_effect.Properties();
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.cc b/third_party/blink/renderer/core/clipboard/system_clipboard.cc index c643434..c8f57fa 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.cc +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -199,6 +199,7 @@ } void SystemClipboard::WriteDataObject(DataObject* data_object) { + DCHECK(data_object); // This plagiarizes the logic in DropDataBuilder::Build, but only extracts the // data needed for the implementation of WriteDataObject. //
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.h b/third_party/blink/renderer/core/clipboard/system_clipboard.h index bb48891..038ec50 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.h +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -63,7 +63,7 @@ String ReadCustomData(const String& type); void WriteDataObject(DataObject*); - // Clipboard write functions that must use CommitWrite for changes to reach + // Clipboard write functions must use CommitWrite for changes to reach // the OS clipboard. void CommitWrite(); @@ -72,6 +72,8 @@ bool IsValidBufferType(mojom::ClipboardBuffer); mojom::blink::ClipboardHostPtr clipboard_; + // In X11, |buffer_| may equal ClipboardBuffer::kStandard or kSelection. + // Outside X11, |buffer_| always equals ClipboardBuffer::kStandard. mojom::ClipboardBuffer buffer_ = mojom::ClipboardBuffer::kStandard; DISALLOW_COPY_AND_ASSIGN(SystemClipboard);
diff --git a/third_party/blink/renderer/core/css/css_property_value_set.cc b/third_party/blink/renderer/core/css/css_property_value_set.cc index a28a3fc..26163af 100644 --- a/third_party/blink/renderer/core/css/css_property_value_set.cc +++ b/third_party/blink/renderer/core/css/css_property_value_set.cc
@@ -41,11 +41,11 @@ namespace blink { -static wtf_size_t SizeForImmutableCSSPropertyValueSetWithPropertyCount( +static AdditionalBytes +AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount( unsigned count) { - return sizeof(ImmutableCSSPropertyValueSet) - sizeof(void*) + - sizeof(Member<CSSValue>) * count + - sizeof(CSSPropertyValueMetadata) * count; + return AdditionalBytes(sizeof(Member<CSSValue>) * count + + sizeof(CSSPropertyValueMetadata) * count); } ImmutableCSSPropertyValueSet* ImmutableCSSPropertyValueSet::Create( @@ -53,10 +53,9 @@ unsigned count, CSSParserMode css_parser_mode) { DCHECK_LE(count, static_cast<unsigned>(kMaxArraySize)); - void* slot = ThreadHeap::Allocate<CSSPropertyValueSet>( - SizeForImmutableCSSPropertyValueSetWithPropertyCount(count)); - return new (slot) - ImmutableCSSPropertyValueSet(properties, count, css_parser_mode); + return MakeGarbageCollected<ImmutableCSSPropertyValueSet>( + AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount(count), + properties, count, css_parser_mode); } CSSPropertyName CSSPropertyValueSet::PropertyReference::Name() const { @@ -645,7 +644,9 @@ unsigned CSSPropertyValueSet::AverageSizeInBytes() { // Please update this if the storage scheme changes so that this longer // reflects the actual size. - return SizeForImmutableCSSPropertyValueSetWithPropertyCount(4); + return sizeof(ImmutableCSSPropertyValueSet) + + AdditionalBytesForImmutableCSSPropertyValueSetWithPropertyCount(4) + .value; } // See the function above if you need to update this.
diff --git a/third_party/blink/renderer/core/css/css_property_value_set.h b/third_party/blink/renderer/core/css/css_property_value_set.h index 47d39c8..02326d58 100644 --- a/third_party/blink/renderer/core/css/css_property_value_set.h +++ b/third_party/blink/renderer/core/css/css_property_value_set.h
@@ -195,23 +195,17 @@ int FindPropertyIndex(T property) const; void TraceAfterDispatch(blink::Visitor*); - - void* operator new(std::size_t, void* location) { return location; } - - void* storage_; }; inline const Member<const CSSValue>* ImmutableCSSPropertyValueSet::ValueArray() const { - return reinterpret_cast<const Member<const CSSValue>*>( - const_cast<const void**>(&(this->storage_))); + return reinterpret_cast<const Member<const CSSValue>*>(this + 1); } inline const CSSPropertyValueMetadata* ImmutableCSSPropertyValueSet::MetadataArray() const { - return reinterpret_cast<const CSSPropertyValueMetadata*>( - &reinterpret_cast<const char*>( - &(this->storage_))[array_size_ * sizeof(Member<CSSValue>)]); + return reinterpret_cast<const CSSPropertyValueMetadata*>(ValueArray() + + array_size_); } template <>
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h index 30e996a..98dc295 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -115,6 +115,12 @@ bool ShouldPaint() const; void DidPaint(); + // Returns true if the last style recalc traversal was blocked at this + // element, either for itself, its children or its descendants. + bool StyleTraversalWasBlocked() { + return blocked_style_traversal_type_ != kStyleUpdateNotRequired; + } + // Returns true if the contents of the associated element should be visible // from and activatable by find-in-page, tab order, anchor links, etc. bool IsActivatable() const;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc index 0e2dbe5..be64fb79 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
@@ -82,13 +82,13 @@ const Element* DisplayLockUtilities::NearestLockedInclusiveAncestor( const Node& node) { - if (!RuntimeEnabledFeatures::DisplayLockingEnabled() || + if (!node.IsElementNode()) + return NearestLockedExclusiveAncestor(node); + if (!RuntimeEnabledFeatures::DisplayLockingEnabled() || !node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 || !node.CanParticipateInFlatTree()) { return nullptr; } - if (!node.IsElementNode()) - return NearestLockedExclusiveAncestor(node); if (auto* context = ToElement(node).GetDisplayLockContext()) { if (context->IsLocked()) return &ToElement(node); @@ -103,7 +103,7 @@ Element* DisplayLockUtilities::NearestLockedExclusiveAncestor( const Node& node) { - if (!RuntimeEnabledFeatures::DisplayLockingEnabled() || + if (!RuntimeEnabledFeatures::DisplayLockingEnabled() || !node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 || !node.CanParticipateInFlatTree()) { return nullptr;
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 1a78710..d48b02a 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -717,10 +717,12 @@ } else if (imports_controller_) { fetcher_ = FrameFetchContext::CreateFetcherForImportedDocument(this); } else { + auto& properties = + *MakeGarbageCollected<DetachableResourceFetcherProperties>( + *MakeGarbageCollected<NullResourceFetcherProperties>()); fetcher_ = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *MakeGarbageCollected<NullResourceFetcherProperties>(), - &FetchContext::NullInstance(), GetTaskRunner(TaskType::kNetworking), - nullptr /* loader_factory */)); + properties, &FetchContext::NullInstance(), + GetTaskRunner(TaskType::kNetworking), nullptr /* loader_factory */)); } DCHECK(fetcher_); @@ -2420,9 +2422,22 @@ bool Document::NeedsLayoutTreeUpdateForNode(const Node& node, bool ignore_adjacent_style) const { + // TODO(rakina): Switch some callers that may need to call + // NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked instead of this. + if (DisplayLockUtilities::NearestLockedExclusiveAncestor(node)) { + // |node| is in a locked-subtree, so we don't need to update it. + return false; + } + return NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked( + node, ignore_adjacent_style); +} + +bool Document::NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked( + const Node& node, + bool ignore_adjacent_style) const { if (!node.CanParticipateInFlatTree()) return false; - if (!NeedsLayoutTreeUpdate()) + if (locked_display_lock_count_ == 0 && !NeedsLayoutTreeUpdate()) return false; if (!node.isConnected()) return false; @@ -2442,13 +2457,34 @@ (ancestor->NeedsAdjacentStyleRecalc() && !ignore_adjacent_style)) { return true; } + if (!ancestor->IsElementNode()) + continue; + if (auto* context = ToElement(ancestor)->GetDisplayLockContext()) { + // Even if the ancestor is style-clean, we might've previously + // blocked a style traversal going to the ancestor or its descendants. + if (context->StyleTraversalWasBlocked()) + return true; + } } return false; } void Document::UpdateStyleAndLayoutTreeForNode(const Node* node) { DCHECK(node); - if (!NeedsLayoutTreeUpdateForNode(*node)) + if (!node->InActiveDocument()) { + // If |node| is not in the active document, we can't update its style or + // layout tree. + DCHECK_EQ(node->ownerDocument(), this); + return; + } + DCHECK(node->GetDocument().GetPage()); + DCHECK(!node->GetDocument() + .GetPage() + ->Animator() + .UpdatingLayoutAndStyleForPainting()) + << "UpdateStyleAndLayoutTreeForNode called from within a lifecycle " + "update"; + if (!NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*node)) return; DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 2547333..032447a 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -506,8 +506,15 @@ void SetupFontBuilder(ComputedStyle& document_style); bool NeedsLayoutTreeUpdate() const; + // Whether we need layout tree update for this node or not, without + // considering nodes in display locked subtrees. bool NeedsLayoutTreeUpdateForNode(const Node&, bool ignore_adjacent_style = false) const; + // Whether we need layout tree update for this node or not, including nodes in + // display locked subtrees. + bool NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked( + const Node&, + bool ignore_adjacent_style = false) const; // Update ComputedStyles and attach LayoutObjects if necessary, but don't // lay out.
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc index d1cef10..4d4b713 100644 --- a/third_party/blink/renderer/core/dom/document_test.cc +++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -322,6 +322,7 @@ void DocumentDetached(const Document&) override { document_detached_was_called = true; } + void DidChangeFocusTo(const Node*) override {} void WillBeDestroyed() override {} // virtual void Trace(Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/dom/element_data.cc b/third_party/blink/renderer/core/dom/element_data.cc index c7dd67c4..92e725d 100644 --- a/third_party/blink/renderer/core/dom/element_data.cc +++ b/third_party/blink/renderer/core/dom/element_data.cc
@@ -46,8 +46,9 @@ static_assert(sizeof(ElementData) == sizeof(SameSizeAsElementData), "ElementData should stay small"); -static size_t SizeForShareableElementDataWithAttributeCount(unsigned count) { - return sizeof(ShareableElementData) + sizeof(Attribute) * count; +static AdditionalBytes AdditionalBytesForShareableElementDataWithAttributeCount( + unsigned count) { + return AdditionalBytes(sizeof(Attribute) * count); } ElementData::ElementData() @@ -145,9 +146,10 @@ ShareableElementData* ShareableElementData::CreateWithAttributes( const Vector<Attribute>& attributes) { - void* slot = ThreadHeap::Allocate<ElementData>( - SizeForShareableElementDataWithAttributeCount(attributes.size())); - return new (slot) ShareableElementData(attributes); + return MakeGarbageCollected<ShareableElementData>( + AdditionalBytesForShareableElementDataWithAttributeCount( + attributes.size()), + attributes); } UniqueElementData::UniqueElementData() = default; @@ -174,9 +176,10 @@ } ShareableElementData* UniqueElementData::MakeShareableCopy() const { - void* slot = ThreadHeap::Allocate<ElementData>( - SizeForShareableElementDataWithAttributeCount(attribute_vector_.size())); - return new (slot) ShareableElementData(*this); + return MakeGarbageCollected<ShareableElementData>( + AdditionalBytesForShareableElementDataWithAttributeCount( + attribute_vector_.size()), + *this); } void UniqueElementData::TraceAfterDispatch(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/dom/element_data.h b/third_party/blink/renderer/core/dom/element_data.h index 3a6541f1..72aacbc 100644 --- a/third_party/blink/renderer/core/dom/element_data.h +++ b/third_party/blink/renderer/core/dom/element_data.h
@@ -131,13 +131,6 @@ ElementData::TraceAfterDispatch(visitor); } - // Add support for placement new as ShareableElementData is not allocated - // with a fixed size. Instead the allocated memory size is computed based on - // the number of attributes. This requires us to use ThreadHeap::allocate - // directly with the computed size and subsequently call placement new with - // the allocated memory address. - void* operator new(std::size_t, void* location) { return location; } - AttributeCollection Attributes() const; Attribute attribute_array_[0];
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index 85fde89..e9ee5c3 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -5426,7 +5426,9 @@ // selection bounds, selectRange() will select the *next* element. That's // strictly correct, as hit-testing checks the pixel to the lower-right of // the input coordinate, but it's a wart on the API. - return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1); + if (rect.width > 0) + return WebPoint(rect.x + rect.width - 1, rect.y + rect.height - 1); + return WebPoint(rect.x + rect.width, rect.y + rect.height - 1); } static WebRect ElementBounds(WebLocalFrame* frame, const WebString& id) {
diff --git a/third_party/blink/renderer/core/html/anchor_element_metrics.cc b/third_party/blink/renderer/core/html/anchor_element_metrics.cc index b5ecbd2..4624e5d6 100644 --- a/third_party/blink/renderer/core/html/anchor_element_metrics.cc +++ b/third_party/blink/renderer/core/html/anchor_element_metrics.cc
@@ -138,10 +138,6 @@ } // anonymous namespace -// Webpage with more than |kMaxAnchorElementMetricsSize| anchor element metrics -// to report will be ignored, so it should be large enough to cover most pages. -const int AnchorElementMetrics::kMaxAnchorElementMetricsSize = 40; - // static base::Optional<AnchorElementMetrics> AnchorElementMetrics::Create( const HTMLAnchorElement* anchor_element) { @@ -303,8 +299,10 @@ anchor_elements_metrics.push_back(anchor_metric.value().CreateMetricsPtr()); - if (anchor_elements_metrics.size() > kMaxAnchorElementMetricsSize) - return; + // Webpages with more than 40 anchors will stop processing at the 40th + // anchor element. + if (anchor_elements_metrics.size() >= 40) + break; } if (anchor_elements_metrics.IsEmpty())
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc index fc8f2ab..6f6cb46 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -366,15 +366,6 @@ return ListedElement::IsValidElement(); } -void HTMLFormControlElement::DispatchBlurEvent( - Element* new_focused_element, - WebFocusType type, - InputDeviceCapabilities* source_capabilities) { - HTMLElement::DispatchBlurEvent(new_focused_element, type, - source_capabilities); - HideVisibleValidationMessage(); -} - bool HTMLFormControlElement::IsSuccessfulSubmitButton() const { return CanBeSuccessfulSubmitButton() && !IsDisabledFormControl(); }
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.h b/third_party/blink/renderer/core/html/forms/html_form_control_element.h index a4d2775..30fd4ef49 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.h +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.h
@@ -146,9 +146,6 @@ bool SupportsFocus() const override; bool IsKeyboardFocusable() const override; bool ShouldHaveFocusAppearance() const final; - void DispatchBlurEvent(Element* new_focused_element, - WebFocusType, - InputDeviceCapabilities* source_capabilities) override; void DidRecalcStyle(const StyleRecalcChange) override;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc index 6726d520..3eadd53 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc
@@ -43,6 +43,7 @@ } void DocumentDetached(const Document&) override {} + void DidChangeFocusTo(const Node*) override {} void WillBeDestroyed() override {} void Trace(Visitor* visitor) override { visitor->Trace(anchor_);
diff --git a/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h b/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h index 0d2696b..0abb2d6 100644 --- a/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h +++ b/third_party/blink/renderer/core/html/forms/text_control_inner_elements.h
@@ -40,6 +40,7 @@ protected: LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; + bool TypeShouldForceLegacyLayout() const final { return true; } }; class EditingViewPortElement final : public HTMLDivElement { @@ -52,6 +53,7 @@ scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() override; private: + bool TypeShouldForceLegacyLayout() const final { return true; } bool SupportsFocus() const override { return false; } }; @@ -68,6 +70,7 @@ private: LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override; + bool TypeShouldForceLegacyLayout() const final { return true; } scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() override; bool SupportsFocus() const override { return false; } bool is_visible_ = true; @@ -83,6 +86,7 @@ bool WillRespondToMouseClickEvents() override; private: + bool TypeShouldForceLegacyLayout() const final { return true; } bool SupportsFocus() const override { return false; } };
diff --git a/third_party/blink/renderer/core/html/media/html_audio_element.h b/third_party/blink/renderer/core/html/media/html_audio_element.h index a5add00..bafd92f 100644 --- a/third_party/blink/renderer/core/html/media/html_audio_element.h +++ b/third_party/blink/renderer/core/html/media/html_audio_element.h
@@ -50,6 +50,7 @@ void MediaRemotingStarted( const WebString& remote_device_friendly_name) override {} void MediaRemotingStopped(WebLocalizedString::Name error_msg) override {} + void PictureInPictureStopped() override { NOTREACHED(); } void OnPictureInPictureStateChange() final { NOTREACHED(); } void ActivateViewportIntersectionMonitoring(bool) final {} };
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc index 311f3664..7ed409b 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.cc +++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -730,6 +730,11 @@ PictureInPictureController::Status::kEnabled; } +void HTMLVideoElement::PictureInPictureStopped() { + PictureInPictureController::From(GetDocument()) + .OnExitedPictureInPicture(nullptr); +} + WebMediaPlayer::DisplayType HTMLVideoElement::DisplayType() const { if (is_auto_picture_in_picture_ || PictureInPictureController::IsElementInPictureInPicture(this)) {
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.h b/third_party/blink/renderer/core/html/media/html_video_element.h index 4c1c87ff..2978d06 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.h +++ b/third_party/blink/renderer/core/html/media/html_video_element.h
@@ -186,6 +186,7 @@ void MediaRemotingStarted(const WebString& remote_device_friendly_name) final; bool SupportsPictureInPicture() const final; + void PictureInPictureStopped() final; void MediaRemotingStopped(WebLocalizedString::Name error_msg) final; WebMediaPlayer::DisplayType DisplayType() const final; bool IsInAutoPIP() const final;
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc index 18a5a19..a695e86 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
@@ -209,8 +209,14 @@ } if (target->IsBox()) return LayoutRect(ToLayoutBoxModelObject(target)->BorderBoundingBox()); - if (target->IsLayoutInline()) - return ToLayoutInline(target)->PhysicalLinesBoundingBox(); + if (target->IsLayoutInline()) { + return EnclosingLayoutRect( + target + ->AncestorToLocalQuad( + nullptr, FloatQuad(target->AbsoluteBoundingBoxFloatRect()), + kUseTransforms | kApplyContainerFlip) + .BoundingBox()); + } return ToLayoutText(target)->PhysicalLinesBoundingBox(); }
diff --git a/third_party/blink/renderer/core/layout/layout_theme_mac.mm b/third_party/blink/renderer/core/layout/layout_theme_mac.mm index 501d389..0a07d91 100644 --- a/third_party/blink/renderer/core/layout/layout_theme_mac.mm +++ b/third_party/blink/renderer/core/layout/layout_theme_mac.mm
@@ -32,7 +32,6 @@ #import "third_party/blink/renderer/core/fileapi/file_list.h" #import "third_party/blink/renderer/core/html_names.h" #import "third_party/blink/renderer/core/layout/layout_progress.h" -#import "third_party/blink/renderer/core/layout/layout_theme_default.h" #import "third_party/blink/renderer/core/layout/layout_view.h" #import "third_party/blink/renderer/core/style/shadow_list.h" #import "third_party/blink/renderer/platform/data_resource_helper.h" @@ -139,13 +138,6 @@ namespace { -class LayoutThemeMacRefresh final : public LayoutThemeDefault { - public: - static scoped_refptr<LayoutTheme> Create() { - return base::AdoptRef(new LayoutThemeMacRefresh()); - } -}; - // Inflate an IntRect to account for specific padding around margins. enum { kTopMargin = 0, kRightMargin = 1, kBottomMargin = 2, kLeftMargin = 3 }; @@ -1019,14 +1011,8 @@ } LayoutTheme& LayoutTheme::NativeTheme() { - if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) { - DEFINE_STATIC_REF(LayoutTheme, layout_theme, - (LayoutThemeMacRefresh::Create())); - return *layout_theme; - } else { - DEFINE_STATIC_REF(LayoutTheme, layout_theme, (LayoutThemeMac::Create())); - return *layout_theme; - } + DEFINE_STATIC_REF(LayoutTheme, layout_theme, (LayoutThemeMac::Create())); + return *layout_theme; } scoped_refptr<LayoutTheme> LayoutThemeMac::Create() {
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc index c21fcb9..12f2825 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -243,6 +243,7 @@ } void BaseFetchContext::Trace(blink::Visitor* visitor) { + visitor->Trace(fetcher_properties_); FetchContext::Trace(visitor); }
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h index 48674c8..de03346 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.h +++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -19,6 +19,7 @@ namespace blink { class ConsoleMessage; +class DetachableResourceFetcherProperties; class KURL; class PreviewsResourceLoadingHints; class SecurityOrigin; @@ -45,6 +46,11 @@ void Trace(blink::Visitor*) override; + const DetachableResourceFetcherProperties& GetResourceFetcherProperties() + const { + return *fetcher_properties_; + } + virtual KURL GetSiteForCookies() const = 0; // Returns the origin of the top frame in the document. @@ -63,7 +69,9 @@ virtual const ContentSecurityPolicy* GetContentSecurityPolicy() const = 0; protected: - BaseFetchContext() = default; + explicit BaseFetchContext( + const DetachableResourceFetcherProperties& properties) + : fetcher_properties_(properties) {} // Used for security checks. virtual bool AllowScriptFromSource(const KURL&) const = 0; @@ -92,6 +100,8 @@ virtual void AddConsoleMessage(ConsoleMessage*) const = 0; private: + const Member<const DetachableResourceFetcherProperties> fetcher_properties_; + void PrintAccessDeniedMessage(const KURL&) const; // Utility methods that are used in default implement for CanRequest,
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc index 235401d5..cc4d4bf0 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
@@ -46,8 +46,9 @@ class MockBaseFetchContext final : public BaseFetchContext { public: - explicit MockBaseFetchContext(ExecutionContext* execution_context) - : execution_context_(execution_context) {} + MockBaseFetchContext(const DetachableResourceFetcherProperties& properties, + ExecutionContext* execution_context) + : BaseFetchContext(properties), execution_context_(execution_context) {} ~MockBaseFetchContext() override = default; // BaseFetchContext overrides: @@ -118,14 +119,15 @@ execution_context_ = MakeGarbageCollected<NullExecutionContext>(); static_cast<NullExecutionContext*>(execution_context_.Get()) ->SetUpSecurityContext(); - fetch_context_ = - MakeGarbageCollected<MockBaseFetchContext>(execution_context_); resource_fetcher_properties_ = MakeGarbageCollected<TestResourceFetcherProperties>( *MakeGarbageCollected<FetchClientSettingsObjectImpl>( *execution_context_)); + auto& properties = resource_fetcher_properties_->MakeDetachable(); + fetch_context_ = MakeGarbageCollected<MockBaseFetchContext>( + properties, execution_context_); resource_fetcher_ = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*resource_fetcher_properties_, fetch_context_, + ResourceFetcherInit(properties, fetch_context_, base::MakeRefCounted<scheduler::FakeTaskRunner>(), MakeGarbageCollected<TestLoaderFactory>())); }
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index 84ec841..ec23377 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -213,18 +213,21 @@ ResourceFetcher* FrameFetchContext::CreateFetcherForCommittedDocument( DocumentLoader& loader, Document& document) { - auto* frame_or_imported_document = - MakeGarbageCollected<FrameOrImportedDocument>(loader, document); - auto* resource_fetcher_properties = - MakeGarbageCollected<FrameResourceFetcherProperties>( - *frame_or_imported_document); - LocalFrame& frame = frame_or_imported_document->GetFrame(); + auto& frame_or_imported_document = + *MakeGarbageCollected<FrameOrImportedDocument>(loader, document); + auto& properties = *MakeGarbageCollected<DetachableResourceFetcherProperties>( + *MakeGarbageCollected<FrameResourceFetcherProperties>( + frame_or_imported_document)); + LocalFrame& frame = frame_or_imported_document.GetFrame(); ResourceFetcherInit init( - *resource_fetcher_properties, - MakeGarbageCollected<FrameFetchContext>(*frame_or_imported_document), + properties, + MakeGarbageCollected<FrameFetchContext>(frame_or_imported_document, + properties), frame.GetTaskRunner(TaskType::kNetworking), - MakeGarbageCollected<LoaderFactoryForFrame>(*frame_or_imported_document)); - init.console_logger = &document; + MakeGarbageCollected<LoaderFactoryForFrame>(frame_or_imported_document)); + auto* console_logger = + MakeGarbageCollected<DetachableConsoleLogger>(&document); + init.console_logger = console_logger; // Frame loading should normally start with |kTight| throttling, as the // frame will be in layout-blocking state until the <body> tag is inserted init.initial_throttling_policy = @@ -234,7 +237,7 @@ ResourceFetcher* fetcher = MakeGarbageCollected<ResourceFetcher>(init); fetcher->SetResourceLoadObserver( MakeGarbageCollected<ResourceLoadObserverForFrame>( - *frame_or_imported_document, fetcher->GetProperties())); + frame_or_imported_document, fetcher->GetProperties())); fetcher->SetImagesEnabled(frame.GetSettings()->GetImagesEnabled()); fetcher->SetAutoLoadImages( frame.GetSettings()->GetLoadsImagesAutomatically()); @@ -248,14 +251,19 @@ DCHECK(!document->GetFrame()); auto& frame_or_imported_document = *MakeGarbageCollected<FrameOrImportedDocument>(*document); + auto& properties = *MakeGarbageCollected<DetachableResourceFetcherProperties>( + *MakeGarbageCollected<FrameResourceFetcherProperties>( + frame_or_imported_document)); LocalFrame& frame = frame_or_imported_document.GetFrame(); ResourceFetcherInit init( - *MakeGarbageCollected<FrameResourceFetcherProperties>( - frame_or_imported_document), - MakeGarbageCollected<FrameFetchContext>(frame_or_imported_document), + properties, + MakeGarbageCollected<FrameFetchContext>(frame_or_imported_document, + properties), document->GetTaskRunner(blink::TaskType::kNetworking), MakeGarbageCollected<LoaderFactoryForFrame>(frame_or_imported_document)); - init.console_logger = document; + auto* console_logger = + MakeGarbageCollected<DetachableConsoleLogger>(document); + init.console_logger = console_logger; init.frame_scheduler = frame.GetFrameScheduler(); auto* fetcher = MakeGarbageCollected<ResourceFetcher>(init); fetcher->SetResourceLoadObserver( @@ -265,8 +273,10 @@ } FrameFetchContext::FrameFetchContext( - const FrameOrImportedDocument& frame_or_imported_document) - : frame_or_imported_document_(frame_or_imported_document), + const FrameOrImportedDocument& frame_or_imported_document, + const DetachableResourceFetcherProperties& properties) + : BaseFetchContext(properties), + frame_or_imported_document_(frame_or_imported_document), save_data_enabled_( GetNetworkStateNotifier().SaveDataEnabled() && !GetFrame()->GetSettings()->GetDataSaverHoldbackWebApi()) {}
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h index 88f0be9f..756bbef 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -66,7 +66,8 @@ // |document_loader_| will be set to nullptr. static ResourceFetcher* CreateFetcherForImportedDocument(Document* document); - explicit FrameFetchContext(const FrameOrImportedDocument&); + FrameFetchContext(const FrameOrImportedDocument&, + const DetachableResourceFetcherProperties&); ~FrameFetchContext() override = default; void AddAdditionalRequestHeaders(ResourceRequest&) override;
diff --git a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc index d0ca82f9..2292755 100644 --- a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc
@@ -65,7 +65,8 @@ global_scope_->Initialize(response_url, response_referrer_policy, script_data->GetResponseAddressSpace(), - response_content_security_policy->Headers()); + response_content_security_policy->Headers(), + script_data->CreateOriginTrialTokens().get()); } ModuleScriptCreationParams params(
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc index a6536ff..f8e6a18d 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
@@ -166,7 +166,7 @@ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(security_origin_); fetcher_ = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, fetch_context, + ResourceFetcherInit(properties->MakeDetachable(), fetch_context, base::MakeRefCounted<scheduler::FakeTaskRunner>(), MakeGarbageCollected<TestLoaderFactory>())); modulator_ = MakeGarbageCollected<ModuleScriptLoaderTestModulator>( @@ -178,7 +178,7 @@ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(security_origin_); fetcher_ = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, fetch_context, + ResourceFetcherInit(properties->MakeDetachable(), fetch_context, base::MakeRefCounted<scheduler::FakeTaskRunner>(), MakeGarbageCollected<TestLoaderFactory>())); reporting_proxy_ = std::make_unique<MockWorkerReportingProxy>();
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc index 187aeba8..30399ed 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -6,6 +6,7 @@ #include "services/network/public/mojom/referrer_policy.mojom-shared.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h" @@ -113,10 +114,15 @@ response_content_security_policy->DidReceiveHeaders( ContentSecurityPolicyResponseHeaders(resource->GetResponse())); + std::unique_ptr<Vector<String>> response_origin_trial_tokens = + OriginTrialContext::ParseHeaderValue( + resource->GetResponse().HttpHeaderField(http_names::kOriginTrial)); + // Step 12.3-12.6 are implemented in Initialize(). global_scope_->Initialize(response_url, response_referrer_policy, response_address_space, - response_content_security_policy->Headers()); + response_content_security_policy->Headers(), + response_origin_trial_tokens.get()); } ModuleScriptCreationParams params(
diff --git a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc index 859dd0d..85b72c9 100644 --- a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc +++ b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
@@ -64,9 +64,10 @@ MockFetchContext* context = MakeGarbageCollected<MockFetchContext>(); auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *properties, context, base::MakeRefCounted<scheduler::FakeTaskRunner>(), - MakeGarbageCollected<TestLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>( + ResourceFetcherInit(properties->MakeDetachable(), context, + base::MakeRefCounted<scheduler::FakeTaskRunner>(), + MakeGarbageCollected<TestLoaderFactory>())); // Fetch to cache a resource. ResourceRequest request1(url);
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc index 8b15efc7..decab27 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_test.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
@@ -358,10 +358,10 @@ ResourceFetcher* CreateFetcher() { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); - return MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, MakeGarbageCollected<MockFetchContext>(), - base::MakeRefCounted<scheduler::FakeTaskRunner>(), - MakeGarbageCollected<TestLoaderFactory>())); + return MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), MakeGarbageCollected<MockFetchContext>(), + base::MakeRefCounted<scheduler::FakeTaskRunner>(), + MakeGarbageCollected<TestLoaderFactory>())); } TEST(ImageResourceTest, MultipartImage) { @@ -1870,14 +1870,15 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner = page_holder->GetFrame().GetTaskRunner(TaskType::kInternalTest); auto* context = MakeGarbageCollected<MockFetchContext>(); - auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); + auto& properties = + MakeGarbageCollected<TestResourceFetcherProperties>()->MakeDetachable(); auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, task_runner, + ResourceFetcherInit(properties, context, task_runner, MakeGarbageCollected<TestLoaderFactory>())); auto frame_scheduler = std::make_unique<scheduler::FakeFrameScheduler>(); auto* scheduler = MakeGarbageCollected<ResourceLoadScheduler>( - ResourceLoadScheduler::ThrottlingPolicy::kNormal, *properties, - frame_scheduler.get(), *MakeGarbageCollected<NullConsoleLogger>()); + ResourceLoadScheduler::ThrottlingPolicy::kNormal, properties, + frame_scheduler.get(), *MakeGarbageCollected<DetachableConsoleLogger>()); ImageResource* image_resource = ImageResource::CreateForTest(test_url); // Ensure that |image_resource| has a loader.
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc index 4fcf3ace..1ad9473 100644 --- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -35,12 +35,14 @@ WorkerFetchContext::~WorkerFetchContext() = default; WorkerFetchContext::WorkerFetchContext( + const DetachableResourceFetcherProperties& properties, WorkerOrWorkletGlobalScope& global_scope, scoped_refptr<WebWorkerFetchContext> web_context, SubresourceFilter* subresource_filter, ContentSecurityPolicy& content_security_policy, WorkerResourceTimingNotifier& resource_timing_notifier) - : global_scope_(global_scope), + : BaseFetchContext(properties), + global_scope_(global_scope), web_context_(std::move(web_context)), subresource_filter_(subresource_filter), content_security_policy_(&content_security_policy),
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h index 6d0fda6..68671371 100644 --- a/third_party/blink/renderer/core/loader/worker_fetch_context.h +++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -32,7 +32,8 @@ // For more details, see core/workers/README.md. class WorkerFetchContext final : public BaseFetchContext { public: - WorkerFetchContext(WorkerOrWorkletGlobalScope&, + WorkerFetchContext(const DetachableResourceFetcherProperties&, + WorkerOrWorkletGlobalScope&, scoped_refptr<WebWorkerFetchContext>, SubresourceFilter*, ContentSecurityPolicy&,
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 60f7bf3..8e83720 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -92,6 +92,7 @@ #include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/page/popup_opening_observer.h" +#include "third_party/blink/renderer/core/page/validation_message_client.h" #include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h" #include "third_party/blink/renderer/platform/cursor.h" #include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h" @@ -217,6 +218,8 @@ } void ChromeClientImpl::FocusedNodeChanged(Node* from_node, Node* to_node) { + web_view_->GetPage()->GetValidationMessageClient().DidChangeFocusTo(to_node); + if (!web_view_->Client()) return;
diff --git a/third_party/blink/renderer/core/page/page_animator.h b/third_party/blink/renderer/core/page/page_animator.h index 0e2616f8..ba21a58d 100644 --- a/third_party/blink/renderer/core/page/page_animator.h +++ b/third_party/blink/renderer/core/page/page_animator.h
@@ -40,6 +40,9 @@ void UpdateAllLifecyclePhasesExceptPaint(LocalFrame& root_frame); void UpdateLifecycleToLayoutClean(LocalFrame& root_frame); AnimationClock& Clock() { return animation_clock_; } + bool UpdatingLayoutAndStyleForPainting() { + return updating_layout_and_style_for_painting_; + } private: Member<Page> page_;
diff --git a/third_party/blink/renderer/core/page/validation_message_client.h b/third_party/blink/renderer/core/page/validation_message_client.h index 293442f..beb9806 100644 --- a/third_party/blink/renderer/core/page/validation_message_client.h +++ b/third_party/blink/renderer/core/page/validation_message_client.h
@@ -58,6 +58,7 @@ virtual bool IsValidationMessageVisible(const Element& anchor) = 0; virtual void DocumentDetached(const Document&) = 0; + virtual void DidChangeFocusTo(const Node* new_node) = 0; virtual void WillBeDestroyed() = 0;
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.cc b/third_party/blink/renderer/core/page/validation_message_client_impl.cc index fadd416..f88383a 100644 --- a/third_party/blink/renderer/core/page/validation_message_client_impl.cc +++ b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
@@ -155,6 +155,11 @@ HideValidationMessageImmediately(*current_anchor_); } +void ValidationMessageClientImpl::DidChangeFocusTo(const Node* new_node) { + if (current_anchor_ && current_anchor_ != new_node) + HideValidationMessageImmediately(*current_anchor_); +} + void ValidationMessageClientImpl::CheckAnchorStatus(TimerBase*) { DCHECK(current_anchor_); if ((!WebTestSupport::IsRunningWebTest() &&
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.h b/third_party/blink/renderer/core/page/validation_message_client_impl.h index 2164b77..d0f965f 100644 --- a/third_party/blink/renderer/core/page/validation_message_client_impl.h +++ b/third_party/blink/renderer/core/page/validation_message_client_impl.h
@@ -67,6 +67,7 @@ void HideValidationMessage(const Element& anchor) override; bool IsValidationMessageVisible(const Element& anchor) override; void DocumentDetached(const Document&) override; + void DidChangeFocusTo(const Node* new_node) override; void WillBeDestroyed() override; void LayoutOverlay() override; void UpdatePrePaint() override;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_test.cc b/third_party/blink/renderer/core/paint/paint_layer_test.cc index 77fb3ce9..7c0919356 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_test.cc
@@ -1429,7 +1429,13 @@ // span_layer should be marked NeedsRepaint. target_element->setAttribute(html_names::kStyleAttr, "overflow: hidden; float: left"); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + // TODO(yosin): Once multicol in LayoutNG, we should remove following + // assignments. This is because the layout tree maybe reattached. In LayoutNG + // phase 1, layout tree is reattached because multicol forces legacy layout. + target_object = target_element->GetLayoutObject(); + target_layer = ToLayoutBoxModelObject(target_object)->Layer(); EXPECT_FALSE(target_layer->IsSelfPaintingLayer()); if (RuntimeEnabledFeatures::LayoutNGEnabled()) { EXPECT_EQ(span_layer, target_layer->CompositingContainer());
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index 51cc2c5..2eb7cdc 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -813,8 +813,9 @@ bool Internals::isValidationMessageVisible(Element* element) { DCHECK(element); - return IsHTMLFormControlElement(element) && - ToHTMLFormControlElement(element)->IsValidationMessageVisible(); + if (auto* control = ListedElement::From(*element)) + return control->IsValidationMessageVisible(); + return false; } void Internals::selectColorInColorChooser(Element* element,
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc index bea6acc..7431ad9 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -61,12 +61,16 @@ std::unique_ptr<GlobalScopeCreationParams> creation_params, DedicatedWorkerThread* thread, base::TimeTicks time_origin) { + std::unique_ptr<Vector<String>> outside_origin_trial_tokens = + std::move(creation_params->origin_trial_tokens); + // Off-the-main-thread worker script fetch: // Initialize() is called after script fetch. if (creation_params->off_main_thread_fetch_option == OffMainThreadWorkerScriptFetchOption::kEnabled) { return MakeGarbageCollected<DedicatedWorkerGlobalScope>( - std::move(creation_params), thread, time_origin); + std::move(creation_params), thread, time_origin, + std::move(outside_origin_trial_tokens)); } // Legacy on-the-main-thread worker script fetch (to be removed): @@ -76,19 +80,27 @@ mojom::IPAddressSpace response_address_space = *creation_params->response_address_space; auto* global_scope = MakeGarbageCollected<DedicatedWorkerGlobalScope>( - std::move(creation_params), thread, time_origin); - // A dummy CSP headers is passed here as it is superseded by outside's CSP - // headers in Initialize(). + std::move(creation_params), thread, time_origin, + std::move(outside_origin_trial_tokens)); + // Pass dummy CSP headers here as it is superseded by outside's CSP headers in + // Initialize(). + // Pass dummy origin trial tokens here as it is already set to outside's + // origin trial tokens in DedicatedWorkerGlobalScope's constructor. global_scope->Initialize(response_script_url, response_referrer_policy, - response_address_space, Vector<CSPHeaderAndType>()); + response_address_space, Vector<CSPHeaderAndType>(), + nullptr /* response_origin_trial_tokens */); return global_scope; } DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams> creation_params, DedicatedWorkerThread* thread, - base::TimeTicks time_origin) - : WorkerGlobalScope(std::move(creation_params), thread, time_origin) {} + base::TimeTicks time_origin, + std::unique_ptr<Vector<String>> outside_origin_trial_tokens) + : WorkerGlobalScope(std::move(creation_params), thread, time_origin) { + // Inherit the outside's origin trial tokens. + OriginTrialContext::AddTokens(this, outside_origin_trial_tokens.get()); +} DedicatedWorkerGlobalScope::~DedicatedWorkerGlobalScope() = default; @@ -101,7 +113,8 @@ const KURL& response_url, network::mojom::ReferrerPolicy response_referrer_policy, mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& /* not used */) { + const Vector<CSPHeaderAndType>& /* response_csp_headers */, + const Vector<String>* /* response_origin_trial_tokens */) { // Step 12.3. "Set worker global scope's url to response's url." InitializeURL(response_url); @@ -118,11 +131,15 @@ // Step 12.6. "Execute the Initialize a global object's CSP list algorithm // on worker global scope and response. [CSP]" - // DedicatedWorkerGlobalScope inherits the outside's CSP instead of the passed - // CSP. These should be called after SetAddressSpace() to correctly override - // the address space by the "treat-as-public-address" CSP directive. + // DedicatedWorkerGlobalScope inherits the outside's CSP instead of the + // response CSP headers. These should be called after SetAddressSpace() to + // correctly override the address space by the "treat-as-public-address" CSP + // directive. InitContentSecurityPolicyFromVector(OutsideContentSecurityPolicyHeaders()); BindContentSecurityPolicyToExecutionContext(); + + // DedicatedWorkerGlobalScope inherits the outside's OriginTrialTokens in the + // constructor instead of the response origin trial tokens. } // https://html.spec.whatwg.org/C/#worker-processing-model @@ -260,11 +277,14 @@ } // Step 12.3-12.6 are implemented in Initialize(). - // A dummy CSP headers is passed here as it is superseded by outside's CSP - // headers in Initialize(). + // Pass dummy CSP headers here as it is superseded by outside's CSP headers in + // Initialize(). + // Pass dummy origin trial tokens here as it is already set to outside's + // origin trial tokens in DedicatedWorkerGlobalScope's constructor. Initialize(classic_script_loader->ResponseURL(), response_referrer_policy, classic_script_loader->ResponseAddressSpace(), - Vector<CSPHeaderAndType>()); + Vector<CSPHeaderAndType>(), + nullptr /* response_origin_trial_tokens */); // Step 12.7. "Asynchronously complete the perform the fetch steps with // response."
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h index 3b1d3f7c..36bcb564 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
@@ -60,9 +60,11 @@ // Do not call this. Use Create() instead. This is public only for // MakeGarbageCollected. - DedicatedWorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>, - DedicatedWorkerThread*, - base::TimeTicks time_origin); + DedicatedWorkerGlobalScope( + std::unique_ptr<GlobalScopeCreationParams>, + DedicatedWorkerThread*, + base::TimeTicks time_origin, + std::unique_ptr<Vector<String>> outside_origin_trial_tokens); ~DedicatedWorkerGlobalScope() override; @@ -74,11 +76,11 @@ const AtomicString& InterfaceName() const override; // Implements WorkerGlobalScope. - void Initialize( - const KURL& response_url, - network::mojom::ReferrerPolicy response_referrer_policy, - mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) override; + void Initialize(const KURL& response_url, + network::mojom::ReferrerPolicy response_referrer_policy, + mojom::IPAddressSpace response_address_space, + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) override; void FetchAndRunClassicScript( const KURL& script_url, const FetchClientSettingsObjectSnapshot& outside_settings_object,
diff --git a/third_party/blink/renderer/core/workers/experimental/thread_pool_thread.cc b/third_party/blink/renderer/core/workers/experimental/thread_pool_thread.cc index 3701f76c..61cb937 100644 --- a/third_party/blink/renderer/core/workers/experimental/thread_pool_thread.cc +++ b/third_party/blink/renderer/core/workers/experimental/thread_pool_thread.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/workers/experimental/thread_pool_thread.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/workers/experimental/task_worklet_global_scope.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/threaded_object_proxy_base.h" @@ -36,11 +37,11 @@ } // WorkerGlobalScope - void Initialize( - const KURL& response_url, - network::mojom::ReferrerPolicy response_referrer_policy, - mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) override { + void Initialize(const KURL& response_url, + network::mojom::ReferrerPolicy response_referrer_policy, + mojom::IPAddressSpace response_address_space, + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) override { InitializeURL(response_url); SetReferrerPolicy(response_referrer_policy); SetAddressSpace(response_address_space); @@ -49,6 +50,8 @@ // address space by the "treat-as-public-address" CSP directive. InitContentSecurityPolicyFromVector(response_csp_headers); BindContentSecurityPolicyToExecutionContext(); + + OriginTrialContext::AddTokens(this, response_origin_trial_tokens); } void FetchAndRunClassicScript( const KURL& script_url,
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc index 04a208d..13acda45 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
@@ -38,6 +38,7 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h" +#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/workers/shared_worker_thread.h" #include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h" @@ -74,10 +75,13 @@ // off-the-main-thread worker script fetch by default. Vector<CSPHeaderAndType> response_csp_headers = creation_params->outside_content_security_policy_headers; + std::unique_ptr<Vector<String>> response_origin_trial_tokens = + std::move(creation_params->origin_trial_tokens); auto* global_scope = MakeGarbageCollected<SharedWorkerGlobalScope>( std::move(creation_params), thread, time_origin); global_scope->Initialize(response_script_url, response_referrer_policy, - response_address_space, response_csp_headers); + response_address_space, response_csp_headers, + response_origin_trial_tokens.get()); return global_scope; } @@ -98,7 +102,8 @@ const KURL& response_url, network::mojom::ReferrerPolicy response_referrer_policy, mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) { + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) { // Step 12.3. "Set worker global scope's url to response's url." InitializeURL(response_url); @@ -119,6 +124,8 @@ // address space by the "treat-as-public-address" CSP directive. InitContentSecurityPolicyFromVector(response_csp_headers); BindContentSecurityPolicyToExecutionContext(); + + OriginTrialContext::AddTokens(this, response_origin_trial_tokens); } // https://html.spec.whatwg.org/C/#worker-processing-model @@ -226,7 +233,8 @@ classic_script_loader->ResponseAddressSpace(), classic_script_loader->GetContentSecurityPolicy() ? classic_script_loader->GetContentSecurityPolicy()->Headers() - : Vector<CSPHeaderAndType>()); + : Vector<CSPHeaderAndType>(), + classic_script_loader->OriginTrialTokens()); // Step 12.7. "Asynchronously complete the perform the fetch steps with // response."
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.h b/third_party/blink/renderer/core/workers/shared_worker_global_scope.h index bb055e1..0e9938c 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
@@ -68,11 +68,11 @@ const AtomicString& InterfaceName() const override; // WorkerGlobalScope - void Initialize( - const KURL& response_url, - network::mojom::ReferrerPolicy response_referrer_policy, - mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) override; + void Initialize(const KURL& response_url, + network::mojom::ReferrerPolicy response_referrer_policy, + mojom::IPAddressSpace response_address_space, + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) override; void FetchAndRunClassicScript( const KURL& script_url, const FetchClientSettingsObjectSnapshot& outside_settings_object,
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index c1d33b8..54abbb7 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -50,7 +50,6 @@ #include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h" #include "third_party/blink/renderer/core/loader/threadable_loader.h" #include "third_party/blink/renderer/core/messaging/message_port.h" -#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h" #include "third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h" @@ -450,8 +449,6 @@ SetOutsideContentSecurityPolicyHeaders( creation_params->outside_content_security_policy_headers); SetWorkerSettings(std::move(creation_params->worker_settings)); - OriginTrialContext::AddTokens(this, - creation_params->origin_trial_tokens.get()); // TODO(sammc): Require a valid |creation_params->interface_provider| once all // worker types provide a valid |creation_params->interface_provider|.
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index e37eb55..3a2df46 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -151,7 +151,8 @@ const KURL& response_url, network::mojom::ReferrerPolicy response_referrer_policy, mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) = 0; + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) = 0; // These methods should be called in the scope of a pausable // task runner. ie. They should not be called when the context
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc index 5875f6e4..fbff9c2 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -290,28 +290,34 @@ InitializeWebFetchContextIfNeeded(); ResourceFetcher* fetcher = nullptr; if (web_worker_fetch_context_) { + auto& properties = + *MakeGarbageCollected<DetachableResourceFetcherProperties>( + *MakeGarbageCollected<WorkerResourceFetcherProperties>( + *this, fetch_client_settings_object, + web_worker_fetch_context_)); ResourceFetcherInit init( - *MakeGarbageCollected<WorkerResourceFetcherProperties>( - *this, fetch_client_settings_object, web_worker_fetch_context_), - + properties, MakeGarbageCollected<WorkerFetchContext>( - *this, web_worker_fetch_context_, subresource_filter_, + properties, *this, web_worker_fetch_context_, subresource_filter_, content_security_policy, resource_timing_notifier), GetTaskRunner(TaskType::kNetworking), MakeGarbageCollected<LoaderFactoryForWorker>( *this, web_worker_fetch_context_)); - init.console_logger = this; + auto* console_logger = MakeGarbageCollected<DetachableConsoleLogger>(this); + init.console_logger = console_logger; fetcher = MakeGarbageCollected<ResourceFetcher>(init); fetcher->SetResourceLoadObserver( MakeGarbageCollected<ResourceLoadObserverForWorker>( *probe::ToCoreProbeSink(static_cast<ExecutionContext*>(this)), fetcher->GetProperties(), web_worker_fetch_context_)); } else { + auto& properties = + *MakeGarbageCollected<DetachableResourceFetcherProperties>( + *MakeGarbageCollected<NullResourceFetcherProperties>()); // This code path is for unittests. fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *MakeGarbageCollected<NullResourceFetcherProperties>(), - &FetchContext::NullInstance(), GetTaskRunner(TaskType::kNetworking), - nullptr /* loader_factory */)); + properties, &FetchContext::NullInstance(), + GetTaskRunner(TaskType::kNetworking), nullptr /* loader_factory */)); } if (IsContextPaused()) fetcher->SetDefersLoading(true);
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h index cbbc04f..93afffd4 100644 --- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h +++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -18,6 +18,7 @@ #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/inspector/worker_devtools_params.h" +#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/script/script.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" #include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h" @@ -57,16 +58,21 @@ } // WorkerGlobalScope - void Initialize( - const KURL& response_url, - network::mojom::ReferrerPolicy response_referrer_policy, - mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) override { + void Initialize(const KURL& response_url, + network::mojom::ReferrerPolicy response_referrer_policy, + mojom::IPAddressSpace response_address_space, + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) override { InitializeURL(response_url); SetReferrerPolicy(response_referrer_policy); SetAddressSpace(response_address_space); + + // These should be called after SetAddressSpace() to correctly override the + // address space by the "treat-as-public-address" CSP directive. InitContentSecurityPolicyFromVector(response_csp_headers); BindContentSecurityPolicyToExecutionContext(); + + OriginTrialContext::AddTokens(this, response_origin_trial_tokens); } void FetchAndRunClassicScript( const KURL& script_url,
diff --git a/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc b/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc index 0d1f749b..027dcfce 100644 --- a/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc +++ b/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc
@@ -28,9 +28,10 @@ platform_->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); auto* context = MakeGarbageCollected<MockFetchContext>(); - fetcher_ = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *properties, context, base::MakeRefCounted<scheduler::FakeTaskRunner>(), - MakeGarbageCollected<TestLoaderFactory>())); + fetcher_ = MakeGarbageCollected<ResourceFetcher>( + ResourceFetcherInit(properties->MakeDetachable(), context, + base::MakeRefCounted<scheduler::FakeTaskRunner>(), + MakeGarbageCollected<TestLoaderFactory>())); map_ = MakeGarbageCollected<WorkletModuleResponsesMap>(); }
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc index 42958d1e..87d99ce 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc +++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -319,6 +319,7 @@ bool ClipboardPromise::IsFocusedDocument(ExecutionContext* context) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(context); DCHECK(context->IsSecureContext()); // [SecureContext] in IDL Document* doc = To<Document>(context); return doc && doc->hasFocus();
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc index dd8c6e7..ebd2193 100644 --- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc +++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
@@ -359,7 +359,7 @@ } void PictureInPictureControllerImpl::OnStopped() { - OnExitedPictureInPicture(nullptr); + // TODO(940694): implement OnStopped() and remove IPC message. } bool PictureInPictureControllerImpl::ShouldShowMuteButton(
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index bd3c57d..71d551c 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -133,6 +133,8 @@ creation_params->referrer_policy; mojom::IPAddressSpace response_address_space = *creation_params->response_address_space; + std::unique_ptr<Vector<String>> response_origin_trial_tokens = + std::move(creation_params->origin_trial_tokens); // Contrary to the name, |outside_content_security_policy_headers| contains // worker script's response CSP headers in this case. // TODO(nhiroki): Introduce inside's csp headers field in @@ -144,7 +146,8 @@ std::move(creation_params), thread, std::move(cache_storage_info), time_origin); global_scope->Initialize(response_url, response_referrer_policy, - response_address_space, response_csp_headers); + response_address_space, response_csp_headers, + response_origin_trial_tokens.get()); return global_scope; } @@ -256,10 +259,6 @@ } ReportingProxy().DidLoadClassicScript(); - std::unique_ptr<Vector<String>> origin_trial_tokens = - script_data->CreateOriginTrialTokens(); - OriginTrialContext::AddTokens(this, origin_trial_tokens.get()); - auto referrer_policy = network::mojom::ReferrerPolicy::kDefault; if (!script_data->GetReferrerPolicy().IsNull()) { SecurityPolicy::ReferrerPolicyFromHeaderValue( @@ -276,8 +275,9 @@ RunClassicScript( script_url, referrer_policy, script_data->GetResponseAddressSpace(), - content_security_policy->Headers(), script_data->TakeSourceText(), - script_data->TakeMetaData(), stack_id); + content_security_policy->Headers(), + script_data->CreateOriginTrialTokens().get(), + script_data->TakeSourceText(), script_data->TakeMetaData(), stack_id); } void ServiceWorkerGlobalScope::RunInstalledModuleScript( @@ -427,6 +427,7 @@ classic_script_loader->GetContentSecurityPolicy() ? classic_script_loader->GetContentSecurityPolicy()->Headers() : Vector<CSPHeaderAndType>(), + classic_script_loader->OriginTrialTokens(), classic_script_loader->SourceText(), classic_script_loader->ReleaseCachedMetadata(), stack_id); } @@ -436,7 +437,8 @@ const KURL& response_url, network::mojom::ReferrerPolicy response_referrer_policy, mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) { + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) { // Step 4.5. "Set workerGlobalScope's url to serviceWorker's script url." InitializeURL(response_url); @@ -467,6 +469,8 @@ InitContentSecurityPolicyFromVector(response_csp_headers); BindContentSecurityPolicyToExecutionContext(); + OriginTrialContext::AddTokens(this, response_origin_trial_tokens); + // TODO(nhiroki): Clarify mappings between the steps 4.8-4.11 and // implementation. } @@ -477,12 +481,13 @@ network::mojom::ReferrerPolicy response_referrer_policy, mojom::IPAddressSpace response_address_space, const Vector<CSPHeaderAndType> response_csp_headers, + const Vector<String>* response_origin_trial_tokens, const String& source_code, std::unique_ptr<Vector<uint8_t>> cached_meta_data, const v8_inspector::V8StackTraceId& stack_id) { // Step 4.5-4.11 are implemented in Initialize(). Initialize(response_url, response_referrer_policy, response_address_space, - response_csp_headers); + response_csp_headers, response_origin_trial_tokens); // Step 4.12. "Let evaluationStatus be the result of running the classic // script script if script is a classic script, otherwise, the result of
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h index 7bef808..7cc9df7 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -83,11 +83,11 @@ bool ShouldInstallV8Extensions() const final; // Implements WorkerGlobalScope: - void Initialize( - const KURL& response_url, - network::mojom::ReferrerPolicy response_referrer_policy, - mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>& response_csp_headers) override; + void Initialize(const KURL& response_url, + network::mojom::ReferrerPolicy response_referrer_policy, + mojom::IPAddressSpace response_address_space, + const Vector<CSPHeaderAndType>& response_csp_headers, + const Vector<String>* response_origin_trial_tokens) override; // Fetches and runs the top-level classic worker script for the 'new' or // 'update' service worker cases. void FetchAndRunClassicScript( @@ -206,9 +206,10 @@ // https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm void RunClassicScript(const KURL& response_url, - network::mojom::ReferrerPolicy, + network::mojom::ReferrerPolicy response_referrer_policy, mojom::IPAddressSpace response_address_space, - const Vector<CSPHeaderAndType>, + const Vector<CSPHeaderAndType> response_csp_headers, + const Vector<String>* response_origin_trial_tokens, const String& source_code, std::unique_ptr<Vector<uint8_t>> cached_meta_data, const v8_inspector::V8StackTraceId&);
diff --git a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc index 60ae944..ceae9d6 100644 --- a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc
@@ -14,16 +14,13 @@ XRBoundedReferenceSpace::XRBoundedReferenceSpace(XRSession* session) : XRReferenceSpace(session) {} +XRBoundedReferenceSpace::XRBoundedReferenceSpace( + XRSession* session, + XRRigidTransform* origin_offset) + : XRReferenceSpace(session, origin_offset) {} + XRBoundedReferenceSpace::~XRBoundedReferenceSpace() = default; -void XRBoundedReferenceSpace::setOriginOffset(XRRigidTransform* transform) { - XRReferenceSpace::setOriginOffset(transform); - - // Force a bounds update. - stage_parameters_id_ = 0; - EnsureUpdated(); -} - // No default pose for bounded reference spaces. std::unique_ptr<TransformationMatrix> XRBoundedReferenceSpace::DefaultPose() { return nullptr; @@ -51,8 +48,7 @@ // In order to ensure that the bounds continue to line up with the user's // physical environment we need to transform by the inverse of the // originOffset. - TransformationMatrix bounds_transform = - originOffset()->InverseTransformMatrix(); + TransformationMatrix bounds_transform = InverseOriginOffsetMatrix(); if (display_info->stageParameters->bounds) { bounds_geometry_.clear(); @@ -126,4 +122,10 @@ DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this)); } +XRBoundedReferenceSpace* XRBoundedReferenceSpace::cloneWithOriginOffset( + XRRigidTransform* origin_offset) { + return MakeGarbageCollected<XRBoundedReferenceSpace>(this->session(), + origin_offset); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h index e5bfd7a..61b1170 100644 --- a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h +++ b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h
@@ -15,15 +15,14 @@ DEFINE_WRAPPERTYPEINFO(); public: - XRBoundedReferenceSpace(XRSession*); + explicit XRBoundedReferenceSpace(XRSession*); + XRBoundedReferenceSpace(XRSession*, XRRigidTransform*); ~XRBoundedReferenceSpace() override; std::unique_ptr<TransformationMatrix> DefaultPose() override; std::unique_ptr<TransformationMatrix> TransformBasePose( const TransformationMatrix& base_pose) override; - void setOriginOffset(XRRigidTransform*) override; - HeapVector<Member<DOMPointReadOnly>> boundsGeometry(); void Trace(blink::Visitor*) override; @@ -31,6 +30,9 @@ void OnReset() override; private: + XRBoundedReferenceSpace* cloneWithOriginOffset( + XRRigidTransform* origin_offset) override; + void EnsureUpdated(); HeapVector<Member<DOMPointReadOnly>> bounds_geometry_;
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_reference_space.cc index 42bf378..0d26aced 100644 --- a/third_party/blink/renderer/modules/xr/xr_reference_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.cc
@@ -13,9 +13,13 @@ // origin offset starts as identity transform XRReferenceSpace::XRReferenceSpace(XRSession* session) - : XRSpace(session), - origin_offset_(MakeGarbageCollected<XRRigidTransform>(nullptr, nullptr)) { -} + : XRReferenceSpace( + session, + MakeGarbageCollected<XRRigidTransform>(nullptr, nullptr)) {} + +XRReferenceSpace::XRReferenceSpace(XRSession* session, + XRRigidTransform* origin_offset) + : XRSpace(session), origin_offset_(origin_offset) {} XRReferenceSpace::~XRReferenceSpace() = default; @@ -63,14 +67,28 @@ return transform_matrix; } -void XRReferenceSpace::setOriginOffset(XRRigidTransform* transform) { - origin_offset_ = transform; +TransformationMatrix XRReferenceSpace::OriginOffsetMatrix() { + return origin_offset_->TransformMatrix(); } TransformationMatrix XRReferenceSpace::InverseOriginOffsetMatrix() { return origin_offset_->InverseTransformMatrix(); } +XRReferenceSpace* XRReferenceSpace::getOffsetReferenceSpace( + XRRigidTransform* additional_offset) { + auto matrix = + OriginOffsetMatrix().Multiply(additional_offset->TransformMatrix()); + + auto* result_transform = MakeGarbageCollected<XRRigidTransform>(matrix); + return cloneWithOriginOffset(result_transform); +} + +XRReferenceSpace* XRReferenceSpace::cloneWithOriginOffset( + XRRigidTransform* origin_offset) { + return MakeGarbageCollected<XRReferenceSpace>(this->session(), origin_offset); +} + void XRReferenceSpace::Trace(blink::Visitor* visitor) { visitor->Trace(origin_offset_); XRSpace::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.h b/third_party/blink/renderer/modules/xr/xr_reference_space.h index de7b49b..078915f9 100644 --- a/third_party/blink/renderer/modules/xr/xr_reference_space.h +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.h
@@ -19,6 +19,7 @@ public: explicit XRReferenceSpace(XRSession*); + XRReferenceSpace(XRSession*, XRRigidTransform*); ~XRReferenceSpace() override; std::unique_ptr<TransformationMatrix> DefaultPose() override; @@ -30,10 +31,11 @@ std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace() override; - XRRigidTransform* originOffset() const { return origin_offset_; } - virtual void setOriginOffset(XRRigidTransform*); + TransformationMatrix OriginOffsetMatrix() override; TransformationMatrix InverseOriginOffsetMatrix() override; + XRReferenceSpace* getOffsetReferenceSpace(XRRigidTransform* transform); + DEFINE_ATTRIBUTE_EVENT_LISTENER(reset, kReset) void Trace(blink::Visitor*) override; @@ -41,6 +43,9 @@ virtual void OnReset(); private: + virtual XRReferenceSpace* cloneWithOriginOffset( + XRRigidTransform* origin_offset); + Member<XRRigidTransform> origin_offset_; };
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.idl b/third_party/blink/renderer/modules/xr/xr_reference_space.idl index 037a4c7..aa3a3b8 100644 --- a/third_party/blink/renderer/modules/xr/xr_reference_space.idl +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.idl
@@ -16,6 +16,6 @@ Exposed=Window, RuntimeEnabled=WebXR ] interface XRReferenceSpace : XRSpace { - attribute XRRigidTransform originOffset; attribute EventHandler onreset; + XRReferenceSpace getOffsetReferenceSpace(XRRigidTransform originOffset); };
diff --git a/third_party/blink/renderer/modules/xr/xr_space.cc b/third_party/blink/renderer/modules/xr/xr_space.cc index 33de78b..2655d67 100644 --- a/third_party/blink/renderer/modules/xr/xr_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_space.cc
@@ -37,6 +37,11 @@ return nullptr; } +TransformationMatrix XRSpace::OriginOffsetMatrix() { + TransformationMatrix identity; + return identity; +} + TransformationMatrix XRSpace::InverseOriginOffsetMatrix() { TransformationMatrix identity; return identity;
diff --git a/third_party/blink/renderer/modules/xr/xr_space.h b/third_party/blink/renderer/modules/xr/xr_space.h index 772c6c1..d7a4e5de 100644 --- a/third_party/blink/renderer/modules/xr/xr_space.h +++ b/third_party/blink/renderer/modules/xr/xr_space.h
@@ -51,6 +51,7 @@ ExecutionContext* GetExecutionContext() const override; const AtomicString& InterfaceName() const override; + virtual TransformationMatrix OriginOffsetMatrix(); virtual TransformationMatrix InverseOriginOffsetMatrix(); void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.cc index 1ee926e3..a9d98b8 100644 --- a/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.cc
@@ -17,6 +17,12 @@ Subtype subtype) : XRReferenceSpace(session), subtype_(subtype) {} +XRStationaryReferenceSpace::XRStationaryReferenceSpace( + XRSession* session, + XRRigidTransform* transform, + Subtype subtype) + : XRReferenceSpace(session, transform), subtype_(subtype) {} + XRStationaryReferenceSpace::~XRStationaryReferenceSpace() = default; void XRStationaryReferenceSpace::UpdateFloorLevelTransform() { @@ -67,8 +73,8 @@ // Apply the floor-level transform to the base pose. if (floor_level_transform_) { - std::unique_ptr<TransformationMatrix> pose( - std::make_unique<TransformationMatrix>(*floor_level_transform_)); + auto pose = + std::make_unique<TransformationMatrix>(*floor_level_transform_); pose->Multiply(base_pose); return pose; } @@ -77,8 +83,7 @@ // 'position-disabled' poses must not contain any translation components, // and as a result the space the base pose is originally in doesn't matter // much. Strip out translation component and return. - std::unique_ptr<TransformationMatrix> pose( - std::make_unique<TransformationMatrix>(base_pose)); + auto pose = std::make_unique<TransformationMatrix>(base_pose); pose->SetM41(0.0); pose->SetM42(0.0); pose->SetM43(0.0); @@ -98,8 +103,7 @@ const TransformationMatrix& base_pose) { switch (subtype_) { case kSubtypePositionDisabled: { - std::unique_ptr<TransformationMatrix> head_model_pose( - TransformBasePose(base_pose)); + auto head_model_pose = TransformBasePose(base_pose); // Get the positional delta between the base pose and the head model pose. float dx = head_model_pose->M41() - base_pose.M41(); @@ -108,8 +112,7 @@ // Translate the controller by the same delta so that it shows up in the // right relative position. - std::unique_ptr<TransformationMatrix> pose( - std::make_unique<TransformationMatrix>(base_input_pose)); + auto pose = std::make_unique<TransformationMatrix>(base_input_pose); pose->SetM41(pose->M41() + dx); pose->SetM42(pose->M42() + dy); pose->SetM43(pose->M43() + dz); @@ -133,4 +136,10 @@ DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this)); } +XRStationaryReferenceSpace* XRStationaryReferenceSpace::cloneWithOriginOffset( + XRRigidTransform* origin_offset) { + return MakeGarbageCollected<XRStationaryReferenceSpace>( + this->session(), origin_offset, subtype_); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h index e4cce49..c08fe2ca 100644 --- a/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h +++ b/third_party/blink/renderer/modules/xr/xr_stationary_reference_space.h
@@ -21,6 +21,7 @@ }; XRStationaryReferenceSpace(XRSession*, Subtype); + XRStationaryReferenceSpace(XRSession*, XRRigidTransform*, Subtype); ~XRStationaryReferenceSpace() override; std::unique_ptr<TransformationMatrix> DefaultPose() override; @@ -35,6 +36,9 @@ void OnReset() override; private: + XRStationaryReferenceSpace* cloneWithOriginOffset( + XRRigidTransform* origin_offset) override; + void UpdateFloorLevelTransform(); unsigned int display_info_id_ = 0;
diff --git a/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.cc index a93dfe38..14df77bf 100644 --- a/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.cc
@@ -13,6 +13,11 @@ XRUnboundedReferenceSpace::XRUnboundedReferenceSpace(XRSession* session) : XRReferenceSpace(session) {} +XRUnboundedReferenceSpace::XRUnboundedReferenceSpace( + XRSession* session, + XRRigidTransform* origin_offset) + : XRReferenceSpace(session, origin_offset) {} + XRUnboundedReferenceSpace::~XRUnboundedReferenceSpace() = default; // No default pose for unbounded reference spaces. @@ -36,4 +41,10 @@ DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this)); } +XRUnboundedReferenceSpace* XRUnboundedReferenceSpace::cloneWithOriginOffset( + XRRigidTransform* origin_offset) { + return MakeGarbageCollected<XRUnboundedReferenceSpace>(this->session(), + origin_offset); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h index 6c9768b..42f08ea 100644 --- a/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h +++ b/third_party/blink/renderer/modules/xr/xr_unbounded_reference_space.h
@@ -14,7 +14,8 @@ DEFINE_WRAPPERTYPEINFO(); public: - XRUnboundedReferenceSpace(XRSession*); + explicit XRUnboundedReferenceSpace(XRSession*); + XRUnboundedReferenceSpace(XRSession*, XRRigidTransform*); ~XRUnboundedReferenceSpace() override; std::unique_ptr<TransformationMatrix> DefaultPose() override; @@ -26,6 +27,9 @@ void OnReset() override; private: + XRUnboundedReferenceSpace* cloneWithOriginOffset( + XRRigidTransform* origin_offset) override; + std::unique_ptr<TransformationMatrix> pose_transform_; };
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 44ace22..6fc8fc49 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -188,10 +188,6 @@ RuntimeEnabledFeatures::SetForceTallerSelectPopupEnabled(enable); } -void WebRuntimeFeatures::EnableFormControlsRefresh(bool enable) { - RuntimeEnabledFeatures::SetFormControlsRefreshEnabled(enable); -} - void WebRuntimeFeatures::EnableGenericSensor(bool enable) { RuntimeEnabledFeatures::SetSensorEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc index 942533b..b25a88e 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -462,9 +462,7 @@ property_trees_.element_id_to_transform_node_index[compositor_element_id] = id; compositor_node.element_id = compositor_element_id; - - if (transform_node.RequiresCompositingForAnimation()) - CollectAnimationElementId(compositor_element_id); + CollectAnimationElementId(compositor_element_id); } // If this transform is a scroll offset translation, create the associated @@ -945,7 +943,6 @@ if (element_namespace == CompositorElementIdNamespace::kPrimaryTransform || element_namespace == CompositorElementIdNamespace::kPrimaryEffect || element_namespace == CompositorElementIdNamespace::kEffectFilter) { - DCHECK_EQ(0u, animation_element_ids_.count(element_id)); animation_element_ids_.insert(element_id); } } @@ -994,9 +991,7 @@ compositor_element_id)); property_trees_.element_id_to_effect_node_index[compositor_element_id] = effect_node.id; - - if (next_effect.RequiresCompositingForAnimation()) - CollectAnimationElementId(compositor_element_id); + CollectAnimationElementId(compositor_element_id); } effect_stack_.emplace_back(current_);
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h index 4b07732..8f2ae61 100644 --- a/third_party/blink/renderer/platform/heap/heap.h +++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -515,7 +515,8 @@ DISALLOW_COPY_AND_ASSIGN(GarbageCollected); }; -// Constructs an instance of T, which is a garbage collected type. +// Default MakeGarbageCollected: Constructs an instance of T, which is a garbage +// collected type. template <typename T, typename... Args> T* MakeGarbageCollected(Args&&... args) { static_assert(WTF::IsGarbageCollectedType<T>::value, @@ -529,6 +530,28 @@ return object; } +// Used for passing custom sizes to MakeGarbageCollected. +struct AdditionalBytes { + explicit AdditionalBytes(size_t bytes) : value(bytes) {} + const size_t value; +}; + +// Constructs an instance of T, which is a garbage collected type. This special +// version takes size which enables constructing inline objects. +template <typename T, typename... Args> +T* MakeGarbageCollected(AdditionalBytes additional_bytes, Args&&... args) { + static_assert(WTF::IsGarbageCollectedType<T>::value, + "T needs to be a garbage collected object"); + void* memory = T::AllocateObject(sizeof(T) + additional_bytes.value, + IsEagerlyFinalizedType<T>::value); + HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory); + header->MarkIsInConstruction(); + // Placement new as regular operator new() is deleted. + T* object = ::new (memory) T(std::forward<Args>(args)...); + header->UnmarkIsInConstruction(); + return object; +} + // Assigning class types to their arenas. // // We use sized arenas for most 'normal' objects to improve memory locality.
diff --git a/third_party/blink/renderer/platform/loader/BUILD.gn b/third_party/blink/renderer/platform/loader/BUILD.gn index 9206af1..29698d2 100644 --- a/third_party/blink/renderer/platform/loader/BUILD.gn +++ b/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -64,6 +64,7 @@ "fetch/resource_error.h", "fetch/resource_fetcher.cc", "fetch/resource_fetcher.h", + "fetch/resource_fetcher_properties.cc", "fetch/resource_fetcher_properties.h", "fetch/resource_finish_observer.h", "fetch/resource_load_info.h", @@ -141,6 +142,7 @@ "fetch/memory_cache_correctness_test.cc", "fetch/memory_cache_test.cc", "fetch/raw_resource_test.cc", + "fetch/resource_fetcher_properties_test.cc", "fetch/resource_fetcher_test.cc", "fetch/resource_load_scheduler_test.cc", "fetch/resource_loader_defer_loading_test.cc",
diff --git a/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc b/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc index dd93ca30..4a554a39 100644 --- a/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc +++ b/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
@@ -5,13 +5,10 @@ #include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h" #include "third_party/blink/renderer/platform/loader/fetch/console_logger.h" -#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h" -#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/network/http_names.h" #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h" -#include "third_party/blink/renderer/platform/weborigin/security_origin.h" namespace blink { @@ -161,10 +158,8 @@ // Check for certain non-executable MIME types. // See: // https://fetch.spec.whatwg.org/#should-response-to-request-be-blocked-due-to-mime-type? - bool same_origin = context.GetResourceFetcherProperties() - .GetFetchClientSettingsObject() - .GetSecurityOrigin() - ->CanRequest(response.CurrentRequestUrl()); + const bool same_origin = + response.GetType() == network::mojom::FetchResponseType::kBasic; // For any MIME type, we can do three things: accept/reject it, print a // warning into the console, and count it using a use counter.
diff --git a/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc b/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc index e8e48d4..a26edc1 100644 --- a/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc +++ b/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc
@@ -106,9 +106,9 @@ SecurityOrigin::Create(url)); auto* context = CountUsageMockFetchContext::Create(); // Bind |properties| to |context| through a ResourceFetcher. - MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<TestLoaderFactory>())); + MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<TestLoaderFactory>())); Persistent<MockConsoleLogger> logger = MakeGarbageCollected<MockConsoleLogger>(); ResourceResponse response(url); @@ -133,51 +133,58 @@ } TEST_F(AllowedByNosniffTest, Counters) { + constexpr auto kBasic = network::mojom::FetchResponseType::kBasic; + constexpr auto kOpaque = network::mojom::FetchResponseType::kOpaque; + constexpr auto kCors = network::mojom::FetchResponseType::kCors; const char* bla = "https://bla.com"; const char* blubb = "https://blubb.com"; struct { const char* url; const char* origin; const char* mimetype; + network::mojom::FetchResponseType response_type; WebFeature expected; } data[] = { // Test same- vs cross-origin cases. - {bla, "", "text/plain", WebFeature::kCrossOriginTextScript}, - {bla, "", "text/plain", WebFeature::kCrossOriginTextPlain}, - {bla, blubb, "text/plain", WebFeature::kCrossOriginTextScript}, - {bla, blubb, "text/plain", WebFeature::kCrossOriginTextPlain}, - {bla, bla, "text/plain", WebFeature::kSameOriginTextScript}, - {bla, bla, "text/plain", WebFeature::kSameOriginTextPlain}, + {bla, "", "text/plain", kOpaque, WebFeature::kCrossOriginTextScript}, + {bla, "", "text/plain", kCors, WebFeature::kCrossOriginTextPlain}, + {bla, blubb, "text/plain", kCors, WebFeature::kCrossOriginTextScript}, + {bla, blubb, "text/plain", kOpaque, WebFeature::kCrossOriginTextPlain}, + {bla, bla, "text/plain", kBasic, WebFeature::kSameOriginTextScript}, + {bla, bla, "text/plain", kBasic, WebFeature::kSameOriginTextPlain}, // Test mime type and subtype handling. - {bla, bla, "text/xml", WebFeature::kSameOriginTextScript}, - {bla, bla, "text/xml", WebFeature::kSameOriginTextXml}, + {bla, bla, "text/xml", kBasic, WebFeature::kSameOriginTextScript}, + {bla, bla, "text/xml", kBasic, WebFeature::kSameOriginTextXml}, // Test mime types from crbug.com/765544, with random cross/same site // origins. - {bla, bla, "text/plain", WebFeature::kSameOriginTextPlain}, - {bla, blubb, "text/xml", WebFeature::kCrossOriginTextXml}, - {blubb, blubb, "application/octet-stream", + {bla, bla, "text/plain", kBasic, WebFeature::kSameOriginTextPlain}, + {bla, bla, "text/xml", kOpaque, WebFeature::kCrossOriginTextXml}, + {blubb, blubb, "application/octet-stream", kBasic, WebFeature::kSameOriginApplicationOctetStream}, - {blubb, bla, "application/xml", WebFeature::kCrossOriginApplicationXml}, - {bla, bla, "text/html", WebFeature::kSameOriginTextHtml}, + {blubb, blubb, "application/xml", kCors, + WebFeature::kCrossOriginApplicationXml}, + {bla, bla, "text/html", kBasic, WebFeature::kSameOriginTextHtml}, }; for (auto& testcase : data) { - SCOPED_TRACE(testing::Message() << "\n url: " << testcase.url - << "\n origin: " << testcase.origin - << "\n mime type: " << testcase.mimetype - << "\n webfeature: " << testcase.expected); + SCOPED_TRACE(testing::Message() + << "\n url: " << testcase.url << "\n origin: " + << testcase.origin << "\n mime type: " << testcase.mimetype + << "\n response type: " << testcase.response_type + << "\n webfeature: " << testcase.expected); auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>( SecurityOrigin::Create(KURL(testcase.origin))); auto* context = CountUsageMockFetchContext::Create(); // Bind |properties| to |context| through a ResourceFetcher. - MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<TestLoaderFactory>())); + MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<TestLoaderFactory>())); Persistent<MockConsoleLogger> logger = MakeGarbageCollected<MockConsoleLogger>(); ResourceResponse response(KURL(testcase.url)); + response.SetType(testcase.response_type); response.SetHttpHeaderField("Content-Type", testcase.mimetype); EXPECT_CALL(*context, CountUsage(testcase.expected)); @@ -218,9 +225,9 @@ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); auto* context = CountUsageMockFetchContext::Create(); // Bind |properties| to |context| through a ResourceFetcher. - MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<TestLoaderFactory>())); + MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<TestLoaderFactory>())); Persistent<MockConsoleLogger> logger = MakeGarbageCollected<MockConsoleLogger>(); EXPECT_CALL(*logger, AddConsoleMessage(_, _, _))
diff --git a/third_party/blink/renderer/platform/loader/fetch/console_logger.h b/third_party/blink/renderer/platform/loader/fetch/console_logger.h index 92df929..33b9344c 100644 --- a/third_party/blink/renderer/platform/loader/fetch/console_logger.h +++ b/third_party/blink/renderer/platform/loader/fetch/console_logger.h
@@ -13,6 +13,9 @@ namespace blink { // A pure virtual interface for console logging. +// Retaining an instance of ConsoleLogger may be dangerous because after the +// associated fetcher is detached it leads to a leak. Use +// DetachableConsoleLogger in such a case. class PLATFORM_EXPORT ConsoleLogger : public GarbageCollectedMixin { public: ConsoleLogger() = default; @@ -23,18 +26,37 @@ const String& message) = 0; }; -class PLATFORM_EXPORT NullConsoleLogger final - : public GarbageCollected<NullConsoleLogger>, +// A ConsoleLogger subclass which has Detach() method. An instance of +// DetachableConsoleLogger can be kept even when the associated fetcher is +// detached. +class PLATFORM_EXPORT DetachableConsoleLogger final + : public GarbageCollected<DetachableConsoleLogger>, public ConsoleLogger { - USING_GARBAGE_COLLECTED_MIXIN(NullConsoleLogger); + USING_GARBAGE_COLLECTED_MIXIN(DetachableConsoleLogger); public: - NullConsoleLogger() = default; - ~NullConsoleLogger() override = default; + DetachableConsoleLogger() : DetachableConsoleLogger(nullptr) {} + DetachableConsoleLogger(ConsoleLogger* logger) : logger_(logger) {} - void AddConsoleMessage(mojom::ConsoleMessageSource, - mojom::ConsoleMessageLevel, - const String&) override {} + // Detaches |logger_|. After this function is called AddConsoleMessage will + // be no-op. + void Detach() { logger_ = nullptr; } + + void AddConsoleMessage(mojom::ConsoleMessageSource source, + mojom::ConsoleMessageLevel level, + const String& message) override { + if (!logger_) { + return; + } + logger_->AddConsoleMessage(source, level, message); + } + + void Trace(Visitor* visitor) override { + visitor->Trace(logger_); + ConsoleLogger::Trace(visitor); + } + + Member<ConsoleLogger> logger_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc index 1ef3572..46682ae 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -30,9 +30,7 @@ #include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h" -#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" -#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h" #include "third_party/blink/renderer/platform/platform_probe_sink.h" #include "third_party/blink/renderer/platform/probe/platform_trace_events_agent.h" @@ -62,7 +60,6 @@ void FetchContext::Trace(blink::Visitor* visitor) { visitor->Trace(platform_probe_sink_); - visitor->Trace(resource_fetcher_properties_); } void FetchContext::AddAdditionalRequestHeaders(ResourceRequest&) {}
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h index 54daece..bb6c6528 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -60,7 +60,6 @@ class ClientHintsPreferences; class KURL; class PlatformProbeSink; -class ResourceFetcherProperties; class ResourceTimingInfo; class WebScopedVirtualTimePauser; @@ -80,23 +79,10 @@ virtual ~FetchContext() = default; - // Called from a ResourceFetcher constructor. This is called only once. - // TODO(yhirano): Consider removing this. - void Init(const ResourceFetcherProperties& properties) { - DCHECK(!resource_fetcher_properties_); - resource_fetcher_properties_ = &properties; - } - virtual void Trace(blink::Visitor*); virtual void AddAdditionalRequestHeaders(ResourceRequest&); - // This function must not be called before |Init| is called. - const ResourceFetcherProperties& GetResourceFetcherProperties() const { - DCHECK(resource_fetcher_properties_); - return *resource_fetcher_properties_; - } - // Returns the cache policy for the resource. ResourceRequest is not passed as // a const reference as a header needs to be added for doc.write blocking // intervention. @@ -163,9 +149,7 @@ // with "keepalive" specified). // Returns a "detached" fetch context which cannot be null. virtual FetchContext* Detach() { - DCHECK(resource_fetcher_properties_); auto* context = &NullInstance(); - context->Init(*resource_fetcher_properties_); return context; } @@ -178,7 +162,6 @@ private: Member<PlatformProbeSink> platform_probe_sink_; - Member<const ResourceFetcherProperties> resource_fetcher_properties_; DISALLOW_COPY_AND_ASSIGN(FetchContext); };
diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc b/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc index 44c5a5c..14e59ed 100644 --- a/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
@@ -120,9 +120,10 @@ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(security_origin_); properties->SetShouldBlockLoadingSubResource(true); - fetcher_ = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *properties, context, base::MakeRefCounted<scheduler::FakeTaskRunner>(), - MakeGarbageCollected<TestLoaderFactory>())); + fetcher_ = MakeGarbageCollected<ResourceFetcher>( + ResourceFetcherInit(properties->MakeDetachable(), context, + base::MakeRefCounted<scheduler::FakeTaskRunner>(), + MakeGarbageCollected<TestLoaderFactory>())); } void TearDown() override { GetMemoryCache()->EvictResources();
diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc b/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc index 18dcc3b..ea53c42 100644 --- a/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
@@ -103,7 +103,7 @@ MakeGarbageCollected<MemoryCache>(platform_->test_task_runner())); auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); fetcher_ = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *properties, MakeGarbageCollected<MockFetchContext>(), + properties->MakeDetachable(), MakeGarbageCollected<MockFetchContext>(), base::MakeRefCounted<scheduler::FakeTaskRunner>(), MakeGarbageCollected<TestLoaderFactory>())); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 788045c..761a021 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -346,7 +346,7 @@ } // namespace ResourceFetcherInit::ResourceFetcherInit( - const ResourceFetcherProperties& properties, + DetachableResourceFetcherProperties& properties, FetchContext* context, scoped_refptr<base::SingleThreadTaskRunner> task_runner, ResourceFetcher::LoaderFactory* loader_factory) @@ -401,121 +401,6 @@ return mojom::RequestContextType::SUBRESOURCE; } -class ResourceFetcher::DetachableConsoleLogger final - : public GarbageCollectedFinalized<DetachableConsoleLogger>, - public ConsoleLogger { - USING_GARBAGE_COLLECTED_MIXIN(DetachableConsoleLogger); - - public: - DetachableConsoleLogger(ConsoleLogger& logger) : logger_(logger) {} - - void Detach() { logger_ = nullptr; } - - // ConsoleLogger implementation. - void AddConsoleMessage(mojom::ConsoleMessageSource source, - mojom::ConsoleMessageLevel level, - const String& message) override { - if (logger_) { - logger_->AddConsoleMessage(source, level, message); - } - } - void Trace(Visitor* visitor) override { - visitor->Trace(logger_); - ConsoleLogger::Trace(visitor); - } - - private: - Member<ConsoleLogger> logger_; -}; - -// A delegating ResourceFetcherProperties subclass which can be from the -// original ResourceFetcherProperties. -class ResourceFetcher::DetachableProperties final - : public ResourceFetcherProperties { - public: - explicit DetachableProperties(const ResourceFetcherProperties& properties) - : properties_(properties) {} - ~DetachableProperties() override = default; - - void Detach() { - if (!properties_) { - // Already detached. - return; - } - - fetch_client_settings_object_ = - MakeGarbageCollected<FetchClientSettingsObjectSnapshot>( - properties_->GetFetchClientSettingsObject()); - is_main_frame_ = properties_->IsMainFrame(); - paused_ = properties_->IsPaused(); - load_complete_ = properties_->IsLoadComplete(); - is_subframe_deprioritization_enabled_ = - properties_->IsSubframeDeprioritizationEnabled(); - - properties_ = nullptr; - } - - void Trace(Visitor* visitor) override { - visitor->Trace(properties_); - visitor->Trace(fetch_client_settings_object_); - ResourceFetcherProperties::Trace(visitor); - } - - // ResourceFetcherProperties implementation - // Add a test in resource_fetcher_test.cc when you change behaviors. - const FetchClientSettingsObject& GetFetchClientSettingsObject() - const override { - return properties_ ? properties_->GetFetchClientSettingsObject() - : *fetch_client_settings_object_; - } - bool IsMainFrame() const override { - return properties_ ? properties_->IsMainFrame() : is_main_frame_; - } - ControllerServiceWorkerMode GetControllerServiceWorkerMode() const override { - return properties_ ? properties_->GetControllerServiceWorkerMode() - : ControllerServiceWorkerMode::kNoController; - } - int64_t ServiceWorkerId() const override { - // When detached, GetControllerServiceWorkerMode returns kNoController, so - // this function must not be called. - DCHECK(properties_); - return properties_->ServiceWorkerId(); - } - bool IsPaused() const override { - return properties_ ? properties_->IsPaused() : paused_; - } - bool IsDetached() const override { - return properties_ ? properties_->IsDetached() : true; - } - bool IsLoadComplete() const override { - return properties_ ? properties_->IsLoadComplete() : load_complete_; - } - bool ShouldBlockLoadingSubResource() const override { - // Returns true when detached in order to preserve the existing behavior. - return properties_ ? properties_->ShouldBlockLoadingSubResource() : true; - } - bool IsSubframeDeprioritizationEnabled() const override { - return properties_ ? properties_->IsSubframeDeprioritizationEnabled() - : is_subframe_deprioritization_enabled_; - } - - scheduler::FrameStatus GetFrameStatus() const override { - return properties_ ? properties_->GetFrameStatus() - : scheduler::FrameStatus::kNone; - } - - private: - // |properties_| is null if and only if detached. - Member<const ResourceFetcherProperties> properties_; - - // The following members are used when detached. - Member<const FetchClientSettingsObject> fetch_client_settings_object_; - bool is_main_frame_ = false; - bool paused_ = false; - bool load_complete_ = false; - bool is_subframe_deprioritization_enabled_ = false; -}; - ResourceLoadPriority ResourceFetcher::ComputeLoadPriority( ResourceType type, const ResourceRequest& resource_request, @@ -614,13 +499,12 @@ } ResourceFetcher::ResourceFetcher(const ResourceFetcherInit& init) - : properties_( - *MakeGarbageCollected<DetachableProperties>(*init.properties)), + : properties_(*init.properties), context_(init.context), task_runner_(init.task_runner), - console_logger_(MakeGarbageCollected<DetachableConsoleLogger>( - init.console_logger ? *init.console_logger - : *MakeGarbageCollected<NullConsoleLogger>())), + console_logger_(init.console_logger + ? init.console_logger.Get() + : MakeGarbageCollected<DetachableConsoleLogger>()), loader_factory_(init.loader_factory), scheduler_(MakeGarbageCollected<ResourceLoadScheduler>( init.initial_throttling_policy, @@ -643,17 +527,12 @@ InstanceCounters::IncrementCounter(InstanceCounters::kResourceFetcherCounter); if (IsMainThread()) MainThreadFetchersSet().insert(this); - context_->Init(*properties_); } ResourceFetcher::~ResourceFetcher() { InstanceCounters::DecrementCounter(InstanceCounters::kResourceFetcherCounter); } -const ResourceFetcherProperties& ResourceFetcher::GetProperties() const { - return *properties_; -} - bool ResourceFetcher::IsDetached() const { return properties_->IsDetached(); } @@ -1777,10 +1656,6 @@ } } -ConsoleLogger& ResourceFetcher::GetConsoleLogger() { - return *console_logger_; -} - int ResourceFetcher::BlockingRequestCount() const { return loaders_.size(); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h index 9d8c787..7e3f370 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -50,7 +50,8 @@ enum class ResourceType : uint8_t; class CodeCacheLoader; -class ConsoleLogger; +class DetachableConsoleLogger; +class DetachableResourceFetcherProperties; class FetchContext; class FrameScheduler; class MHTMLArchive; @@ -58,7 +59,6 @@ class PreflightTimingInfo; class Resource; class ResourceError; -class ResourceFetcherProperties; class ResourceLoadObserver; class ResourceTimingInfo; class WebURLLoader; @@ -108,11 +108,9 @@ // - This function returns the same object throughout this fetcher's // entire life. // - The returned object remains valid after ClearContext() is called. - // - This function returns a different object from the corresponding - // argument in the constructor. - // - This function should be used rather than the properties given - // to the ResourceFetcher constructor. - const ResourceFetcherProperties& GetProperties() const; + const DetachableResourceFetcherProperties& GetProperties() const { + return *properties_; + } // Returns whether this fetcher is detached from the associated context. bool IsDetached() const; @@ -170,7 +168,7 @@ FetchContext& Context() const; void ClearContext(); - ConsoleLogger& GetConsoleLogger(); + DetachableConsoleLogger& GetConsoleLogger() { return *console_logger_; } int BlockingRequestCount() const; int NonblockingRequestCount() const; @@ -268,8 +266,6 @@ private: friend class ResourceCacheValidationSuppressor; - class DetachableConsoleLogger; - class DetachableProperties; enum class StopFetchingTarget { kExcludingKeepaliveLoaders, kIncludingKeepaliveLoaders, @@ -373,7 +369,7 @@ void ScheduleStaleRevalidate(Resource* stale_resource); void RevalidateStaleResource(Resource* stale_resource); - Member<DetachableProperties> properties_; + Member<DetachableResourceFetcherProperties> properties_; Member<ResourceLoadObserver> resource_load_observer_; Member<FetchContext> context_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; @@ -455,17 +451,16 @@ public: // |context| and |task_runner| must not be null. // |loader_factory| can be null if |properties.IsDetached()| is true. - // The given ResourceFetcherProperties is kept until ClearContext() is called. - ResourceFetcherInit(const ResourceFetcherProperties& properties, + ResourceFetcherInit(DetachableResourceFetcherProperties& properties, FetchContext* context, scoped_refptr<base::SingleThreadTaskRunner> task_runner, ResourceFetcher::LoaderFactory* loader_factory); - const Member<const ResourceFetcherProperties> properties; + const Member<DetachableResourceFetcherProperties> properties; const Member<FetchContext> context; const scoped_refptr<base::SingleThreadTaskRunner> task_runner; const Member<ResourceFetcher::LoaderFactory> loader_factory; - Member<ConsoleLogger> console_logger; + Member<DetachableConsoleLogger> console_logger; ResourceLoadScheduler::ThrottlingPolicy initial_throttling_policy = ResourceLoadScheduler::ThrottlingPolicy::kNormal; Member<MHTMLArchive> archive;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc new file mode 100644 index 0000000..2ab0d51 --- /dev/null +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.cc
@@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h" + +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h" + +namespace blink { + +void DetachableResourceFetcherProperties::Detach() { + if (!properties_) { + // Already detached. + return; + } + + fetch_client_settings_object_ = + MakeGarbageCollected<FetchClientSettingsObjectSnapshot>( + properties_->GetFetchClientSettingsObject()); + is_main_frame_ = properties_->IsMainFrame(); + paused_ = properties_->IsPaused(); + load_complete_ = properties_->IsLoadComplete(); + is_subframe_deprioritization_enabled_ = + properties_->IsSubframeDeprioritizationEnabled(); + + properties_ = nullptr; +} + +void DetachableResourceFetcherProperties::Trace(Visitor* visitor) { + visitor->Trace(properties_); + visitor->Trace(fetch_client_settings_object_); + ResourceFetcherProperties::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h index a68533ed..dc5ab3d 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h
@@ -24,6 +24,10 @@ // GetCachePolicy(const ResourceRequest&, ResourceType). Do not put a function // with default implementation. // +// Storing a non-null ResourceFetcherProperties in an object that can be valid +// after the associated ResourceFetcher is detached is dangerous. Use +// DetachedResourceFetcherProperties below. +// // The distinction between FetchClientSettingsObject and // ResourceFetcherProperties is sometimes ambiguous. Put a property in // FetchClientSettingsObject when the property is clearly defined in the spec. @@ -80,6 +84,75 @@ virtual scheduler::FrameStatus GetFrameStatus() const = 0; }; +// A delegating ResourceFetcherProperties subclass which can be retained +// even when the associated ResourceFetcher is detached. +class PLATFORM_EXPORT DetachableResourceFetcherProperties final + : public ResourceFetcherProperties { + public: + explicit DetachableResourceFetcherProperties( + const ResourceFetcherProperties& properties) + : properties_(properties) {} + ~DetachableResourceFetcherProperties() override = default; + + void Detach(); + + void Trace(Visitor* visitor) override; + + // ResourceFetcherProperties implementation + // Add a test in resource_fetcher_test.cc when you change behaviors. + const FetchClientSettingsObject& GetFetchClientSettingsObject() + const override { + return properties_ ? properties_->GetFetchClientSettingsObject() + : *fetch_client_settings_object_; + } + bool IsMainFrame() const override { + return properties_ ? properties_->IsMainFrame() : is_main_frame_; + } + ControllerServiceWorkerMode GetControllerServiceWorkerMode() const override { + return properties_ ? properties_->GetControllerServiceWorkerMode() + : ControllerServiceWorkerMode::kNoController; + } + int64_t ServiceWorkerId() const override { + // When detached, GetControllerServiceWorkerMode returns kNoController, so + // this function must not be called. + DCHECK(properties_); + return properties_->ServiceWorkerId(); + } + bool IsPaused() const override { + return properties_ ? properties_->IsPaused() : paused_; + } + bool IsDetached() const override { + return properties_ ? properties_->IsDetached() : true; + } + bool IsLoadComplete() const override { + return properties_ ? properties_->IsLoadComplete() : load_complete_; + } + bool ShouldBlockLoadingSubResource() const override { + // Returns true when detached in order to preserve the existing behavior. + return properties_ ? properties_->ShouldBlockLoadingSubResource() : true; + } + bool IsSubframeDeprioritizationEnabled() const override { + return properties_ ? properties_->IsSubframeDeprioritizationEnabled() + : is_subframe_deprioritization_enabled_; + } + + scheduler::FrameStatus GetFrameStatus() const override { + return properties_ ? properties_->GetFrameStatus() + : scheduler::FrameStatus::kNone; + } + + private: + // |properties_| is null if and only if detached. + Member<const ResourceFetcherProperties> properties_; + + // The following members are used when detached. + Member<const FetchClientSettingsObject> fetch_client_settings_object_; + bool is_main_frame_ = false; + bool paused_ = false; + bool load_complete_ = false; + bool is_subframe_deprioritization_enabled_ = false; +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_FETCHER_PROPERTIES_H_
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc new file mode 100644 index 0000000..a914377 --- /dev/null +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc
@@ -0,0 +1,126 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h" +#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h" + +namespace blink { + +namespace { + +class DetachableResourceFetcherPropertiesTest : public testing::Test { + public: + const FetchClientSettingsObjectSnapshot& CreateFetchClientSettingsObject( + mojom::IPAddressSpace address_space) { + return *MakeGarbageCollected<FetchClientSettingsObjectSnapshot>( + KURL("https://example.com/foo.html"), + KURL("https://example.com/foo.html"), + SecurityOrigin::Create(KURL("https://example.com/")), + network::mojom::ReferrerPolicy::kDefault, + "https://example.com/foo.html", HttpsState::kModern, + AllowedByNosniff::MimeTypeCheck::kStrict, address_space, + kLeaveInsecureRequestsAlone, + FetchClientSettingsObject::InsecureNavigationsSet(), + false /* mixed_autoupgrade_opt_out */); + } +}; + +TEST_F(DetachableResourceFetcherPropertiesTest, DetachWithDefaultValues) { + const auto& original_client_settings_object = + CreateFetchClientSettingsObject(mojom::IPAddressSpace::kPublic); + auto& properties = *MakeGarbageCollected<DetachableResourceFetcherProperties>( + *MakeGarbageCollected<TestResourceFetcherProperties>( + original_client_settings_object)); + + const auto& client_settings_object = + properties.GetFetchClientSettingsObject(); + EXPECT_EQ(&original_client_settings_object, &client_settings_object); + EXPECT_FALSE(properties.IsMainFrame()); + EXPECT_EQ(properties.GetControllerServiceWorkerMode(), + mojom::ControllerServiceWorkerMode::kNoController); + // We cannot call ServiceWorkerId as the service worker mode is kNoController. + EXPECT_FALSE(properties.IsPaused()); + EXPECT_FALSE(properties.IsDetached()); + EXPECT_FALSE(properties.IsLoadComplete()); + EXPECT_FALSE(properties.ShouldBlockLoadingSubResource()); + EXPECT_FALSE(properties.IsSubframeDeprioritizationEnabled()); + EXPECT_EQ(scheduler::FrameStatus::kNone, properties.GetFrameStatus()); + + properties.Detach(); + + EXPECT_NE(&client_settings_object, + &properties.GetFetchClientSettingsObject()); + EXPECT_EQ(properties.GetFetchClientSettingsObject().BaseUrl(), + KURL("https://example.com/foo.html")); + EXPECT_FALSE(properties.IsMainFrame()); + EXPECT_EQ(properties.GetControllerServiceWorkerMode(), + mojom::ControllerServiceWorkerMode::kNoController); + // We cannot call ServiceWorkerId as the service worker mode is kNoController. + EXPECT_FALSE(properties.IsPaused()); + EXPECT_TRUE(properties.IsDetached()); + EXPECT_FALSE(properties.IsLoadComplete()); + EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); + EXPECT_FALSE(properties.IsSubframeDeprioritizationEnabled()); + EXPECT_EQ(scheduler::FrameStatus::kNone, properties.GetFrameStatus()); +} + +TEST_F(DetachableResourceFetcherPropertiesTest, DetachWithNonDefaultValues) { + const auto& original_client_settings_object = + CreateFetchClientSettingsObject(mojom::IPAddressSpace::kPublic); + auto& original_properties = + *MakeGarbageCollected<TestResourceFetcherProperties>( + original_client_settings_object); + auto& properties = *MakeGarbageCollected<DetachableResourceFetcherProperties>( + original_properties); + + original_properties.SetIsMainFrame(true); + original_properties.SetControllerServiceWorkerMode( + mojom::ControllerServiceWorkerMode::kControlled); + original_properties.SetServiceWorkerId(133); + original_properties.SetIsPaused(true); + original_properties.SetIsLoadComplete(true); + original_properties.SetShouldBlockLoadingSubResource(true); + original_properties.SetIsSubframeDeprioritizationEnabled(true); + original_properties.SetFrameStatus(scheduler::FrameStatus::kMainFrameVisible); + + const auto& client_settings_object = + properties.GetFetchClientSettingsObject(); + EXPECT_EQ(&original_client_settings_object, &client_settings_object); + EXPECT_TRUE(properties.IsMainFrame()); + EXPECT_EQ(properties.GetControllerServiceWorkerMode(), + mojom::ControllerServiceWorkerMode::kControlled); + EXPECT_EQ(properties.ServiceWorkerId(), 133); + EXPECT_TRUE(properties.IsPaused()); + EXPECT_FALSE(properties.IsDetached()); + EXPECT_TRUE(properties.IsLoadComplete()); + EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); + EXPECT_TRUE(properties.IsSubframeDeprioritizationEnabled()); + EXPECT_EQ(scheduler::FrameStatus::kMainFrameVisible, + properties.GetFrameStatus()); + + properties.Detach(); + + EXPECT_NE(&client_settings_object, + &properties.GetFetchClientSettingsObject()); + EXPECT_EQ(properties.GetFetchClientSettingsObject().BaseUrl(), + KURL("https://example.com/foo.html")); + EXPECT_TRUE(properties.IsMainFrame()); + EXPECT_EQ(properties.GetControllerServiceWorkerMode(), + mojom::ControllerServiceWorkerMode::kNoController); + // We cannot call ServiceWorkerId as the service worker mode is kNoController. + EXPECT_TRUE(properties.IsPaused()); + EXPECT_TRUE(properties.IsDetached()); + EXPECT_TRUE(properties.IsLoadComplete()); + EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); + EXPECT_TRUE(properties.IsSubframeDeprioritizationEnabled()); + EXPECT_EQ(scheduler::FrameStatus::kNone, properties.GetFrameStatus()); +} + +} // namespace + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc index bbad9b8..8a47cdc9 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -49,7 +49,6 @@ #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h" -#include "third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h" #include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_error.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h" @@ -163,13 +162,15 @@ scoped_refptr<scheduler::FakeTaskRunner> CreateTaskRunner() { return base::MakeRefCounted<scheduler::FakeTaskRunner>(); } - ResourceFetcher* CreateFetcher(const ResourceFetcherProperties& properties, - FetchContext* context) { - return MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(properties, context, CreateTaskRunner(), - MakeGarbageCollected<TestLoaderFactory>())); + ResourceFetcher* CreateFetcher( + const TestResourceFetcherProperties& properties, + FetchContext* context) { + return MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties.MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<TestLoaderFactory>())); } - ResourceFetcher* CreateFetcher(const ResourceFetcherProperties& properties) { + ResourceFetcher* CreateFetcher( + const TestResourceFetcherProperties& properties) { return CreateFetcher(properties, MakeGarbageCollected<MockFetchContext>()); } ResourceFetcher* CreateFetcher() { @@ -190,9 +191,8 @@ KURL secure_url("https://secureorigin.test/image.png"); // Try to request a url. The request should fail, and a resource in an error // state should be returned, and no resource should be present in the cache. - auto* fetcher = - CreateFetcher(*MakeGarbageCollected<NullResourceFetcherProperties>(), - &FetchContext::NullInstance()); + auto* fetcher = CreateFetcher(); + fetcher->ClearContext(); ResourceRequest resource_request(secure_url); resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL); FetchParameters fetch_params(resource_request); @@ -373,9 +373,10 @@ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(source_origin_); MockFetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher2 = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *properties, context, base::MakeRefCounted<scheduler::FakeTaskRunner>(), - MakeGarbageCollected<TestLoaderFactory>())); + auto* fetcher2 = MakeGarbageCollected<ResourceFetcher>( + ResourceFetcherInit(properties->MakeDetachable(), context, + base::MakeRefCounted<scheduler::FakeTaskRunner>(), + MakeGarbageCollected<TestLoaderFactory>())); ResourceRequest resource_request2(GetResource()->Url()); resource_request2.SetCacheMode(mojom::FetchCacheMode::kValidateCache); FetchParameters fetch_params2(resource_request2); @@ -526,9 +527,9 @@ void Request(const WebString& url) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context_, task_runner_, - MakeGarbageCollected<TestLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context_, task_runner_, + MakeGarbageCollected<TestLoaderFactory>())); ResourceRequest resource_request(url); resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL); FetchParameters fetch_params(resource_request); @@ -1067,105 +1068,22 @@ } } -TEST_F(ResourceFetcherTest, DetachedPropertiesWithDefaultValues) { - const auto& original_client_settings_object = - CreateFetchClientSettingsObject(mojom::IPAddressSpace::kPublic); - const auto& original_properties = - *MakeGarbageCollected<TestResourceFetcherProperties>( - original_client_settings_object); - auto* const fetcher = CreateFetcher(original_properties); - const auto& properties = fetcher->GetProperties(); +TEST_F(ResourceFetcherTest, Detach) { + DetachableResourceFetcherProperties& properties = + MakeGarbageCollected<TestResourceFetcherProperties>()->MakeDetachable(); + auto* const fetcher = + MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties, MakeGarbageCollected<MockFetchContext>(), + CreateTaskRunner(), MakeGarbageCollected<TestLoaderFactory>())); - EXPECT_NE(&original_properties, &properties); - - const auto& client_settings_object = - properties.GetFetchClientSettingsObject(); - EXPECT_EQ(&original_client_settings_object, &client_settings_object); - EXPECT_FALSE(properties.IsMainFrame()); - EXPECT_EQ(properties.GetControllerServiceWorkerMode(), - mojom::ControllerServiceWorkerMode::kNoController); - // We cannot call ServiceWorkerId as the service worker mode is kNoController. - EXPECT_FALSE(properties.IsPaused()); + EXPECT_EQ(&properties, &fetcher->GetProperties()); EXPECT_FALSE(properties.IsDetached()); - EXPECT_FALSE(properties.IsLoadComplete()); - EXPECT_FALSE(properties.ShouldBlockLoadingSubResource()); - EXPECT_FALSE(properties.IsSubframeDeprioritizationEnabled()); - EXPECT_EQ(scheduler::FrameStatus::kNone, properties.GetFrameStatus()); fetcher->ClearContext(); // ResourceFetcher::GetProperties always returns the same object. EXPECT_EQ(&properties, &fetcher->GetProperties()); - EXPECT_NE(&client_settings_object, - &properties.GetFetchClientSettingsObject()); - EXPECT_EQ(properties.GetFetchClientSettingsObject().BaseUrl(), - KURL("https://example.com/foo.html")); - EXPECT_FALSE(properties.IsMainFrame()); - EXPECT_EQ(properties.GetControllerServiceWorkerMode(), - mojom::ControllerServiceWorkerMode::kNoController); - // We cannot call ServiceWorkerId as the service worker mode is kNoController. - EXPECT_FALSE(properties.IsPaused()); EXPECT_TRUE(properties.IsDetached()); - EXPECT_FALSE(properties.IsLoadComplete()); - EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); - EXPECT_FALSE(properties.IsSubframeDeprioritizationEnabled()); - EXPECT_EQ(scheduler::FrameStatus::kNone, properties.GetFrameStatus()); -} - -TEST_F(ResourceFetcherTest, DetachedPropertiesWithNonDefaultValues) { - const auto& original_client_settings_object = - CreateFetchClientSettingsObject(mojom::IPAddressSpace::kPublic); - auto& original_properties = - *MakeGarbageCollected<TestResourceFetcherProperties>( - original_client_settings_object); - auto* const fetcher = CreateFetcher(original_properties); - const auto& properties = fetcher->GetProperties(); - - EXPECT_NE(&original_properties, &properties); - - original_properties.SetIsMainFrame(true); - original_properties.SetControllerServiceWorkerMode( - mojom::ControllerServiceWorkerMode::kControlled); - original_properties.SetServiceWorkerId(133); - original_properties.SetIsPaused(true); - original_properties.SetIsLoadComplete(true); - original_properties.SetShouldBlockLoadingSubResource(true); - original_properties.SetIsSubframeDeprioritizationEnabled(true); - original_properties.SetFrameStatus(scheduler::FrameStatus::kMainFrameVisible); - - const auto& client_settings_object = - properties.GetFetchClientSettingsObject(); - EXPECT_EQ(&original_client_settings_object, &client_settings_object); - EXPECT_TRUE(properties.IsMainFrame()); - EXPECT_EQ(properties.GetControllerServiceWorkerMode(), - mojom::ControllerServiceWorkerMode::kControlled); - EXPECT_EQ(properties.ServiceWorkerId(), 133); - EXPECT_TRUE(properties.IsPaused()); - EXPECT_FALSE(properties.IsDetached()); - EXPECT_TRUE(properties.IsLoadComplete()); - EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); - EXPECT_TRUE(properties.IsSubframeDeprioritizationEnabled()); - EXPECT_EQ(scheduler::FrameStatus::kMainFrameVisible, - properties.GetFrameStatus()); - - fetcher->ClearContext(); - // ResourceFetcher::GetProperties always returns the same object. - EXPECT_EQ(&properties, &fetcher->GetProperties()); - - EXPECT_NE(&client_settings_object, - &properties.GetFetchClientSettingsObject()); - EXPECT_EQ(properties.GetFetchClientSettingsObject().BaseUrl(), - KURL("https://example.com/foo.html")); - EXPECT_TRUE(properties.IsMainFrame()); - EXPECT_EQ(properties.GetControllerServiceWorkerMode(), - mojom::ControllerServiceWorkerMode::kNoController); - // We cannot call ServiceWorkerId as the service worker mode is kNoController. - EXPECT_TRUE(properties.IsPaused()); - EXPECT_TRUE(properties.IsDetached()); - EXPECT_TRUE(properties.IsLoadComplete()); - EXPECT_TRUE(properties.ShouldBlockLoadingSubResource()); - EXPECT_TRUE(properties.IsSubframeDeprioritizationEnabled()); - EXPECT_EQ(scheduler::FrameStatus::kNone, properties.GetFrameStatus()); } // TODO(crbug.com/850785): Reenable this.
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc index 99839fe..789596cf 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
@@ -97,7 +97,7 @@ } size_t GetOutstandingThrottledLimit( - const ResourceFetcherProperties& properties) { + const DetachableResourceFetcherProperties& properties) { if (!RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled()) return ResourceLoadScheduler::kOutstandingUnlimited; @@ -127,7 +127,7 @@ class ResourceLoadScheduler::TrafficMonitor { public: explicit TrafficMonitor( - const ResourceFetcherProperties& resource_fetcher_properties); + const DetachableResourceFetcherProperties& resource_fetcher_properties); ~TrafficMonitor(); // Notified when the ThrottlingState is changed. @@ -140,7 +140,7 @@ void ReportAll(); private: - const Persistent<const ResourceFetcherProperties> + const Persistent<const DetachableResourceFetcherProperties> resource_fetcher_properties_; scheduler::SchedulingLifecycleState current_state_ = @@ -162,7 +162,7 @@ }; ResourceLoadScheduler::TrafficMonitor::TrafficMonitor( - const ResourceFetcherProperties& resource_fetcher_properties) + const DetachableResourceFetcherProperties& resource_fetcher_properties) : resource_fetcher_properties_(resource_fetcher_properties), traffic_kilobytes_per_frame_status_( "Blink.ResourceLoadScheduler.TrafficBytes.KBPerFrameStatus", @@ -351,9 +351,9 @@ ResourceLoadScheduler::ResourceLoadScheduler( ThrottlingPolicy initial_throttling_policy, - const ResourceFetcherProperties& resource_fetcher_properties, + const DetachableResourceFetcherProperties& resource_fetcher_properties, FrameScheduler* frame_scheduler, - ConsoleLogger& console_logger) + DetachableConsoleLogger& console_logger) : resource_fetcher_properties_(resource_fetcher_properties), policy_(initial_throttling_policy), outstanding_limit_for_throttled_frame_scheduler_(
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h index dd8ca10..1a8697f 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
@@ -17,8 +17,8 @@ namespace blink { -class ConsoleLogger; -class ResourceFetcherProperties; +class DetachableConsoleLogger; +class DetachableResourceFetcherProperties; // Client interface to use the throttling/scheduling functionality that // ResourceLoadScheduler provides. @@ -147,9 +147,9 @@ std::numeric_limits<size_t>::max(); ResourceLoadScheduler(ThrottlingPolicy initial_throttling_poilcy, - const ResourceFetcherProperties&, + const DetachableResourceFetcherProperties&, FrameScheduler*, - ConsoleLogger& console_logger); + DetachableConsoleLogger& console_logger); ~ResourceLoadScheduler() override; void Trace(blink::Visitor*); @@ -272,7 +272,8 @@ void ShowConsoleMessageIfNeeded(); - const Member<const ResourceFetcherProperties> resource_fetcher_properties_; + const Member<const DetachableResourceFetcherProperties> + resource_fetcher_properties_; // A flag to indicate an internal running state. // TODO(toyoshim): We may want to use enum once we start to have more states. @@ -339,7 +340,7 @@ std::unique_ptr<FrameScheduler::LifecycleObserverHandle> scheduler_observer_handle_; - const Member<ConsoleLogger> console_logger_; + const Member<DetachableConsoleLogger> console_logger_; DISALLOW_COPY_AND_ASSIGN(ResourceLoadScheduler); };
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc index 9e2a157..729dd7c 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
@@ -58,8 +58,8 @@ } private: - Member<ConsoleLogger> console_logger_ = - MakeGarbageCollected<NullConsoleLogger>(); + Member<DetachableConsoleLogger> console_logger_ = + MakeGarbageCollected<DetachableConsoleLogger>(); MockClientDelegate* delegate_; bool was_run_ = false; }; @@ -91,8 +91,9 @@ auto frame_scheduler = std::make_unique<scheduler::FakeFrameScheduler>(); console_logger_ = MakeGarbageCollected<MockConsoleLogger>(); scheduler_ = MakeGarbageCollected<ResourceLoadScheduler>( - ResourceLoadScheduler::ThrottlingPolicy::kTight, *properties, - frame_scheduler.get(), *console_logger_); + ResourceLoadScheduler::ThrottlingPolicy::kTight, + properties->MakeDetachable(), frame_scheduler.get(), + *MakeGarbageCollected<DetachableConsoleLogger>(console_logger_)); Scheduler()->SetOutstandingLimitForTesting(1); } void TearDown() override { Scheduler()->Shutdown(); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc index a9ec4d2..4978be07 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
@@ -37,7 +37,7 @@ ResourceFetcher* CreateFetcher() { return MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( - *MakeGarbageCollected<TestResourceFetcherProperties>(), + MakeGarbageCollected<TestResourceFetcherProperties>()->MakeDetachable(), MakeGarbageCollected<MockFetchContext>(), base::MakeRefCounted<scheduler::FakeTaskRunner>(), MakeGarbageCollected<TestLoaderFactory>()));
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc index b28bb82..2d7bcfb 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc
@@ -179,9 +179,9 @@ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(origin); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); ResourceRequest request; request.SetUrl(test.url); request.SetFetchRequestMode(test.request_mode); @@ -213,9 +213,9 @@ TEST_F(ResourceLoaderTest, LoadResponseBody) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); KURL url("https://www.example.com/"); ResourceRequest request(url); @@ -277,9 +277,9 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndNonStream) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); // Fetch a data url. KURL url("data:text/plain,Hello%20World!"); @@ -332,9 +332,9 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndStream) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); scheduler::FakeTaskRunner* task_runner = static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get()); @@ -371,9 +371,9 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncEmptyData) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); // Fetch an empty data url. KURL url("data:text/html,"); @@ -394,9 +394,9 @@ TEST_F(ResourceLoaderTest, LoadDataURL_Sync) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); // Fetch a data url synchronously. KURL url("data:text/plain,Hello%20World!"); @@ -419,9 +419,9 @@ TEST_F(ResourceLoaderTest, LoadDataURL_SyncEmptyData) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); // Fetch an empty data url synchronously. KURL url("data:text/html,"); @@ -440,9 +440,9 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndNonStream) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); scheduler::FakeTaskRunner* task_runner = static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get()); @@ -486,9 +486,9 @@ TEST_F(ResourceLoaderTest, LoadDataURL_DefersAsyncAndStream) { auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); scheduler::FakeTaskRunner* task_runner = static_cast<scheduler::FakeTaskRunner*>(fetcher->GetTaskRunner().get()); @@ -559,9 +559,9 @@ auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>(origin); FetchContext* context = MakeGarbageCollected<MockFetchContext>(); - auto* fetcher = MakeGarbageCollected<ResourceFetcher>( - ResourceFetcherInit(*properties, context, CreateTaskRunner(), - MakeGarbageCollected<NoopLoaderFactory>())); + auto* fetcher = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit( + properties->MakeDetachable(), context, CreateTaskRunner(), + MakeGarbageCollected<NoopLoaderFactory>())); ResourceRequest request; request.SetUrl(foo_url_); request.SetRequestContext(mojom::RequestContextType::FETCH);
diff --git a/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h b/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h index 157133d..9cda1a0 100644 --- a/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h +++ b/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h
@@ -25,6 +25,10 @@ void Trace(Visitor* visitor) override; + DetachableResourceFetcherProperties& MakeDetachable() const { + return *MakeGarbageCollected<DetachableResourceFetcherProperties>(*this); + } + // ResourceFetcherProperties implementation const FetchClientSettingsObject& GetFetchClientSettingsObject() const override {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 3648344b..67f03a9 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -601,11 +601,6 @@ name: "FormAssociatedCustomElements", status: "experimental", }, - // This is to communicate features::FormControlsRefresh from ui (and can be - // removed when the feature launches). - { - name: "FormControlsRefresh", - }, { name: "FormDataEvent", status: "experimental",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 67a51f64c..73f6a48 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3954,8 +3954,6 @@ crbug.com/835717 virtual/omt-worker-fetch/external/wpt/content-security-policy/inside-worker/dedicated-inheritance.html [ Skip ] # This is failing because of the lack of CSP support. crbug.com/940316 virtual/omt-worker-fetch/external/wpt/content-security-policy/inside-worker/shared-script.html [ Failure Pass ] -# This is failing because of the lack of origin trial context support. -crbug.com/945215 virtual/omt-worker-fetch/http/tests/origin_trials/sample-api-workers.html [ Failure ] # This fails because AllowedByNoSniff::MimeTypeAsScript() blocks the nested worker's # worker script, because the script url has a .html file extension.
diff --git a/third_party/blink/web_tests/custom-elements/form-validation-bubble-blur.html b/third_party/blink/web_tests/custom-elements/form-validation-bubble-blur.html new file mode 100644 index 0000000..d9b21533 --- /dev/null +++ b/third_party/blink/web_tests/custom-elements/form-validation-bubble-blur.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<style> +control-element { + display: inline-block; + width: 10em; + height: 2em; +} +</style> +<body> +<script> +class ControlElement extends HTMLElement { + static formAssociated = true; + constructor() { + super(); + this.i = this.attachInternals(); + this.i.setValidity({tooShort: true}, 'Too short'); + } +} +customElements.define('control-element', ControlElement); + +async_test(t => { + assert_own_property(window, 'internals'); + document.body.insertAdjacentHTML('afterbegin', '<control-element tabindex=0></control-element>'); + let control = document.body.querySelector('control-element'); + control.i.reportValidity(); + assert_true(internals.isValidationMessageVisible(control), + 'prereq: A validation bubble should be shown.'); + assert_equals(document.activeElement, control, + 'prereq: The control should be focused.'); + + control.blur(); + requestAnimationFrame(t.step_func_done(() => { + assert_false(internals.isValidationMessageVisible(control)); + })); +}, 'Ensure that removing focus from an invalid form-associated custom ' + + 'element with a validation bubble closes the validation bubble.'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index c1ab574..b9bd504 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -15103,6 +15103,18 @@ {} ] ], + "css/CSS2/normal-flow/dynamic-percentage-height.html": [ + [ + "css/CSS2/normal-flow/dynamic-percentage-height.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], "css/CSS2/normal-flow/float-percentage-resolution-quirks-mode.html": [ [ "css/CSS2/normal-flow/float-percentage-resolution-quirks-mode.html", @@ -58001,6 +58013,114 @@ {} ] ], + "css/css-position/position-absolute-dynamic-list-marker.html": [ + [ + "css/css-position/position-absolute-dynamic-list-marker.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-overflow-001.html": [ + [ + "css/css-position/position-absolute-dynamic-overflow-001.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-overflow-002.html": [ + [ + "css/css-position/position-absolute-dynamic-overflow-002.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-static-position-floats-001.html": [ + [ + "css/css-position/position-absolute-dynamic-static-position-floats-001.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-static-position-floats-002.html": [ + [ + "css/css-position/position-absolute-dynamic-static-position-floats-002.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-static-position-floats-003.html": [ + [ + "css/css-position/position-absolute-dynamic-static-position-floats-003.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-static-position-margin-001.html": [ + [ + "css/css-position/position-absolute-dynamic-static-position-margin-001.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-static-position-margin-002.html": [ + [ + "css/css-position/position-absolute-dynamic-static-position-margin-002.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/position-absolute-dynamic-static-position.html": [ + [ + "css/css-position/position-absolute-dynamic-static-position.html", + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], "css/css-position/position-relative-table-tbody-left-absolute-child.html": [ [ "css/css-position/position-relative-table-tbody-left-absolute-child.html", @@ -65013,6 +65133,174 @@ {} ] ], + "css/css-text/line-break/line-break-anywhere-003.html": [ + [ + "css/css-text/line-break/line-break-anywhere-003.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-003-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-004.html": [ + [ + "css/css-text/line-break/line-break-anywhere-004.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-005.html": [ + [ + "css/css-text/line-break/line-break-anywhere-005.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-006.html": [ + [ + "css/css-text/line-break/line-break-anywhere-006.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-007.html": [ + [ + "css/css-text/line-break/line-break-anywhere-007.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-008.html": [ + [ + "css/css-text/line-break/line-break-anywhere-008.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-009.html": [ + [ + "css/css-text/line-break/line-break-anywhere-009.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-010.html": [ + [ + "css/css-text/line-break/line-break-anywhere-010.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-011.html": [ + [ + "css/css-text/line-break/line-break-anywhere-011.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-012.html": [ + [ + "css/css-text/line-break/line-break-anywhere-012.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-013.html": [ + [ + "css/css-text/line-break/line-break-anywhere-013.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-014.html": [ + [ + "css/css-text/line-break/line-break-anywhere-014.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-015.html": [ + [ + "css/css-text/line-break/line-break-anywhere-015.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-break/line-break-anywhere-016.html": [ + [ + "css/css-text/line-break/line-break-anywhere-016.html", + [ + [ + "/css/css-text/line-break/reference/line-break-anywhere-004-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/line-break/line-break-loose-011.xht": [ [ "css/css-text/line-break/line-break-loose-011.xht", @@ -70061,6 +70349,54 @@ {} ] ], + "css/css-text/word-break/word-break-break-all-016.html": [ + [ + "css/css-text/word-break/word-break-break-all-016.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-017.html": [ + [ + "css/css-text/word-break/word-break-break-all-017.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-018.html": [ + [ + "css/css-text/word-break/word-break-break-all-018.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-019.html": [ + [ + "css/css-text/word-break/word-break-break-all-019.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/word-break/word-break-break-all-020.html": [ [ "css/css-text/word-break/word-break-break-all-020.html", @@ -70073,6 +70409,102 @@ {} ] ], + "css/css-text/word-break/word-break-break-all-021.html": [ + [ + "css/css-text/word-break/word-break-break-all-021.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-022.html": [ + [ + "css/css-text/word-break/word-break-break-all-022.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-023.html": [ + [ + "css/css-text/word-break/word-break-break-all-023.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-024.html": [ + [ + "css/css-text/word-break/word-break-break-all-024.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-025.html": [ + [ + "css/css-text/word-break/word-break-break-all-025.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-026.html": [ + [ + "css/css-text/word-break/word-break-break-all-026.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-027.html": [ + [ + "css/css-text/word-break/word-break-break-all-027.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/word-break/word-break-break-all-028.html": [ + [ + "css/css-text/word-break/word-break-break-all-028.html", + [ + [ + "/css/css-text/word-break/reference/word-break-break-all-010-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/word-break/word-break-break-word-overflow-wrap-interactions.html": [ [ "css/css-text/word-break/word-break-break-word-overflow-wrap-interactions.html", @@ -149546,6 +149978,16 @@ {} ] ], + "css/css-text/line-break/reference/line-break-anywhere-003-ref.html": [ + [ + {} + ] + ], + "css/css-text/line-break/reference/line-break-anywhere-004-ref.html": [ + [ + {} + ] + ], "css/css-text/line-break/reference/line-break-loose-011-ref.xht": [ [ {} @@ -149871,11 +150313,6 @@ {} ] ], - "css/css-text/parsing/line-break-valid-expected.txt": [ - [ - {} - ] - ], "css/css-text/parsing/overflow-wrap-valid-expected.txt": [ [ {} @@ -153366,11 +153803,6 @@ {} ] ], - "css/css-typed-om/the-stylepropertymap/properties/line-break-expected.txt": [ - [ - {} - ] - ], "css/css-typed-om/the-stylepropertymap/properties/line-height-expected.txt": [ [ {} @@ -358431,6 +358863,10 @@ "f30ace92e9def67f70bc1b6b6b4ad6e43f1561bd", "testharness" ], + "css/CSS2/normal-flow/dynamic-percentage-height.html": [ + "2e995963edc200aa857663e4816d0f7807e2969b", + "reftest" + ], "css/CSS2/normal-flow/float-percentage-resolution-quirks-mode.html": [ "a3794579f0ea242f9e7faaffcc16de5a3a69cf7c", "reftest" @@ -393951,6 +394387,42 @@ "3968f685849663574ca213fcb90dc5fb3eaffaa3", "testharness" ], + "css/css-position/position-absolute-dynamic-list-marker.html": [ + "79535326396e451d0db5ae6b6a1cfe56b810c443", + "reftest" + ], + "css/css-position/position-absolute-dynamic-overflow-001.html": [ + "c07919b90f61d8446c53b01e249ad65095202c51", + "reftest" + ], + "css/css-position/position-absolute-dynamic-overflow-002.html": [ + "0c3d36275b2cfc687cd68dd06469799b31fa6f3b", + "reftest" + ], + "css/css-position/position-absolute-dynamic-static-position-floats-001.html": [ + "a63df41089e7e75d33ee1f46d458e97c8ebf0fb0", + "reftest" + ], + "css/css-position/position-absolute-dynamic-static-position-floats-002.html": [ + "49e3807224fcf034e51c1734c60cca34ea24d300", + "reftest" + ], + "css/css-position/position-absolute-dynamic-static-position-floats-003.html": [ + "fa7cc695c361f5b43300b42f3c5872e89b5c0879", + "reftest" + ], + "css/css-position/position-absolute-dynamic-static-position-margin-001.html": [ + "78b0ced9df2fd0ea299a7cc35e9ca0c360f453fa", + "reftest" + ], + "css/css-position/position-absolute-dynamic-static-position-margin-002.html": [ + "98b18efcf96d12581583b7a74b1437b41aaa9a2f", + "reftest" + ], + "css/css-position/position-absolute-dynamic-static-position.html": [ + "35d5f65055d09b377e55a7d3e5dcaf8d3b609a39", + "reftest" + ], "css/css-position/position-absolute-in-inline-001.html": [ "204260ee6784c9e648ab9f1e86b113f0d7227e22", "testharness" @@ -401344,11 +401816,67 @@ "support" ], "css/css-text/line-break/line-break-anywhere-001.html": [ - "8c8252eb56374c9f8bef59d677ccc195eaddcce8", + "a031765b3245aa8b4efe303b5d4cd6019b6aa4a0", "reftest" ], "css/css-text/line-break/line-break-anywhere-002.html": [ - "79d9daba1ccef1363ec92e03e95448ec9da8509a", + "ddbf554730740798b119e3e34e321c094be2742f", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-003.html": [ + "c1d177777050fe7e144f3902215d4c28bc4c6e24", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-004.html": [ + "95b73c28e35ee37c0a0269048ca9e54e145526a5", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-005.html": [ + "7c9c61744d34b35d5c4120b12fe318aa16abb40d", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-006.html": [ + "874846c7743081cfbb330e74eb053901d2ce62ba", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-007.html": [ + "9f097ee9ffbb9de9d4b62e5d28454e10d499dcd3", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-008.html": [ + "c10310939259e2f30301a5fc03faf859bfd56347", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-009.html": [ + "7beba06190183f50e27a63667764f1d59e0efc5b", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-010.html": [ + "2e0c7178e987536418ace1dfa7c34fca1fed8eac", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-011.html": [ + "acc46dbbef3c7b6d54cf9b0488120c238eee1dd6", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-012.html": [ + "e2c5d363fcf4c8b9a275794a0b9e8fd3dfcde1a7", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-013.html": [ + "6b0a1bde2110bd50225387af6b16099c023c8d7f", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-014.html": [ + "bfe72e6aeaab46e37f50751a64fc732112bf9835", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-015.html": [ + "9fe998d8ae8eabd1d235f237af9509d580c3c90f", + "reftest" + ], + "css/css-text/line-break/line-break-anywhere-016.html": [ + "923a6c318226a6bdd0feddd5f643823e2bcd6398", "reftest" ], "css/css-text/line-break/line-break-loose-011.xht": [ @@ -401479,6 +402007,14 @@ "ff74b3bce2d5ece698b404ecd30b53538c0eb420", "support" ], + "css/css-text/line-break/reference/line-break-anywhere-003-ref.html": [ + "ceec198d03b27a1b5de9a48f3f120ae5360fcec6", + "support" + ], + "css/css-text/line-break/reference/line-break-anywhere-004-ref.html": [ + "0e0300a72dc920a5ffb54cda6fbe84a2f517d010", + "support" + ], "css/css-text/line-break/reference/line-break-loose-011-ref.xht": [ "cc6d9023c0843f126ce179674127ead69abb2076", "support" @@ -401892,7 +402428,7 @@ "reftest" ], "css/css-text/overflow-wrap/overflow-wrap-break-word-008.html": [ - "9a3a95ba382e770eb6506102a64771caaf4f00af", + "d3c0f491ee78df226585f0f2b3f2043752faeafd", "reftest" ], "css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html": [ @@ -402039,10 +402575,6 @@ "aca16649360766eed8a2b91d1692890cd03a5e4b", "testharness" ], - "css/css-text/parsing/line-break-valid-expected.txt": [ - "adb0181ecebe89688191257ba9d6abdbf5ffb30d", - "support" - ], "css/css-text/parsing/line-break-valid.html": [ "caaae9a5a0150a35563662a8c917046fb08e79fb", "testharness" @@ -403880,7 +404412,7 @@ "reftest" ], "css/css-text/white-space/break-spaces-009.html": [ - "36aa9dafd6e588c292f598179465233be653ab54", + "128aeaf5ed151807092b083ed765082f0482c8e0", "reftest" ], "css/css-text/white-space/break-spaces-before-first-char-001.html": [ @@ -404811,10 +405343,58 @@ "9602a1f2cf0bab45bc7f70dbe3fa0aeb75d6df79", "reftest" ], + "css/css-text/word-break/word-break-break-all-016.html": [ + "8917d428d0f3fa2f99fb95e70a4e10c0dd5e3705", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-017.html": [ + "6cf3be6b90f8a7bf617aa46472d0d291031d9e55", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-018.html": [ + "be092be8512ea94b0e3e8c188a7072a5a53031a6", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-019.html": [ + "66dba54f41df2b1819c5fb53abcbf01210482353", + "reftest" + ], "css/css-text/word-break/word-break-break-all-020.html": [ "ac1840131c3f214b993ffd58dcd2124523f89b6b", "reftest" ], + "css/css-text/word-break/word-break-break-all-021.html": [ + "80f2dda836ac33e566833e8c76887e735f9f62ac", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-022.html": [ + "73e8503bb8ceaace26567abe5435f8b063405d3c", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-023.html": [ + "3e9791f81138ba60d7ef9eaeda8c3beba9c76595", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-024.html": [ + "0f6bb5b7333302a1e9ab0a485eda657a1b03fa65", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-025.html": [ + "eedd49a59d0da7ad4b9d365c2e5ea92ede199f1f", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-026.html": [ + "001d83f3a01e2fa15fc7554e730b5c769bb75671", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-027.html": [ + "4d34872951738ff34d1e0b8c3bdd6e174f6e71b2", + "reftest" + ], + "css/css-text/word-break/word-break-break-all-028.html": [ + "dd0d2949ceb17edfdb602b944faf5593caf8f9c8", + "reftest" + ], "css/css-text/word-break/word-break-break-word-overflow-wrap-interactions-ref.html": [ "3c6ab3863f88646f2fe9132963704c72d6b8d3d7", "support" @@ -412363,10 +412943,6 @@ "aec16433723313664ba37974c5190be08a540ad7", "testharness" ], - "css/css-typed-om/the-stylepropertymap/properties/line-break-expected.txt": [ - "69e86aa9ac59850b828d90c98984a1595341b703", - "support" - ], "css/css-typed-om/the-stylepropertymap/properties/line-break.html": [ "481a9e97fe852c5b2d69f0d5616dc618fd53b51e", "testharness" @@ -496016,7 +496592,7 @@ "support" ], "tools/ci/website_build.sh": [ - "66593eb55290a9711c3e74b7786a91fd1be2a4e0", + "f91975719be21e7c1461e4f8603c4f34639b840f", "support" ], "tools/conftest.py": [
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/inline-with-block-child-client-rect.html b/third_party/blink/web_tests/external/wpt/intersection-observer/inline-with-block-child-client-rect.html new file mode 100644 index 0000000..81a8fd1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/intersection-observer/inline-with-block-child-client-rect.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/intersection-observer-test-utils.js"></script> + +<style> +pre, #log { + position: absolute; + top: 120px; + left: 0; +} +#target { + display: inline; +} +</style> + +<div id="target"> + <div> + <img width=100 height=100 /> + </div> +</div> + +<script> +var vw = document.documentElement.clientWidth; +var vh = document.documentElement.clientHeight; +var entries = []; +var target; + +runTestCycle(function() { + target = document.getElementById("target"); + assert_true(!!target, "target exists"); + var observer = new IntersectionObserver(function(changes) { + entries = entries.concat(changes) + }); + observer.observe(target); + entries = entries.concat(observer.takeRecords()); + assert_equals(entries.length, 0, "No initial notifications."); + runTestCycle(step0, "First rAF"); +}, "Inline target containing a block child"); + +function step0() { + assert_equals(entries.length, 1); + checkRect(entries[0].boundingClientRect, clientBounds(target), + "entry.boundingClientRect == target.getBoundingClientRect()"); +} +</script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/website_build.sh b/third_party/blink/web_tests/external/wpt/tools/ci/website_build.sh index 66593eb..f919757 100755 --- a/third_party/blink/web_tests/external/wpt/tools/ci/website_build.sh +++ b/third_party/blink/web_tests/external/wpt/tools/ci/website_build.sh
@@ -56,12 +56,12 @@ # Prepare the output directory so that the new build can be pushed to the # repository as an incremental change to the prior build. -mkdir --parents docs/_build/html +mkdir -p docs/_build/html cd docs/_build/html git init git fetch --depth 1 ${remote_url} gh-pages git checkout FETCH_HEAD -git rm -r . +git rm -rf . # Build the website cd ../.. @@ -78,7 +78,7 @@ # Publish the website by pushing the built contents to the `gh-pages` branch git add . -if ! git diff --exit-code --quiet --staged ; then +if git diff --exit-code --quiet --staged ; then echo No change to the website contents. Exiting without publishing. exit ${neutral_status}
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt index 45331013..c488c45e 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 202 tests; 200 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 202 tests; 201 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Navigator: original interface defined PASS Partial dictionary WebGLContextAttributes: original dictionary defined @@ -74,7 +74,7 @@ PASS XRReferenceSpace interface: existence and properties of interface prototype object PASS XRReferenceSpace interface: existence and properties of interface prototype object's "constructor" property PASS XRReferenceSpace interface: existence and properties of interface prototype object's @@unscopables property -FAIL XRReferenceSpace interface: operation getOffsetReferenceSpace(XRRigidTransform) assert_own_property: interface prototype object missing non-static operation expected property "getOffsetReferenceSpace" missing +PASS XRReferenceSpace interface: operation getOffsetReferenceSpace(XRRigidTransform) PASS XRReferenceSpace interface: attribute onreset PASS XRBoundedReferenceSpace interface: existence and properties of interface object PASS XRBoundedReferenceSpace interface object length
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html index a8015e3..e3dd77b 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrFrame_getPose.https.html
@@ -37,7 +37,7 @@ let space2 = spaces[1]; // Rotate 90 degrees about x axis, then move 1 meter along y axis. - space1.originOffset = new XRRigidTransform( + space1 = space1.getOffsetReferenceSpace(new XRRigidTransform( DOMPointReadOnly.fromPoint({ x : 0, y : 1, @@ -50,10 +50,10 @@ z : 0, w : Math.cos(radians / 2) }) - ); + )); // Rotate 90 degrees about z axis, then move 1 meter along x axis. - space2.originOffset = new XRRigidTransform( + space2 = space2.getOffsetReferenceSpace(new XRRigidTransform( DOMPointReadOnly.fromPoint({ x : 1, y : 0, @@ -66,7 +66,7 @@ z : Math.sin(radians / 2), w : Math.cos(radians / 2) }) - ); + )); let space1_from_space2 = xrFrame.getPose(space1, space2); const EXPECTED_POSE_MATRIX = [
diff --git a/third_party/blink/web_tests/fast/forms/validation-bubble-blur.html b/third_party/blink/web_tests/fast/forms/validation-bubble-blur.html new file mode 100644 index 0000000..0ad9684 --- /dev/null +++ b/third_party/blink/web_tests/fast/forms/validation-bubble-blur.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<input required> +<script> +async_test(t => { + let input = document.querySelector('input'); + assert_own_property(window, 'internals'); + input.reportValidity(); + assert_true(internals.isValidationMessageVisible(input)); + assert_equals(document.activeElement, input); + + input.blur(); + requestAnimationFrame(t.step_func_done(() => { + assert_false(internals.isValidationMessageVisible(input)); + })); +}, 'Ensure that removing focus from an invalid control with ' + + 'a validation bubble closes the validation bubble.'); +</script>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 8add08bf..e9e0338 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -10626,10 +10626,9 @@ interface XRReferenceSpace : XRSpace attribute @@toStringTag getter onreset - getter originOffset method constructor + method getOffsetReferenceSpace setter onreset - setter originOffset interface XRReferenceSpaceEvent : Event attribute @@toStringTag getter referenceSpace
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/locked-style.html b/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/locked-style.html new file mode 100644 index 0000000..bd563333 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/locked-style.html
@@ -0,0 +1,60 @@ +<!doctype HTML> +<html> +<meta charset="utf8"> +<title>Display Locking: style on locked element & child</title> +<link rel="author" title="Rakina Zata Amni" href="mailto:rakina@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> +<style> +#container { + contain: style layout; +} +</style> + +<div id="container"> + <div id="child"> + <div id="grandchild"></div> + </div> +</div> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test((t) => { + async function runTest() { + let container = document.getElementById("container"); + await container.displayLock.acquire({ timeout: Infinity }); + + container.style = "color: blue;"; + t.step(() => assert_equals(getComputedStyle(container).color, "rgb(0, 0, 255)", "container color changed to blue")); + t.step(() => assert_equals(getComputedStyle(child).color, "rgb(0, 0, 255)", "child inherits blue color")); + t.step(() => assert_equals(getComputedStyle(grandchild).color, "rgb(0, 0, 255)", "grandchild inherits blue color")); + + child.style = "color: green;"; + t.step(() => assert_equals(getComputedStyle(container).color, "rgb(0, 0, 255)", "container color is still blue")); + t.step(() => assert_equals(getComputedStyle(child).color, "rgb(0, 128, 0)", "child color changed to green")); + t.step(() => assert_equals(getComputedStyle(grandchild).color, "rgb(0, 128, 0)", "grandchild inherits green color")); + + // Commit container, lock child. + await container.displayLock.commit(); + child.style = "contain: style layout"; + await child.displayLock.acquire({ timeout: Infinity }); + + // Update style outside of the locked subtree. + container.style = "color: red;"; + container.offsetTop; + + // Inheritance works as usual through locked boundaries. + t.step(() => assert_equals(getComputedStyle(grandchild).color, "rgb(255, 0, 0)", "grandchild inherits red color")); + t.step(() => assert_equals(getComputedStyle(child).color, "rgb(255, 0, 0)", "child inherits red color")); + t.step(() => assert_equals(getComputedStyle(container).color, "rgb(255, 0, 0)", "container color changed to red")); + + t.done(); + } + + window.onload = function() { + requestAnimationFrame(() => requestAnimationFrame(runTest)); + }; +}, "getComputedStyle gets up-to-date style"); +</script> +
diff --git a/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html b/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html index c8342eb5..4dbdb07 100644 --- a/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html +++ b/third_party/blink/web_tests/xr/xrReferenceSpace_originOffset.html
@@ -63,13 +63,19 @@ input_source.pointerOffset = POINTER_OFFSET_WITH_ROTATION; fakeDeviceController.addInputSource(input_source); + const RADIANS_90D = Math.PI / 2; + const EXPECTED_VIEW_MATRIX_1 = [0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, -1, -1, -1, 1]; const EXPECTED_GRIP_MATRIX_1 = [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 2, 3, 1]; const EXPECTED_RAY_MATRIX_1 = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 2, 2, 1, 1]; - const EXPECTED_VIEW_MATRIX_2 = [0.7419161200523376, 0.6434604525566101, -0.1884651929140091, 0, -0.1884651929140091, -0.06961867958307266, -0.9796091318130493, 0, -0.6434604525566101, 0.7623069882392883, 0.06961867958307266, 0, -4, 4, 9, 1]; - const EXPECTED_GRIP_MATRIX_2 = [-0.6434604525566101, 0.06961867958307266, -0.7623069882392883, 0, 0.7419161200523376, -0.1884651929140091, -0.6434604525566101, 0, -0.1884651929140091, -0.9796091318130493, 0.06961867958307266, 0, 4.118846416473389, 8.01339340209961, -5.368484020233154, 1]; - const EXPECTED_RAY_MATRIX_2 = [0.7419161200523376, -0.1884651929140091, -0.6434604525566101, 0, 0.6434604525566101, -0.06961867958307266, 0.7623069882392883, 0, -0.1884651929140091, -0.9796091318130493, 0.06961867958307266, 0, 2.643460512161255, 7.1730217933654785, -6.823479652404785, 1]; + const EXPECTED_VIEW_MATRIX_2 = [0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, 0, -4, 4, 9, 1]; + const EXPECTED_GRIP_MATRIX_2 = [0, -1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, -9, -2, -5, 1]; + const EXPECTED_RAY_MATRIX_2 = [0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 0, -8, -4, -5, 1]; + + const EXPECTED_VIEW_MATRIX_3 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -4, 6, 14, 1]; + const EXPECTED_GRIP_MATRIX_3 = [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 5, -4, -14, 1]; + const EXPECTED_RAY_MATRIX_3 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 5, -6, -13, 1]; // Must have a reference space to get input poses. eye-level doesn't apply // any transforms to the given matrix. @@ -77,7 +83,7 @@ function OnFrame(time, frame) { let source = session.getInputSources()[0]; - function CheckState(expected_view_matrix, expected_grip_matrix, expected_ray_matrix) { + function CheckState(referenceSpace, expected_view_matrix, expected_grip_matrix, expected_ray_matrix) { let pose = frame.getViewerPose(referenceSpace); let grip_pose = frame.getPose(source.gripSpace, referenceSpace); let input_pose = frame.getPose(source.targetRaySpace, referenceSpace); @@ -91,25 +97,38 @@ assert_matrices_approx_equal(ray_matrix, expected_ray_matrix); } - CheckState(EXPECTED_VIEW_MATRIX_1, EXPECTED_GRIP_MATRIX_1, EXPECTED_RAY_MATRIX_1); + CheckState(referenceSpace, EXPECTED_VIEW_MATRIX_1, EXPECTED_GRIP_MATRIX_1, EXPECTED_RAY_MATRIX_1); - const new_position = { - x : 10, - y : -3, - z : 5 + const new_position1 = { + x: 10, + y: -3, + z: 5, + }; + const new_orientation1 = { + x: Math.sin(RADIANS_90D / 2), + y: 0, + z: 0, + w: Math.cos(RADIANS_90D / 2), }; - const degrees_45 = Math.PI / 4; - const rotation = Math.sin(degrees_45 / 2); - const new_orientation = { - x : rotation, - y : rotation * -1, - z : rotation * 3, - w : Math.cos(degrees_45 / 2) + referenceSpace = referenceSpace.getOffsetReferenceSpace(new XRRigidTransform(new_position1, new_orientation1)); + CheckState(referenceSpace, EXPECTED_VIEW_MATRIX_2, EXPECTED_GRIP_MATRIX_2, EXPECTED_RAY_MATRIX_2); + + const new_position2 = { + x: 5, + y: 2, + z: 0, + }; + const new_orientation2 = { + x: 0, + y: Math.sin(RADIANS_90D / 2), + z: 0, + w: Math.cos(RADIANS_90D / 2), }; - referenceSpace.originOffset = new XRRigidTransform(new_position, new_orientation); - CheckState(EXPECTED_VIEW_MATRIX_2, EXPECTED_GRIP_MATRIX_2, EXPECTED_RAY_MATRIX_2); + referenceSpace = referenceSpace.getOffsetReferenceSpace(new XRRigidTransform(new_position2, new_orientation2)); + CheckState(referenceSpace, EXPECTED_VIEW_MATRIX_3, EXPECTED_GRIP_MATRIX_3, EXPECTED_RAY_MATRIX_3); + resolve(); }
diff --git a/third_party/closure_compiler/externs/html_imports.js b/third_party/closure_compiler/externs/html_imports.js new file mode 100644 index 0000000..906713e --- /dev/null +++ b/third_party/closure_compiler/externs/html_imports.js
@@ -0,0 +1,7 @@ +/** @fileoverview Externs for HTML imports polyfill. */ + +/** @see https://github.com/webcomponents/html-imports */ +var HTMLImports = {}; + +/** @param {!Function} callback */ +HTMLImports.whenReady = function(callback) {};
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn index b72da6c..8a204e5 100644 --- a/third_party/wayland-protocols/BUILD.gn +++ b/third_party/wayland-protocols/BUILD.gn
@@ -55,7 +55,6 @@ wayland_protocol("gaming_input_protocol") { sources = [ - "unstable/gaming-input/gaming-input-unstable-v1.xml", "unstable/gaming-input/gaming-input-unstable-v2.xml", ] }
diff --git a/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v1.xml b/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v1.xml deleted file mode 100644 index 8ae1872..0000000 --- a/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v1.xml +++ /dev/null
@@ -1,127 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<protocol name="gaming_input_unstable_v1"> - - <copyright> - Copyright 2016 The Chromium Authors. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - </copyright> - - <interface name="zcr_gaming_input_v1" version="1"> - <description summary="extends wl_seat with gaming input devices"> - A global interface to provide gaming input devices for a given seat. - - Currently only gamepad devices are supported. - - Warning! The protocol described in this file is experimental and - backward incompatible changes may be made. Backward compatible changes - may be added together with the corresponding uinterface version bump. - Backward incompatible changes are done by bumping the version number in - the protocol and uinterface names and resetting the interface version. - Once the protocol is to be declared stable, the 'z' prefix and the - version number in the protocol and interface names are removed and the - interface version number is reset. - </description> - - <request name="get_gamepad"> - <description summary="get gamepad device assigned to seat"> - Create gamepad object. See zcr_gamepad_v1 interface for details. - </description> - <arg name="id" type="new_id" interface="zcr_gamepad_v1"/> - <arg name="seat" type="object" interface="wl_seat"/> - </request> - </interface> - - <interface name="zcr_gamepad_v1" version="1"> - <description summary="gamepad input device"> - The zcr_gamepad_v1 interface represents one or more gamepad input devices, - which are reported as a normalized 'Standard Gamepad' as it is specified - by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping - </description> - - <request name="destroy" type="destructor"> - <description summary="destroy gamepad object"/> - </request> - - <enum name="gamepad_state"> - <description summary="connection state"/> - <entry name="off" value="0" summary="no gamepads are connected or on."/> - <entry name="on" value="1" summary="at least one gamepad is connected."/> - </enum> - - <event name="state_change"> - <description summary="state change event"> - Notification that this seat's connection state has changed. - </description> - <arg name="state" type="uint" enum="gamepad_state" summary="new state"/> - </event> - - <event name="axis"> - <description summary="axis change event"> - Notification of axis change. - - The axis id specifies which axis has changed as defined by the W3C - 'Standard Gamepad'. - - The value is calibrated and normalized to the -1 to 1 range. - </description> - <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> - <arg name="axis" type="uint" summary="axis that produced this event"/> - <arg name="value" type="fixed" summary="new value of axis"/> - </event> - - <enum name="button_state"> - <description summary="physical button state"> - Describes the physical state of a button that produced the button - event. - </description> - <entry name="released" value="0" summary="the button is not pressed"/> - <entry name="pressed" value="1" summary="the button is pressed"/> - </enum> - - <event name="button"> - <description summary="Gamepad button changed"> - Notification of button change. - - The button id specifies which button has changed as defined by the W3C - 'Standard Gamepad'. - - A button can have a digital and an analog value. The analog value is - normalized to a 0 to 1 range. - If a button does not provide an analog value, it will be derived from - the digital state. - </description> - <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> - <arg name="button" type="uint" summary="id of button"/> - <arg name="state" type="uint" enum="button_state" summary="digital state of the button"/> - <arg name="analog" type="fixed" summary="analog value of the button"/> - </event> - - <event name="frame"> - <description summary="Notifies end of a series of gamepad changes."> - Indicates the end of a set of events that logically belong together. - A client is expected to accumulate the data in all events within the - frame before proceeding. - </description> - <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> - </event> - </interface> - -</protocol>
diff --git a/third_party/webxr_test_pages/webxr-samples/input-selection.html b/third_party/webxr_test_pages/webxr-samples/input-selection.html index 04251b2..1aaa6c1 100644 --- a/third_party/webxr_test_pages/webxr-samples/input-selection.html +++ b/third_party/webxr_test_pages/webxr-samples/input-selection.html
@@ -429,8 +429,8 @@ {x: invPosition[0], y: invPosition[1], z: invPosition[2]}, {x: invOrientation[0], y: invOrientation[1], z: invOrientation[2], w: invOrientation[3]}); - // Update originOffset to use the teleported player position and orientation - refSpace.originOffset = xform; + // Update refSpace to use a new originOffset with the teleported player position and orientation + refSpace = refSpace.getOffsetReferenceSpace(xform); console.log('teleport to', trackingSpaceOriginInWorldSpace); }
diff --git a/third_party/webxr_test_pages/webxr-samples/room-scale.html b/third_party/webxr_test_pages/webxr-samples/room-scale.html index dbb6fad..97344c10 100644 --- a/third_party/webxr_test_pages/webxr-samples/room-scale.html +++ b/third_party/webxr_test_pages/webxr-samples/room-scale.html
@@ -173,8 +173,7 @@ // right level. (Here we're moving it 1.6 meters, which should // *very* roughly align us with the eye height of an "average" // adult human.) - refSpace.originOffset = new XRRigidTransform({y: -1.6}); - return refSpace; + return refSpace.getOffsetReferenceSpace(new XRRigidTransform({y: -1.6})); }); } else { throw e;
diff --git a/tools/grit/grit/node/include.py b/tools/grit/grit/node/include.py index 667ee61..daf5e72 100644 --- a/tools/grit/grit/node/include.py +++ b/tools/grit/grit/node/include.py
@@ -76,7 +76,12 @@ # We have no control over code that calles ToRealPath later, so convert # the path to be relative against our basedir. if self.attrs.get('use_base_dir', 'true') != 'true': - return os.path.relpath(self.attrs['file'], self.GetRoot().GetBaseDir()) + # Normalize the directory path to use the appropriate OS separator. + # GetBaseDir() may return paths\like\this or paths/like/this, since it is + # read from the base_dir attribute in the grd file. + norm_base_dir = os.path.normpath( + self.GetRoot().GetBaseDir().replace('\\', '/')) + return os.path.relpath(self.attrs['file'], norm_base_dir) return self.attrs['file']
diff --git a/tools/grit/grit/node/include_unittest.py b/tools/grit/grit/node/include_unittest.py index cef8c09..b4dcb8a 100755 --- a/tools/grit/grit/node/include_unittest.py +++ b/tools/grit/grit/node/include_unittest.py
@@ -65,9 +65,11 @@ includes.AddChild(include_node) root.EndParsing() + last_dir = os.path.basename(os.getcwd()) + expected_path = util.normpath(os.path.join( + u'..', last_dir, u'flugel/kugel.pdf')) self.assertEqual(root.ToRealPath(include_node.GetInputPath()), - util.normpath( - os.path.join(ur'../', ur'flugel/kugel.pdf'))) + expected_path) def testCompressGzip(self): root = util.ParseGrdForUnittest('''
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index e902451..c1fb8ec 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -51531,14 +51531,17 @@ <enum name="SignedExchangeSignatureVerificationResult"> <int value="0" label="Success"/> - <int value="1" label="No certificate"/> - <int value="2" label="No cert-sha256"/> + <int value="1" label="No certificate (deprecated)"/> + <int value="2" label="No cert-sha256 (deprecated)"/> <int value="3" label="cert-sha256 mismatch"/> - <int value="4" label="Failed to reconstruct signed message"/> + <int value="4" label="Failed to reconstruct signed message (deprecated)"/> <int value="5" label="Failed to verify signature"/> <int value="6" label="Invalid integrity scheme"/> - <int value="7" label="Invalid timestamp"/> + <int value="7" label="Invalid timestamp (deprecated)"/> <int value="8" label="Unsupported certificate type"/> + <int value="9" label="Validity period is loo long"/> + <int value="10" label="Signature is not yet valid"/> + <int value="11" label="Signature is expired"/> </enum> <enum name="SignedExchangeValidityPingResult">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4b782e4..dbeee8d9 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -121640,6 +121640,30 @@ </summary> </histogram> +<histogram name="Stability.Android.OomKillReverseRank" units="rank" + expires_after="2020-04-10"> + <owner>boliu@chromium.org</owner> + <owner>ssid@chromium.org</owner> + <summary> + Records the reverse rank of a child process when it is killed by android if + applicable. Chrome on Android ranks some child processes and provides hints + to android that it should kill from lowest to highest ranked. The lowest + ranked process has reverse rank 0. This is a measure how good the hints to + android are; if hints were perfect, then all android kills should have + reverse rank 0. + </summary> +</histogram> + +<histogram name="Stability.Android.OomKillReverseRankSuccess" + enum="BooleanSuccess" expires_after="2020-04-10"> + <owner>boliu@chromium.org</owner> + <owner>ssid@chromium.org</owner> + <summary> + Getting value for OomKillReverseRank may fail. Recorded when an applicable + child process is killed by android. + </summary> +</histogram> + <histogram name="Stability.Android.PendingMinidumpsOnStartup" units="minidumps" expires_after="2017-05-16"> <obsolete>
diff --git a/tools/perf/bootstrap_deps b/tools/perf/bootstrap_deps index a277bc0..c3efae9 100644 --- a/tools/perf/bootstrap_deps +++ b/tools/perf/bootstrap_deps
@@ -9,6 +9,7 @@ "src/build/android": "", "src/chrome/test/data/perf/canvas_bench": "", "src/chrome/test/data/third_party/spaceport": "", + "src/components/variations/service": "", "src/tools/json_comment_eater": "", "src/tools/json_to_struct": "", "src/tools/perf/benchmarks": "",
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index d3aac86..715f95f 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -815,23 +815,23 @@ # that live in tools/perf/core. We need to verify off of that list. def get_telemetry_tests_in_performance_test_suite(): tests = set() - add_benchmarks_from_sharding_map( - tests, "shard_maps/linux-perf_map.json") - add_benchmarks_from_sharding_map( - tests, "shard_maps/android-pixel2-perf_map.json") + for platform in bot_platforms.OFFICIAL_PLATFORMS: + add_benchmarks_from_sharding_map( + tests, platform.shards_map_file_path) return tests -def add_benchmarks_from_sharding_map(tests, shard_map_name): - path = os.path.join(os.path.dirname(__file__), shard_map_name) - if os.path.exists(path): - with open(path) as f: - sharding_map = json.load(f) - for shard, benchmarks in sharding_map.iteritems(): - if "extra_infos" in shard: - continue - for benchmark, _ in benchmarks['benchmarks'].iteritems(): - tests.add(benchmark) +def add_benchmarks_from_sharding_map(tests, shard_map_path): + if not os.path.exists(shard_map_path): + raise RuntimeError( + 'Platform does not have a shard map at %s.' % shard_map_path) + with open(shard_map_path) as f: + shard_map = json.load(f) + for shard, benchmarks in shard_map.iteritems(): + if "extra_infos" in shard: + continue + for benchmark, _ in benchmarks['benchmarks'].iteritems(): + tests.add(benchmark) def get_scheduled_non_telemetry_benchmarks(perf_waterfall_file):
diff --git a/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java b/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java index 123c8f1..80c64ed 100644 --- a/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java +++ b/ui/android/java/src/org/chromium/ui/resources/ResourceExtractor.java
@@ -40,7 +40,6 @@ private static final String FALLBACK_LOCALE = "en-US"; private static final String COMPRESSED_LOCALES_DIR = "locales"; private static final String COMPRESSED_LOCALES_FALLBACK_DIR = "fallback-locales"; - private static final int BUFFER_SIZE = 16 * 1024; private class ExtractTask implements Runnable { private final List<Runnable> mCompletionCallbacks = new ArrayList<Runnable>(); @@ -105,19 +104,13 @@ throw new RuntimeException(); } - AssetManager assetManager = ContextUtils.getApplicationAssets(); - byte[] buffer = new byte[BUFFER_SIZE]; for (int n = 0; n < assetPaths.length; ++n) { String assetPath = assetPaths[n]; File output = new File(outputDir, outputNames[n]); - TraceEvent.begin("ExtractResource"); - try (InputStream inputStream = assetManager.open(assetPath)) { - FileUtils.copyFileStreamAtomicWithBuffer(inputStream, output, buffer); - } catch (IOException e) { + if (!FileUtils.extractAsset( + ContextUtils.getApplicationContext(), assetPath, output)) { // The app would just crash later if files are missing. - throw new RuntimeException(e); - } finally { - TraceEvent.end("ExtractResource"); + throw new RuntimeException(); } } } @@ -345,21 +338,15 @@ return new File(getAppDataDir(), "paks"); } - private static void deleteFile(File file) { - if (file.exists() && !file.delete()) { - Log.w(TAG, "Unable to remove %s", file.getName()); - } - } - private void deleteFiles(String[] existingFileNames) { // These used to be extracted, but no longer are, so just clean them up. - deleteFile(new File(getAppDataDir(), ICU_DATA_FILENAME)); - deleteFile(new File(getAppDataDir(), V8_NATIVES_DATA_FILENAME)); - deleteFile(new File(getAppDataDir(), V8_SNAPSHOT_DATA_FILENAME)); + FileUtils.recursivelyDeleteFile(new File(getAppDataDir(), ICU_DATA_FILENAME)); + FileUtils.recursivelyDeleteFile(new File(getAppDataDir(), V8_NATIVES_DATA_FILENAME)); + FileUtils.recursivelyDeleteFile(new File(getAppDataDir(), V8_SNAPSHOT_DATA_FILENAME)); if (existingFileNames != null) { for (String fileName : existingFileNames) { - deleteFile(new File(getOutputDir(), fileName)); + FileUtils.recursivelyDeleteFile(new File(getOutputDir(), fileName)); } } }
diff --git a/ui/base/clipboard/clipboard_format_type_win.cc b/ui/base/clipboard/clipboard_format_type_win.cc index 129ef0c..c477acb 100644 --- a/ui/base/clipboard/clipboard_format_type_win.cc +++ b/ui/base/clipboard/clipboard_format_type_win.cc
@@ -17,30 +17,17 @@ // ClipboardFormatType implementation. ClipboardFormatType::ClipboardFormatType() = default; -ClipboardFormatType::ClipboardFormatType(UINT native_format) { - // There's no good way to actually initialize this in the constructor in - // C++03. - data_.cfFormat = static_cast<CLIPFORMAT>(native_format); - data_.dwAspect = DVASPECT_CONTENT; - data_.lindex = -1; - data_.tymed = TYMED_HGLOBAL; -} +ClipboardFormatType::ClipboardFormatType(UINT native_format) + : ClipboardFormatType(native_format, -1) {} -ClipboardFormatType::ClipboardFormatType(UINT native_format, LONG index) { - // There's no good way to actually initialize this in the constructor in - // C++03. - data_.cfFormat = static_cast<CLIPFORMAT>(native_format); - data_.dwAspect = DVASPECT_CONTENT; - data_.lindex = index; - data_.tymed = TYMED_HGLOBAL; -} +ClipboardFormatType::ClipboardFormatType(UINT native_format, LONG index) + : ClipboardFormatType(native_format, index, TYMED_HGLOBAL) {} -// TODO(https://crbug.com/949411): Use delegating constructors. ClipboardFormatType::ClipboardFormatType(UINT native_format, LONG index, DWORD tymed) { // There's no good way to actually initialize this in the constructor in - // C++03. + // C++14. In C++ 20, we can use designated initializers. data_.cfFormat = static_cast<CLIPFORMAT>(native_format); data_.dwAspect = DVASPECT_CONTENT; data_.lindex = index;
diff --git a/ui/base/ime/chromeos/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc index a0e968f..c8daab1 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.cc +++ b/ui/base/ime/chromeos/input_method_chromeos.cc
@@ -776,7 +776,7 @@ } void InputMethodChromeOS::HidePreeditText() { - if (composition_.text.empty() || IsTextInputTypeNone()) + if (IsTextInputTypeNone()) return; // Intentionally leaves |composing_text_| unchanged.
diff --git a/ui/chromeos/user_activity_power_manager_notifier.cc b/ui/chromeos/user_activity_power_manager_notifier.cc index bb905ee..d28cc106 100644 --- a/ui/chromeos/user_activity_power_manager_notifier.cc +++ b/ui/chromeos/user_activity_power_manager_notifier.cc
@@ -4,7 +4,6 @@ #include "ui/chromeos/user_activity_power_manager_notifier.h" -#include "chromeos/dbus/power/power_manager_client.h" #include "services/device/public/mojom/constants.mojom.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/base/user_activity/user_activity_detector.h" @@ -50,6 +49,7 @@ : detector_(detector), fingerprint_observer_binding_(this) { detector_->AddObserver(this); ui::InputDeviceManager::GetInstance()->AddObserver(this); + chromeos::PowerManagerClient::Get()->AddObserver(this); // Connector can be null in tests. if (connector) { @@ -63,6 +63,7 @@ } UserActivityPowerManagerNotifier::~UserActivityPowerManagerNotifier() { + chromeos::PowerManagerClient::Get()->RemoveObserver(this); ui::InputDeviceManager::GetInstance()->RemoveObserver(this); detector_->RemoveObserver(this); } @@ -99,11 +100,26 @@ base::TimeTicks now = base::TimeTicks::Now(); // InSeconds() truncates rather than rounding, so it's fine for this // comparison. - if (last_notify_time_.is_null() || + // powerd depends on this D-Bus call to track input events. When the + // system is about to suspend or in dark resume, report user activity + // immediately so that powerd can transition to full resume and turn the + // display on as soon as possible. OnUserActivity calls are rate-limited by + // the sender, so it's safe to always notify while we're suspending. + if (suspending_ || last_notify_time_.is_null() || (now - last_notify_time_).InSeconds() >= kNotifyIntervalSec) { chromeos::PowerManagerClient::Get()->NotifyUserActivity(user_activity_type); last_notify_time_ = now; } } +void UserActivityPowerManagerNotifier::SuspendImminent( + power_manager::SuspendImminent::Reason reason) { + suspending_ = true; +} + +void UserActivityPowerManagerNotifier::SuspendDone( + const base::TimeDelta& sleep_duration) { + suspending_ = false; +} + } // namespace ui
diff --git a/ui/chromeos/user_activity_power_manager_notifier.h b/ui/chromeos/user_activity_power_manager_notifier.h index 1710fdb..6c9db45 100644 --- a/ui/chromeos/user_activity_power_manager_notifier.h +++ b/ui/chromeos/user_activity_power_manager_notifier.h
@@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/time/time.h" +#include "chromeos/dbus/power/power_manager_client.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/device/public/mojom/fingerprint.mojom.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -27,7 +28,8 @@ class UI_CHROMEOS_EXPORT UserActivityPowerManagerNotifier : public InputDeviceEventObserver, public UserActivityObserver, - public device::mojom::FingerprintObserver { + public device::mojom::FingerprintObserver, + public chromeos::PowerManagerClient::Observer { public: // Registers and unregisters itself as an observer of |detector| on // construction and destruction. @@ -52,6 +54,10 @@ bool enroll_session_complete, int percent_complete) override; + // chromeos::PowerManagerClient::Observer: + void SuspendImminent(power_manager::SuspendImminent::Reason reason) override; + void SuspendDone(const base::TimeDelta& sleep_duration) override; + private: // Notifies power manager that the user is active and activity type. No-op if // it is within 5 seconds from |last_notify_time_|. @@ -67,6 +73,10 @@ // Last time that the power manager was notified. base::TimeTicks last_notify_time_; + // True after SuspendImminent has been received and when SuspendDone has not + // been received. + bool suspending_ = false; + DISALLOW_COPY_AND_ASSIGN(UserActivityPowerManagerNotifier); };
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js index e7983f4..9262ac1 100644 --- a/ui/file_manager/file_manager/common/js/util.js +++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1166,6 +1166,50 @@ }; /** + * Returns true if specified entry is a special entry such as MyFiles/Downloads, + * MyFiles/PluginVm or Linux files root which cannot be modified such as + * deleted/cut or renamed. + * + * @param {!VolumeManager} volumeManager + * @param {(Entry|FakeEntry)} entry Entry or a fake entry. + * @return {boolean} + */ +util.isNonModifiable = (volumeManager, entry) => { + if (!entry) { + return false; + } + if (util.isFakeEntry(entry)) { + return true; + } + + // If the entry is not a valid entry. + if (!volumeManager) { + return false; + } + + const volumeInfo = volumeManager.getVolumeInfo(entry); + if (!volumeInfo) { + return false; + } + + if (volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS) { + if (util.isMyFilesVolumeEnabled() && entry.fullPath === '/Downloads') { + return true; + } + if (util.isPluginVmEnabled() && entry.fullPath === '/PluginVm') { + return true; + } + } + + if (volumeInfo.volumeType === VolumeManagerCommon.RootType.CROSTINI && + entry.fullPath === '/') { + return true; + } + + return false; +}; + +/** * Checks if the specified set of allowed effects contains the given effect. * See: http://www.w3.org/TR/html5/editing.html#the-datatransfer-interface *
diff --git a/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js b/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js index be393f1..858a44c 100644 --- a/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js +++ b/ui/file_manager/file_manager/foreground/js/dialog_action_controller.js
@@ -5,509 +5,477 @@ /** * Controler for handling behaviors of the Files app opened as a file/folder * selection dialog. - * - * @param {DialogType} dialogType Dialog type. - * @param {!DialogFooter} dialogFooter Dialog footer. - * @param {!DirectoryModel} directoryModel Directory model. - * @param {!MetadataModel} metadataModel Metadata cache. - * @param {!VolumeManager} volumeManager Volume manager. - * @param {!FileFilter} fileFilter File filter model. - * @param {!NamingController} namingController Naming controller. - * @param {!FileSelectionHandler} fileSelectionHandler Initial file selection. - * @param {!LaunchParam} launchParam Whether the dialog should return local - * path or not. - * @constructor - * @struct */ -function DialogActionController( - dialogType, dialogFooter, directoryModel, metadataModel, volumeManager, - fileFilter, namingController, fileSelectionHandler, launchParam) { +class DialogActionController { /** - * @type {!DialogType} - * @const - * @private + * @param {!DialogType} dialogType Dialog type. + * @param {!DialogFooter} dialogFooter Dialog footer. + * @param {!DirectoryModel} directoryModel Directory model. + * @param {!MetadataModel} metadataModel Metadata cache. + * @param {!VolumeManager} volumeManager Volume manager. + * @param {!FileFilter} fileFilter File filter model. + * @param {!NamingController} namingController Naming controller. + * @param {!FileSelectionHandler} fileSelectionHandler Initial file selection. + * @param {!LaunchParam} launchParam Whether the dialog should return local + * path or not. */ - this.dialogType_ = dialogType; + constructor( + dialogType, dialogFooter, directoryModel, metadataModel, volumeManager, + fileFilter, namingController, fileSelectionHandler, launchParam) { + /** @private @const {!DialogType} */ + this.dialogType_ = dialogType; - /** - * @type {!DialogFooter} - * @const - * @private - */ - this.dialogFooter_ = dialogFooter; + /** @private @const {!DialogFooter} */ + this.dialogFooter_ = dialogFooter; - /** - * @type {!DirectoryModel} - * @const - * @private - */ - this.directoryModel_ = directoryModel; + /** @private @const {!DirectoryModel} */ + this.directoryModel_ = directoryModel; - /** - * @type {!MetadataModel} - * @const - * @private - */ - this.metadataModel_ = metadataModel; + /** @private @const {!MetadataModel} */ + this.metadataModel_ = metadataModel; - /** - * @type {!VolumeManager} - * @const - * @private - */ - this.volumeManager_ = volumeManager; + /** @private @const {!VolumeManager} */ + this.volumeManager_ = volumeManager; - /** - * @type {!FileFilter} - * @const - * @private - */ - this.fileFilter_ = fileFilter; + /** @private @const {!FileFilter} */ + this.fileFilter_ = fileFilter; - /** - * @type {!NamingController} - * @const - * @private - */ - this.namingController_ = namingController; + /** @private @const {!NamingController} */ + this.namingController_ = namingController; - /** - * @type {!FileSelectionHandler} - * @private - * @const - */ - this.fileSelectionHandler_ = fileSelectionHandler; + /** @private @const {!FileSelectionHandler} */ + this.fileSelectionHandler_ = fileSelectionHandler; - /** - * List of acceptable file types for open dialog. - * @type {!Array<Object>} - * @const - * @private - */ - this.fileTypes_ = launchParam.typeList || []; + /** + * List of acceptable file types for open dialog. + * @private @const {!Array<Object>} + */ + this.fileTypes_ = launchParam.typeList || []; - /** - * @type {!AllowedPaths} - * @const - * @private - */ - this.allowedPaths_ = launchParam.allowedPaths; + /** @private @const {!AllowedPaths} */ + this.allowedPaths_ = launchParam.allowedPaths; - /** - * Bound function for onCancel_. - * @type {!function(this:DialogActionController, Event)} - * @private - */ - this.onCancelBound_ = this.processCancelAction_.bind(this); + /** + * Bound function for onCancel_. + * @private @const {!function(this:DialogActionController, Event)} + */ + this.onCancelBound_ = this.processCancelAction_.bind(this); - dialogFooter.okButton.addEventListener( - 'click', this.processOKAction_.bind(this)); - dialogFooter.cancelButton.addEventListener('click', this.onCancelBound_); - dialogFooter.newFolderButton.addEventListener( - 'click', this.processNewFolderAction_.bind(this)); - dialogFooter.fileTypeSelector.addEventListener( - 'change', this.onFileTypeFilterChanged_.bind(this)); - dialogFooter.filenameInput.addEventListener( - 'input', this.updateOkButton_.bind(this)); - fileSelectionHandler.addEventListener( - FileSelectionHandler.EventType.CHANGE_THROTTLED, - this.onFileSelectionChanged_.bind(this)); - volumeManager.addEventListener( - 'drive-connection-changed', this.updateOkButton_.bind(this)); + dialogFooter.okButton.addEventListener( + 'click', this.processOKAction_.bind(this)); + dialogFooter.cancelButton.addEventListener('click', this.onCancelBound_); + dialogFooter.newFolderButton.addEventListener( + 'click', this.processNewFolderAction_.bind(this)); + dialogFooter.fileTypeSelector.addEventListener( + 'change', this.onFileTypeFilterChanged_.bind(this)); + dialogFooter.filenameInput.addEventListener( + 'input', this.updateOkButton_.bind(this)); + fileSelectionHandler.addEventListener( + FileSelectionHandler.EventType.CHANGE_THROTTLED, + this.onFileSelectionChanged_.bind(this)); + volumeManager.addEventListener( + 'drive-connection-changed', this.updateOkButton_.bind(this)); - dialogFooter.initFileTypeFilter(this.fileTypes_, launchParam.includeAllFiles); - this.onFileTypeFilterChanged_(); + dialogFooter.initFileTypeFilter( + this.fileTypes_, launchParam.includeAllFiles); + this.onFileTypeFilterChanged_(); - this.newFolderCommand_ = - /** @type {cr.ui.Command} */ ($('new-folder')); - this.newFolderCommand_.addEventListener( - 'disabledChange', this.updateNewFolderButton_.bind(this)); -} - -/** - * @private - */ -DialogActionController.prototype.processOKActionForSaveDialog_ = function() { - const selection = this.fileSelectionHandler_.selection; - - // If OK action is clicked when a directory is selected, open the directory. - if (selection.directoryCount === 1 && selection.fileCount === 0) { - this.directoryModel_.changeDirectoryEntry( - /** @type {!DirectoryEntry} */ (selection.entries[0])); - return; + this.newFolderCommand_ = + /** @type {cr.ui.Command} */ ($('new-folder')); + this.newFolderCommand_.addEventListener( + 'disabledChange', this.updateNewFolderButton_.bind(this)); } - // Save-as doesn't require a valid selection from the list, since - // we're going to take the filename from the text input. - const filename = this.dialogFooter_.filenameInput.value; - if (!filename) { - throw new Error('Missing filename!'); - } + /** + * @private + */ + processOKActionForSaveDialog_() { + const selection = this.fileSelectionHandler_.selection; - this.namingController_.validateFileNameForSaving(filename) - .then(url => { - // TODO(mtomasz): Clean this up by avoiding constructing a URL - // via string concatenation. - this.selectFilesAndClose_({ - urls: [url], - multiple: false, - filterIndex: this.dialogFooter_.selectedFilterIndex + // If OK action is clicked when a directory is selected, open the directory. + if (selection.directoryCount === 1 && selection.fileCount === 0) { + this.directoryModel_.changeDirectoryEntry( + /** @type {!DirectoryEntry} */ (selection.entries[0])); + return; + } + + // Save-as doesn't require a valid selection from the list, since + // we're going to take the filename from the text input. + const filename = this.dialogFooter_.filenameInput.value; + if (!filename) { + throw new Error('Missing filename!'); + } + + this.namingController_.validateFileNameForSaving(filename) + .then(url => { + // TODO(mtomasz): Clean this up by avoiding constructing a URL + // via string concatenation. + this.selectFilesAndClose_({ + urls: [url], + multiple: false, + filterIndex: this.dialogFooter_.selectedFilterIndex + }); + }) + .catch(error => { + if (error instanceof Error) { + console.error(error.stack && error); + } }); - }) - .catch(error => { - if (error instanceof Error) { - console.error(error.stack && error); - } - }); -}; - -/** - * Handle a click of the ok button. - * - * The ok button has different UI labels depending on the type of dialog, but - * in code it's always referred to as 'ok'. - * - * @private - */ -DialogActionController.prototype.processOKAction_ = function() { - if (this.dialogFooter_.okButton.disabled) { - throw new Error('Disabled!'); - } - if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { - this.processOKActionForSaveDialog_(); - return; } - const files = []; - const selectedIndexes = - this.directoryModel_.getFileListSelection().selectedIndexes; + /** + * Handle a click of the ok button. + * + * The ok button has different UI labels depending on the type of dialog, but + * in code it's always referred to as 'ok'. + * + * @private + */ + processOKAction_() { + if (this.dialogFooter_.okButton.disabled) { + throw new Error('Disabled!'); + } + if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { + this.processOKActionForSaveDialog_(); + return; + } - if (DialogType.isFolderDialog(this.dialogType_) && - selectedIndexes.length === 0) { - const url = this.directoryModel_.getCurrentDirEntry().toURL(); + const files = []; + const selectedIndexes = + this.directoryModel_.getFileListSelection().selectedIndexes; + + if (DialogType.isFolderDialog(this.dialogType_) && + selectedIndexes.length === 0) { + const url = this.directoryModel_.getCurrentDirEntry().toURL(); + const singleSelection = { + urls: [url], + multiple: false, + filterIndex: this.dialogFooter_.selectedFilterIndex + }; + this.selectFilesAndClose_(singleSelection); + return; + } + + // All other dialog types require at least one selected list item. + // The logic to control whether or not the ok button is enabled should + // prevent us from ever getting here, but we sanity check to be sure. + if (!selectedIndexes.length) { + throw new Error('Nothing selected!'); + } + + const dm = this.directoryModel_.getFileList(); + for (let i = 0; i < selectedIndexes.length; i++) { + const entry = dm.item(selectedIndexes[i]); + if (!entry) { + console.error('Error locating selected file at index: ' + i); + continue; + } + + files.push(entry.toURL()); + } + + // Multi-file selection has no other restrictions. + if (this.dialogType_ === DialogType.SELECT_OPEN_MULTI_FILE) { + const multipleSelection = { + urls: files, + multiple: true, + }; + this.selectFilesAndClose_(multipleSelection); + return; + } + + // Everything else must have exactly one. + if (files.length > 1) { + throw new Error('Too many files selected!'); + } + + const selectedEntry = dm.item(selectedIndexes[0]); + + if (DialogType.isFolderDialog(this.dialogType_)) { + if (!selectedEntry.isDirectory) { + throw new Error('Selected entry is not a folder!'); + } + } else if (this.dialogType_ === DialogType.SELECT_OPEN_FILE) { + if (!selectedEntry.isFile) { + throw new Error('Selected entry is not a file!'); + } + } + const singleSelection = { - urls: [url], + urls: [files[0]], multiple: false, filterIndex: this.dialogFooter_.selectedFilterIndex }; this.selectFilesAndClose_(singleSelection); - return; } - // All other dialog types require at least one selected list item. - // The logic to control whether or not the ok button is enabled should - // prevent us from ever getting here, but we sanity check to be sure. - if (!selectedIndexes.length) { - throw new Error('Nothing selected!'); + /** + * Cancels file selection and closes the file selection dialog. + * @private + */ + processCancelAction_() { + chrome.fileManagerPrivate.cancelDialog(); + window.close(); } - const dm = this.directoryModel_.getFileList(); - for (let i = 0; i < selectedIndexes.length; i++) { - const entry = dm.item(selectedIndexes[i]); - if (!entry) { - console.error('Error locating selected file at index: ' + i); - continue; - } - - files.push(entry.toURL()); + /** + * Creates a new folder using new-folder command. + * @private + */ + processNewFolderAction_() { + this.newFolderCommand_.canExecuteChange(this.dialogFooter_.newFolderButton); + this.newFolderCommand_.execute(this.dialogFooter_.newFolderButton); } - // Multi-file selection has no other restrictions. - if (this.dialogType_ === DialogType.SELECT_OPEN_MULTI_FILE) { - const multipleSelection = { - urls: files, - multiple: true, - }; - this.selectFilesAndClose_(multipleSelection); - return; + /** + * Handles disabledChange event to update the new-folder button's + * avaliability. + * @private + */ + updateNewFolderButton_() { + this.dialogFooter_.newFolderButton.disabled = + this.newFolderCommand_.disabled; } - // Everything else must have exactly one. - if (files.length > 1) { - throw new Error('Too many files selected!'); - } - - const selectedEntry = dm.item(selectedIndexes[0]); - - if (DialogType.isFolderDialog(this.dialogType_)) { - if (!selectedEntry.isDirectory) { - throw new Error('Selected entry is not a folder!'); - } - } else if (this.dialogType_ === DialogType.SELECT_OPEN_FILE) { - if (!selectedEntry.isFile) { - throw new Error('Selected entry is not a file!'); - } - } - - const singleSelection = { - urls: [files[0]], - multiple: false, - filterIndex: this.dialogFooter_.selectedFilterIndex - }; - this.selectFilesAndClose_(singleSelection); -}; - -/** - * Cancels file selection and closes the file selection dialog. - * @private - */ -DialogActionController.prototype.processCancelAction_ = () => { - chrome.fileManagerPrivate.cancelDialog(); - window.close(); -}; - -/** - * Creates a new folder using new-folder command. - * @private - */ -DialogActionController.prototype.processNewFolderAction_ = function() { - this.newFolderCommand_.canExecuteChange(this.dialogFooter_.newFolderButton); - this.newFolderCommand_.execute(this.dialogFooter_.newFolderButton); -}; - -/** - * Handles disabledChange event to update the new-folder button's avaliability. - * @private - */ -DialogActionController.prototype.updateNewFolderButton_ = function() { - this.dialogFooter_.newFolderButton.disabled = this.newFolderCommand_.disabled; -}; - -/** - * Tries to close this modal dialog with some files selected. - * Performs preprocessing if needed (e.g. for Drive). - * @param {Object} selection Contains urls, filterIndex and multiple fields. - * @private - */ -DialogActionController.prototype.selectFilesAndClose_ = function(selection) { - const currentRootType = this.directoryModel_.getCurrentRootType(); - const callSelectFilesApiAndClose = callback => { - const onFileSelected = () => { - callback(); - if (!chrome.runtime.lastError) { - // Call next method on a timeout, as it's unsafe to - // close a window from a callback. - setTimeout(window.close.bind(window), 0); + /** + * Tries to close this modal dialog with some files selected. + * Performs preprocessing if needed (e.g. for Drive). + * @param {Object} selection Contains urls, filterIndex and multiple fields. + * @private + */ + selectFilesAndClose_(selection) { + const currentRootType = this.directoryModel_.getCurrentRootType(); + const callSelectFilesApiAndClose = callback => { + const onFileSelected = () => { + callback(); + if (!chrome.runtime.lastError) { + // Call next method on a timeout, as it's unsafe to + // close a window from a callback. + setTimeout(window.close.bind(window), 0); + } + }; + // Record the root types of chosen files in OPEN dialog. + if (this.dialogType_ == DialogType.SELECT_OPEN_FILE || + this.dialogType_ == DialogType.SELECT_OPEN_MULTI_FILE) { + metrics.recordEnum( + 'OpenFiles.RootType', currentRootType, + VolumeManagerCommon.RootTypesForUMA); + } + if (selection.multiple) { + chrome.fileManagerPrivate.selectFiles( + selection.urls, this.allowedPaths_ === AllowedPaths.NATIVE_PATH, + onFileSelected); + } else { + chrome.fileManagerPrivate.selectFile( + selection.urls[0], selection.filterIndex, + this.dialogType_ !== + DialogType.SELECT_SAVEAS_FILE /* for opening */, + this.allowedPaths_ === AllowedPaths.NATIVE_PATH, onFileSelected); } }; - // Record the root types of chosen files in OPEN dialog. - if (this.dialogType_ == DialogType.SELECT_OPEN_FILE || - this.dialogType_ == DialogType.SELECT_OPEN_MULTI_FILE) { - metrics.recordEnum( - 'OpenFiles.RootType', currentRootType, - VolumeManagerCommon.RootTypesForUMA); - } - if (selection.multiple) { - chrome.fileManagerPrivate.selectFiles( - selection.urls, this.allowedPaths_ === AllowedPaths.NATIVE_PATH, - onFileSelected); - } else { - chrome.fileManagerPrivate.selectFile( - selection.urls[0], selection.filterIndex, - this.dialogType_ !== DialogType.SELECT_SAVEAS_FILE /* for opening */, - this.allowedPaths_ === AllowedPaths.NATIVE_PATH, onFileSelected); - } - }; - if (currentRootType !== VolumeManagerCommon.VolumeType.DRIVE || - this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { - callSelectFilesApiAndClose(() => {}); - return; - } - - const shade = document.createElement('div'); - shade.className = 'shade'; - const footer = this.dialogFooter_.element; - const progress = footer.querySelector('.progress-track'); - progress.style.width = '0%'; - const cancelled = false; - - const progressMap = {}; - let filesStarted = 0; - let filesTotal = selection.urls.length; - for (let index = 0; index < selection.urls.length; index++) { - progressMap[selection.urls[index]] = -1; - } - let lastPercent = 0; - let bytesTotal = 0; - let bytesDone = 0; - - const onFileTransfersUpdated = status => { - if (!(status.fileUrl in progressMap)) { - return; - } - if (status.total === -1) { + if (currentRootType !== VolumeManagerCommon.VolumeType.DRIVE || + this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { + callSelectFilesApiAndClose(() => {}); return; } - let old = progressMap[status.fileUrl]; - if (old === -1) { - // -1 means we don't know file size yet. - bytesTotal += status.total; - filesStarted++; - old = 0; + const shade = document.createElement('div'); + shade.className = 'shade'; + const footer = this.dialogFooter_.element; + const progress = footer.querySelector('.progress-track'); + progress.style.width = '0%'; + const cancelled = false; + + const progressMap = {}; + let filesStarted = 0; + let filesTotal = selection.urls.length; + for (let index = 0; index < selection.urls.length; index++) { + progressMap[selection.urls[index]] = -1; } - bytesDone += status.processed - old; - progressMap[status.fileUrl] = status.processed; + let lastPercent = 0; + let bytesTotal = 0; + let bytesDone = 0; - let percent = bytesTotal === 0 ? 0 : bytesDone / bytesTotal; - // For files we don't have information about, assume the progress is zero. - percent = percent * filesStarted / filesTotal * 100; - // Do not decrease the progress. This may happen, if first downloaded - // file is small, and the second one is large. - lastPercent = Math.max(lastPercent, percent); - progress.style.width = lastPercent + '%'; - }; + const onFileTransfersUpdated = status => { + if (!(status.fileUrl in progressMap)) { + return; + } + if (status.total === -1) { + return; + } - const setup = () => { - document.querySelector('.dialog-container').appendChild(shade); - setTimeout(() => { - shade.setAttribute('fadein', 'fadein'); - }, 100); - footer.setAttribute('progress', 'progress'); - this.dialogFooter_.cancelButton.removeEventListener( - 'click', this.onCancelBound_); - this.dialogFooter_.cancelButton.addEventListener('click', onCancel); - chrome.fileManagerPrivate.onFileTransfersUpdated.addListener( - onFileTransfersUpdated); - }; + let old = progressMap[status.fileUrl]; + if (old === -1) { + // -1 means we don't know file size yet. + bytesTotal += status.total; + filesStarted++; + old = 0; + } + bytesDone += status.processed - old; + progressMap[status.fileUrl] = status.processed; - const cleanup = () => { - shade.parentNode.removeChild(shade); - footer.removeAttribute('progress'); - this.dialogFooter_.cancelButton.removeEventListener('click', onCancel); - this.dialogFooter_.cancelButton.addEventListener( - 'click', this.onCancelBound_); - chrome.fileManagerPrivate.onFileTransfersUpdated.removeListener( - onFileTransfersUpdated); - }; + let percent = bytesTotal === 0 ? 0 : bytesDone / bytesTotal; + // For files we don't have information about, assume the progress is zero. + percent = percent * filesStarted / filesTotal * 100; + // Do not decrease the progress. This may happen, if first downloaded + // file is small, and the second one is large. + lastPercent = Math.max(lastPercent, percent); + progress.style.width = lastPercent + '%'; + }; - const onCancel = () => { - // According to API cancel may fail, but there is no proper UI to reflect - // this. So, we just silently assume that everything is cancelled. - util.URLsToEntries(selection.urls).then(entries => { - chrome.fileManagerPrivate.cancelFileTransfers( - entries, util.checkAPIError); + const setup = () => { + document.querySelector('.dialog-container').appendChild(shade); + setTimeout(() => { + shade.setAttribute('fadein', 'fadein'); + }, 100); + footer.setAttribute('progress', 'progress'); + this.dialogFooter_.cancelButton.removeEventListener( + 'click', this.onCancelBound_); + this.dialogFooter_.cancelButton.addEventListener('click', onCancel); + chrome.fileManagerPrivate.onFileTransfersUpdated.addListener( + onFileTransfersUpdated); + }; + + const cleanup = () => { + shade.parentNode.removeChild(shade); + footer.removeAttribute('progress'); + this.dialogFooter_.cancelButton.removeEventListener('click', onCancel); + this.dialogFooter_.cancelButton.addEventListener( + 'click', this.onCancelBound_); + chrome.fileManagerPrivate.onFileTransfersUpdated.removeListener( + onFileTransfersUpdated); + }; + + const onCancel = () => { + // According to API cancel may fail, but there is no proper UI to reflect + // this. So, we just silently assume that everything is cancelled. + util.URLsToEntries(selection.urls).then(entries => { + chrome.fileManagerPrivate.cancelFileTransfers( + entries, util.checkAPIError); + }); + }; + + const onProperties = properties => { + for (let i = 0; i < properties.length; i++) { + if (properties[i].present) { + // For files already in GCache, we don't get any transfer updates. + filesTotal--; + } + } + callSelectFilesApiAndClose(cleanup); + }; + + setup(); + + // TODO(mtomasz): Use Entry instead of URLs, if possible. + util.URLsToEntries(selection.urls, entries => { + this.metadataModel_.get(entries, ['present']).then(onProperties); }); - }; + } - const onProperties = properties => { - for (let i = 0; i < properties.length; i++) { - if (properties[i].present) { - // For files already in GCache, we don't get any transfer updates. - filesTotal--; - } - } - callSelectFilesApiAndClose(cleanup); - }; + /** + * Filters file according to the selected file type. + * @private + */ + onFileTypeFilterChanged_() { + this.fileFilter_.removeFilter('fileType'); + const selectedIndex = this.dialogFooter_.selectedFilterIndex; + if (selectedIndex > 0) { // Specific filter selected. + const regexp = new RegExp( + '\\.(' + this.fileTypes_[selectedIndex - 1].extensions.join('|') + + ')$', + 'i'); + const filter = entry => { + return entry.isDirectory || regexp.test(entry.name); + }; + this.fileFilter_.addFilter('fileType', filter); - setup(); - - // TODO(mtomasz): Use Entry instead of URLs, if possible. - util.URLsToEntries(selection.urls, entries => { - this.metadataModel_.get(entries, ['present']).then(onProperties); - }); -}; - -/** - * Filters file according to the selected file type. - * @private - */ -DialogActionController.prototype.onFileTypeFilterChanged_ = function() { - this.fileFilter_.removeFilter('fileType'); - const selectedIndex = this.dialogFooter_.selectedFilterIndex; - if (selectedIndex > 0) { // Specific filter selected. - const regexp = new RegExp( - '\\.(' + this.fileTypes_[selectedIndex - 1].extensions.join('|') + ')$', - 'i'); - const filter = entry => { - return entry.isDirectory || regexp.test(entry.name); - }; - this.fileFilter_.addFilter('fileType', filter); - - // In save dialog, update the destination name extension. - if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { - const current = this.dialogFooter_.filenameInput.value; - const newExt = this.fileTypes_[selectedIndex - 1].extensions[0]; - if (newExt && !regexp.test(current)) { - const i = current.lastIndexOf('.'); - if (i >= 0) { - this.dialogFooter_.filenameInput.value = - current.substr(0, i) + '.' + newExt; - this.dialogFooter_.selectTargetNameInFilenameInput(); + // In save dialog, update the destination name extension. + if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { + const current = this.dialogFooter_.filenameInput.value; + const newExt = this.fileTypes_[selectedIndex - 1].extensions[0]; + if (newExt && !regexp.test(current)) { + const i = current.lastIndexOf('.'); + if (i >= 0) { + this.dialogFooter_.filenameInput.value = + current.substr(0, i) + '.' + newExt; + this.dialogFooter_.selectTargetNameInFilenameInput(); + } } } } } -}; -/** - * Handles selection change. - * - * @private - */ -DialogActionController.prototype.onFileSelectionChanged_ = function() { - // If this is a save-as dialog, copy the selected file into the filename - // input text box. - const selection = this.fileSelectionHandler_.selection; - if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE && - selection.totalCount === 1 && selection.entries[0].isFile && - this.dialogFooter_.filenameInput.value !== selection.entries[0].name) { - this.dialogFooter_.filenameInput.value = selection.entries[0].name; - } - - this.updateOkButton_(); - if (!this.dialogFooter_.okButton.disabled) { - util.testSendMessage('dialog-ready'); - } -}; - -/** - * Updates the Ok button enabled state. - * @private - */ -DialogActionController.prototype.updateOkButton_ = function() { - const selection = this.fileSelectionHandler_.selection; - - if (this.dialogType_ === DialogType.FULL_PAGE) { - // No "select" buttons on the full page UI. - this.dialogFooter_.okButton.disabled = false; - return; - } - - if (DialogType.isFolderDialog(this.dialogType_)) { - // In SELECT_FOLDER mode, we allow to select current directory - // when nothing is selected. - this.dialogFooter_.okButton.disabled = - selection.directoryCount > 1 || selection.fileCount !== 0; - return; - } - - if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { - if (selection.directoryCount === 1 && selection.fileCount === 0) { - this.dialogFooter_.okButtonLabel.textContent = str('OPEN_LABEL'); - this.dialogFooter_.okButton.disabled = false; - } else { - this.dialogFooter_.okButtonLabel.textContent = str('SAVE_LABEL'); - this.dialogFooter_.okButton.disabled = - this.directoryModel_.isReadOnly() || - !this.dialogFooter_.filenameInput.value || - !this.fileSelectionHandler_.isAvailable(); + /** + * Handles selection change. + * @private + */ + onFileSelectionChanged_() { + // If this is a save-as dialog, copy the selected file into the filename + // input text box. + const selection = this.fileSelectionHandler_.selection; + if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE && + selection.totalCount === 1 && selection.entries[0].isFile && + this.dialogFooter_.filenameInput.value !== selection.entries[0].name) { + this.dialogFooter_.filenameInput.value = selection.entries[0].name; } - return; + + this.updateOkButton_(); + if (!this.dialogFooter_.okButton.disabled) { + util.testSendMessage('dialog-ready'); + } } - if (this.dialogType_ === DialogType.SELECT_OPEN_FILE) { - this.dialogFooter_.okButton.disabled = selection.directoryCount !== 0 || - selection.fileCount !== 1 || !this.fileSelectionHandler_.isAvailable(); - return; - } + /** + * Updates the Ok button enabled state. + * @private + */ + updateOkButton_() { + const selection = this.fileSelectionHandler_.selection; - if (this.dialogType_ === DialogType.SELECT_OPEN_MULTI_FILE) { - this.dialogFooter_.okButton.disabled = selection.directoryCount !== 0 || - selection.fileCount === 0 || !this.fileSelectionHandler_.isAvailable(); - return; - } + if (this.dialogType_ === DialogType.FULL_PAGE) { + // No "select" buttons on the full page UI. + this.dialogFooter_.okButton.disabled = false; + return; + } - assertNotReached('Unknown dialog type.'); -}; + if (DialogType.isFolderDialog(this.dialogType_)) { + // In SELECT_FOLDER mode, we allow to select current directory + // when nothing is selected. + this.dialogFooter_.okButton.disabled = + selection.directoryCount > 1 || selection.fileCount !== 0; + return; + } + + if (this.dialogType_ === DialogType.SELECT_SAVEAS_FILE) { + if (selection.directoryCount === 1 && selection.fileCount === 0) { + this.dialogFooter_.okButtonLabel.textContent = str('OPEN_LABEL'); + this.dialogFooter_.okButton.disabled = false; + } else { + this.dialogFooter_.okButtonLabel.textContent = str('SAVE_LABEL'); + this.dialogFooter_.okButton.disabled = + this.directoryModel_.isReadOnly() || + !this.dialogFooter_.filenameInput.value || + !this.fileSelectionHandler_.isAvailable(); + } + return; + } + + if (this.dialogType_ === DialogType.SELECT_OPEN_FILE) { + this.dialogFooter_.okButton.disabled = selection.directoryCount !== 0 || + selection.fileCount !== 1 || + !this.fileSelectionHandler_.isAvailable(); + return; + } + + if (this.dialogType_ === DialogType.SELECT_OPEN_MULTI_FILE) { + this.dialogFooter_.okButton.disabled = selection.directoryCount !== 0 || + selection.fileCount === 0 || + !this.fileSelectionHandler_.isAvailable(); + return; + } + + assertNotReached('Unknown dialog type.'); + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js b/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js index d28452b..405081ed 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js +++ b/ui/file_manager/file_manager/foreground/js/directory_tree_naming_controller.js
@@ -4,291 +4,273 @@ /** * Naming controller for directory tree. - * @param {!DirectoryModel} directoryModel - * @param {!DirectoryTree} directoryTree - * @param {!cr.ui.dialogs.AlertDialog} alertDialog - * @constructor - * @struct */ -function DirectoryTreeNamingController( - directoryModel, directoryTree, alertDialog) { +class DirectoryTreeNamingController { /** - * @private {!DirectoryModel} - * @const + * @param {!DirectoryModel} directoryModel + * @param {!DirectoryTree} directoryTree + * @param {!cr.ui.dialogs.AlertDialog} alertDialog */ - this.directoryModel_ = directoryModel; + constructor(directoryModel, directoryTree, alertDialog) { + /** @private @const {!DirectoryModel} */ + this.directoryModel_ = directoryModel; - /** - * @private {!DirectoryTree} - * @const - */ - this.directoryTree_ = directoryTree; + /** @private @const {!DirectoryTree} */ + this.directoryTree_ = directoryTree; - /** - * @private {!cr.ui.dialogs.AlertDialog} - * @const - */ - this.alertDialog_ = alertDialog; + /** @private @const {!cr.ui.dialogs.AlertDialog} */ + this.alertDialog_ = alertDialog; - /** - * @private {DirectoryItem} - */ - this.currentDirectoryItem_ = null; + /** @private {?DirectoryItem} */ + this.currentDirectoryItem_ = null; - /** - * @private {boolean} - */ - this.editting_ = false; + /** @private {boolean} */ + this.editting_ = false; - /** - * @private {boolean} - */ - this.isRemovableRoot_ = false; + /** @private {boolean} */ + this.isRemovableRoot_ = false; - /** - * @private {VolumeInfo} - */ - this.volumeInfo_ = null; + /** @private {?VolumeInfo} */ + this.volumeInfo_ = null; - /** - * @private {!HTMLInputElement} - * @const - */ - this.inputElement_ = /** @type {!HTMLInputElement} */ - (document.createElement('input')); - this.inputElement_.type = 'text'; - this.inputElement_.spellcheck = false; - this.inputElement_.addEventListener('keydown', this.onKeyDown_.bind(this)); - this.inputElement_.addEventListener('blur', this.commitRename_.bind(this)); - this.inputElement_.addEventListener('click', event => { - // Stop propagation of click event to prevent it being captured by directory - // item and current directory is changed to editing item. - event.stopPropagation(); - }); -} - -/** - * Returns input element. - * @return {!HTMLInputElement} - */ -DirectoryTreeNamingController.prototype.getInputElement = function() { - return this.inputElement_; -}; - -/** - * Attaches naming controller to specified directory item and start rename. - * @param {!DirectoryItem} directoryItem An html element of a node of the - * target. - * @param {boolean} isRemovableRoot Indicates whether the target is removable - * node or not. - * @param {VolumeInfo} volumeInfo A volume information about the target node. - * |volumeInfo| can be null if method is invoked on a folder that is in the - * tree view and is not root of an external drive. - */ -DirectoryTreeNamingController.prototype.attachAndStart = function( - directoryItem, isRemovableRoot, volumeInfo) { - this.isRemovableRoot_ = isRemovableRoot; - this.volumeInfo_ = this.isRemovableRoot_ ? assert(volumeInfo) : null; - - if (this.currentDirectoryItem_) { - return; + /** @private @const {!HTMLInputElement} */ + this.inputElement_ = /** @type {!HTMLInputElement} */ + (document.createElement('input')); + this.inputElement_.type = 'text'; + this.inputElement_.spellcheck = false; + this.inputElement_.addEventListener('keydown', this.onKeyDown_.bind(this)); + this.inputElement_.addEventListener('blur', this.commitRename_.bind(this)); + this.inputElement_.addEventListener('click', event => { + // Stop propagation of click event to prevent it being captured by + // directory item and current directory is changed to editing item. + event.stopPropagation(); + }); } - this.currentDirectoryItem_ = directoryItem; - this.currentDirectoryItem_.setAttribute('renaming', true); - - const renameInputElementPlaceholder = - this.currentDirectoryItem_.firstElementChild.getElementsByClassName( - 'rename-placeholder'); - - if (this.isRemovableRoot_ && renameInputElementPlaceholder.length === 1) { - renameInputElementPlaceholder[0].appendChild(this.inputElement_); - } else { - this.currentDirectoryItem_.firstElementChild.appendChild( - this.inputElement_); + /** + * Returns input element. + * @return {!HTMLInputElement} + */ + getInputElement() { + return this.inputElement_; } - this.inputElement_.value = this.currentDirectoryItem_.label; - this.inputElement_.select(); - this.inputElement_.focus(); + /** + * Attaches naming controller to specified directory item and start rename. + * @param {!DirectoryItem} directoryItem An html element of a node of the + * target. + * @param {boolean} isRemovableRoot Indicates whether the target is removable + * node or not. + * @param {VolumeInfo} volumeInfo A volume information about the target node. + * |volumeInfo| can be null if method is invoked on a folder that is in + * the tree view and is not root of an external drive. + */ + attachAndStart(directoryItem, isRemovableRoot, volumeInfo) { + this.isRemovableRoot_ = isRemovableRoot; + this.volumeInfo_ = this.isRemovableRoot_ ? assert(volumeInfo) : null; - this.editting_ = true; -}; + if (this.currentDirectoryItem_) { + return; + } -/** - * Commits rename. - * @private - */ -DirectoryTreeNamingController.prototype.commitRename_ = function() { - if (!this.editting_) { - return; - } - this.editting_ = false; + this.currentDirectoryItem_ = directoryItem; + this.currentDirectoryItem_.setAttribute('renaming', true); - const entry = this.currentDirectoryItem_.entry; - const newName = this.inputElement_.value; + const renameInputElementPlaceholder = + this.currentDirectoryItem_.firstElementChild.getElementsByClassName( + 'rename-placeholder'); - // If new name is the same as current name or empty, do nothing. - if (newName === this.currentDirectoryItem_.label || newName.length == 0) { - this.detach_(); - return; + if (this.isRemovableRoot_ && renameInputElementPlaceholder.length === 1) { + renameInputElementPlaceholder[0].appendChild(this.inputElement_); + } else { + this.currentDirectoryItem_.firstElementChild.appendChild( + this.inputElement_); + } + + this.inputElement_.value = this.currentDirectoryItem_.label; + this.inputElement_.select(); + this.inputElement_.focus(); + + this.editting_ = true; } - if (this.isRemovableRoot_) { - // Validate new name. - util.validateExternalDriveName(newName, assert(this.volumeInfo_)) + /** + * Commits rename. + * @private + */ + commitRename_() { + if (!this.editting_) { + return; + } + this.editting_ = false; + + const entry = this.currentDirectoryItem_.entry; + const newName = this.inputElement_.value; + + // If new name is the same as current name or empty, do nothing. + if (newName === this.currentDirectoryItem_.label || newName.length == 0) { + this.detach_(); + return; + } + + if (this.isRemovableRoot_) { + // Validate new name. + util.validateExternalDriveName(newName, assert(this.volumeInfo_)) + .then( + this.performExternalDriveRename_.bind(this, entry, newName), + errorMessage => { + this.alertDialog_.show( + /** @type {string} */ (errorMessage), + this.detach_.bind(this)); + }); + } else { + // Validate new name. + new Promise(entry.getParent.bind(entry)) + .then(parentEntry => { + return util.validateFileName( + parentEntry, newName, + !this.directoryModel_.getFileFilter().isHiddenFilesVisible()); + }) + .then( + this.performRename_.bind(this, entry, newName), errorMessage => { + this.alertDialog_.show( + /** @type {string} */ (errorMessage), + this.detach_.bind(this)); + }); + } + } + + /** + * Performs rename operation. + * @param {!DirectoryEntry} entry + * @param {string} newName Validated name. + * @private + */ + performRename_(entry, newName) { + const renamingCurrentDirectory = + util.isSameEntry(entry, this.directoryModel_.getCurrentDirEntry()); + if (renamingCurrentDirectory) { + this.directoryModel_.setIgnoringCurrentDirectoryDeletion( + true /* ignore */); + } + + // TODO(yawano): Rename might take time on some volumes. Optimistically show + // new name in the UI before actual rename is completed. + new Promise(util.rename.bind(null, entry, newName)) .then( - this.performExternalDriveRename_.bind(this, entry, newName), - errorMessage => { - this.alertDialog_.show( - /** @type {string} */ (errorMessage), - this.detach_.bind(this)); + newEntry => { + // Show new name before detaching input element to prevent showing + // old name. + const label = + this.currentDirectoryItem_.firstElementChild.querySelector( + '.label'); + label.textContent = newName; + + this.currentDirectoryItem_.entry = newEntry; + this.currentDirectoryItem_.updateSubDirectories( + true /* recursive */); + + this.detach_(); + + // If renamed directory was current directory, change it to new + // one. + if (renamingCurrentDirectory) { + this.directoryModel_.changeDirectoryEntry( + newEntry, + this.directoryModel_.setIgnoringCurrentDirectoryDeletion + .bind(this.directoryModel_, false /* not ignore */)); + } + }, + error => { + this.directoryModel_.setIgnoringCurrentDirectoryDeletion( + false /* not ignore*/); + this.detach_(); + + this.alertDialog_.show(util.getRenameErrorMessage( + /** @type {DOMError} */ (error), entry, newName)); }); - } else { - // Validate new name. - new Promise(entry.getParent.bind(entry)) - .then(parentEntry => { - return util.validateFileName( - parentEntry, newName, - !this.directoryModel_.getFileFilter().isHiddenFilesVisible()); - }) - .then(this.performRename_.bind(this, entry, newName), errorMessage => { - this.alertDialog_.show( - /** @type {string} */ (errorMessage), this.detach_.bind(this)); - }); - } -}; - -/** - * Performs rename operation. - * @param {!DirectoryEntry} entry - * @param {string} newName Validated name. - * @private - */ -DirectoryTreeNamingController.prototype.performRename_ = function( - entry, newName) { - const renamingCurrentDirectory = - util.isSameEntry(entry, this.directoryModel_.getCurrentDirEntry()); - if (renamingCurrentDirectory) { - this.directoryModel_.setIgnoringCurrentDirectoryDeletion(true /* ignore */); } - // TODO(yawano): Rename might take time on some volumes. Optimistically show - // new name in the UI before actual rename is completed. - new Promise(util.rename.bind(null, entry, newName)) - .then( - newEntry => { - // Show new name before detaching input element to prevent showing - // old name. - const label = - this.currentDirectoryItem_.firstElementChild.querySelector( - '.label'); - label.textContent = newName; + /** + * Performs external drive rename operation. + * @param {!DirectoryEntry} entry + * @param {string} newName Validated name. + * @private + */ + performExternalDriveRename_(entry, newName) { + // Invoke external drive rename + chrome.fileManagerPrivate.renameVolume(this.volumeInfo_.volumeId, newName); + // Show new name before detaching input element to prevent showing old + // name. + const label = + this.currentDirectoryItem_.firstElementChild.querySelector('.label'); + label.textContent = newName; - this.currentDirectoryItem_.entry = newEntry; - this.currentDirectoryItem_.updateSubDirectories( - true /* recursive */); - - this.detach_(); - - // If renamed directory was current directory, change it to new one. - if (renamingCurrentDirectory) { - this.directoryModel_.changeDirectoryEntry( - newEntry, - this.directoryModel_.setIgnoringCurrentDirectoryDeletion.bind( - this.directoryModel_, false /* not ignore */)); - } - }, - error => { - this.directoryModel_.setIgnoringCurrentDirectoryDeletion( - false /* not ignore*/); - this.detach_(); - - this.alertDialog_.show(util.getRenameErrorMessage( - /** @type {DOMError} */ (error), entry, newName)); - }); -}; - -/** - * Performs external drive rename operation. - * @param {!DirectoryEntry} entry - * @param {string} newName Validated name. - * @private - */ -DirectoryTreeNamingController.prototype.performExternalDriveRename_ = function( - entry, newName) { - // Invoke external drive rename - chrome.fileManagerPrivate.renameVolume(this.volumeInfo_.volumeId, newName); - // Show new name before detaching input element to prevent showing old - // name. - const label = - this.currentDirectoryItem_.firstElementChild.querySelector('.label'); - label.textContent = newName; - - this.detach_(); -}; - -/** - * Cancels rename. - * @private - */ -DirectoryTreeNamingController.prototype.cancelRename_ = function() { - if (!this.editting_) { - return; - } - this.editting_ = false; - - this.detach_(); -}; - -/** - * Detaches controller from current directory item. - * @private - */ -DirectoryTreeNamingController.prototype.detach_ = function() { - assert(!!this.currentDirectoryItem_); - - const renameInputElementPlaceholder = - this.currentDirectoryItem_.firstElementChild.getElementsByClassName( - 'rename-placeholder'); - - if (this.isRemovableRoot_ && renameInputElementPlaceholder.length === 1) { - renameInputElementPlaceholder[0].removeChild(this.inputElement_); - } else { - this.currentDirectoryItem_.firstElementChild.removeChild( - this.inputElement_); + this.detach_(); } - this.currentDirectoryItem_.removeAttribute('renaming'); - this.currentDirectoryItem_ = null; + /** + * Cancels rename. + * @private + */ + cancelRename_() { + if (!this.editting_) { + return; + } + this.editting_ = false; - // Restore focus to directory tree. - this.directoryTree_.focus(); -}; - -/** - * Handles keydown event. - * @param {!Event} event - * @private - */ -DirectoryTreeNamingController.prototype.onKeyDown_ = function(event) { - // Ignore key events if event.keyCode is VK_PROCESSKEY(229). - // TODO(fukino): Remove this workaround once crbug.com/644140 is fixed. - if (event.keyCode === 229) { - return; + this.detach_(); } - event.stopPropagation(); + /** + * Detaches controller from current directory item. + * @private + */ + detach_() { + assert(!!this.currentDirectoryItem_); - switch (util.getKeyModifiers(event) + event.key) { - case 'Escape': - this.cancelRename_(); - event.preventDefault(); - break; + const renameInputElementPlaceholder = + this.currentDirectoryItem_.firstElementChild.getElementsByClassName( + 'rename-placeholder'); - case 'Enter': - this.commitRename_(); - event.preventDefault(); - break; + if (this.isRemovableRoot_ && renameInputElementPlaceholder.length === 1) { + renameInputElementPlaceholder[0].removeChild(this.inputElement_); + } else { + this.currentDirectoryItem_.firstElementChild.removeChild( + this.inputElement_); + } + + this.currentDirectoryItem_.removeAttribute('renaming'); + this.currentDirectoryItem_ = null; + + // Restore focus to directory tree. + this.directoryTree_.focus(); } -}; + + /** + * Handles keydown event. + * @param {!Event} event + * @private + */ + onKeyDown_(event) { + // Ignore key events if event.keyCode is VK_PROCESSKEY(229). + // TODO(fukino): Remove this workaround once crbug.com/644140 is fixed. + if (event.keyCode === 229) { + return; + } + + event.stopPropagation(); + + switch (util.getKeyModifiers(event) + event.key) { + case 'Escape': + this.cancelRename_(); + event.preventDefault(); + break; + + case 'Enter': + this.commitRename_(); + event.preventDefault(); + break; + } + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index 40719f3..e092d70 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -601,7 +601,7 @@ this.toolbarController_ = new ToolbarController( this.ui_.toolbar, this.ui_.dialogNavigationList, this.ui_.listContainer, assert(this.ui_.locationLine), this.selectionHandler_, - this.directoryModel_); + this.directoryModel_, this.volumeManager_); this.emptyFolderController_ = new EmptyFolderController( this.ui_.emptyFolder, this.directoryModel_, this.ui_.alertDialog); this.actionsController_ = new ActionsController(
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index 2a46822..db884c6 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -272,42 +272,6 @@ }; /** - * If entry is MyFiles/Downloads or MyFiles/PluginVm, we don't allow - * cut/delete/rename. - * @param {!VolumeManager} volumeManager - * @param {(Entry|FakeEntry)} entry Entry or a fake entry. - * @return {boolean} - */ -CommandUtil.isReadOnly = (volumeManager, entry) => { - if (!entry) { - return false; - } - if (util.isFakeEntry(entry)) { - return false; - } - - // If the entry is not a valid entry. - if (!volumeManager) { - return false; - } - - const volumeInfo = volumeManager.getVolumeInfo(entry); - if (!volumeInfo) { - return false; - } - - if (volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS) { - if (util.isMyFilesVolumeEnabled() && entry.fullPath === '/Downloads') { - return true; - } - if (util.isPluginVmEnabled() && entry.fullPath === '/PluginVm') { - return true; - } - } - return false; -}; - -/** * Returns whether all of the given entries have the given capability. * * @param {!Array<Entry>} entries List of entries to check capabilities for. @@ -1065,7 +1029,7 @@ return entries.some(entry => { const locationInfo = fileManager.volumeManager.getLocationInfo(entry); return (locationInfo && locationInfo.isReadOnly) || - CommandUtil.isReadOnly(fileManager.volumeManager, entry); + util.isNonModifiable(fileManager.volumeManager, entry); }); } }; @@ -1224,7 +1188,7 @@ } // For MyFiles/Downloads and MyFiles/PluginVm we only allow copy. - if (isMove && CommandUtil.isReadOnly(volumeManager, entry)) { + if (isMove && util.isNonModifiable(volumeManager, entry)) { return false; } @@ -1262,7 +1226,7 @@ // For MyFiles/Downloads we only allow copy. if (isMove && fileManager.getSelection().entries.some( - CommandUtil.isReadOnly.bind(null, volumeManager))) { + util.isNonModifiable.bind(null, volumeManager))) { return false; } @@ -1294,7 +1258,7 @@ */ execute: function(event, fileManager) { const entry = CommandUtil.getCommandEntry(fileManager, event.target); - if (CommandUtil.isReadOnly(fileManager.volumeManager, entry)) { + if (util.isNonModifiable(fileManager.volumeManager, entry)) { return; } if (event.target instanceof DirectoryTree || @@ -1369,7 +1333,7 @@ !CommandUtil.shouldShowMenuItemsForEntry( fileManager.volumeManager, entries[0]) || entries.some( - CommandUtil.isReadOnly.bind(null, fileManager.volumeManager))) { + util.isNonModifiable.bind(null, fileManager.volumeManager))) { event.canExecute = false; event.command.setHidden(true); return;
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js index 38a4acd..63c71e10 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -5,134 +5,1203 @@ /** * Represents a collection of available tasks to execute for a specific list * of entries. - * - * @param {!VolumeManager} volumeManager - * @param {!MetadataModel} metadataModel - * @param {!DirectoryModel} directoryModel - * @param {!FileManagerUI} ui - * @param {!Array<!Entry>} entries - * @param {!Array<?string>} mimeTypes - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks - * @param {chrome.fileManagerPrivate.FileTask} defaultTask - * @param {!TaskHistory} taskHistory - * @param {!NamingController} namingController - * @param {!Crostini} crostini - * @constructor - * @struct */ -function FileTasks( - volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, tasks, - defaultTask, taskHistory, namingController, crostini) { +class FileTasks { /** - * @private {!VolumeManager} - * @const + * @param {!VolumeManager} volumeManager + * @param {!MetadataModel} metadataModel + * @param {!DirectoryModel} directoryModel + * @param {!FileManagerUI} ui + * @param {!Array<!Entry>} entries + * @param {!Array<?string>} mimeTypes + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks + * @param {chrome.fileManagerPrivate.FileTask} defaultTask + * @param {!TaskHistory} taskHistory + * @param {!NamingController} namingController + * @param {!Crostini} crostini */ - this.volumeManager_ = volumeManager; + constructor( + volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, + tasks, defaultTask, taskHistory, namingController, crostini) { + /** @private @const {!VolumeManager} */ + this.volumeManager_ = volumeManager; - /** - * @private {!MetadataModel} - * @const - */ - this.metadataModel_ = metadataModel; + /** @private @const {!MetadataModel} */ + this.metadataModel_ = metadataModel; - /** - * @private {!DirectoryModel} - * @const - */ - this.directoryModel_ = directoryModel; + /** @private @const {!DirectoryModel} */ + this.directoryModel_ = directoryModel; - /** - * @private {!FileManagerUI} - * @const - */ - this.ui_ = ui; + /** @private @const {!FileManagerUI} */ + this.ui_ = ui; - /** - * @private {!Array<!Entry>} - * @const - */ - this.entries_ = entries; + /** @private @const {!Array<!Entry>} */ + this.entries_ = entries; - /** - * @private {!Array<?string>} - * @const - */ - this.mimeTypes_ = mimeTypes; + /** @private @const {!Array<?string>} */ + this.mimeTypes_ = mimeTypes; - /** - * @private {!Array<!chrome.fileManagerPrivate.FileTask>} - * @const - */ - this.tasks_ = tasks; + /** @private @const {!Array<!chrome.fileManagerPrivate.FileTask>} */ + this.tasks_ = tasks; - /** - * @private {chrome.fileManagerPrivate.FileTask} - * @const - */ - this.defaultTask_ = defaultTask; + /** @private @const {chrome.fileManagerPrivate.FileTask} */ + this.defaultTask_ = defaultTask; - /** - * @private {!TaskHistory} - * @const - */ - this.taskHistory_ = taskHistory; + /** @private @const {!TaskHistory} */ + this.taskHistory_ = taskHistory; - /** - * @private {!NamingController} - * @const - */ - this.namingController_ = namingController; + /** @private @const {!NamingController} */ + this.namingController_ = namingController; - /** - * @private {!Crostini} - * @const - */ - this.crostini_ = crostini; -} + /** @private @const {!Crostini} */ + this.crostini_ = crostini; + } -FileTasks.prototype = { /** * @return {!Array<!Entry>} */ get entries() { return this.entries_; } -}; + + /** + * Creates an instance of FileTasks for the specified list of entries with + * mime types. + * + * @param {!VolumeManager} volumeManager + * @param {!MetadataModel} metadataModel + * @param {!DirectoryModel} directoryModel + * @param {!FileManagerUI} ui + * @param {!Array<!Entry>} entries + * @param {!Array<?string>} mimeTypes + * @param {!TaskHistory} taskHistory + * @param {!NamingController} namingController + * @param {!Crostini} crostini + * @return {!Promise<!FileTasks>} + */ + static create( + volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, + taskHistory, namingController, crostini) { + const tasksPromise = new Promise(fulfill => { + // getFileTasks supports only native entries. + entries = entries.filter(util.isNativeEntry); + if (entries.length === 0) { + fulfill([]); + return; + } + chrome.fileManagerPrivate.getFileTasks(entries, taskItems => { + if (chrome.runtime.lastError) { + console.error( + 'Failed to fetch file tasks due to: ' + + chrome.runtime.lastError.message); + Promise.reject(); + return; + } + + // Linux package installation is currently only supported for a single + // file which is inside the Linux container, or in a shareable volume. + // TODO(timloh): Instead of filtering these out, we probably should + // show a dialog with an error message, similar to when attempting to + // run Crostini tasks with non-Crostini entries. + if (entries.length !== 1 || + !(FileTasks.isCrostiniEntry(entries[0], volumeManager) || + crostini.canSharePath( + constants.DEFAULT_CROSTINI_VM, entries[0], + false /* persist */))) { + taskItems = taskItems.filter(item => { + const taskParts = item.taskId.split('|'); + const appId = taskParts[0]; + const taskType = taskParts[1]; + const actionId = taskParts[2]; + return !( + appId === chrome.runtime.id && taskType === 'app' && + actionId === 'install-linux-package'); + }); + } + + // Filters out Pack with Zip Archiver task because it will be + // accessible via 'Zip selection' context menu button + taskItems = taskItems.filter(item => { + return item.taskId !== FileTasks.ZIP_ARCHIVER_ZIP_TASK_ID && + item.taskId !== FileTasks.ZIP_ARCHIVER_ZIP_USING_TMP_TASK_ID; + }); + + fulfill(FileTasks.annotateTasks_(assert(taskItems), entries)); + }); + }); + + const defaultTaskPromise = tasksPromise.then(tasks => { + return FileTasks.getDefaultTask(tasks, taskHistory); + }); + + return Promise.all([tasksPromise, defaultTaskPromise]).then(args => { + return new FileTasks( + volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, + args[0], args[1], taskHistory, namingController, crostini); + }); + } + + /** + * Gets task items. + * @return {!Array<!chrome.fileManagerPrivate.FileTask>} + */ + getTaskItems() { + return this.tasks_; + } + + /** + * Gets tasks which are categorized as OPEN tasks. + * @return {!Array<!chrome.fileManagerPrivate.FileTask>} + */ + getOpenTaskItems() { + return this.tasks_.filter(FileTasks.isOpenTask); + } + + /** + * Gets tasks which are not categorized as OPEN tasks. + * @return {!Array<!chrome.fileManagerPrivate.FileTask>} + */ + getNonOpenTaskItems() { + return this.tasks_.filter(task => !FileTasks.isOpenTask(task)); + } + + /** + * Opens the suggest file dialog. + * + * @param {function()} onSuccess Success callback. + * @param {function()} onCancelled User-cancelled callback. + * @param {function()} onFailure Failure callback. + */ + openSuggestAppsDialog(onSuccess, onCancelled, onFailure) { + if (this.entries_.length !== 1) { + onFailure(); + return; + } + + const entry = this.entries_[0]; + const mimeType = this.mimeTypes_[0]; + const basename = entry.name; + const splitted = util.splitExtension(basename); + const extension = splitted[1]; + + // Returns with failure if the file has neither extension nor MIME type. + if (!extension && !mimeType) { + onFailure(); + return; + } + + const onDialogClosed = (result, itemId) => { + switch (result) { + case SuggestAppsDialog.Result.SUCCESS: + onSuccess(); + break; + case SuggestAppsDialog.Result.FAILED: + onFailure(); + break; + default: + onCancelled(); + } + }; + + this.ui_.suggestAppsDialog.showByExtensionAndMime( + extension, mimeType, onDialogClosed); + } + + /** + * Returns whether the system is currently offline. + * + * @param {!VolumeManager} volumeManager + * @return {boolean} True if the network status is offline. + * @private + */ + static isOffline_(volumeManager) { + const connection = volumeManager.getDriveConnectionState(); + return connection.type == VolumeManagerCommon.DriveConnectionType.OFFLINE && + connection.reason == + VolumeManagerCommon.DriveConnectionReason.NO_NETWORK; + } + + /** + * Records a metric, as well as recording online and offline versions of it. + * + * @param {!VolumeManager} volumeManager + * @param {string} name Metric name. + * @param {!*} value Enum value. + * @param {!Array<*>} values Array of valid values. + */ + static recordEnumWithOnlineAndOffline_(volumeManager, name, value, values) { + metrics.recordEnum(name, value, values); + if (FileTasks.isOffline_(volumeManager)) { + metrics.recordEnum(name + '.Offline', value, values); + } else { + metrics.recordEnum(name + '.Online', value, values); + } + } + + /** + * Records trial of opening file grouped by extensions. + * + * @param {!VolumeManager} volumeManager + * @param {Array<!Entry>} entries The entries to be opened. + * @private + */ + static recordViewingFileTypeUMA_(volumeManager, entries) { + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + let extension = FileType.getExtension(entry).toLowerCase(); + if (FileTasks.UMA_INDEX_KNOWN_EXTENSIONS.indexOf(extension) < 0) { + extension = 'other'; + } + FileTasks.recordEnumWithOnlineAndOffline_( + volumeManager, 'ViewingFileType', extension, + FileTasks.UMA_INDEX_KNOWN_EXTENSIONS); + } + } + + /** + * Records trial of opening file grouped by root types. + * + * @param {!VolumeManager} volumeManager + * @param {?VolumeManagerCommon.RootType} rootType The type of the root where + * entries are being opened. + * @private + */ + static recordViewingRootTypeUMA_(volumeManager, rootType) { + if (rootType !== null) { + FileTasks.recordEnumWithOnlineAndOffline_( + volumeManager, 'ViewingRootType', rootType, + VolumeManagerCommon.RootTypesForUMA); + } + } + + static recordZipHandlerUMA_(taskId) { + if (FileTasks.UMA_ZIP_HANDLER_TASK_IDS_.indexOf(taskId) != -1) { + metrics.recordEnum( + 'ZipFileTask', taskId, FileTasks.UMA_ZIP_HANDLER_TASK_IDS_); + } + } + + /** + * Records the type of dialog shown when using a crostini app to open a file. + * @param {!FileTasks.CrostiniShareDialogType} dialogType + * @private + */ + static recordCrostiniShareDialogTypeUMA_(dialogType) { + metrics.recordEnum( + 'CrostiniShareDialog', dialogType, + FileTasks.UMA_CROSTINI_SHARE_DIALOG_TYPES_); + } + + /** + * Returns true if the taskId is for an internal task. + * + * @param {string} taskId Task identifier. + * @return {boolean} True if the task ID is for an internal task. + * @private + */ + static isInternalTask_(taskId) { + const taskParts = taskId.split('|'); + const appId = taskParts[0]; + const taskType = taskParts[1]; + const actionId = taskParts[2]; + return ( + appId === chrome.runtime.id && taskType === 'app' && + (actionId === 'mount-archive' || actionId === 'install-linux-package')); + } + + /** + * Returns true if the given task is categorized as an OPEN task. + * + * @param {!chrome.fileManagerPrivate.FileTask} task + * @return {boolean} True if the given task is an OPEN task. + */ + static isOpenTask(task) { + // We consider following types of tasks as OPEN tasks. + // - Files app's internal tasks + // - file_handler tasks with OPEN_WITH verb + return !task.verb || task.verb == chrome.fileManagerPrivate.Verb.OPEN_WITH; + } + + /** + * Annotates tasks returned from the API. + * + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks Input tasks from + * the API. + * @param {!Array<!Entry>} entries List of entries for the tasks. + * @return {!Array<!chrome.fileManagerPrivate.FileTask>} Annotated tasks. + * @private + */ + static annotateTasks_(tasks, entries) { + const result = []; + const id = chrome.runtime.id; + for (let i = 0; i < tasks.length; i++) { + const task = tasks[i]; + const taskParts = task.taskId.split('|'); + + // Skip internal Files app's handlers. + if (taskParts[0] === id && + (taskParts[2] === 'select' || taskParts[2] === 'open')) { + continue; + } + + // Tweak images, titles of internal tasks. + if (taskParts[0] === id && taskParts[1] === 'app') { + if (taskParts[2] === 'mount-archive') { + task.iconType = 'archive'; + task.title = loadTimeData.getString('MOUNT_ARCHIVE'); + task.verb = undefined; + } else if (taskParts[2] === 'open-hosted-generic') { + if (entries.length > 1) { + task.iconType = 'generic'; + } else { // Use specific icon. + task.iconType = FileType.getIcon(entries[0]); + } + task.title = loadTimeData.getString('TASK_OPEN'); + task.verb = undefined; + } else if (taskParts[2] === 'open-hosted-gdoc') { + task.iconType = 'gdoc'; + task.title = loadTimeData.getString('TASK_OPEN_GDOC'); + task.verb = undefined; + } else if (taskParts[2] === 'open-hosted-gsheet') { + task.iconType = 'gsheet'; + task.title = loadTimeData.getString('TASK_OPEN_GSHEET'); + task.verb = undefined; + } else if (taskParts[2] === 'open-hosted-gslides') { + task.iconType = 'gslides'; + task.title = loadTimeData.getString('TASK_OPEN_GSLIDES'); + task.verb = undefined; + } else if (taskParts[2] === 'install-linux-package') { + task.iconType = 'crostini'; + task.title = loadTimeData.getString('TASK_INSTALL_LINUX_PACKAGE'); + task.verb = undefined; + } else if (taskParts[2] === 'view-swf') { + // Do not render this task if disabled. + if (!loadTimeData.getBoolean('SWF_VIEW_ENABLED')) { + continue; + } + task.iconType = 'generic'; + task.title = loadTimeData.getString('TASK_VIEW'); + task.verb = undefined; + } else if (taskParts[2] === 'view-pdf') { + // Do not render this task if disabled. + if (!loadTimeData.getBoolean('PDF_VIEW_ENABLED')) { + continue; + } + task.iconType = 'pdf'; + task.title = loadTimeData.getString('TASK_VIEW'); + task.verb = undefined; + } else if (taskParts[2] === 'view-in-browser') { + task.iconType = 'generic'; + task.title = loadTimeData.getString('TASK_VIEW'); + task.verb = undefined; + } + } + if (!task.iconType && taskParts[1] === 'web-intent') { + task.iconType = 'generic'; + } + + // Add verb to title. + if (task.verb) { + let verbButtonLabel = ''; + switch (task.verb) { + case chrome.fileManagerPrivate.Verb.ADD_TO: + verbButtonLabel = 'ADD_TO_VERB_BUTTON_LABEL'; + break; + case chrome.fileManagerPrivate.Verb.PACK_WITH: + verbButtonLabel = 'PACK_WITH_VERB_BUTTON_LABEL'; + break; + case chrome.fileManagerPrivate.Verb.SHARE_WITH: + // Even when the task has SHARE_WITH verb, we don't prefix the title + // with "Share with" when the task is from SEND/SEND_MULTIPLE intent + // handlers from Android apps, since the title can already have an + // appropriate verb. + if (!(taskParts[1] == 'arc' && + (taskParts[2] == 'send' || + taskParts[2] == 'send_multiple'))) { + verbButtonLabel = 'SHARE_WITH_VERB_BUTTON_LABEL'; + } + break; + case chrome.fileManagerPrivate.Verb.OPEN_WITH: + verbButtonLabel = 'OPEN_WITH_VERB_BUTTON_LABEL'; + break; + default: + console.error('Invalid task verb: ' + task.verb + '.'); + } + if (verbButtonLabel) { + task.label = loadTimeData.getStringF(verbButtonLabel, task.title); + } + } + + result.push(task); + } + + return result; + } + + /** + * @param {!Entry} entry + * @param {!VolumeManager} volumeManager + * @return {boolean} True if the entry is from crostini. + */ + static isCrostiniEntry(entry, volumeManager) { + return volumeManager.getLocationInfo(entry).rootType === + VolumeManagerCommon.RootType.CROSTINI; + } + + /** + * Returns true if task requires entries to be shared before executing task. + * @param {!chrome.fileManagerPrivate.FileTask} task Task to run. + * @return {boolean} true if task requires entries to be shared. + */ + static taskRequiresCrostiniSharing(task) { + const taskParts = task.taskId.split('|'); + const taskType = taskParts[1]; + const actionId = taskParts[2]; + return taskType === 'crostini' || actionId === 'install-linux-package'; + } + + /** + * Checks if task is a crostini task and all entries are accessible to, or can + * be shared with crostini. Shares files as required if possible and invokes + * callback, or shows Unable to Open error dialog and does not invoke + * callback. + * @param {!chrome.fileManagerPrivate.FileTask} task Task to run. + * @param {function()} callback Callback is called when all files (if any) are + * accessible to crostini, else error dialog is shown. + * @private + */ + maybeShareWithCrostiniOrShowDialog_(task, callback) { + // Check if this is a crostini task. + if (!FileTasks.taskRequiresCrostiniSharing(task)) { + return callback(); + } + + let showUnableToOpen = false; + const entriesToShare = []; + + for (let i = 0; i < this.entries_.length; i++) { + const entry = this.entries_[i]; + if (FileTasks.isCrostiniEntry(entry, this.volumeManager_) || + this.crostini_.isPathShared(constants.DEFAULT_CROSTINI_VM, entry)) { + continue; + } + if (!this.crostini_.canSharePath( + constants.DEFAULT_CROSTINI_VM, entry, false /* persist */)) { + showUnableToOpen = true; + break; + } + entriesToShare.push(entry); + } + + // Show unable to open alert dialog. + if (showUnableToOpen) { + this.ui_.alertDialog.showHtml( + strf('UNABLE_TO_OPEN_CROSTINI_TITLE', task.title), + strf('UNABLE_TO_OPEN_CROSTINI', task.title)); + FileTasks.recordCrostiniShareDialogTypeUMA_( + FileTasks.CrostiniShareDialogType.UnableToOpen); + return; + } + + // No sharing required. + if (entriesToShare.length === 0) { + FileTasks.recordCrostiniShareDialogTypeUMA_( + FileTasks.CrostiniShareDialogType.None); + return callback(); + } + + // Share then invoke callback. + FileTasks.recordCrostiniShareDialogTypeUMA_( + FileTasks.CrostiniShareDialogType.ShareBeforeOpen); + // Set persist to false when sharing paths to open with a crostini app. + chrome.fileManagerPrivate.sharePathsWithCrostini( + constants.DEFAULT_CROSTINI_VM, entriesToShare, false /* persist */, + () => { + // It is unexpected to get an error sharing any files since we have + // already validated that all selected files can be shared. + // But if it happens, log error, and do not execute callback. + if (chrome.runtime.lastError) { + return console.error( + 'Error sharing with linux to execute: ' + + chrome.runtime.lastError.message); + } + // crbug.com/925973. Do not register non-persisted shared paths since + // we can't be sure at any time that the VM has not restarted and they + // are still shared. + callback(); + }); + } + + /** + * Executes default task. + * + * @param {function(boolean, Array<!Entry>)=} opt_callback Called when the + * default task is executed, or the error is occurred. + */ + executeDefault(opt_callback) { + FileTasks.recordViewingFileTypeUMA_(this.volumeManager_, this.entries_); + FileTasks.recordViewingRootTypeUMA_( + this.volumeManager_, this.directoryModel_.getCurrentRootType()); + this.executeDefaultInternal_(opt_callback); + } + + /** + * Executes default task. + * + * @param {function(boolean, Array<!Entry>)=} opt_callback Called when the + * default task is executed, or the error is occurred. + * @private + */ + executeDefaultInternal_(opt_callback) { + const callback = opt_callback || ((arg1, arg2) => {}); + + if (this.defaultTask_ !== null) { + this.executeInternal_(this.defaultTask_); + callback(true, this.entries_); + return; + } + + const nonGenericTasks = this.tasks_.filter(t => !t.isGenericFileHandler); + // If there is only one task that is not a generic file handler, it should + // be executed as a default task. If there are multiple tasks that are not + // generic file handlers, and none of them are considered as default, we + // show a task picker to ask the user to choose one. + if (nonGenericTasks.length >= 2) { + this.showTaskPicker( + this.ui_.defaultTaskPicker, str('OPEN_WITH_BUTTON_LABEL'), + '', task => { + this.execute(task); + }, FileTasks.TaskPickerType.OpenWith); + return; + } + + // We don't have tasks, so try to show a file in a browser tab. + // We only do that for single selection to avoid confusion. + if (this.entries_.length !== 1) { + return; + } + + const filename = this.entries_[0].name; + const extension = util.splitExtension(filename)[1] || null; + const mimeType = this.mimeTypes_[0] || null; + + const showAlert = () => { + let textMessageId; + let titleMessageId; + switch (extension) { + case '.exe': + case '.msi': + textMessageId = 'NO_TASK_FOR_EXECUTABLE'; + break; + case '.dmg': + textMessageId = 'NO_TASK_FOR_DMG'; + break; + case '.crx': + textMessageId = 'NO_TASK_FOR_CRX'; + titleMessageId = 'NO_TASK_FOR_CRX_TITLE'; + break; + default: + textMessageId = 'NO_TASK_FOR_FILE'; + } + + const webStoreUrl = webStoreUtils.createWebStoreLink(extension, mimeType); + const text = + strf(textMessageId, webStoreUrl, str('NO_TASK_FOR_FILE_URL')); + const title = titleMessageId ? str(titleMessageId) : filename; + this.ui_.alertDialog.showHtml(title, text, null, null, null); + callback(false, this.entries_); + }; + + const onViewFilesFailure = () => { + if (extension && + (FileTasks.EXTENSIONS_TO_SKIP_SUGGEST_APPS_.indexOf(extension) !== + -1 || + constants.EXECUTABLE_EXTENSIONS.indexOf(assert(extension)) !== -1)) { + showAlert(); + return; + } + + this.openSuggestAppsDialog( + () => { + FileTasks + .create( + this.volumeManager_, this.metadataModel_, + this.directoryModel_, this.ui_, this.entries_, + this.mimeTypes_, this.taskHistory_, this.namingController_, + this.crostini_) + .then( + tasks => { + tasks.executeDefault(); + callback(true, this.entries_); + }, + () => { + callback(false, this.entries_); + }); + }, + () => { + callback(false, this.entries_); + }, + showAlert); + }; + + const onViewFiles = result => { + switch (result) { + case 'opened': + callback(true, this.entries_); + break; + case 'message_sent': + util.isTeleported(window).then(teleported => { + if (teleported) { + this.ui_.showOpenInOtherDesktopAlert(this.entries_); + } + }); + callback(true, this.entries_); + break; + case 'empty': + callback(true, this.entries_); + break; + case 'failed': + // Suppress the Unchecked runtime.lastError console message + if (chrome.runtime.lastError) { + console.debug(chrome.runtime.lastError.message); + } + onViewFilesFailure(); + break; + } + }; + + this.checkAvailability_(() => { + const taskId = chrome.runtime.id + '|file|view-in-browser'; + chrome.fileManagerPrivate.executeTask(taskId, this.entries_, onViewFiles); + }); + } + + /** + * Executes a single task. + * + * @param {chrome.fileManagerPrivate.FileTask} task FileTask. + */ + execute(task) { + FileTasks.recordViewingFileTypeUMA_(this.volumeManager_, this.entries_); + FileTasks.recordViewingRootTypeUMA_( + this.volumeManager_, this.directoryModel_.getCurrentRootType()); + this.executeInternal_(task); + } + + /** + * The core implementation to execute a single task. + * + * @param {chrome.fileManagerPrivate.FileTask} task FileTask. + * @private + */ + executeInternal_(task) { + this.checkAvailability_(() => { + this.maybeShareWithCrostiniOrShowDialog_(task, () => { + this.taskHistory_.recordTaskExecuted(task.taskId); + let msg; + if (this.entries.length === 1) { + msg = strf('OPEN_A11Y', this.entries_[0].name); + } else { + msg = strf('OPEN_A11Y_PLURAL', this.entries_.length); + } + this.ui_.speakA11yMessage(msg); + if (FileTasks.isInternalTask_(task.taskId)) { + this.executeInternalTask_(task.taskId); + } else { + FileTasks.recordZipHandlerUMA_(task.taskId); + chrome.fileManagerPrivate.executeTask( + task.taskId, this.entries_, (result) => { + if (result !== 'message_sent') { + return; + } + util.isTeleported(window).then((teleported) => { + if (teleported) { + this.ui_.showOpenInOtherDesktopAlert(this.entries_); + } + }); + }); + } + }); + }); + } + + /** + * Ensures that the all files are available right now. + * + * Must not call before initialization. + * @param {function()} callback Called when checking is completed and all + * files are available. Otherwise not called. + * @private + */ + checkAvailability_(callback) { + const areAll = (entries, props, name) => { + // TODO(cmihail): Make files in directories available offline. + // See http://crbug.com/569767. + let okEntriesNum = 0; + for (let i = 0; i < entries.length; i++) { + // If got no properties, we safely assume that item is available. + if (props[i] && (props[i][name] || entries[i].isDirectory)) { + okEntriesNum++; + } + } + return okEntriesNum === props.length; + }; + + const containsDriveEntries = this.entries_.some(entry => { + const volumeInfo = this.volumeManager_.getVolumeInfo(entry); + return volumeInfo && + volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE; + }); + + // Availability is not checked for non-Drive files, as availableOffline, nor + // availableWhenMetered are not exposed for other types of volumes at this + // moment. + if (!containsDriveEntries) { + callback(); + return; + } + + const isDriveOffline = + this.volumeManager_.getDriveConnectionState().type === + VolumeManagerCommon.DriveConnectionType.OFFLINE; + + if (isDriveOffline) { + this.metadataModel_.get(this.entries_, ['availableOffline', 'hosted']) + .then(props => { + if (areAll(this.entries_, props, 'availableOffline')) { + callback(); + return; + } + + this.ui_.alertDialog.showHtml( + loadTimeData.getString('OFFLINE_HEADER'), + props[0].hosted ? + loadTimeData.getStringF( + this.entries_.length === 1 ? + 'HOSTED_OFFLINE_MESSAGE' : + 'HOSTED_OFFLINE_MESSAGE_PLURAL') : + loadTimeData.getStringF( + this.entries_.length === 1 ? 'OFFLINE_MESSAGE' : + 'OFFLINE_MESSAGE_PLURAL', + loadTimeData.getString('OFFLINE_COLUMN_LABEL')), + null, null, null); + }); + return; + } + + const isOnMetered = this.volumeManager_.getDriveConnectionState().type === + VolumeManagerCommon.DriveConnectionType.METERED; + + if (isOnMetered) { + this.metadataModel_.get(this.entries_, ['availableWhenMetered', 'size']) + .then(props => { + if (areAll(this.entries_, props, 'availableWhenMetered')) { + callback(); + return; + } + + let sizeToDownload = 0; + for (let i = 0; i !== this.entries_.length; i++) { + if (!props[i].availableWhenMetered) { + sizeToDownload += props[i].size; + } + } + this.ui_.confirmDialog.show( + loadTimeData.getStringF( + this.entries_.length === 1 ? + 'CONFIRM_MOBILE_DATA_USE' : + 'CONFIRM_MOBILE_DATA_USE_PLURAL', + util.bytesToString(sizeToDownload)), + callback, null, null); + }); + return; + } + + callback(); + } + + /** + * Executes an internal task. + * + * @param {string} taskId The task id. + * @private + */ + executeInternalTask_(taskId) { + const taskParts = taskId.split('|'); + if (taskParts[2] === 'mount-archive') { + this.mountArchivesInternal_(); + return; + } + if (taskParts[2] === 'install-linux-package') { + this.installLinuxPackageInternal_(); + return; + } + + console.error('The specified task is not a valid internal task: ' + taskId); + } + + /** + * Install a Linux Package in the Linux container. + * @private + */ + installLinuxPackageInternal_() { + assert(this.entries_.length === 1); + this.ui_.installLinuxPackageDialog.showInstallLinuxPackageDialog( + this.entries_[0]); + } + + /** + * The core implementation of mounts archives. + * @private + */ + mountArchivesInternal_() { + const tracker = this.directoryModel_.createDirectoryChangeTracker(); + tracker.start(); + + // TODO(mtomasz): Move conversion from entry to url to custom bindings. + // crbug.com/345527. + const urls = util.entriesToURLs(this.entries_); + for (let index = 0; index < urls.length; ++index) { + // TODO(mtomasz): Pass Entry instead of URL. + this.volumeManager_.mountArchive(urls[index], volumeInfo => { + if (tracker.hasChanged) { + tracker.stop(); + return; + } + volumeInfo.resolveDisplayRoot( + displayRoot => { + if (tracker.hasChanged) { + tracker.stop(); + return; + } + this.directoryModel_.changeDirectoryEntry(displayRoot); + }, + () => { + console.warn( + 'Failed to resolve the display root after mounting.'); + tracker.stop(); + }); + }, ((url, error) => { + tracker.stop(); + const path = util.extractFilePath(url); + const namePos = path.lastIndexOf('/'); + this.ui_.alertDialog.show( + strf('ARCHIVE_MOUNT_FAILED', path.substr(namePos + 1), error), + null, null); + }).bind(null, urls[index])); + } + } + + /** + * Displays the list of tasks in a open task picker combobutton and a share + * options menu. + * + * @param {!cr.ui.ComboButton} openCombobutton The open task picker + * combobutton. + * @param {!cr.ui.MultiMenuButton} shareMenuButton Button for share options. + * @public + */ + display(openCombobutton, shareMenuButton) { + const openTasks = []; + const otherTasks = []; + for (let i = 0; i < this.tasks_.length; i++) { + const task = this.tasks_[i]; + if (FileTasks.isOpenTask(task)) { + openTasks.push(task); + } else { + otherTasks.push(task); + } + } + this.updateOpenComboButton_(openCombobutton, openTasks); + this.updateShareMenuButton_(shareMenuButton, otherTasks); + } + + /** + * Setup a task picker combobutton based on the given tasks. + * @param {!cr.ui.ComboButton} combobutton + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks + */ + updateOpenComboButton_(combobutton, tasks) { + combobutton.hidden = tasks.length == 0; + if (tasks.length == 0) { + return; + } + + combobutton.clear(); + + // If there exist defaultTask show it on the combobutton. + if (this.defaultTask_) { + combobutton.defaultItem = + FileTasks.createComboButtonItem_(this.defaultTask_, str('TASK_OPEN')); + } else { + combobutton.defaultItem = { + type: FileTasks.TaskMenuButtonItemType.ShowMenu, + label: str('OPEN_WITH_BUTTON_LABEL') + }; + } + + // If there exist 2 or more available tasks, show them in context menu + // (including defaultTask). If only one generic task is available, we + // also show it in the context menu. + const items = this.createItems_(tasks); + if (items.length > 1 || + (items.length === 1 && this.defaultTask_ === null)) { + for (let j = 0; j < items.length; j++) { + combobutton.addDropDownItem(items[j]); + } + + // If there exist non generic task (i.e. defaultTask is set), we show + // an item to change default task. + if (this.defaultTask_) { + combobutton.addSeparator(); + const changeDefaultMenuItem = combobutton.addDropDownItem({ + type: FileTasks.TaskMenuButtonItemType.ChangeDefaultTask, + label: loadTimeData.getString('CHANGE_DEFAULT_MENU_ITEM') + }); + changeDefaultMenuItem.classList.add('change-default'); + } + } + } + + /** + * Setup a menu button for sharing options based on the given tasks. + * @param {!cr.ui.MultiMenuButton} shareMenuButton + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks + */ + updateShareMenuButton_(shareMenuButton, tasks) { + let driveShareCommand = + shareMenuButton.menu.querySelector('cr-menu-item[command="#share"]'); + let driveShareCommandSeparator = + shareMenuButton.menu.querySelector('#drive-share-separator'); + let moreActionsSeparator = + shareMenuButton.menu.querySelector('#more-actions-separator'); + + // Hide share icon for New Folder creation. See https://crbug.com/571355. + shareMenuButton.hidden = + (driveShareCommand.disabled && tasks.length == 0) || + this.namingController_.isRenamingInProgress(); + moreActionsSeparator.hidden = true; + + // Show the separator if Drive share command is enabled and there is at + // least one other share actions. + driveShareCommandSeparator.hidden = + driveShareCommand.disabled || tasks.length == 0; + + // Temporarily remove the more actions item while the rest of the menu + // items are being cleared out so we don't lose it and make it hidden for + // now + let moreActions = shareMenuButton.menu.querySelector( + 'cr-menu-item[command="#show-submenu"]'); + moreActions.remove(); + moreActions.setAttribute('hidden', ''); + // Remove the separator as well + moreActionsSeparator.remove(); + + // Clear menu items except for drive share menu and a separator for it. + // As querySelectorAll() returns live NodeList, we need to copy elements to + // Array object to modify DOM in the for loop. + const itemsToRemove = [].slice.call(shareMenuButton.menu.querySelectorAll( + 'cr-menu-item:not([command="#share"])')); + for (let i = 0; i < itemsToRemove.length; i++) { + const item = itemsToRemove[i]; + item.parentNode.removeChild(item); + } + // Clear menu items in the overflow sub-menu since we'll repopulate it + // with any relevant items below. + if (shareMenuButton.overflow !== null) { + while (shareMenuButton.overflow.firstChild !== null) { + shareMenuButton.overflow.removeChild( + shareMenuButton.overflow.firstChild); + } + } + + // Add menu items for the new tasks. + const items = this.createItems_(tasks); + let menu = /** @type {!cr.ui.Menu} */ (shareMenuButton.menu); + for (let i = 0; i < items.length; i++) { + // If we have at least 10 entries, split off into a sub-menu + if (i == NUM_TOP_LEVEL_ENTRIES && MAX_NON_SPLIT_ENTRIES <= items.length) { + moreActions.removeAttribute('hidden'); + moreActionsSeparator.hidden = false; + menu = shareMenuButton.overflow; + } + const menuitem = menu.addMenuItem(items[i]); + cr.ui.decorate(menuitem, cr.ui.FilesMenuItem); + menuitem.data = items[i]; + if (items[i].iconType) { + menuitem.style.backgroundImage = ''; + menuitem.setAttribute('file-type-icon', items[i].iconType); + } + } + // Replace the more actions menu item and separator + shareMenuButton.menu.appendChild(moreActionsSeparator); + shareMenuButton.menu.appendChild(moreActions); + } + + /** + * Creates sorted array of available task descriptions such as title and icon. + * + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks Tasks to create + * items. + * @return {!Array<!FileTasks.ComboButtonItem>} Created array can be used to + * feed combobox, menus and so on. + * @private + */ + createItems_(tasks) { + const items = []; + + // Create items. + for (let index = 0; index < tasks.length; index++) { + const task = tasks[index]; + if (task === this.defaultTask_) { + const title = + task.title + ' ' + loadTimeData.getString('DEFAULT_TASK_LABEL'); + items.push(FileTasks.createComboButtonItem_(task, title, true, true)); + } else { + items.push(FileTasks.createComboButtonItem_(task)); + } + } + + // Sort items (Sort order: isDefault, lastExecutedTime, label). + items.sort((a, b) => { + // Sort by isDefaultTask. + const isDefault = (b.isDefault ? 1 : 0) - (a.isDefault ? 1 : 0); + if (isDefault !== 0) { + return isDefault; + } + + // Sort by last-executed time. + const aTime = this.taskHistory_.getLastExecutedTime(a.task.taskId); + const bTime = this.taskHistory_.getLastExecutedTime(b.task.taskId); + if (aTime != bTime) { + return bTime - aTime; + } + + // Sort by label. + return a.label.localeCompare(b.label); + }); + + return items; + } + + /** + * Creates combobutton item based on task. + * + * @param {!chrome.fileManagerPrivate.FileTask} task Task to convert. + * @param {string=} opt_title Title. + * @param {boolean=} opt_bold Make a menu item bold. + * @param {boolean=} opt_isDefault Mark the item as default item. + * @return {!FileTasks.ComboButtonItem} Item appendable to combobutton + * drop-down list. + * @private + */ + static createComboButtonItem_(task, opt_title, opt_bold, opt_isDefault) { + return { + type: FileTasks.TaskMenuButtonItemType.RunTask, + label: opt_title || task.label || task.title, + iconUrl: task.iconUrl || '', + iconType: task.iconType || '', + task: task, + bold: opt_bold || false, + isDefault: opt_isDefault || false, + isGenericFileHandler: /** @type {boolean} */ (task.isGenericFileHandler) + }; + } + + /** + * Shows modal task picker dialog with currently available list of tasks. + * + * @param {cr.filebrowser.DefaultTaskDialog} taskDialog Task dialog to show + * and update. + * @param {string} title Title to use. + * @param {string} message Message to use. + * @param {function(!chrome.fileManagerPrivate.FileTask)} onSuccess Callback + * to pass selected task. + * @param {FileTasks.TaskPickerType} pickerType Task picker type. + */ + showTaskPicker(taskDialog, title, message, onSuccess, pickerType) { + const tasks = pickerType == FileTasks.TaskPickerType.MoreActions ? + this.getNonOpenTaskItems() : + this.getOpenTaskItems(); + let items = this.createItems_(tasks); + if (pickerType == FileTasks.TaskPickerType.ChangeDefault) { + items = items.filter(item => !item.isGenericFileHandler); + } + + let defaultIdx = 0; + for (let j = 0; j < items.length; j++) { + if (this.defaultTask_ && + items[j].task.taskId === this.defaultTask_.taskId) { + defaultIdx = j; + } + } + + taskDialog.showDefaultTaskDialog( + title, message, items, defaultIdx, item => { + onSuccess(item.task); + }); + } + + /** + * Gets the default task from tasks. In case there is no such task (i.e. all + * tasks are generic file handlers), then return null. + * + * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks The list of + * tasks from where to choose the default task. + * @param {!TaskHistory} taskHistory + * @return {?chrome.fileManagerPrivate.FileTask} the default task, or null if + * no default task found. + */ + static getDefaultTask(tasks, taskHistory) { + // 1. Default app set for MIME or file extension by user, or built-in app. + for (let i = 0; i < tasks.length; i++) { + if (tasks[i].isDefault) { + return tasks[i]; + } + } + const nonGenericTasks = tasks.filter(t => !t.isGenericFileHandler); + // 2. Most recently executed non-generic task. + const latest = nonGenericTasks[0]; + if (latest && taskHistory.getLastExecutedTime(latest.taskId)) { + return latest; + } + // 3. Sole non-generic handler. + if (nonGenericTasks.length == 1) { + return nonGenericTasks[0]; + } + return null; + } +} /** * The app ID of the video player app. - * @const - * @type {string} + * @const {string} */ FileTasks.VIDEO_PLAYER_ID = 'jcgeabjmjgoblfofpppfkcoakmfobdko'; /** * The task id of the zip unpacker app. - * @const - * @type {string} + * @const {string} */ FileTasks.ZIP_UNPACKER_TASK_ID = 'oedeeodfidgoollimchfdnbmhcpnklnd|app|zip'; /** * The task id of unzip action of Zip Archiver app. - * @const - * @type {string} + * @const {string} */ FileTasks.ZIP_ARCHIVER_UNZIP_TASK_ID = 'dmboannefpncccogfdikhmhpmdnddgoe|app|open'; /** * The task id of zip action of Zip Archiver app. - * @const - * @type {string} + * @const {string} */ FileTasks.ZIP_ARCHIVER_ZIP_TASK_ID = 'dmboannefpncccogfdikhmhpmdnddgoe|app|pack'; /** * The task id of zip action of Zip Archiver app, using temporary dir as workdir - * @const - * @type {string} + * @const {string} */ FileTasks.ZIP_ARCHIVER_ZIP_USING_TMP_TASK_ID = 'dmboannefpncccogfdikhmhpmdnddgoe|app|pack_using_tmp'; @@ -159,158 +1228,12 @@ }; /** - * Creates an instance of FileTasks for the specified list of entries with mime - * types. - * - * @param {!VolumeManager} volumeManager - * @param {!MetadataModel} metadataModel - * @param {!DirectoryModel} directoryModel - * @param {!FileManagerUI} ui - * @param {!Array<!Entry>} entries - * @param {!Array<?string>} mimeTypes - * @param {!TaskHistory} taskHistory - * @param {!NamingController} namingController - * @param {!Crostini} crostini - * @return {!Promise<!FileTasks>} - */ -FileTasks.create = - (volumeManager, metadataModel, directoryModel, ui, entries, mimeTypes, - taskHistory, namingController, crostini) => { - const tasksPromise = new Promise(fulfill => { - // getFileTasks supports only native entries. - entries = entries.filter(util.isNativeEntry); - if (entries.length === 0) { - fulfill([]); - return; - } - chrome.fileManagerPrivate.getFileTasks(entries, taskItems => { - if (chrome.runtime.lastError) { - console.error( - 'Failed to fetch file tasks due to: ' + - chrome.runtime.lastError.message); - Promise.reject(); - return; - } - - // Linux package installation is currently only supported for a single - // file which is inside the Linux container, or in a shareable volume. - // TODO(timloh): Instead of filtering these out, we probably should - // show a dialog with an error message, similar to when attempting to - // run Crostini tasks with non-Crostini entries. - if (entries.length !== 1 || - !(FileTasks.isCrostiniEntry(entries[0], volumeManager) || - crostini.canSharePath( - constants.DEFAULT_CROSTINI_VM, entries[0], - false /* persist */))) { - taskItems = taskItems.filter(item => { - const taskParts = item.taskId.split('|'); - const appId = taskParts[0]; - const taskType = taskParts[1]; - const actionId = taskParts[2]; - return !( - appId === chrome.runtime.id && taskType === 'app' && - actionId === 'install-linux-package'); - }); - } - - // Filters out Pack with Zip Archiver task because it will be - // accessible via 'Zip selection' context menu button - taskItems = taskItems.filter(item => { - return item.taskId !== FileTasks.ZIP_ARCHIVER_ZIP_TASK_ID && - item.taskId !== FileTasks.ZIP_ARCHIVER_ZIP_USING_TMP_TASK_ID; - }); - - fulfill(FileTasks.annotateTasks_(assert(taskItems), entries)); - }); - }); - - const defaultTaskPromise = tasksPromise.then(tasks => { - return FileTasks.getDefaultTask(tasks, taskHistory); - }); - - return Promise.all([tasksPromise, defaultTaskPromise]).then(args => { - return new FileTasks( - volumeManager, metadataModel, directoryModel, ui, entries, - mimeTypes, args[0], args[1], taskHistory, namingController, - crostini); - }); - }; - -/** - * Obtains the task items. - * @return {!Array<!chrome.fileManagerPrivate.FileTask>} - */ -FileTasks.prototype.getTaskItems = function() { - return this.tasks_; -}; - -/** - * Obtain tasks which are categorized as OPEN tasks. - * @return {!Array<!chrome.fileManagerPrivate.FileTask>} - */ -FileTasks.prototype.getOpenTaskItems = function() { - return this.tasks_.filter(FileTasks.isOpenTask); -}; - -/** - * Obtain tasks which are not categorized as OPEN tasks. - * @return {!Array<!chrome.fileManagerPrivate.FileTask>} - */ -FileTasks.prototype.getNonOpenTaskItems = function() { - return this.tasks_.filter(task => !FileTasks.isOpenTask(task)); -}; - -/** - * Opens the suggest file dialog. - * - * @param {function()} onSuccess Success callback. - * @param {function()} onCancelled User-cancelled callback. - * @param {function()} onFailure Failure callback. - */ -FileTasks.prototype.openSuggestAppsDialog = function( - onSuccess, onCancelled, onFailure) { - if (this.entries_.length !== 1) { - onFailure(); - return; - } - - const entry = this.entries_[0]; - const mimeType = this.mimeTypes_[0]; - const basename = entry.name; - const splitted = util.splitExtension(basename); - const extension = splitted[1]; - - // Returns with failure if the file has neither extension nor MIME type. - if (!extension && !mimeType) { - onFailure(); - return; - } - - const onDialogClosed = (result, itemId) => { - switch (result) { - case SuggestAppsDialog.Result.SUCCESS: - onSuccess(); - break; - case SuggestAppsDialog.Result.FAILED: - onFailure(); - break; - default: - onCancelled(); - } - }; - - this.ui_.suggestAppsDialog.showByExtensionAndMime( - extension, mimeType, onDialogClosed); -}; - -/** * The list of known extensions to record UMA. * Note: Because the data is recorded by the index, so new item shouldn't be * inserted. * Must match the ViewFileType entry in enums.xml. * - * @const - * @type {Array<string>} + * @const {Array<string>} */ FileTasks.UMA_INDEX_KNOWN_EXTENSIONS = Object.freeze([ 'other', '.3ga', '.3gp', @@ -340,9 +1263,7 @@ /** * The list of extensions to skip the suggest app dialog. - * @const - * @type {Array<string>} - * @private + * @private @const {Array<string>} */ FileTasks.EXTENSIONS_TO_SKIP_SUGGEST_APPS_ = Object.freeze([ '.crdownload', @@ -362,80 +1283,6 @@ ]); /** - * Returns whether the system is currently offline. - * - * @param {!VolumeManager} volumeManager - * @return {boolean} True if the network status is offline. - * @private - */ -FileTasks.isOffline_ = volumeManager => { - const connection = volumeManager.getDriveConnectionState(); - return connection.type == VolumeManagerCommon.DriveConnectionType.OFFLINE && - connection.reason == VolumeManagerCommon.DriveConnectionReason.NO_NETWORK; -}; - -/** - * Records a metric, as well as recording online and offline versions of it. - * - * @param {!VolumeManager} volumeManager - * @param {string} name Metric name. - * @param {!*} value Enum value. - * @param {!Array<*>} values Array of valid values. - */ -FileTasks.recordEnumWithOnlineAndOffline_ = - (volumeManager, name, value, values) => { - metrics.recordEnum(name, value, values); - if (FileTasks.isOffline_(volumeManager)) { - metrics.recordEnum(name + '.Offline', value, values); - } else { - metrics.recordEnum(name + '.Online', value, values); - } - }; - -/** - * Records trial of opening file grouped by extensions. - * - * @param {!VolumeManager} volumeManager - * @param {Array<!Entry>} entries The entries to be opened. - * @private - */ -FileTasks.recordViewingFileTypeUMA_ = (volumeManager, entries) => { - for (let i = 0; i < entries.length; i++) { - const entry = entries[i]; - let extension = FileType.getExtension(entry).toLowerCase(); - if (FileTasks.UMA_INDEX_KNOWN_EXTENSIONS.indexOf(extension) < 0) { - extension = 'other'; - } - FileTasks.recordEnumWithOnlineAndOffline_( - volumeManager, 'ViewingFileType', extension, - FileTasks.UMA_INDEX_KNOWN_EXTENSIONS); - } -}; - -/** - * Records trial of opening file grouped by root types. - * - * @param {!VolumeManager} volumeManager - * @param {?VolumeManagerCommon.RootType} rootType The type of the root where - * entries are being opened. - * @private - */ -FileTasks.recordViewingRootTypeUMA_ = (volumeManager, rootType) => { - if (rootType !== null) { - FileTasks.recordEnumWithOnlineAndOffline_( - volumeManager, 'ViewingRootType', rootType, - VolumeManagerCommon.RootTypesForUMA); - } -}; - -FileTasks.recordZipHandlerUMA_ = taskId => { - if (FileTasks.UMA_ZIP_HANDLER_TASK_IDS_.indexOf(taskId) != -1) { - metrics.recordEnum( - 'ZipFileTask', taskId, FileTasks.UMA_ZIP_HANDLER_TASK_IDS_); - } -}; - -/** * Crostini Share Dialog types. * Keep in sync with enums.xml FileManagerCrostiniShareDialogType. * @enum {string} @@ -456,686 +1303,13 @@ FileTasks.CrostiniShareDialogType.UnableToOpen, ]); - -/** - * Records the type of dialog shown when using a crostini app to open a file. - * @param {!FileTasks.CrostiniShareDialogType} dialogType - * @private - */ -FileTasks.recordCrostiniShareDialogTypeUMA_ = dialogType => { - metrics.recordEnum( - 'CrostiniShareDialog', dialogType, - FileTasks.UMA_CROSTINI_SHARE_DIALOG_TYPES_); -}; - -/** - * Returns true if the taskId is for an internal task. - * - * @param {string} taskId Task identifier. - * @return {boolean} True if the task ID is for an internal task. - * @private - */ -FileTasks.isInternalTask_ = taskId => { - const taskParts = taskId.split('|'); - const appId = taskParts[0]; - const taskType = taskParts[1]; - const actionId = taskParts[2]; - return ( - appId === chrome.runtime.id && taskType === 'app' && - (actionId === 'mount-archive' || actionId === 'install-linux-package')); -}; - -/** - * Returns true if the given task is categorized as an OPEN task. - * - * @param {!chrome.fileManagerPrivate.FileTask} task - * @return {boolean} True if the given task is an OPEN task. - */ -FileTasks.isOpenTask = task => { - // We consider following types of tasks as OPEN tasks. - // - Files app's internal tasks - // - file_handler tasks with OPEN_WITH verb - return !task.verb || task.verb == chrome.fileManagerPrivate.Verb.OPEN_WITH; -}; - -/** - * Annotates tasks returned from the API. - * - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks Input tasks from - * the API. - * @param {!Array<!Entry>} entries List of entries for the tasks. - * @return {!Array<!chrome.fileManagerPrivate.FileTask>} Annotated tasks. - * @private - */ -FileTasks.annotateTasks_ = (tasks, entries) => { - const result = []; - const id = chrome.runtime.id; - for (let i = 0; i < tasks.length; i++) { - const task = tasks[i]; - const taskParts = task.taskId.split('|'); - - // Skip internal Files app's handlers. - if (taskParts[0] === id && - (taskParts[2] === 'select' || taskParts[2] === 'open')) { - continue; - } - - // Tweak images, titles of internal tasks. - if (taskParts[0] === id && taskParts[1] === 'app') { - if (taskParts[2] === 'mount-archive') { - task.iconType = 'archive'; - task.title = loadTimeData.getString('MOUNT_ARCHIVE'); - task.verb = undefined; - } else if (taskParts[2] === 'open-hosted-generic') { - if (entries.length > 1) { - task.iconType = 'generic'; - } else { // Use specific icon. - task.iconType = FileType.getIcon(entries[0]); - } - task.title = loadTimeData.getString('TASK_OPEN'); - task.verb = undefined; - } else if (taskParts[2] === 'open-hosted-gdoc') { - task.iconType = 'gdoc'; - task.title = loadTimeData.getString('TASK_OPEN_GDOC'); - task.verb = undefined; - } else if (taskParts[2] === 'open-hosted-gsheet') { - task.iconType = 'gsheet'; - task.title = loadTimeData.getString('TASK_OPEN_GSHEET'); - task.verb = undefined; - } else if (taskParts[2] === 'open-hosted-gslides') { - task.iconType = 'gslides'; - task.title = loadTimeData.getString('TASK_OPEN_GSLIDES'); - task.verb = undefined; - } else if (taskParts[2] === 'install-linux-package') { - task.iconType = 'crostini'; - task.title = loadTimeData.getString('TASK_INSTALL_LINUX_PACKAGE'); - task.verb = undefined; - } else if (taskParts[2] === 'view-swf') { - // Do not render this task if disabled. - if (!loadTimeData.getBoolean('SWF_VIEW_ENABLED')) { - continue; - } - task.iconType = 'generic'; - task.title = loadTimeData.getString('TASK_VIEW'); - task.verb = undefined; - } else if (taskParts[2] === 'view-pdf') { - // Do not render this task if disabled. - if (!loadTimeData.getBoolean('PDF_VIEW_ENABLED')) { - continue; - } - task.iconType = 'pdf'; - task.title = loadTimeData.getString('TASK_VIEW'); - task.verb = undefined; - } else if (taskParts[2] === 'view-in-browser') { - task.iconType = 'generic'; - task.title = loadTimeData.getString('TASK_VIEW'); - task.verb = undefined; - } - } - if (!task.iconType && taskParts[1] === 'web-intent') { - task.iconType = 'generic'; - } - - // Add verb to title. - if (task.verb) { - let verbButtonLabel = ''; - switch (task.verb) { - case chrome.fileManagerPrivate.Verb.ADD_TO: - verbButtonLabel = 'ADD_TO_VERB_BUTTON_LABEL'; - break; - case chrome.fileManagerPrivate.Verb.PACK_WITH: - verbButtonLabel = 'PACK_WITH_VERB_BUTTON_LABEL'; - break; - case chrome.fileManagerPrivate.Verb.SHARE_WITH: - // Even when the task has SHARE_WITH verb, we don't prefix the title - // with "Share with" when the task is from SEND/SEND_MULTIPLE intent - // handlers from Android apps, since the title can already have an - // appropriate verb. - if (!(taskParts[1] == 'arc' && - (taskParts[2] == 'send' || taskParts[2] == 'send_multiple'))) { - verbButtonLabel = 'SHARE_WITH_VERB_BUTTON_LABEL'; - } - break; - case chrome.fileManagerPrivate.Verb.OPEN_WITH: - verbButtonLabel = 'OPEN_WITH_VERB_BUTTON_LABEL'; - break; - default: - console.error('Invalid task verb: ' + task.verb + '.'); - } - if (verbButtonLabel) { - task.label = loadTimeData.getStringF(verbButtonLabel, task.title); - } - } - - result.push(task); - } - - return result; -}; - -/** - * @param {!Entry} entry - * @param {!VolumeManager} volumeManager - * @return {boolean} True if the entry is from crostini. - */ -FileTasks.isCrostiniEntry = (entry, volumeManager) => { - return volumeManager.getLocationInfo(entry).rootType === - VolumeManagerCommon.RootType.CROSTINI; -}; - -/** - * Returns true if task requires entries to be shared before executing task. - * @param {!chrome.fileManagerPrivate.FileTask} task Task to run. - * @return {boolean} true if task requires entries to be shared. - */ -FileTasks.taskRequiresCrostiniSharing = task => { - const taskParts = task.taskId.split('|'); - const taskType = taskParts[1]; - const actionId = taskParts[2]; - return taskType === 'crostini' || actionId === 'install-linux-package'; -}; - -/** - * Checks if task is a crostini task and all entries are accessible to, or can - * be shared with crostini. Shares files as required if possible and invokes - * callback, or shows Unable to Open error dialog and does not invoke callback. - * @param {!chrome.fileManagerPrivate.FileTask} task Task to run. - * @param {function()} callback Callback is called when all files (if any) are - * accessible to crostini, else error dialog is shown. - * @private - */ -FileTasks.prototype.maybeShareWithCrostiniOrShowDialog_ = function( - task, callback) { - // Check if this is a crostini task. - if (!FileTasks.taskRequiresCrostiniSharing(task)) { - return callback(); - } - - let showUnableToOpen = false; - const entriesToShare = []; - - for (let i = 0; i < this.entries_.length; i++) { - const entry = this.entries_[i]; - if (FileTasks.isCrostiniEntry(entry, this.volumeManager_) || - this.crostini_.isPathShared(constants.DEFAULT_CROSTINI_VM, entry)) { - continue; - } - if (!this.crostini_.canSharePath( - constants.DEFAULT_CROSTINI_VM, entry, false /* persist */)) { - showUnableToOpen = true; - break; - } - entriesToShare.push(entry); - } - - // Show unable to open alert dialog. - if (showUnableToOpen) { - this.ui_.alertDialog.showHtml( - strf('UNABLE_TO_OPEN_CROSTINI_TITLE', task.title), - strf('UNABLE_TO_OPEN_CROSTINI', task.title)); - FileTasks.recordCrostiniShareDialogTypeUMA_( - FileTasks.CrostiniShareDialogType.UnableToOpen); - return; - } - - // No sharing required. - if (entriesToShare.length === 0) { - FileTasks.recordCrostiniShareDialogTypeUMA_( - FileTasks.CrostiniShareDialogType.None); - return callback(); - } - - // Share then invoke callback. - FileTasks.recordCrostiniShareDialogTypeUMA_( - FileTasks.CrostiniShareDialogType.ShareBeforeOpen); - // Set persist to false when sharing paths to open with a crostini app. - chrome.fileManagerPrivate.sharePathsWithCrostini( - constants.DEFAULT_CROSTINI_VM, entriesToShare, false /* persist */, - () => { - // It is unexpected to get an error sharing any files since we have - // already validated that all selected files can be shared. - // But if it happens, log error, and do not execute callback. - if (chrome.runtime.lastError) { - return console.error( - 'Error sharing with linux to execute: ' + - chrome.runtime.lastError.message); - } - // crbug.com/925973. Do not register non-persisted shared paths since - // we can't be sure at any time that the VM has not restarted and they - // are still shared. - callback(); - }); -}; - -/** - * Executes default task. - * - * @param {function(boolean, Array<!Entry>)=} opt_callback Called when the - * default task is executed, or the error is occurred. - */ -FileTasks.prototype.executeDefault = function(opt_callback) { - FileTasks.recordViewingFileTypeUMA_(this.volumeManager_, this.entries_); - FileTasks.recordViewingRootTypeUMA_( - this.volumeManager_, this.directoryModel_.getCurrentRootType()); - this.executeDefaultInternal_(opt_callback); -}; - -/** - * Executes default task. - * - * @param {function(boolean, Array<!Entry>)=} opt_callback Called when the - * default task is executed, or the error is occurred. - * @private - */ -FileTasks.prototype.executeDefaultInternal_ = function(opt_callback) { - const callback = opt_callback || ((arg1, arg2) => {}); - - if (this.defaultTask_ !== null) { - this.executeInternal_(this.defaultTask_); - callback(true, this.entries_); - return; - } - - const nonGenericTasks = this.tasks_.filter(t => !t.isGenericFileHandler); - // If there is only one task that is not a generic file handler, it should be - // executed as a default task. If there are multiple tasks that are not - // generic file handlers, and none of them are considered as default, we show - // a task picker to ask the user to choose one. - if (nonGenericTasks.length >= 2) { - this.showTaskPicker( - this.ui_.defaultTaskPicker, str('OPEN_WITH_BUTTON_LABEL'), '', task => { - this.execute(task); - }, FileTasks.TaskPickerType.OpenWith); - return; - } - - // We don't have tasks, so try to show a file in a browser tab. - // We only do that for single selection to avoid confusion. - if (this.entries_.length !== 1) { - return; - } - - const filename = this.entries_[0].name; - const extension = util.splitExtension(filename)[1] || null; - const mimeType = this.mimeTypes_[0] || null; - - const showAlert = () => { - let textMessageId; - let titleMessageId; - switch (extension) { - case '.exe': - case '.msi': - textMessageId = 'NO_TASK_FOR_EXECUTABLE'; - break; - case '.dmg': - textMessageId = 'NO_TASK_FOR_DMG'; - break; - case '.crx': - textMessageId = 'NO_TASK_FOR_CRX'; - titleMessageId = 'NO_TASK_FOR_CRX_TITLE'; - break; - default: - textMessageId = 'NO_TASK_FOR_FILE'; - } - - const webStoreUrl = webStoreUtils.createWebStoreLink(extension, mimeType); - const text = strf(textMessageId, webStoreUrl, str('NO_TASK_FOR_FILE_URL')); - const title = titleMessageId ? str(titleMessageId) : filename; - this.ui_.alertDialog.showHtml(title, text, null, null, null); - callback(false, this.entries_); - }; - - const onViewFilesFailure = () => { - if (extension && - (FileTasks.EXTENSIONS_TO_SKIP_SUGGEST_APPS_.indexOf(extension) !== -1 || - constants.EXECUTABLE_EXTENSIONS.indexOf(assert(extension)) !== -1)) { - showAlert(); - return; - } - - this.openSuggestAppsDialog( - () => { - FileTasks - .create( - this.volumeManager_, this.metadataModel_, - this.directoryModel_, this.ui_, this.entries_, - this.mimeTypes_, this.taskHistory_, this.namingController_, - this.crostini_) - .then( - tasks => { - tasks.executeDefault(); - callback(true, this.entries_); - }, - () => { - callback(false, this.entries_); - }); - }, - () => { - callback(false, this.entries_); - }, - showAlert); - }; - - const onViewFiles = result => { - switch (result) { - case 'opened': - callback(true, this.entries_); - break; - case 'message_sent': - util.isTeleported(window).then(teleported => { - if (teleported) { - this.ui_.showOpenInOtherDesktopAlert(this.entries_); - } - }); - callback(true, this.entries_); - break; - case 'empty': - callback(true, this.entries_); - break; - case 'failed': - // Suppress the Unchecked runtime.lastError console message - if (chrome.runtime.lastError) { - console.debug(chrome.runtime.lastError.message); - } - onViewFilesFailure(); - break; - } - }; - - this.checkAvailability_(() => { - const taskId = chrome.runtime.id + '|file|view-in-browser'; - chrome.fileManagerPrivate.executeTask(taskId, this.entries_, onViewFiles); - }); -}; - -/** - * Executes a single task. - * - * @param {chrome.fileManagerPrivate.FileTask} task FileTask. - */ -FileTasks.prototype.execute = function(task) { - FileTasks.recordViewingFileTypeUMA_(this.volumeManager_, this.entries_); - FileTasks.recordViewingRootTypeUMA_( - this.volumeManager_, this.directoryModel_.getCurrentRootType()); - this.executeInternal_(task); -}; - -/** - * The core implementation to execute a single task. - * - * @param {chrome.fileManagerPrivate.FileTask} task FileTask. - * @private - */ -FileTasks.prototype.executeInternal_ = function(task) { - this.checkAvailability_(() => { - this.maybeShareWithCrostiniOrShowDialog_(task, () => { - this.taskHistory_.recordTaskExecuted(task.taskId); - let msg; - if (this.entries.length === 1) { - msg = strf('OPEN_A11Y', this.entries_[0].name); - } else { - msg = strf('OPEN_A11Y_PLURAL', this.entries_.length); - } - this.ui_.speakA11yMessage(msg); - if (FileTasks.isInternalTask_(task.taskId)) { - this.executeInternalTask_(task.taskId); - } else { - FileTasks.recordZipHandlerUMA_(task.taskId); - chrome.fileManagerPrivate.executeTask( - task.taskId, this.entries_, (result) => { - if (result !== 'message_sent') { - return; - } - util.isTeleported(window).then((teleported) => { - if (teleported) { - this.ui_.showOpenInOtherDesktopAlert(this.entries_); - } - }); - }); - } - }); - }); -}; - -/** - * Ensures that the all files are available right now. - * - * Must not call before initialization. - * @param {function()} callback Called when checking is completed and all files - * are available. Otherwise not called. - * @private - */ -FileTasks.prototype.checkAvailability_ = function(callback) { - const areAll = (entries, props, name) => { - // TODO(cmihail): Make files in directories available offline. - // See http://crbug.com/569767. - let okEntriesNum = 0; - for (let i = 0; i < entries.length; i++) { - // If got no properties, we safely assume that item is available. - if (props[i] && (props[i][name] || entries[i].isDirectory)) { - okEntriesNum++; - } - } - return okEntriesNum === props.length; - }; - - const containsDriveEntries = this.entries_.some(entry => { - const volumeInfo = this.volumeManager_.getVolumeInfo(entry); - return volumeInfo && - volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE; - }); - - // Availability is not checked for non-Drive files, as availableOffline, nor - // availableWhenMetered are not exposed for other types of volumes at this - // moment. - if (!containsDriveEntries) { - callback(); - return; - } - - const isDriveOffline = this.volumeManager_.getDriveConnectionState().type === - VolumeManagerCommon.DriveConnectionType.OFFLINE; - - if (isDriveOffline) { - this.metadataModel_.get(this.entries_, ['availableOffline', 'hosted']) - .then(props => { - if (areAll(this.entries_, props, 'availableOffline')) { - callback(); - return; - } - - this.ui_.alertDialog.showHtml( - loadTimeData.getString('OFFLINE_HEADER'), - props[0].hosted ? - loadTimeData.getStringF( - this.entries_.length === 1 ? - 'HOSTED_OFFLINE_MESSAGE' : - 'HOSTED_OFFLINE_MESSAGE_PLURAL') : - loadTimeData.getStringF( - this.entries_.length === 1 ? 'OFFLINE_MESSAGE' : - 'OFFLINE_MESSAGE_PLURAL', - loadTimeData.getString('OFFLINE_COLUMN_LABEL')), - null, null, null); - }); - return; - } - - const isOnMetered = this.volumeManager_.getDriveConnectionState().type === - VolumeManagerCommon.DriveConnectionType.METERED; - - if (isOnMetered) { - this.metadataModel_.get(this.entries_, ['availableWhenMetered', 'size']) - .then(props => { - if (areAll(this.entries_, props, 'availableWhenMetered')) { - callback(); - return; - } - - let sizeToDownload = 0; - for (let i = 0; i !== this.entries_.length; i++) { - if (!props[i].availableWhenMetered) { - sizeToDownload += props[i].size; - } - } - this.ui_.confirmDialog.show( - loadTimeData.getStringF( - this.entries_.length === 1 ? 'CONFIRM_MOBILE_DATA_USE' : - 'CONFIRM_MOBILE_DATA_USE_PLURAL', - util.bytesToString(sizeToDownload)), - callback, null, null); - }); - return; - } - - callback(); -}; - -/** - * Executes an internal task. - * - * @param {string} taskId The task id. - * @private - */ -FileTasks.prototype.executeInternalTask_ = function(taskId) { - const taskParts = taskId.split('|'); - if (taskParts[2] === 'mount-archive') { - this.mountArchivesInternal_(); - return; - } - if (taskParts[2] === 'install-linux-package') { - this.installLinuxPackageInternal_(); - return; - } - - console.error('The specified task is not a valid internal task: ' + taskId); -}; - -/** - * Install a Linux Package in the Linux container. - * @private - */ -FileTasks.prototype.installLinuxPackageInternal_ = function() { - assert(this.entries_.length === 1); - this.ui_.installLinuxPackageDialog.showInstallLinuxPackageDialog( - this.entries_[0]); -}; - -/** - * The core implementation of mounts archives. - * @private - */ -FileTasks.prototype.mountArchivesInternal_ = function() { - const tracker = this.directoryModel_.createDirectoryChangeTracker(); - tracker.start(); - - // TODO(mtomasz): Move conversion from entry to url to custom bindings. - // crbug.com/345527. - const urls = util.entriesToURLs(this.entries_); - for (let index = 0; index < urls.length; ++index) { - // TODO(mtomasz): Pass Entry instead of URL. - this.volumeManager_.mountArchive(urls[index], volumeInfo => { - if (tracker.hasChanged) { - tracker.stop(); - return; - } - volumeInfo.resolveDisplayRoot( - displayRoot => { - if (tracker.hasChanged) { - tracker.stop(); - return; - } - this.directoryModel_.changeDirectoryEntry(displayRoot); - }, - () => { - console.warn('Failed to resolve the display root after mounting.'); - tracker.stop(); - }); - }, ((url, error) => { - tracker.stop(); - const path = util.extractFilePath(url); - const namePos = path.lastIndexOf('/'); - this.ui_.alertDialog.show( - strf('ARCHIVE_MOUNT_FAILED', path.substr(namePos + 1), error), - null, null); - }).bind(null, urls[index])); - } -}; - -/** - * Displays the list of tasks in a open task picker combobutton and a share - * options menu. - * - * @param {!cr.ui.ComboButton} openCombobutton The open task picker combobutton. - * @param {!cr.ui.MultiMenuButton} shareMenuButton Button for share options. - * @public - */ -FileTasks.prototype.display = function(openCombobutton, shareMenuButton) { - const openTasks = []; - const otherTasks = []; - for (let i = 0; i < this.tasks_.length; i++) { - const task = this.tasks_[i]; - if (FileTasks.isOpenTask(task)) { - openTasks.push(task); - } else { - otherTasks.push(task); - } - } - this.updateOpenComboButton_(openCombobutton, openTasks); - this.updateShareMenuButton_(shareMenuButton, otherTasks); -}; - -/** - * Setup a task picker combobutton based on the given tasks. - * @param {!cr.ui.ComboButton} combobutton - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks - */ -FileTasks.prototype.updateOpenComboButton_ = function(combobutton, tasks) { - combobutton.hidden = tasks.length == 0; - if (tasks.length == 0) { - return; - } - - combobutton.clear(); - - // If there exist defaultTask show it on the combobutton. - if (this.defaultTask_) { - combobutton.defaultItem = - this.createCombobuttonItem_(this.defaultTask_, str('TASK_OPEN')); - } else { - combobutton.defaultItem = { - type: FileTasks.TaskMenuButtonItemType.ShowMenu, - label: str('OPEN_WITH_BUTTON_LABEL') - }; - } - - // If there exist 2 or more available tasks, show them in context menu - // (including defaultTask). If only one generic task is available, we - // also show it in the context menu. - const items = this.createItems_(tasks); - if (items.length > 1 || (items.length === 1 && this.defaultTask_ === null)) { - for (let j = 0; j < items.length; j++) { - combobutton.addDropDownItem(items[j]); - } - - // If there exist non generic task (i.e. defaultTask is set), we show - // an item to change default task. - if (this.defaultTask_) { - combobutton.addSeparator(); - const changeDefaultMenuItem = combobutton.addDropDownItem({ - type: FileTasks.TaskMenuButtonItemType.ChangeDefaultTask, - label: loadTimeData.getString('CHANGE_DEFAULT_MENU_ITEM') - }); - changeDefaultMenuItem.classList.add('change-default'); - } - } -}; - /** * The number of menu-item entries in the top level menu * before we split and show the 'More actions' option * @const {number} */ const NUM_TOP_LEVEL_ENTRIES = 6; + /** * Don't split the menu if the number of entries is smaller * than this. e.g. with 7 entries it'd be poor to show a @@ -1145,124 +1319,6 @@ const MAX_NON_SPLIT_ENTRIES = 10; /** - * Setup a menu button for sharing options based on the given tasks. - * @param {!cr.ui.MultiMenuButton} shareMenuButton - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks - */ -FileTasks.prototype.updateShareMenuButton_ = function(shareMenuButton, tasks) { - let driveShareCommand = - shareMenuButton.menu.querySelector('cr-menu-item[command="#share"]'); - let driveShareCommandSeparator = - shareMenuButton.menu.querySelector('#drive-share-separator'); - let moreActionsSeparator = - shareMenuButton.menu.querySelector('#more-actions-separator'); - - // Hide share icon for New Folder creation. See https://crbug.com/571355. - shareMenuButton.hidden = (driveShareCommand.disabled && tasks.length == 0) || - this.namingController_.isRenamingInProgress(); - moreActionsSeparator.hidden = true; - - // Show the separator if Drive share command is enabled and there is at least - // one other share actions. - driveShareCommandSeparator.hidden = - driveShareCommand.disabled || tasks.length == 0; - - // Temporarily remove the more actions item while the rest of the menu - // items are being cleared out so we don't lose it and make it hidden for now - let moreActions = shareMenuButton.menu.querySelector( - 'cr-menu-item[command="#show-submenu"]'); - moreActions.remove(); - moreActions.setAttribute('hidden', ''); - // Remove the separator as well - moreActionsSeparator.remove(); - - // Clear menu items except for drive share menu and a separator for it. - // As querySelectorAll() returns live NodeList, we need to copy elements to - // Array object to modify DOM in the for loop. - const itemsToRemove = [].slice.call(shareMenuButton.menu.querySelectorAll( - 'cr-menu-item:not([command="#share"])')); - for (let i = 0; i < itemsToRemove.length; i++) { - const item = itemsToRemove[i]; - item.parentNode.removeChild(item); - } - // Clear menu items in the overflow sub-menu since we'll repopulate it - // with any relevant items below. - if (shareMenuButton.overflow !== null) { - while (shareMenuButton.overflow.firstChild !== null) { - shareMenuButton.overflow.removeChild(shareMenuButton.overflow.firstChild); - } - } - - // Add menu items for the new tasks. - const items = this.createItems_(tasks); - let menu = /** @type {!cr.ui.Menu} */ (shareMenuButton.menu); - for (let i = 0; i < items.length; i++) { - // If we have at least 10 entries, split off into a sub-menu - if (i == NUM_TOP_LEVEL_ENTRIES && MAX_NON_SPLIT_ENTRIES <= items.length) { - moreActions.removeAttribute('hidden'); - moreActionsSeparator.hidden = false; - menu = shareMenuButton.overflow; - } - const menuitem = menu.addMenuItem(items[i]); - cr.ui.decorate(menuitem, cr.ui.FilesMenuItem); - menuitem.data = items[i]; - if (items[i].iconType) { - menuitem.style.backgroundImage = ''; - menuitem.setAttribute('file-type-icon', items[i].iconType); - } - } - // Replace the more actions menu item and separator - shareMenuButton.menu.appendChild(moreActionsSeparator); - shareMenuButton.menu.appendChild(moreActions); -}; - -/** - * Creates sorted array of available task descriptions such as title and icon. - * - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks Tasks to create - * items. - * @return {!Array<!FileTasks.ComboButtonItem>} Created array can be used to - * feed combobox, menus and so on. - * @private - */ -FileTasks.prototype.createItems_ = function(tasks) { - const items = []; - - // Create items. - for (let index = 0; index < tasks.length; index++) { - const task = tasks[index]; - if (task === this.defaultTask_) { - const title = - task.title + ' ' + loadTimeData.getString('DEFAULT_TASK_LABEL'); - items.push(this.createCombobuttonItem_(task, title, true, true)); - } else { - items.push(this.createCombobuttonItem_(task)); - } - } - - // Sort items (Sort order: isDefault, lastExecutedTime, label). - items.sort((a, b) => { - // Sort by isDefaultTask. - const isDefault = (b.isDefault ? 1 : 0) - (a.isDefault ? 1 : 0); - if (isDefault !== 0) { - return isDefault; - } - - // Sort by last-executed time. - const aTime = this.taskHistory_.getLastExecutedTime(a.task.taskId); - const bTime = this.taskHistory_.getLastExecutedTime(b.task.taskId); - if (aTime != bTime) { - return bTime - aTime; - } - - // Sort by label. - return a.label.localeCompare(b.label); - }); - - return items; -}; - -/** * @typedef {{ * type: !FileTasks.TaskMenuButtonItemType, * label: string, @@ -1275,92 +1331,3 @@ * }} */ FileTasks.ComboButtonItem; - -/** - * Creates combobutton item based on task. - * - * @param {!chrome.fileManagerPrivate.FileTask} task Task to convert. - * @param {string=} opt_title Title. - * @param {boolean=} opt_bold Make a menu item bold. - * @param {boolean=} opt_isDefault Mark the item as default item. - * @return {!FileTasks.ComboButtonItem} Item appendable to combobutton drop-down - * list. - * @private - */ -FileTasks.prototype.createCombobuttonItem_ = - (task, opt_title, opt_bold, opt_isDefault) => { - return { - type: FileTasks.TaskMenuButtonItemType.RunTask, - label: opt_title || task.label || task.title, - iconUrl: task.iconUrl || '', - iconType: task.iconType || '', - task: task, - bold: opt_bold || false, - isDefault: opt_isDefault || false, - isGenericFileHandler: /** @type {boolean} */ (task.isGenericFileHandler) - }; - }; - -/** - * Shows modal task picker dialog with currently available list of tasks. - * - * @param {cr.filebrowser.DefaultTaskDialog} taskDialog Task dialog to show and - * update. - * @param {string} title Title to use. - * @param {string} message Message to use. - * @param {function(!chrome.fileManagerPrivate.FileTask)} onSuccess Callback to - * pass selected task. - * @param {FileTasks.TaskPickerType} pickerType Task picker type. - */ -FileTasks.prototype.showTaskPicker = function( - taskDialog, title, message, onSuccess, pickerType) { - const tasks = pickerType == FileTasks.TaskPickerType.MoreActions ? - this.getNonOpenTaskItems() : - this.getOpenTaskItems(); - let items = this.createItems_(tasks); - if (pickerType == FileTasks.TaskPickerType.ChangeDefault) { - items = items.filter(item => !item.isGenericFileHandler); - } - - let defaultIdx = 0; - for (let j = 0; j < items.length; j++) { - if (this.defaultTask_ && - items[j].task.taskId === this.defaultTask_.taskId) { - defaultIdx = j; - } - } - - taskDialog.showDefaultTaskDialog(title, message, items, defaultIdx, item => { - onSuccess(item.task); - }); -}; - -/** - * Gets the default task from tasks. In case there is no such task (i.e. all - * tasks are generic file handlers), then return null. - * - * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks The list of tasks - * from where to choose the default task. - * @param {!TaskHistory} taskHistory - * @return {?chrome.fileManagerPrivate.FileTask} the default task, or null if - * no default task found. - */ -FileTasks.getDefaultTask = (tasks, taskHistory) => { - // 1. Default app set for MIME or file extension by user, or built-in app. - for (let i = 0; i < tasks.length; i++) { - if (tasks[i].isDefault) { - return tasks[i]; - } - } - const nonGenericTasks = tasks.filter(t => !t.isGenericFileHandler); - // 2. Most recently executed non-generic task. - const latest = nonGenericTasks[0]; - if (latest && taskHistory.getLastExecutedTime(latest.taskId)) { - return latest; - } - // 3. Sole non-generic handler. - if (nonGenericTasks.length == 1) { - return nonGenericTasks[0]; - } - return null; -};
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js index 48ec7bf..e44c6eef 100644 --- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js +++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
@@ -725,7 +725,7 @@ /** * Preloads an image thumbnail for the specified file entry. * - * @param {Entry} entry Entry to preload a thumbnail for. + * @param {!Entry} entry Entry to preload a thumbnail for. * @private */ preloadThumbnailImage_(entry) {
diff --git a/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js b/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js index 1a8526a9..aa1ed75a 100644 --- a/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js +++ b/ui/file_manager/file_manager/foreground/js/gear_menu_controller.js
@@ -2,180 +2,157 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * @param {!cr.ui.MultiMenuButton} gearButton - * @param {!FilesToggleRipple} toggleRipple - * @param {!GearMenu} gearMenu - * @param {!ProvidersMenu} providersMenu - * @param {!DirectoryModel} directoryModel - * @param {!CommandHandler} commandHandler - * @param {!ProvidersModel} providersModel - * @constructor - * @struct - */ -function GearMenuController( - gearButton, toggleRipple, gearMenu, providersMenu, directoryModel, - commandHandler, providersModel) { +class GearMenuController { /** - * @type {!FilesToggleRipple} - * @const - * @private + * @param {!cr.ui.MultiMenuButton} gearButton + * @param {!FilesToggleRipple} toggleRipple + * @param {!GearMenu} gearMenu + * @param {!ProvidersMenu} providersMenu + * @param {!DirectoryModel} directoryModel + * @param {!CommandHandler} commandHandler + * @param {!ProvidersModel} providersModel */ - this.toggleRipple_ = toggleRipple; + constructor( + gearButton, toggleRipple, gearMenu, providersMenu, directoryModel, + commandHandler, providersModel) { + /** @private @const {!FilesToggleRipple} */ + this.toggleRipple_ = toggleRipple; - /** - * @type {!GearMenu} - * @const - * @private - */ - this.gearMenu_ = gearMenu; + /** @private @const {!GearMenu} */ + this.gearMenu_ = gearMenu; - /** - * @type {!ProvidersMenu} - * @const - * @private - */ - this.providersMenu_ = providersMenu; + /** @private @const {!ProvidersMenu} */ + this.providersMenu_ = providersMenu; - /** - * @type {!DirectoryModel} - * @const - * @private - */ - this.directoryModel_ = directoryModel; + /** @private @const {!DirectoryModel} */ + this.directoryModel_ = directoryModel; - /** - * @type {!CommandHandler} - * @const - * @private - */ - this.commandHandler_ = commandHandler; + /** @private @const {!CommandHandler} */ + this.commandHandler_ = commandHandler; - /** - * @type {!ProvidersModel} - * @const - * @private - */ - this.providersModel_ = providersModel; + /** @private @const {!ProvidersModel} */ + this.providersModel_ = providersModel; - gearButton.addEventListener('menushow', this.onShowGearMenu_.bind(this)); - gearButton.addEventListener('menuhide', this.onHideGearMenu_.bind(this)); - directoryModel.addEventListener( - 'directory-changed', this.onDirectoryChanged_.bind(this)); - chrome.fileManagerPrivate.onPreferencesChanged.addListener( - this.onPreferencesChanged_.bind(this)); - this.onPreferencesChanged_(); -} - -/** - * @private - */ -GearMenuController.prototype.onShowGearMenu_ = function() { - this.toggleRipple_.activated = true; - this.refreshRemainingSpace_(false); /* Without loading caption. */ - this.updateNewServiceItem(); -}; - -/** - * Update "New service" menu item to either directly show the Webstore dialog - * when there isn't any service/FSP extension installed, or display the - * providers menu with the currently installed extensions and also install new - * service. - * - * @private - */ -GearMenuController.prototype.updateNewServiceItem = function() { - this.providersModel_.getMountableProviders().then(providers => { - // Go straight to webstore to install the first provider. - let desiredMenu = '#install-new-extension'; - let label = str('INSTALL_NEW_EXTENSION_LABEL'); - - const shouldDisplayProvidersMenu = providers.length > 0; - if (shouldDisplayProvidersMenu) { - // Open the providers menu with an installed provider and an install new - // provider option. - desiredMenu = '#new-service'; - label = str('ADD_NEW_SERVICES_BUTTON_LABEL'); - // Trigger an update of the providers submenu. - this.providersMenu_.updateSubMenu(); - } - - this.gearMenu_.setNewServiceCommand(desiredMenu, label); - }); -}; - -/** - * @private - */ -GearMenuController.prototype.onHideGearMenu_ = function() { - this.toggleRipple_.activated = false; -}; - -/** - * @param {Event} event - * @private - */ -GearMenuController.prototype.onDirectoryChanged_ = function(event) { - event = /** @type {DirectoryChangeEvent} */ (event); - if (event.volumeChanged) { - this.refreshRemainingSpace_(true); - } // Show loading caption. -}; - -/** - * Refreshes space info of the current volume. - * @param {boolean} showLoadingCaption Whether show loading caption or not. - * @private - */ -GearMenuController.prototype.refreshRemainingSpace_ = function( - showLoadingCaption) { - const currentDirectory = this.directoryModel_.getCurrentDirEntry(); - if (!currentDirectory || util.isRecentRoot(currentDirectory)) { - this.gearMenu_.setSpaceInfo(null, false); - return; + gearButton.addEventListener('menushow', this.onShowGearMenu_.bind(this)); + gearButton.addEventListener('menuhide', this.onHideGearMenu_.bind(this)); + directoryModel.addEventListener( + 'directory-changed', this.onDirectoryChanged_.bind(this)); + chrome.fileManagerPrivate.onPreferencesChanged.addListener( + this.onPreferencesChanged_.bind(this)); + this.onPreferencesChanged_(); } - const currentVolumeInfo = this.directoryModel_.getCurrentVolumeInfo(); - if (!currentVolumeInfo) { - return; + /** + * @private + */ + onShowGearMenu_() { + this.toggleRipple_.activated = true; + this.refreshRemainingSpace_(false); /* Without loading caption. */ + this.updateNewServiceItem(); } - // TODO(mtomasz): Add support for remaining space indication for provided - // file systems. - // TODO(fukino): Add support for remaining space indication for documents - // provider roots. crbug.com/953657. - if (currentVolumeInfo.volumeType == VolumeManagerCommon.VolumeType.PROVIDED || - currentVolumeInfo.volumeType == - VolumeManagerCommon.VolumeType.MEDIA_VIEW || - currentVolumeInfo.volumeType == - VolumeManagerCommon.VolumeType.DOCUMENTS_PROVIDER || - currentVolumeInfo.volumeType == VolumeManagerCommon.VolumeType.ARCHIVE) { - this.gearMenu_.setSpaceInfo(null, false); - return; + /** + * Update "New service" menu item to either directly show the Webstore dialog + * when there isn't any service/FSP extension installed, or display the + * providers menu with the currently installed extensions and also install new + * service. + * + * @private + */ + updateNewServiceItem() { + this.providersModel_.getMountableProviders().then(providers => { + // Go straight to webstore to install the first provider. + let desiredMenu = '#install-new-extension'; + let label = str('INSTALL_NEW_EXTENSION_LABEL'); + + const shouldDisplayProvidersMenu = providers.length > 0; + if (shouldDisplayProvidersMenu) { + // Open the providers menu with an installed provider and an install new + // provider option. + desiredMenu = '#new-service'; + label = str('ADD_NEW_SERVICES_BUTTON_LABEL'); + // Trigger an update of the providers submenu. + this.providersMenu_.updateSubMenu(); + } + + this.gearMenu_.setNewServiceCommand(desiredMenu, label); + }); } - this.gearMenu_.setSpaceInfo( - new Promise(fulfill => { - chrome.fileManagerPrivate.getSizeStats( - currentVolumeInfo.volumeId, fulfill); - }), - true); -}; + /** + * @private + */ + onHideGearMenu_() { + this.toggleRipple_.activated = false; + } -/** - * Handles preferences change and updates menu. - * @private - */ -GearMenuController.prototype.onPreferencesChanged_ = function() { - chrome.fileManagerPrivate.getPreferences(prefs => { - if (chrome.runtime.lastError) { + /** + * @param {Event} event + * @private + */ + onDirectoryChanged_(event) { + event = /** @type {DirectoryChangeEvent} */ (event); + if (event.volumeChanged) { + this.refreshRemainingSpace_(true); + } // Show loading caption. + } + + /** + * Refreshes space info of the current volume. + * @param {boolean} showLoadingCaption Whether show loading caption or not. + * @private + */ + refreshRemainingSpace_(showLoadingCaption) { + const currentDirectory = this.directoryModel_.getCurrentDirEntry(); + if (!currentDirectory || util.isRecentRoot(currentDirectory)) { + this.gearMenu_.setSpaceInfo(null, false); return; } - if (prefs.cellularDisabled) { - this.gearMenu_.syncButton.setAttribute('checked', ''); - } else { - this.gearMenu_.syncButton.removeAttribute('checked'); + const currentVolumeInfo = this.directoryModel_.getCurrentVolumeInfo(); + if (!currentVolumeInfo) { + return; } - }); -}; + + // TODO(mtomasz): Add support for remaining space indication for provided + // file systems. + // TODO(fukino): Add support for remaining space indication for documents + // provider roots. crbug.com/953657. + if (currentVolumeInfo.volumeType == + VolumeManagerCommon.VolumeType.PROVIDED || + currentVolumeInfo.volumeType == + VolumeManagerCommon.VolumeType.MEDIA_VIEW || + currentVolumeInfo.volumeType == + VolumeManagerCommon.VolumeType.DOCUMENTS_PROVIDER || + currentVolumeInfo.volumeType == + VolumeManagerCommon.VolumeType.ARCHIVE) { + this.gearMenu_.setSpaceInfo(null, false); + return; + } + + this.gearMenu_.setSpaceInfo( + new Promise(fulfill => { + chrome.fileManagerPrivate.getSizeStats( + currentVolumeInfo.volumeId, fulfill); + }), + true); + } + + /** + * Handles preferences change and updates menu. + * @private + */ + onPreferencesChanged_() { + chrome.fileManagerPrivate.getPreferences(prefs => { + if (chrome.runtime.lastError) { + return; + } + + if (prefs.cellularDisabled) { + this.gearMenu_.syncButton.setAttribute('checked', ''); + } else { + this.gearMenu_.syncButton.removeAttribute('checked'); + } + }); + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller.js b/ui/file_manager/file_manager/foreground/js/import_controller.js index 8d1a3b01..b7a2339 100644 --- a/ui/file_manager/file_manager/foreground/js/import_controller.js +++ b/ui/file_manager/file_manager/foreground/js/import_controller.js
@@ -19,89 +19,442 @@ /** * Class that orchestrates background activity and UI changes on * behalf of Cloud Import. - * - * @constructor - * @struct - * - * @param {!importer.ControllerEnvironment} environment The class providing - * access to runtime environmental information, like the current directory, - * volume lookup and so-on. - * @param {!importer.MediaScanner} scanner - * @param {!importer.ImportRunner} importRunner - * @param {!importer.CommandWidget} commandWidget */ -importer.ImportController = function( - environment, scanner, importRunner, commandWidget) { - /** @private {!importer.ControllerEnvironment} */ - this.environment_ = environment; +importer.ImportController = class { + /** + * @param {!importer.ControllerEnvironment} environment The class providing + * access to runtime environmental information, like the current + * directory, volume lookup and so-on. + * @param {!importer.MediaScanner} scanner + * @param {!importer.ImportRunner} importRunner + * @param {!importer.CommandWidget} commandWidget + */ + constructor(environment, scanner, importRunner, commandWidget) { + /** @private @const {!importer.ControllerEnvironment} */ + this.environment_ = environment; - /** @private {!importer.ChromeLocalStorage} */ - this.storage_ = importer.ChromeLocalStorage.getInstance(); + /** @private @const {!importer.ChromeLocalStorage} */ + this.storage_ = importer.ChromeLocalStorage.getInstance(); - /** @private {!importer.ImportRunner} */ - this.importRunner_ = importRunner; + /** @private @const {!importer.ImportRunner} */ + this.importRunner_ = importRunner; - /** @private {!importer.MediaScanner} */ - this.scanner_ = scanner; + /** @private @const {!importer.MediaScanner} */ + this.scanner_ = scanner; - /** @private {!importer.CommandWidget} */ - this.commandWidget_ = commandWidget; + /** @private @const {!importer.CommandWidget} */ + this.commandWidget_ = commandWidget; - /** @type {!importer.ScanManager} */ - this.scanManager_ = new importer.ScanManager(environment, scanner); + /** @private @const {!importer.ScanManager} */ + this.scanManager_ = new importer.ScanManager(environment, scanner); + + /** + * The active import task, if any. + * @private {?importer.TaskDetails_} + */ + this.activeImport_ = null; + + /** + * The previous import task, if any. + * @private {?importer.TaskDetails_} + */ + this.previousImport_ = null; + + /** @private {!importer.ActivityState} */ + this.lastActivityState_ = importer.ActivityState.HIDDEN; + + /** + * Whether the window was opened by plugging a media device and user hadn't + * navigated to other directories. + * @private {boolean} + */ + this.isRightAfterPluggingMedia_ = false; + + const listener = this.onScanEvent_.bind(this); + this.scanner_.addObserver(listener); + // Remove the observer when the foreground window is closed. + window.addEventListener('pagehide', () => { + this.scanner_.removeObserver(listener); + }); + + this.environment_.addWindowCloseListener(this.onWindowClosing_.bind(this)); + + this.environment_.addVolumeUnmountListener( + this.onVolumeUnmounted_.bind(this)); + + this.environment_.addDirectoryChangedListener( + this.onDirectoryChanged_.bind(this)); + + this.environment_.addSelectionChangedListener( + this.onSelectionChanged_.bind(this)); + + this.commandWidget_.addClickListener(this.onClick_.bind(this)); + + this.storage_.get(importer.Setting.HAS_COMPLETED_IMPORT, false) + .then( + /** @param {boolean} importCompleted If so, we hide the banner */ + importCompleted => { + this.commandWidget_.setDetailsBannerVisible(!importCompleted); + }); + } /** - * The active import task, if any. - * @private {?importer.TaskDetails_} + * @param {!importer.ScanEvent} event Command event. + * @param {importer.ScanResult} scan + * @private */ - this.activeImport_ = null; + onScanEvent_(event, scan) { + if (!this.scanManager_.isActiveScan(scan)) { + return; + } + + switch (event) { + case importer.ScanEvent.INVALIDATED: + this.onScanInvalidated_(); + case importer.ScanEvent.FINALIZED: + case importer.ScanEvent.UPDATED: + this.checkState_(scan); + break; + } + } + + /** @private */ + onWindowClosing_() { + this.scanManager_.reset(); // Will cancel any active scans. + } /** - * The previous import task, if any. - * @private {?importer.TaskDetails_} + * @param {string} volumeId + * @private */ - this.previousImport_ = null; + onVolumeUnmounted_(volumeId) { + if (this.activeImport_) { + this.activeImport_.task.requestCancel(); + this.finalizeActiveImport_(); + metrics.recordBoolean('ImportController.DeviceYanked'); + } + this.scanManager_.reset(); + this.checkState_(); + } /** - * @private {!importer.ActivityState} + * @param {!Event} event + * @private */ - this.lastActivityState_ = importer.ActivityState.HIDDEN; + onDirectoryChanged_(event) { + this.isRightAfterPluggingMedia_ = !event.previousDirEntry; + + this.scanManager_.reset(); + if (this.isCurrentDirectoryScannable_()) { + this.checkState_( + this.scanManager_.getDirectoryScan(importer.ScanMode.HISTORY)); + } else { + this.checkState_(); + } + } + + /** @private */ + onSelectionChanged_() { + // NOTE: Empty selection changed events can and will fire for a directory + // before we receive the the corresponding directory changed event and when + // the selection is empty. These are spurious events and we ignore them. + if (!this.scanManager_.hasSelectionScan() && + this.environment_.getSelection().length === 0) { + return; + } + + // NOTE: We clear the scan here, but don't immediately initiate + // a new scan. checkState will attempt to initialize the scan + // during normal processing. + // Also, in the case the selection is transitioning to empty, + // we want to reinstate the underlying directory scan (if + // in fact, one is possible). + this.scanManager_.clearSelectionScan(); + if (this.environment_.getSelection().length === 0 && + this.isCurrentDirectoryScannable_()) { + this.checkState_( + this.scanManager_.getDirectoryScan(importer.ScanMode.HISTORY)); + } else { + this.checkState_(); + } + } /** - * Whether the window was opened by plugging a media device and user hadn't - * navigated to other directories. - * @private {boolean} + * @param {!importer.MediaImportHandler.ImportTask} task + * @private */ - this.isRightAfterPluggingMedia_ = false; + onImportFinished_(task) { + this.finalizeActiveImport_(); + this.scanManager_.reset(); + this.storage_.set(importer.Setting.HAS_COMPLETED_IMPORT, true); + this.commandWidget_.setDetailsBannerVisible(false); + this.checkState_(); + } - const listener = this.onScanEvent_.bind(this); - this.scanner_.addObserver(listener); - // Remove the observer when the foreground window is closed. - window.addEventListener('pagehide', () => { - this.scanner_.removeObserver(listener); - }); + /** @private */ + onScanInvalidated_() { + this.scanManager_.reset(); + if (this.environment_.getSelection().length === 0 && + this.isCurrentDirectoryScannable_()) { + this.checkState_( + this.scanManager_.getDirectoryScan(importer.ScanMode.HISTORY)); + } else { + this.checkState_(); + } + } - this.environment_.addWindowCloseListener(this.onWindowClosing_.bind(this)); + /** + * Does book keeping necessary to finalize the active task. + * @private + */ + finalizeActiveImport_() { + console.assert( + !!this.activeImport_, 'Cannot finish import when none is running.'); + this.previousImport_ = this.activeImport_; + this.activeImport_ = null; + } - this.environment_.addVolumeUnmountListener( - this.onVolumeUnmounted_.bind(this)); + /** + * Handles button clicks emenating from the panel or toolbar. + * @param {!importer.ClickSource} source + */ + onClick_(source) { + switch (source) { + case importer.ClickSource.MAIN: + if (this.lastActivityState_ === importer.ActivityState.READY) { + this.commandWidget_.performMainButtonRippleAnimation(); + this.execute_(); + } else { + this.commandWidget_.toggleDetails(); + } + break; + case importer.ClickSource.IMPORT: + this.execute_(); + break; + case importer.ClickSource.CANCEL: + this.cancel_(); + break; + case importer.ClickSource.DESTINATION: + if (this.activeImport_) { + this.environment_.showImportDestination(this.activeImport_.started); + } else if (this.previousImport_) { + this.environment_.showImportDestination(this.previousImport_.started); + } else { + this.environment_.showImportRoot(); + } + break; + case importer.ClickSource.SIDE: + // Intentionally unhandled...panel controls toggling of details panel. + break; + default: + assertNotReached('Unhandled click source: ' + source); + } + } - this.environment_.addDirectoryChangedListener( - this.onDirectoryChanged_.bind(this)); + /** + * Executes import against the current context. Should only be called + * after the current context has been validated by a scan. + * + * @private + */ + startImportTask_() { + console.assert( + !this.activeImport_, + 'Cannot execute while an import task is already active.'); - this.environment_.addSelectionChangedListener( - this.onSelectionChanged_.bind(this)); + const scan = this.scanManager_.getActiveScan(); + assert(scan != null); - this.commandWidget_.addClickListener(this.onClick_.bind(this)); + const startDate = new Date(); + const importTask = this.importRunner_.importFromScanResult( + scan, importer.Destination.GOOGLE_DRIVE, + this.environment_.getImportDestination(startDate)); - this.storage_.get(importer.Setting.HAS_COMPLETED_IMPORT, false) - .then( - /** - * @param {boolean} importCompleted If so, we hide the banner - */ - importCompleted => { - this.commandWidget_.setDetailsBannerVisible(!importCompleted); - }); + this.activeImport_ = {scan: scan, task: importTask, started: startDate}; + const taskFinished = this.onImportFinished_.bind(this, importTask); + importTask.whenFinished.then(taskFinished).catch(taskFinished); + } + + /** + * Executes import against the current context. Should only be called + * when user clicked an import button after the current context has + * been validated by a scan. + * + * @private + */ + execute_() { + this.startImportTask_(); + this.checkState_(); + } + + /** + * Cancels the active task. + * @private + */ + cancel_() { + if (this.activeImport_) { + this.activeImport_.task.requestCancel(); + this.finalizeActiveImport_(); + metrics.recordBoolean('ImportController.ImportCancelled'); + } + + this.scanManager_.reset(); + this.checkState_(); + } + + /** + * Checks the environment and updates UI as needed. + * @param {importer.ScanResult=} opt_scan If supplied, + * @private + */ + checkState_(opt_scan) { + // If there is no Google Drive mount, Drive may be disabled + // or the machine may be running in guest mode. + if (!this.environment_.isGoogleDriveMounted()) { + this.updateUi_(importer.ActivityState.HIDDEN); + return; + } + + if (this.activeImport_) { + this.updateUi_(importer.ActivityState.IMPORTING, this.activeImport_.scan); + return; + } + + // If we don't have an existing scan, we'll try to create + // one. When we do end up creating one (not getting + // one from the cache) it'll be empty...even if there is + // a current selection. This is because scans are + // resolved asynchronously. And we like it that way. + // We'll get notification when the scan is updated. When + // that happens, we'll be called back with opt_scan + // set to that scan....and subsequently skip over this + // block to update the UI. + if (!opt_scan) { + // NOTE, that tryScan_ lazily initializes scans...so if + // no scan is returned, no scan is possible for the + // current context. + const scan = this.tryScan_(importer.ScanMode.HISTORY); + // If no scan is created, then no scan is possible in + // the current context...so hide the UI. + if (!scan) { + this.updateUi_(importer.ActivityState.HIDDEN); + } + return; + } + + // At this point we have an existing scan, and a relatively + // validate environment for an import...so we'll proceed + // with making updates to the UI. + if (!opt_scan.isFinal()) { + this.updateUi_(importer.ActivityState.SCANNING, opt_scan); + return; + } + + if (opt_scan.getFileEntries().length === 0) { + if (opt_scan.getDuplicateFileEntries().length === 0) { + this.updateUi_(importer.ActivityState.NO_MEDIA); + return; + } + // Some scanned files found already exist in Drive. + // It means those files weren't marked as already backed up but need to + // be. Trigger sync for that purpose, but no files will actually be + // copied. + this.startImportTask_(); + this.updateUi_(importer.ActivityState.IMPORTING, this.activeImport_.scan); + return; + } + + // We have a final scan that is either too big, or juuuussttt right. + Promise + .all([ + this.environment_.getFreeStorageSpace( + VolumeManagerCommon.VolumeType.DOWNLOADS), + this.environment_.getFreeStorageSpace( + VolumeManagerCommon.VolumeType.DRIVE), + ]) + .then(/** @param {Array<number>} availableSpace in bytes */ + availableSpace => { + // TODO(smckay): We might want to disqualify some small amount + // of local storage in this calculation on the assumption that + // we don't want to completely max out storage...even though + // synced files will eventually be evicted from the cache. + if (availableSpace[0] < opt_scan.getStatistics().sizeBytes) { + // Doesn't fit in local space. + this.updateUi_( + importer.ActivityState.INSUFFICIENT_LOCAL_SPACE, opt_scan, + availableSpace[0]); + return; + } + if (availableSpace[1] !== -1 && + availableSpace[1] < opt_scan.getStatistics().sizeBytes) { + // Could retrieve cloud quota and doesn't fit. + this.updateUi_( + importer.ActivityState.INSUFFICIENT_CLOUD_SPACE, opt_scan, + availableSpace[1]); + return; + } + + // Enough space available! + this.updateUi_( + importer.ActivityState.READY, // to import... + opt_scan); + if (this.isRightAfterPluggingMedia_) { + this.isRightAfterPluggingMedia_ = false; + this.commandWidget_.setDetailsVisible(true); + } + }) + .catch(error => { + // If an error occurs, it will appear to scan forever - hide the + // cloud backup option in that case. + importer.getLogger().catcher('import-controller-check-state')(error); + this.updateUi_(importer.ActivityState.HIDDEN); + }); + } + + /** + * @param {importer.ActivityState} activityState + * @param {importer.ScanResult=} opt_scan + * @param {number=} opt_destinationSizeBytes specifies the destination size in + * bytes in case of space issues. + * @private + */ + updateUi_(activityState, opt_scan, opt_destinationSizeBytes) { + this.lastActivityState_ = activityState; + this.commandWidget_.update( + activityState, opt_scan, opt_destinationSizeBytes); + } + + /** + * @return {boolean} true if the current directory is scan eligible. + * @private + */ + isCurrentDirectoryScannable_() { + const directory = this.environment_.getCurrentDirectory(); + return !!directory && + importer.isMediaDirectory(directory, this.environment_.volumeManager); + } + + /** + * Attempts to scan the current context. + * + * @param {importer.ScanMode} mode How to detect new files. + * @return {importer.ScanResult} A scan object, + * or null if scan is not possible in current context. + * @private + */ + tryScan_(mode) { + const entries = this.environment_.getSelection(); + if (entries.length) { + if (entries.every(importer.isEligibleEntry.bind( + null, this.environment_.volumeManager))) { + return this.scanManager_.getSelectionScan(entries, mode); + } + } else if (this.isCurrentDirectoryScannable_()) { + return this.scanManager_.getDirectoryScan(mode); + } + + return null; + } }; /** @@ -112,409 +465,52 @@ * task: !importer.MediaImportHandler.ImportTask, * started: !Date * }} + * * @private */ importer.TaskDetails_; /** - * @param {!importer.ScanEvent} event Command event. - * @param {importer.ScanResult} scan - * - * @private - */ -importer.ImportController.prototype.onScanEvent_ = function(event, scan) { - if (!this.scanManager_.isActiveScan(scan)) { - return; - } - - switch (event) { - case importer.ScanEvent.INVALIDATED: - this.onScanInvalidated_(); - case importer.ScanEvent.FINALIZED: - case importer.ScanEvent.UPDATED: - this.checkState_(scan); - break; - } -}; - -/** @private */ -importer.ImportController.prototype.onWindowClosing_ = function() { - this.scanManager_.reset(); // Will cancel any active scans. -}; - -/** - * @param {string} volumeId - * @private - */ -importer.ImportController.prototype.onVolumeUnmounted_ = function(volumeId) { - if (this.activeImport_) { - this.activeImport_.task.requestCancel(); - this.finalizeActiveImport_(); - metrics.recordBoolean('ImportController.DeviceYanked'); - } - this.scanManager_.reset(); - this.checkState_(); -}; - -/** - * @param {!Event} event - * @private - */ -importer.ImportController.prototype.onDirectoryChanged_ = function(event) { - this.isRightAfterPluggingMedia_ = !event.previousDirEntry; - - this.scanManager_.reset(); - if (this.isCurrentDirectoryScannable_()) { - this.checkState_( - this.scanManager_.getDirectoryScan(importer.ScanMode.HISTORY)); - } else { - this.checkState_(); - } -}; - -/** @private */ -importer.ImportController.prototype.onSelectionChanged_ = function() { - // NOTE: Empty selection changed events can and will fire for a directory - // before we receive the the corresponding directory changed event - // and when the selection is empty. These are spurios events - // and we ignore them. - if (!this.scanManager_.hasSelectionScan() && - this.environment_.getSelection().length === 0) { - return; - } - - // NOTE: We clear the scan here, but don't immediately initiate - // a new scan. checkState will attempt to initialize the scan - // during normal processing. - // Also, in the case the selection is transitioning to empty, - // we want to reinstate the underlying directory scan (if - // in fact, one is possible). - this.scanManager_.clearSelectionScan(); - if (this.environment_.getSelection().length === 0 && - this.isCurrentDirectoryScannable_()) { - this.checkState_( - this.scanManager_.getDirectoryScan(importer.ScanMode.HISTORY)); - } else { - this.checkState_(); - } -}; - -/** - * @param {!importer.MediaImportHandler.ImportTask} task - * @private - */ -importer.ImportController.prototype.onImportFinished_ = function(task) { - this.finalizeActiveImport_(); - this.scanManager_.reset(); - this.storage_.set(importer.Setting.HAS_COMPLETED_IMPORT, true); - this.commandWidget_.setDetailsBannerVisible(false); - this.checkState_(); -}; - -/** @private */ -importer.ImportController.prototype.onScanInvalidated_ = function() { - this.scanManager_.reset(); - if (this.environment_.getSelection().length === 0 && - this.isCurrentDirectoryScannable_()) { - this.checkState_( - this.scanManager_.getDirectoryScan(importer.ScanMode.HISTORY)); - } else { - this.checkState_(); - } -}; - -/** - * Does book keeping necessary to finalize the active task. - * @private - */ -importer.ImportController.prototype.finalizeActiveImport_ = function() { - console.assert( - !!this.activeImport_, 'Cannot finish import when none is running.'); - this.previousImport_ = this.activeImport_; - this.activeImport_ = null; -}; - -/** - * Handles button clicks emenating from the panel or toolbar. - * @param {!importer.ClickSource} source - */ -importer.ImportController.prototype.onClick_ = function(source) { - switch (source) { - case importer.ClickSource.MAIN: - if (this.lastActivityState_ === importer.ActivityState.READY) { - this.commandWidget_.performMainButtonRippleAnimation(); - this.execute_(); - } else { - this.commandWidget_.toggleDetails(); - } - break; - case importer.ClickSource.IMPORT: - this.execute_(); - break; - case importer.ClickSource.CANCEL: - this.cancel_(); - break; - case importer.ClickSource.DESTINATION: - if (this.activeImport_) { - this.environment_.showImportDestination(this.activeImport_.started); - } else if (this.previousImport_) { - this.environment_.showImportDestination(this.previousImport_.started); - } else { - this.environment_.showImportRoot(); - } - break; - case importer.ClickSource.SIDE: - // Intentionally unhandled...panel controls toggling of details panel. - break; - default: - assertNotReached('Unhandled click source: ' + source); - } -}; - -/** - * Executes import against the current context. Should only be called - * after the current context has been validated by a scan. - * - * @private - */ -importer.ImportController.prototype.startImportTask_ = function() { - console.assert( - !this.activeImport_, - 'Cannot execute while an import task is already active.'); - - const scan = this.scanManager_.getActiveScan(); - assert(scan != null); - - const startDate = new Date(); - const importTask = this.importRunner_.importFromScanResult( - scan, importer.Destination.GOOGLE_DRIVE, - this.environment_.getImportDestination(startDate)); - - this.activeImport_ = {scan: scan, task: importTask, started: startDate}; - const taskFinished = this.onImportFinished_.bind(this, importTask); - importTask.whenFinished.then(taskFinished).catch(taskFinished); -}; - -/** - * Executes import against the current context. Should only be called - * when user clicked an import button after the current context has - * been validated by a scan. - * - * @private - */ -importer.ImportController.prototype.execute_ = function() { - this.startImportTask_(); - this.checkState_(); -}; - -/** - * Cancels the active task. - * @private - */ -importer.ImportController.prototype.cancel_ = function() { - if (this.activeImport_) { - this.activeImport_.task.requestCancel(); - this.finalizeActiveImport_(); - metrics.recordBoolean('ImportController.ImportCancelled'); - } - - this.scanManager_.reset(); - this.checkState_(); -}; - -/** - * Checks the environment and updates UI as needed. - * @param {importer.ScanResult=} opt_scan If supplied, - * @private - */ -importer.ImportController.prototype.checkState_ = function(opt_scan) { - // If there is no Google Drive mount, Drive may be disabled - // or the machine may be running in guest mode. - if (!this.environment_.isGoogleDriveMounted()) { - this.updateUi_(importer.ActivityState.HIDDEN); - return; - } - - if (this.activeImport_) { - this.updateUi_(importer.ActivityState.IMPORTING, this.activeImport_.scan); - return; - } - - // If we don't have an existing scan, we'll try to create - // one. When we do end up creating one (not getting - // one from the cache) it'll be empty...even if there is - // a current selection. This is because scans are - // resolved asynchronously. And we like it that way. - // We'll get notification when the scan is updated. When - // that happens, we'll be called back with opt_scan - // set to that scan....and subsequently skip over this - // block to update the UI. - if (!opt_scan) { - // NOTE, that tryScan_ lazily initializes scans...so if - // no scan is returned, no scan is possible for the - // current context. - const scan = this.tryScan_(importer.ScanMode.HISTORY); - // If no scan is created, then no scan is possible in - // the current context...so hide the UI. - if (!scan) { - this.updateUi_(importer.ActivityState.HIDDEN); - } - return; - } - - // At this point we have an existing scan, and a relatively - // validate environment for an import...so we'll proceed - // with making updates to the UI. - if (!opt_scan.isFinal()) { - this.updateUi_(importer.ActivityState.SCANNING, opt_scan); - return; - } - - if (opt_scan.getFileEntries().length === 0) { - if (opt_scan.getDuplicateFileEntries().length === 0) { - this.updateUi_(importer.ActivityState.NO_MEDIA); - return; - } - // Some scanned files found already exist in Drive. - // It means those files weren't marked as already backed up but need to be. - // Trigger sync for that purpose, but no files will actually be copied. - this.startImportTask_(); - this.updateUi_(importer.ActivityState.IMPORTING, this.activeImport_.scan); - return; - } - - // We have a final scan that is either too big, or juuuussttt right. - Promise - .all([ - this.environment_.getFreeStorageSpace( - VolumeManagerCommon.VolumeType.DOWNLOADS), - this.environment_.getFreeStorageSpace( - VolumeManagerCommon.VolumeType.DRIVE), - ]) - .then(/** @param {Array<number>} availableSpace in bytes */ - availableSpace => { - // TODO(smckay): We might want to disqualify some small amount of - // local storage in this calculation on the assumption that we - // don't want to completely max out storage...even though synced - // files will eventually be evicted from the cache. - if (availableSpace[0] < opt_scan.getStatistics().sizeBytes) { - // Doesn't fit in local space. - this.updateUi_( - importer.ActivityState.INSUFFICIENT_LOCAL_SPACE, opt_scan, - availableSpace[0]); - return; - } - if (availableSpace[1] !== -1 && - availableSpace[1] < opt_scan.getStatistics().sizeBytes) { - // Could retrieve cloud quota and doesn't fit. - this.updateUi_( - importer.ActivityState.INSUFFICIENT_CLOUD_SPACE, opt_scan, - availableSpace[1]); - return; - } - - // Enough space available! - this.updateUi_( - importer.ActivityState.READY, // to import... - opt_scan); - if (this.isRightAfterPluggingMedia_) { - this.isRightAfterPluggingMedia_ = false; - this.commandWidget_.setDetailsVisible(true); - } - }) - .catch(error => { - // If an error occurs, it will appear to scan forever - hide the - // cloud backup option in that case. - importer.getLogger().catcher('import-controller-check-state')(error); - this.updateUi_(importer.ActivityState.HIDDEN); - }); -}; - -/** - * @param {importer.ActivityState} activityState - * @param {importer.ScanResult=} opt_scan - * @param {number=} opt_destinationSizeBytes specifies the destination size in - * bytes in case of space issues. - * @private - */ -importer.ImportController.prototype.updateUi_ = function( - activityState, opt_scan, opt_destinationSizeBytes) { - this.lastActivityState_ = activityState; - this.commandWidget_.update(activityState, opt_scan, opt_destinationSizeBytes); -}; - -/** - * @return {boolean} true if the current directory is scan eligible. - * @private - */ -importer.ImportController.prototype.isCurrentDirectoryScannable_ = function() { - const directory = this.environment_.getCurrentDirectory(); - return !!directory && - importer.isMediaDirectory(directory, this.environment_.volumeManager); -}; - -/** - * Attempts to scan the current context. - * - * @param {importer.ScanMode} mode How to detect new files. - * @return {importer.ScanResult} A scan object, - * or null if scan is not possible in current context. - * @private - */ -importer.ImportController.prototype.tryScan_ = function(mode) { - const entries = this.environment_.getSelection(); - if (entries.length) { - if (entries.every(importer.isEligibleEntry.bind( - null, this.environment_.volumeManager))) { - return this.scanManager_.getSelectionScan(entries, mode); - } - } else if (this.isCurrentDirectoryScannable_()) { - return this.scanManager_.getDirectoryScan(mode); - } - - return null; -}; - -/** * Class that adapts from the new non-command button to the old * command style interface. * * @interface */ -importer.CommandWidget = function() {}; +importer.CommandWidget = class { + /** + * Installs a listener that gets called when the user wants to initiate + * import. + * + * @param {function(!importer.ClickSource)} listener + */ + addClickListener(listener) {} -/** - * Install a listener that get's called when the user wants to initiate - * import. - * - * @param {function(!importer.ClickSource)} listener - */ -importer.CommandWidget.prototype.addClickListener; + /** + * @param {importer.ActivityState} activityState + * @param {importer.ScanResult=} opt_scan + * @param {number=} opt_destinationSizeBytes specifies the destination size in + * bytes in case of space issues. + */ + update(activityState, opt_scan, opt_destinationSizeBytes) {} -/** - * @param {importer.ActivityState} activityState - * @param {importer.ScanResult=} opt_scan - * @param {number=} opt_destinationSizeBytes specifies the destination size in - * bytes in case of space issues. - */ -importer.CommandWidget.prototype.update; + /** + * Directly sets the visibility of the details panel. + * @param {boolean} visible + */ + setDetailsVisible(visible) {} -/** - * Directly sets the visibility of the details panel. - * - * @param {boolean} visible - */ -importer.CommandWidget.prototype.setDetailsVisible; + /** Ripples the main button when it's clicked. */ + performMainButtonRippleAnimation() {} -/** - * Toggles the visibility state of the details panel. - */ -importer.CommandWidget.prototype.toggleDetails; + /** Toggles the visibility state of the details panel. */ + toggleDetails() {} -/** - * Sets the details banner visibility. - */ -importer.CommandWidget.prototype.setDetailsBannerVisible; + /** + * Sets the details banner visibility. + * @param {boolean} visible + */ + setDetailsBannerVisible(visible) {} +}; /** * @enum {string} @@ -530,508 +526,494 @@ /** * Runtime implementation of CommandWidget. * - * @constructor * @implements {importer.CommandWidget} - * @struct */ -importer.RuntimeCommandWidget = function() { - /** @private {HTMLElement} */ - this.detailsPanel_ = /** @type {HTMLElement} */ ( - document.querySelector('#cloud-import-details')); - this.detailsPanel_.addEventListener( - 'transitionend', this.onDetailsTransitionEnd_.bind(this), false); +importer.RuntimeCommandWidget = class { + constructor() { + /** @private @const {!HTMLElement} */ + this.detailsPanel_ = queryRequiredElement('#cloud-import-details'); + this.detailsPanel_.addEventListener( + 'transitionend', this.onDetailsTransitionEnd_.bind(this), false); - // Any clicks on document outside of the details panel - // result in the panel being hidden. - document.onclick = this.onDetailsFocusLost_.bind(this); + // Any clicks on document outside of the details panel + // result in the panel being hidden. + document.onclick = this.onDetailsFocusLost_.bind(this); - // Stop further propagation of click events. - // This allows us to listen for *any other* clicks - // to hide the panel. - this.detailsPanel_.onclick = event => { - event.stopPropagation(); - }; - - /** @private {!Element} */ - this.comboButton_ = getRequiredElement('cloud-import-combo-button'); - - /** @private {!Element} */ - this.mainButton_ = - queryRequiredElement('#cloud-import-button', this.comboButton_); - this.mainButton_.onclick = - this.onButtonClicked_.bind(this, importer.ClickSource.MAIN); - - /** @private {!PaperRipple}*/ - this.mainButtonRipple_ = - /** @type {!PaperRipple} */ ( - queryRequiredElement('.ripples > paper-ripple', this.comboButton_)); - - /** @private {Element} */ - this.sideButton_ = - queryRequiredElement('#cloud-import-details-button', this.comboButton_); - this.sideButton_.onclick = - this.onButtonClicked_.bind(this, importer.ClickSource.SIDE); - - /** @private {!FilesToggleRipple} */ - this.sideButtonRipple_ = - /** @type {!FilesToggleRipple} */ (queryRequiredElement( - '.ripples > files-toggle-ripple', this.comboButton_)); - - /** @private {Element} */ - this.importButton_ = - document.querySelector('#cloud-import-details paper-button.import'); - this.importButton_.onclick = - this.onButtonClicked_.bind(this, importer.ClickSource.IMPORT); - - /** @private {Element} */ - this.cancelButton_ = - document.querySelector('#cloud-import-details paper-button.cancel'); - this.cancelButton_.onclick = - this.onButtonClicked_.bind(this, importer.ClickSource.CANCEL); - - /** @private {Element} */ - this.statusContent_ = - document.querySelector('#cloud-import-details .status .content'); - this.statusContent_.onclick = - this.onButtonClicked_.bind(this, importer.ClickSource.DESTINATION); - - /** @private {Element} */ - this.toolbarIcon_ = document.querySelector('#cloud-import-button iron-icon'); - this.statusIcon_ = - document.querySelector('#cloud-import-details .status iron-icon'); - - /** @private {Element} */ - this.detailsBanner_ = document.querySelector('#cloud-import-details .banner'); - - /** @private {Element} */ - this.progressContainer_ = - document.querySelector('#cloud-import-details .progress'); - /** @private {Element} */ - this.progressBar_ = - document.querySelector('#cloud-import-details .progress .value'); - - /** @private {function(!importer.ClickSource)} */ - this.clickListener_; - - document.addEventListener('keydown', this.onKeyDown_.bind(this)); - - /** @private{number} */ - this.cloudImportButtonTabIndex_ = - document.querySelector('button#cloud-import-button').tabIndex; -}; - -/** - * Handles document scoped key-down events. - * @param {Event} event Key event. - * @private - */ -importer.RuntimeCommandWidget.prototype.onKeyDown_ = function(event) { - switch (util.getKeyModifiers(event) + event.key) { - case 'Escape': - this.setDetailsVisible(false); - } -}; - -/** - * Ensures that a transitionend event gets sent out after a transition. Similar - * to ensureTransitionEndEvent (see ui/webui/resources/js/util.js) but sends a - * standard-compliant rather than a webkit event. - * - * @param {!HTMLElement} element - * @param {number} timeout In milliseconds. - */ -importer.RuntimeCommandWidget.ensureTransitionEndEvent = (element, timeout) => { - let fired = false; - element.addEventListener('transitionend', function f(e) { - element.removeEventListener('transitionend', f); - fired = true; - }); - // Use a timeout of 400 ms. - window.setTimeout(() => { - if (!fired) { - cr.dispatchSimpleEvent(element, 'transitionend', true); - } - }, timeout); -}; - -/** @override */ -importer.RuntimeCommandWidget.prototype.addClickListener = function(listener) { - this.clickListener_ = listener; -}; - -/** - * @param {!importer.ClickSource} source - * @param {Event} event Click event. - * @private - */ -importer.RuntimeCommandWidget.prototype.onButtonClicked_ = function( - source, event) { - console.assert(!!this.clickListener_, 'Listener not set.'); - - // Clear focus from the toolbar button after it is clicked. - if (source === importer.ClickSource.MAIN) { - this.mainButton_.blur(); - } - - switch (source) { - case importer.ClickSource.MAIN: - case importer.ClickSource.IMPORT: - case importer.ClickSource.CANCEL: - this.clickListener_(source); - break; - case importer.ClickSource.DESTINATION: - // NOTE: The element identified by class 'destination-link' - // comes and goes as the message in the UI changes. - // For this reason we add a click listener on the *container* - // and when handling clicks, check to see if the source - // was an element marked up to look like a link. - if (event.target.classList.contains('destination-link')) { - this.clickListener_(source); - } - case importer.ClickSource.SIDE: - this.toggleDetails(); - break; - default: - assertNotReached('Unhandled click source: ' + source); - } - - event.stopPropagation(); -}; - -importer.RuntimeCommandWidget.prototype.performMainButtonRippleAnimation = - function() { - this.mainButtonRipple_.simulatedRipple(); -}; - -/** @override */ -importer.RuntimeCommandWidget.prototype.toggleDetails = function() { - this.setDetailsVisible(this.detailsPanel_.className === 'hidden'); -}; - -/** @override */ -importer.RuntimeCommandWidget.prototype.setDetailsBannerVisible = function( - visible) { - this.detailsBanner_.hidden = !visible; -}; - -/** - * @param {boolean} visible - */ -importer.RuntimeCommandWidget.prototype.setDetailsVisible = function(visible) { - this.sideButtonRipple_.activated = visible; - - if (visible) { - // Align the detail panel horizontally to the dropdown button. - if (document.documentElement.getAttribute('dir') === 'rtl') { - const anchorLeft = this.comboButton_.getBoundingClientRect().left; - if (anchorLeft) { - this.detailsPanel_.style.left = anchorLeft + 'px'; - } - } else { - const availableWidth = document.body.getBoundingClientRect().width; - const anchorRight = this.comboButton_.getBoundingClientRect().right; - if (anchorRight) { - this.detailsPanel_.style.right = (availableWidth - anchorRight) + 'px'; - } - } - - this.detailsPanel_.hidden = false; - - // The following line is a hacky way to force the container to lay out - // contents so that the transition is triggered. - // This line MUST appear before clearing the classname. - this.detailsPanel_.scrollTop += 0; - - this.detailsPanel_.className = ''; - } else { - this.detailsPanel_.className = 'hidden'; - // transition duration is 200ms. Let's wait for 400ms. - importer.RuntimeCommandWidget.ensureTransitionEndEvent( - /** @type {!HTMLElement} */ (this.detailsPanel_), 400); - } -}; - -/** @private */ -importer.RuntimeCommandWidget.prototype.onDetailsTransitionEnd_ = function() { - if (this.detailsPanel_.className === 'hidden') { - // if we simply make the panel invisible (via opacity) - // it'll still be sitting there grabing mouse events - // and so-on. So we *hide* hide it. - this.detailsPanel_.hidden = true; - } -}; - -/** @private */ -importer.RuntimeCommandWidget.prototype.onDetailsFocusLost_ = function() { - this.setDetailsVisible(false); -}; - -/** - * Overwrites the tabIndexes of all anchors under the given element. - * - * @param {Element} root The root node of all nodes to process. - * @param {number} newTabIndex The tabindex value to be given to <a> elements. - * @private - */ -importer.RuntimeCommandWidget.prototype.updateTabindexOfAnchors_ = - (root, newTabIndex) => { - const anchors = root.querySelectorAll('a'); - anchors.forEach(element => { - element.tabIndex = newTabIndex; - }); + // Stop further propagation of click events. + // This allows us to listen for *any other* clicks + // to hide the panel. + this.detailsPanel_.onclick = event => { + event.stopPropagation(); }; -/** @override */ -importer.RuntimeCommandWidget.prototype.update = function( - activityState, opt_scan, opt_destinationSizeBytes) { - let photosText; - if (opt_scan) { - const detectedFilesCount = opt_scan.getFileEntries().length; - if (detectedFilesCount) { - photosText = detectedFilesCount == 1 ? - strf('CLOUD_IMPORT_ONE_FILE') : - strf('CLOUD_IMPORT_MULTIPLE_FILES', detectedFilesCount); - } else { - photosText = ''; + /** @private @const {!HTMLElement} */ + this.comboButton_ = getRequiredElement('cloud-import-combo-button'); + + /** @private @const {!HTMLElement} */ + this.mainButton_ = + queryRequiredElement('#cloud-import-button', this.comboButton_); + this.mainButton_.onclick = + this.onButtonClicked_.bind(this, importer.ClickSource.MAIN); + + /** @private @const {!PaperRipple}*/ + this.mainButtonRipple_ = + /** @type {!PaperRipple} */ ( + queryRequiredElement('.ripples > paper-ripple', this.comboButton_)); + + /** @private @const {!HTMLElement} */ + this.sideButton_ = + queryRequiredElement('#cloud-import-details-button', this.comboButton_); + this.sideButton_.onclick = + this.onButtonClicked_.bind(this, importer.ClickSource.SIDE); + + /** @private @const {!FilesToggleRipple} */ + this.sideButtonRipple_ = + /** @type {!FilesToggleRipple} */ (queryRequiredElement( + '.ripples > files-toggle-ripple', this.comboButton_)); + + /** @private @const {!HTMLElement} */ + this.importButton_ = + queryRequiredElement('#cloud-import-details paper-button.import'); + this.importButton_.onclick = + this.onButtonClicked_.bind(this, importer.ClickSource.IMPORT); + + /** @private @const {!HTMLElement} */ + this.cancelButton_ = + queryRequiredElement('#cloud-import-details paper-button.cancel'); + this.cancelButton_.onclick = + this.onButtonClicked_.bind(this, importer.ClickSource.CANCEL); + + /** @private @const {!HTMLElement} */ + this.statusContent_ = + queryRequiredElement('#cloud-import-details .status .content'); + this.statusContent_.onclick = + this.onButtonClicked_.bind(this, importer.ClickSource.DESTINATION); + + /** @private @const {!HTMLElement} */ + this.toolbarIcon_ = queryRequiredElement('#cloud-import-button iron-icon'); + + /** @private @const {!HTMLElement} */ + this.statusIcon_ = + queryRequiredElement('#cloud-import-details .status iron-icon'); + + /** @private @const {!HTMLElement} */ + this.detailsBanner_ = queryRequiredElement('#cloud-import-details .banner'); + + /** @private @const {!HTMLElement} */ + this.progressContainer_ = + queryRequiredElement('#cloud-import-details .progress'); + + /** @private @const {!HTMLElement} */ + this.progressBar_ = + queryRequiredElement('#cloud-import-details .progress .value'); + + /** @private {function(!importer.ClickSource)} */ + this.clickListener_; + + document.addEventListener('keydown', this.onKeyDown_.bind(this)); + + /** @private @const{number} */ + this.cloudImportButtonTabIndex_ = + queryRequiredElement('button#cloud-import-button').tabIndex; + } + + /** + * Handles document scoped key-down events. + * @param {Event} event Key event. + * @private + */ + onKeyDown_(event) { + switch (util.getKeyModifiers(event) + event.key) { + case 'Escape': + this.setDetailsVisible(false); } } - switch (activityState) { - case importer.ActivityState.HIDDEN: - this.setDetailsVisible(false); - this.comboButton_.hidden = true; + /** + * Ensures that a transitionend event gets sent out after a transition. + * Similar to ensureTransitionEndEvent (see ui/webui/resources/js/util.js) but + * sends a standard-compliant rather than a webkit event. + * + * @param {!HTMLElement} element + * @param {number} timeout In milliseconds. + */ + static ensureTransitionEndEvent(element, timeout) { + let fired = false; + element.addEventListener('transitionend', function f(e) { + element.removeEventListener('transitionend', f); + fired = true; + }); + // Use a timeout of 400 ms. + window.setTimeout(() => { + if (!fired) { + cr.dispatchSimpleEvent(element, 'transitionend', true); + } + }, timeout); + } - this.toolbarIcon_.setAttribute('icon', 'files:cloud-off'); - this.statusIcon_.setAttribute('icon', 'files:cloud-off'); + /** @override */ + addClickListener(listener) { + this.clickListener_ = listener; + } - break; + /** + * @param {!importer.ClickSource} source + * @param {Event} event Click event. + * @private + */ + onButtonClicked_(source, event) { + console.assert(!!this.clickListener_, 'Listener not set.'); - case importer.ActivityState.IMPORTING: - console.assert(!!opt_scan, 'Scan not defined, but is required.'); - this.setDetailsVisible(false); + // Clear focus from the toolbar button after it is clicked. + if (source === importer.ClickSource.MAIN) { + this.mainButton_.blur(); + } - this.mainButton_.setAttribute( - 'aria-label', strf('CLOUD_IMPORT_TOOLTIP_IMPORTING', photosText)); - this.statusContent_.innerHTML = - strf('CLOUD_IMPORT_STATUS_IMPORTING', photosText); - - this.comboButton_.hidden = false; - this.importButton_.hidden = true; - this.cancelButton_.hidden = false; - this.progressContainer_.hidden = true; - - this.toolbarIcon_.setAttribute('icon', 'files:autorenew'); - this.statusIcon_.setAttribute('icon', 'files:autorenew'); - - break; - - case importer.ActivityState.INSUFFICIENT_CLOUD_SPACE: - case importer.ActivityState.INSUFFICIENT_LOCAL_SPACE: - console.assert(!!opt_scan, 'Scan not defined, but is required.'); - - { - let attrLabel; - let messageLabel; - if (activityState === importer.ActivityState.INSUFFICIENT_CLOUD_SPACE) { - attrLabel = 'CLOUD_IMPORT_TOOLTIP_INSUFFICIENT_CLOUD_SPACE'; - messageLabel = 'CLOUD_IMPORT_STATUS_INSUFFICIENT_CLOUD_SPACE'; - } else { - attrLabel = 'CLOUD_IMPORT_TOOLTIP_INSUFFICIENT_LOCAL_SPACE'; - messageLabel = 'CLOUD_IMPORT_STATUS_INSUFFICIENT_LOCAL_SPACE'; + switch (source) { + case importer.ClickSource.MAIN: + case importer.ClickSource.IMPORT: + case importer.ClickSource.CANCEL: + this.clickListener_(source); + break; + case importer.ClickSource.DESTINATION: + // NOTE: The element identified by class 'destination-link' + // comes and goes as the message in the UI changes. + // For this reason we add a click listener on the *container* + // and when handling clicks, check to see if the source + // was an element marked up to look like a link. + if (event.target.classList.contains('destination-link')) { + this.clickListener_(source); } - this.mainButton_.setAttribute('aria-label', strf(attrLabel)); - this.statusContent_.innerHTML = strf( - messageLabel, photosText, - util.bytesToString( - opt_scan.getStatistics().sizeBytes - opt_destinationSizeBytes)); + case importer.ClickSource.SIDE: + this.toggleDetails(); + break; + default: + assertNotReached('Unhandled click source: ' + source); + } + + event.stopPropagation(); + } + + /** @override */ + performMainButtonRippleAnimation() { + this.mainButtonRipple_.simulatedRipple(); + } + + /** @override */ + toggleDetails() { + this.setDetailsVisible(this.detailsPanel_.className === 'hidden'); + } + + /** @override */ + setDetailsBannerVisible(visible) { + this.detailsBanner_.hidden = !visible; + } + + /** @param {boolean} visible */ + setDetailsVisible(visible) { + this.sideButtonRipple_.activated = visible; + + if (visible) { + // Align the detail panel horizontally to the dropdown button. + if (document.documentElement.getAttribute('dir') === 'rtl') { + const anchorLeft = this.comboButton_.getBoundingClientRect().left; + if (anchorLeft) { + this.detailsPanel_.style.left = anchorLeft + 'px'; + } + } else { + const availableWidth = document.body.getBoundingClientRect().width; + const anchorRight = this.comboButton_.getBoundingClientRect().right; + if (anchorRight) { + this.detailsPanel_.style.right = + (availableWidth - anchorRight) + 'px'; + } } - this.comboButton_.hidden = false; - this.importButton_.hidden = true; - this.cancelButton_.hidden = true; - this.progressContainer_.hidden = true; + this.detailsPanel_.hidden = false; - this.toolbarIcon_.setAttribute('icon', 'files:cloud-off'); - this.statusIcon_.setAttribute('icon', 'files:photo'); - break; + // The following line is a hacky way to force the container to lay out + // contents so that the transition is triggered. + // This line MUST appear before clearing the classname. + this.detailsPanel_.scrollTop += 0; - case importer.ActivityState.NO_MEDIA: - this.mainButton_.setAttribute( - 'aria-label', str('CLOUD_IMPORT_TOOLTIP_NO_MEDIA')); - this.statusContent_.innerHTML = str('CLOUD_IMPORT_STATUS_NO_MEDIA'); - - this.comboButton_.hidden = false; - this.importButton_.hidden = true; - this.cancelButton_.hidden = true; - this.progressContainer_.hidden = true; - - this.toolbarIcon_.setAttribute('icon', 'files:cloud-done'); - this.statusIcon_.setAttribute('icon', 'files:cloud-done'); - break; - - case importer.ActivityState.READY: - console.assert(!!opt_scan, 'Scan not defined, but is required.'); - - this.mainButton_.setAttribute( - 'aria-label', strf('CLOUD_IMPORT_TOOLTIP_READY', photosText)); - this.statusContent_.innerHTML = - strf('CLOUD_IMPORT_STATUS_READY', photosText); - - this.comboButton_.hidden = false; - this.importButton_.hidden = false; - this.cancelButton_.hidden = true; - this.progressContainer_.hidden = true; - - this.toolbarIcon_.setAttribute('icon', 'files:cloud-upload'); - this.statusIcon_.setAttribute('icon', 'files:photo'); - break; - - case importer.ActivityState.SCANNING: - console.assert(!!opt_scan, 'Scan not defined, but is required.'); - - this.mainButton_.setAttribute( - 'aria-label', str('CLOUD_IMPORT_TOOLTIP_SCANNING')); - this.statusContent_.innerHTML = - strf('CLOUD_IMPORT_STATUS_SCANNING', photosText); - - this.comboButton_.hidden = false; - this.importButton_.hidden = true; - // TODO(smckay): implement cancellation for scanning. - this.cancelButton_.hidden = true; - this.progressContainer_.hidden = false; - - const stats = opt_scan.getStatistics(); - this.progressBar_.style.width = stats.progress + '%'; - - this.toolbarIcon_.setAttribute('icon', 'files:autorenew'); - this.statusIcon_.setAttribute('icon', 'files:autorenew'); - break; - - default: - assertNotReached('Unrecognized response id: ' + activityState); - } - // Make all anchors synthesized from the localized text focusable. - if (this.cloudImportButtonTabIndex_) { - this.updateTabindexOfAnchors_( - this.statusContent_, this.cloudImportButtonTabIndex_); - } -}; - -/** - * A cache for ScanResults. - * - * @constructor - * @struct - * - * @param {!importer.ControllerEnvironment} environment - * @param {!importer.MediaScanner} scanner - */ -importer.ScanManager = function(environment, scanner) { - /** @private {!importer.ControllerEnvironment} */ - this.environment_ = environment; - - /** @private {!importer.MediaScanner} */ - this.scanner_ = scanner; - - /** - * The active files scan, if any. - * - * @private {importer.ScanResult} - */ - this.selectionScan_ = null; - - /** - * The active directory scan, if any. - * - * @private {importer.ScanResult} - */ - this.directoryScan_ = null; -}; - -/** - * Cancels and forgets all scans. - */ -importer.ScanManager.prototype.reset = function() { - this.clearSelectionScan(); - this.clearDirectoryScan(); -}; - -/** - * @return {boolean} True if we have an existing selection scan. - */ -importer.ScanManager.prototype.hasSelectionScan = function() { - return !!this.selectionScan_; -}; - -/** - * Cancels and forgets the current selection scan, if any. - */ -importer.ScanManager.prototype.clearSelectionScan = function() { - if (this.selectionScan_) { - this.selectionScan_.cancel(); - } - this.selectionScan_ = null; -}; - -/** - * Cancels and forgets the current directory scan, if any. - */ -importer.ScanManager.prototype.clearDirectoryScan = function() { - if (this.directoryScan_) { - this.directoryScan_.cancel(); - } - this.directoryScan_ = null; -}; - -/** - * @return {importer.ScanResult} Current active scan, or null - * if none. - */ -importer.ScanManager.prototype.getActiveScan = function() { - return this.selectionScan_ || this.directoryScan_; -}; - -/** - * @param {importer.ScanResult} scan - * @return {boolean} True if scan is the active scan...meaning the current - * selection scan or the scan for the current directory. - */ -importer.ScanManager.prototype.isActiveScan = function(scan) { - return scan === this.selectionScan_ || scan === this.directoryScan_; -}; - -/** - * Returns the existing selection scan or a new one for the supplied - * selection. - * - * @param {!Array<!FileEntry>} entries - * @param {!importer.ScanMode} mode - * - * @return {!importer.ScanResult} - */ -importer.ScanManager.prototype.getSelectionScan = function(entries, mode) { - console.assert( - !this.selectionScan_, - 'Cannot create new selection scan with another in the cache.'); - this.selectionScan_ = this.scanner_.scanFiles(entries, mode); - return this.selectionScan_; -}; - -/** - * Returns a scan for the directory. - * - * @param {!importer.ScanMode} mode - * @return {importer.ScanResult} - */ -importer.ScanManager.prototype.getDirectoryScan = function(mode) { - if (!this.directoryScan_) { - const directory = this.environment_.getCurrentDirectory(); - if (directory) { - this.directoryScan_ = this.scanner_.scanDirectory( - /** @type {!DirectoryEntry} */ (directory), mode); + this.detailsPanel_.className = ''; + } else { + this.detailsPanel_.className = 'hidden'; + // transition duration is 200ms. Let's wait for 400ms. + importer.RuntimeCommandWidget.ensureTransitionEndEvent( + /** @type {!HTMLElement} */ (this.detailsPanel_), 400); } } - return this.directoryScan_; + + /** @private */ + onDetailsTransitionEnd_() { + if (this.detailsPanel_.className === 'hidden') { + // if we simply make the panel invisible (via opacity) + // it'll still be sitting there grabbing mouse events + // and so-on. So we *hide* it. + this.detailsPanel_.hidden = true; + } + } + + /** @private */ + onDetailsFocusLost_() { + this.setDetailsVisible(false); + } + + /** + * Overwrites the tabIndexes of all anchors under the given element. + * + * @param {Element} root The root node of all nodes to process. + * @param {number} newTabIndex The tabindex value to be given to <a> elements. + * @private + */ + static updateTabIndexOfAnchors_(root, newTabIndex) { + const anchors = root.querySelectorAll('a'); + anchors.forEach(element => { + element.tabIndex = newTabIndex; + }); + } + + /** @override */ + update(activityState, opt_scan, opt_destinationSizeBytes) { + let photosText; + if (opt_scan) { + const detectedFilesCount = opt_scan.getFileEntries().length; + if (detectedFilesCount) { + photosText = detectedFilesCount == 1 ? + strf('CLOUD_IMPORT_ONE_FILE') : + strf('CLOUD_IMPORT_MULTIPLE_FILES', detectedFilesCount); + } else { + photosText = ''; + } + } + + switch (activityState) { + case importer.ActivityState.HIDDEN: + this.setDetailsVisible(false); + + this.comboButton_.hidden = true; + + this.toolbarIcon_.setAttribute('icon', 'files:cloud-off'); + this.statusIcon_.setAttribute('icon', 'files:cloud-off'); + + break; + + case importer.ActivityState.IMPORTING: + console.assert(!!opt_scan, 'Scan not defined, but is required.'); + this.setDetailsVisible(false); + + this.mainButton_.setAttribute( + 'aria-label', strf('CLOUD_IMPORT_TOOLTIP_IMPORTING', photosText)); + this.statusContent_.innerHTML = + strf('CLOUD_IMPORT_STATUS_IMPORTING', photosText); + + this.comboButton_.hidden = false; + this.importButton_.hidden = true; + this.cancelButton_.hidden = false; + this.progressContainer_.hidden = true; + + this.toolbarIcon_.setAttribute('icon', 'files:autorenew'); + this.statusIcon_.setAttribute('icon', 'files:autorenew'); + + break; + + case importer.ActivityState.INSUFFICIENT_CLOUD_SPACE: + case importer.ActivityState.INSUFFICIENT_LOCAL_SPACE: + console.assert(!!opt_scan, 'Scan not defined, but is required.'); + + { + let attrLabel; + let messageLabel; + if (activityState === + importer.ActivityState.INSUFFICIENT_CLOUD_SPACE) { + attrLabel = 'CLOUD_IMPORT_TOOLTIP_INSUFFICIENT_CLOUD_SPACE'; + messageLabel = 'CLOUD_IMPORT_STATUS_INSUFFICIENT_CLOUD_SPACE'; + } else { + attrLabel = 'CLOUD_IMPORT_TOOLTIP_INSUFFICIENT_LOCAL_SPACE'; + messageLabel = 'CLOUD_IMPORT_STATUS_INSUFFICIENT_LOCAL_SPACE'; + } + this.mainButton_.setAttribute('aria-label', strf(attrLabel)); + this.statusContent_.innerHTML = strf( + messageLabel, photosText, + util.bytesToString( + opt_scan.getStatistics().sizeBytes - + opt_destinationSizeBytes)); + } + + this.comboButton_.hidden = false; + this.importButton_.hidden = true; + this.cancelButton_.hidden = true; + this.progressContainer_.hidden = true; + + this.toolbarIcon_.setAttribute('icon', 'files:cloud-off'); + this.statusIcon_.setAttribute('icon', 'files:photo'); + break; + + case importer.ActivityState.NO_MEDIA: + this.mainButton_.setAttribute( + 'aria-label', str('CLOUD_IMPORT_TOOLTIP_NO_MEDIA')); + this.statusContent_.innerHTML = str('CLOUD_IMPORT_STATUS_NO_MEDIA'); + + this.comboButton_.hidden = false; + this.importButton_.hidden = true; + this.cancelButton_.hidden = true; + this.progressContainer_.hidden = true; + + this.toolbarIcon_.setAttribute('icon', 'files:cloud-done'); + this.statusIcon_.setAttribute('icon', 'files:cloud-done'); + break; + + case importer.ActivityState.READY: + console.assert(!!opt_scan, 'Scan not defined, but is required.'); + + this.mainButton_.setAttribute( + 'aria-label', strf('CLOUD_IMPORT_TOOLTIP_READY', photosText)); + this.statusContent_.innerHTML = + strf('CLOUD_IMPORT_STATUS_READY', photosText); + + this.comboButton_.hidden = false; + this.importButton_.hidden = false; + this.cancelButton_.hidden = true; + this.progressContainer_.hidden = true; + + this.toolbarIcon_.setAttribute('icon', 'files:cloud-upload'); + this.statusIcon_.setAttribute('icon', 'files:photo'); + break; + + case importer.ActivityState.SCANNING: + console.assert(!!opt_scan, 'Scan not defined, but is required.'); + + this.mainButton_.setAttribute( + 'aria-label', str('CLOUD_IMPORT_TOOLTIP_SCANNING')); + this.statusContent_.innerHTML = + strf('CLOUD_IMPORT_STATUS_SCANNING', photosText); + + this.comboButton_.hidden = false; + this.importButton_.hidden = true; + // TODO(smckay): implement cancellation for scanning. + this.cancelButton_.hidden = true; + this.progressContainer_.hidden = false; + + const stats = opt_scan.getStatistics(); + this.progressBar_.style.width = stats.progress + '%'; + + this.toolbarIcon_.setAttribute('icon', 'files:autorenew'); + this.statusIcon_.setAttribute('icon', 'files:autorenew'); + break; + + default: + assertNotReached('Unrecognized response id: ' + activityState); + } + + // Make all anchors synthesized from the localized text focusable. + if (this.cloudImportButtonTabIndex_) { + importer.RuntimeCommandWidget.updateTabIndexOfAnchors_( + this.statusContent_, this.cloudImportButtonTabIndex_); + } + } +}; + +/** A cache for ScanResults. */ +importer.ScanManager = class { + /** + * @param {!importer.ControllerEnvironment} environment + * @param {!importer.MediaScanner} scanner + */ + constructor(environment, scanner) { + /** @private {!importer.ControllerEnvironment} */ + this.environment_ = environment; + + /** @private @const {!importer.MediaScanner} */ + this.scanner_ = scanner; + + /** + * The active files scan, if any. + * @private {?importer.ScanResult} + */ + this.selectionScan_ = null; + + /** + * The active directory scan, if any. + * @private {?importer.ScanResult} + */ + this.directoryScan_ = null; + } + + /** Cancels and forgets all scans. */ + reset() { + this.clearSelectionScan(); + this.clearDirectoryScan(); + } + + /** @return {boolean} True if we have an existing selection scan. */ + hasSelectionScan() { + return !!this.selectionScan_; + } + + /** Cancels and forgets the current selection scan, if any. */ + clearSelectionScan() { + if (this.selectionScan_) { + this.selectionScan_.cancel(); + } + this.selectionScan_ = null; + } + + /** Cancels and forgets the current directory scan, if any. */ + clearDirectoryScan() { + if (this.directoryScan_) { + this.directoryScan_.cancel(); + } + this.directoryScan_ = null; + } + + /** @return {importer.ScanResult} Current active scan, or null if none. */ + getActiveScan() { + return this.selectionScan_ || this.directoryScan_; + } + + /** + * @param {importer.ScanResult} scan + * @return {boolean} True if scan is the active scan...meaning the current + * selection scan or the scan for the current directory. + */ + isActiveScan(scan) { + return scan === this.selectionScan_ || scan === this.directoryScan_; + } + + /** + * Returns the existing selection scan or a new one for the supplied + * selection. + * + * @param {!Array<!FileEntry>} entries + * @param {!importer.ScanMode} mode + * + * @return {!importer.ScanResult} + */ + getSelectionScan(entries, mode) { + console.assert( + !this.selectionScan_, + 'Cannot create new selection scan with another in the cache.'); + this.selectionScan_ = this.scanner_.scanFiles(entries, mode); + return this.selectionScan_; + } + + /** + * Returns a scan for the directory. + * + * @param {!importer.ScanMode} mode + * @return {importer.ScanResult} + */ + getDirectoryScan(mode) { + if (!this.directoryScan_) { + const directory = this.environment_.getCurrentDirectory(); + if (directory) { + this.directoryScan_ = this.scanner_.scanDirectory( + /** @type {!DirectoryEntry} */ (directory), mode); + } + } + return this.directoryScan_; + } }; /** @@ -1041,288 +1023,279 @@ * * @interface */ -importer.ControllerEnvironment = function() {}; +importer.ControllerEnvironment = class { + constructor() { + /** @type {!VolumeManager} */ + this.volumeManager; + } -/** @type {!VolumeManager} */ -importer.ControllerEnvironment.prototype.volumeManager; + /** + * Returns the current file selection, if any. May be empty. + * @return {!Array<!Entry>} + */ + getSelection() {} -/** - * Returns the current file selection, if any. May be empty. - * @return {!Array<!Entry>} - */ -importer.ControllerEnvironment.prototype.getSelection; + /** + * Returns the directory entry for the current directory. + * @return {DirectoryEntry|FilesAppEntry} + */ + getCurrentDirectory() {} -/** - * Returns the directory entry for the current directory. - * @return {DirectoryEntry|FilesAppEntry} - */ -importer.ControllerEnvironment.prototype.getCurrentDirectory; + /** + * @param {!DirectoryEntry} entry + */ + setCurrentDirectory(entry) {} -/** - * @param {!DirectoryEntry} entry - */ -importer.ControllerEnvironment.prototype.setCurrentDirectory; + /** + * Obtains a volume info containing the passed entry. + * @param {!Entry|!FilesAppEntry} entry Entry on the volume to be + * returned. Can be fake. + * @return {VolumeInfo} The VolumeInfo instance or null if not found. + */ + getVolumeInfo(entry) {} -/** - * Obtains a volume info containing the passed entry. - * @param {!Entry|!FilesAppEntry} entry Entry on the volume to be - * returned. Can be fake. - * @return {VolumeInfo} The VolumeInfo instance or null if not found. - */ -importer.ControllerEnvironment.prototype.getVolumeInfo; + /** + * Returns true if the Drive mount is present. + * @return {boolean} + */ + isGoogleDriveMounted() {} -/** - * Returns true if the Drive mount is present. - * @return {boolean} - */ -importer.ControllerEnvironment.prototype.isGoogleDriveMounted; + /** + * Returns the available space for the given volume in bytes, or -1 + * if the the available space is not checkable. + * Rejects if the volume is not mounted. + * @param {!VolumeManagerCommon.VolumeType} volumeType + * @return {!Promise<number>} + */ + getFreeStorageSpace(volumeType) {} -/** - * Returns the available space for the given volume in bytes, or -1 - * if the the available space is not checkable. - * Rejects if the volume is not mounted. - * @param {!VolumeManagerCommon.VolumeType} volumeType - * @return {!Promise<number>} - */ -importer.ControllerEnvironment.prototype.getFreeStorageSpace; + /** + * Installs a 'window closed' listener. Listener is called just + * just before the window is closed. Any business must be + * done synchronously. + * @param {function()} listener + */ + addWindowCloseListener(listener) {} -/** - * Installs a 'window closed' listener. Listener is called just - * just before the window is closed. Any business must be - * done synchronously. - * @param {function()} listener - */ -importer.ControllerEnvironment.prototype.addWindowCloseListener; + /** + * Installs an 'unmount' listener. Listener is called with + * the corresponding volume id when a volume is unmounted. + * @param {function(string)} listener + */ + addVolumeUnmountListener(listener) {} -/** - * Installs an 'unmount' listener. Listener is called with - * the corresponding volume id when a volume is unmounted. - * @param {function(string)} listener - */ -importer.ControllerEnvironment.prototype.addVolumeUnmountListener; + /** + * Installs an 'directory-changed' listener. Listener is called when + * the directory changed. + * @param {function(!Event)} listener + */ + addDirectoryChangedListener(listener) {} -/** - * Installs an 'directory-changed' listener. Listener is called when - * the directory changed. - * @param {function(!Event)} listener - */ -importer.ControllerEnvironment.prototype.addDirectoryChangedListener; + /** + * Installs an 'selection-changed' listener. Listener is called when + * user selected files is changed. + * @param {function()} listener + */ + addSelectionChangedListener(listener) {} -/** - * Installs an 'selection-changed' listener. Listener is called when - * user selected files is changed. - * @param {function()} listener - */ -importer.ControllerEnvironment.prototype.addSelectionChangedListener; + /** + * Reveals the import root directory (the parent of all import destinations) + * in a new Files app window. + * E.g. "Chrome OS Cloud backup". Creates it if it doesn't exist. + * + * @return {!Promise} Resolves when the folder has been shown. + */ + showImportRoot() {} -/** - * Reveals the import root directory (the parent of all import destinations) - * in a new Files app window. - * E.g. "Chrome OS Cloud backup". Creates it if it doesn't exist. - * - * @return {!Promise} Resolves when the folder has been shown. - */ -importer.ControllerEnvironment.prototype.showImportRoot; + /** + * Returns the date-stamped import destination directory in a new + * Files app window. E.g. "2015-12-04". + * Creates it if it doesn't exist. + * + * @param {!Date} date The import date + * @return {!Promise<!DirectoryEntry>} Resolves when the folder is available. + */ + getImportDestination(date) {} -/** - * Returns the date-stamped import destination directory in a new - * Files app window. E.g. "2015-12-04". - * Creates it if it doesn't exist. - * - * @param {!Date} date The import date - * - * @return {!Promise<!DirectoryEntry>} Resolves when the folder is available. - */ -importer.ControllerEnvironment.prototype.getImportDestination; - -/** - * Reveals the date-stamped import destination directory in a new - * Files app window. E.g. "2015-12-04". - * Creates it if it doesn't exist. - * - * @param {!Date} date The import date - * - * @return {!Promise} Resolves when the folder has been shown. - */ -importer.ControllerEnvironment.prototype.showImportDestination; + /** + * Reveals the date-stamped import destination directory in a new + * Files app window. E.g. "2015-12-04". + * Creates it if it doesn't exist. + * + * @param {!Date} date The import date + * @return {!Promise} Resolves when the folder has been shown. + */ + showImportDestination(date) {} +}; /** * Class providing access to various pieces of information in the * FileManager environment, like the current directory, volumeinfo lookup * By hiding file manager we make it easy to test importer.ImportController. * - * @constructor * @implements {importer.ControllerEnvironment} - * - * @param {!CommandHandlerDeps} fileManager - * @param {!FileSelectionHandler} selectionHandler */ -importer.RuntimeControllerEnvironment = function( - fileManager, selectionHandler) { - this.volumeManager = fileManager.volumeManager; +importer.RuntimeControllerEnvironment = class { + /** + * @param {!CommandHandlerDeps} fileManager + * @param {!FileSelectionHandler} selectionHandler + */ + constructor(fileManager, selectionHandler) { + this.volumeManager = fileManager.volumeManager; - /** @private {!CommandHandlerDeps} */ - this.fileManager_ = fileManager; + /** @private {!CommandHandlerDeps} */ + this.fileManager_ = fileManager; - /** @private {!FileSelectionHandler} */ - this.selectionHandler_ = selectionHandler; -}; + /** @private {!FileSelectionHandler} */ + this.selectionHandler_ = selectionHandler; + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.getSelection = function() { - return this.fileManager_.getSelection().entries; -}; + /** @override */ + getSelection() { + return this.fileManager_.getSelection().entries; + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.getCurrentDirectory = - function() { - return this.fileManager_.getCurrentDirectoryEntry(); -}; + /** @override */ + getCurrentDirectory() { + return this.fileManager_.getCurrentDirectoryEntry(); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.setCurrentDirectory = function( - entry) { - this.fileManager_.directoryModel.activateDirectoryEntry(entry); -}; + /** @override */ + setCurrentDirectory(entry) { + this.fileManager_.directoryModel.activateDirectoryEntry(entry); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.getVolumeInfo = function( - entry) { - return this.fileManager_.volumeManager.getVolumeInfo(entry); -}; + /** @override */ + getVolumeInfo(entry) { + return this.fileManager_.volumeManager.getVolumeInfo(entry); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.isGoogleDriveMounted = - function() { - const drive = this.fileManager_.volumeManager.getCurrentProfileVolumeInfo( - VolumeManagerCommon.VolumeType.DRIVE); - return !!drive; -}; + /** @override */ + isGoogleDriveMounted() { + const drive = this.fileManager_.volumeManager.getCurrentProfileVolumeInfo( + VolumeManagerCommon.VolumeType.DRIVE); + return !!drive; + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.getFreeStorageSpace = function( - volumeType) { - // VolumeInfo will exist, because if it doesn't, the scan would never have - // been initiated (see importer.ImportController.prototype.checkState_) - const volumeInfo = assert( - this.fileManager_.volumeManager.getCurrentProfileVolumeInfo(volumeType)); - return new Promise((resolve, reject) => { - chrome.fileManagerPrivate.getSizeStats(volumeInfo.volumeId, stats => { - if (chrome.runtime.lastError) { - reject( - 'Failed to ascertain available free space: ' + - chrome.runtime.lastError.message); - return; - } - if (!stats) { - resolve(-1); - } - resolve(stats.remainingSize); + /** @override */ + getFreeStorageSpace(volumeType) { + // VolumeInfo will exist, because if it doesn't, the scan would never have + // been initiated (see importer.ImportController.prototype.checkState_) + const volumeInfo = + assert(this.fileManager_.volumeManager.getCurrentProfileVolumeInfo( + volumeType)); + return new Promise((resolve, reject) => { + chrome.fileManagerPrivate.getSizeStats(volumeInfo.volumeId, stats => { + if (chrome.runtime.lastError) { + reject( + 'Failed to ascertain available free space: ' + + chrome.runtime.lastError.message); + return; + } + if (!stats) { + resolve(-1); + } + resolve(stats.remainingSize); + }); }); - }); -}; + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.addWindowCloseListener = - listener => { - window.addEventListener('pagehide', listener); - }; + /** @override */ + addWindowCloseListener(listener) { + window.addEventListener('pagehide', listener); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.addVolumeUnmountListener = - listener => { - // TODO(smckay): remove listeners when the page is torn down. - chrome.fileManagerPrivate.onMountCompleted.addListener( - /** - * @param {!chrome.fileManagerPrivate.MountCompletedEvent} event - * @this {importer.RuntimeControllerEnvironment} - */ - event => { - if (event.eventType === 'unmount') { - listener(event.volumeMetadata.volumeId); - } - }); - }; + /** @override */ + addVolumeUnmountListener(listener) { + // TODO(smckay): remove listeners when the page is torn down. + chrome.fileManagerPrivate.onMountCompleted.addListener( + /** + * @param {!chrome.fileManagerPrivate.MountCompletedEvent} event + * @this {importer.RuntimeControllerEnvironment} + */ + event => { + if (event.eventType === 'unmount') { + listener(event.volumeMetadata.volumeId); + } + }); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.addDirectoryChangedListener = - function(listener) { - // TODO(smckay): remove listeners when the page is torn down. - this.fileManager_.directoryModel.addEventListener( - 'directory-changed', listener); -}; + /** @override */ + addDirectoryChangedListener(listener) { + // TODO(smckay): remove listeners when the page is torn down. + this.fileManager_.directoryModel.addEventListener( + 'directory-changed', listener); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.addSelectionChangedListener = - function(listener) { - this.selectionHandler_.addEventListener( - FileSelectionHandler.EventType.CHANGE_THROTTLED, listener); -}; + /** @override */ + addSelectionChangedListener(listener) { + this.selectionHandler_.addEventListener( + FileSelectionHandler.EventType.CHANGE_THROTTLED, listener); + } -/** - * Reveals the directory to the user in the Files app, either creating - * a new window, or focusing if already open in a window. - * - * @param {!DirectoryEntry} directory - * @private - */ -importer.RuntimeControllerEnvironment.prototype.revealDirectory_ = function( - directory) { - this.fileManager_.backgroundPage.launcher.launchFileManager( - {currentDirectoryURL: directory.toURL()}, - /* App ID */ undefined); -}; + /** + * Reveals the directory to the user in the Files app, either creating + * a new window, or focusing if already open in a window. + * @param {!DirectoryEntry} directory + * @private + */ + revealDirectory_(directory) { + this.fileManager_.backgroundPage.launcher.launchFileManager( + {currentDirectoryURL: directory.toURL()}, + /* App ID */ undefined); + } -/** - * Retrieves the user's drive root. - * @return {!Promise<!DirectoryEntry>} - * @private - */ -importer.RuntimeControllerEnvironment.prototype.getDriveRoot_ = function() { - const drive = this.fileManager_.volumeManager.getCurrentProfileVolumeInfo( - VolumeManagerCommon.VolumeType.DRIVE); - return /** @type {!Promise<!DirectoryEntry>} */ (drive.resolveDisplayRoot()); -}; + /** + * Retrieves the user's drive root. + * @return {!Promise<!DirectoryEntry>} + * @private + */ + getDriveRoot_() { + const drive = this.fileManager_.volumeManager.getCurrentProfileVolumeInfo( + VolumeManagerCommon.VolumeType.DRIVE); + return /** @type {!Promise<!DirectoryEntry>} */ ( + drive.resolveDisplayRoot()); + } -/** - * Fetches (creating if necessary) the import destination subdirectory. - * @return {!Promise<!DirectoryEntry>} - * @private - */ -importer.RuntimeControllerEnvironment.prototype.demandCloudFolder_ = root => { - return importer.demandChildDirectory( - root, str('CLOUD_IMPORT_DESTINATION_FOLDER')); -}; + /** + * Fetches (creating if necessary) the import destination subdirectory. + * @return {!Promise<!DirectoryEntry>} + * @private + */ + demandCloudFolder_(root) { + return importer.demandChildDirectory( + root, str('CLOUD_IMPORT_DESTINATION_FOLDER')); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.showImportRoot = function() { - return this.getDriveRoot_() - .then(this.demandCloudFolder_.bind(this)) - .then(this.revealDirectory_.bind(this)) - .catch(importer.getLogger().catcher('import-root-provision-and-reveal')); -}; + /** @override */ + showImportRoot() { + return this.getDriveRoot_() + .then(this.demandCloudFolder_.bind(this)) + .then(this.revealDirectory_.bind(this)) + .catch( + importer.getLogger().catcher('import-root-provision-and-reveal')); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.getImportDestination = function( - date) { - return this.getDriveRoot_() - .then(this.demandCloudFolder_.bind(this)) - .then( - /** - * @param {!DirectoryEntry} root - * @return {!Promise<!DirectoryEntry>} - */ - root => { - return importer.demandChildDirectory( - root, importer.getDirectoryNameForDate(date)); - }) - .catch(importer.getLogger().catcher('import-destination-provision')); -}; + /** @override */ + getImportDestination(date) { + return this.getDriveRoot_() + .then(this.demandCloudFolder_.bind(this)) + .then( + /** + * @param {!DirectoryEntry} root + * @return {!Promise<!DirectoryEntry>} + */ + root => { + return importer.demandChildDirectory( + root, importer.getDirectoryNameForDate(date)); + }) + .catch(importer.getLogger().catcher('import-destination-provision')); + } -/** @override */ -importer.RuntimeControllerEnvironment.prototype.showImportDestination = - function(date) { - return this.getImportDestination(date) - .then(this.revealDirectory_.bind(this)) - .catch(importer.getLogger().catcher('import-destination-reveal')); + /** @override */ + showImportDestination(date) { + return this.getImportDestination(date) + .then(this.revealDirectory_.bind(this)) + .catch(importer.getLogger().catcher('import-destination-reveal')); + } };
diff --git a/ui/file_manager/file_manager/foreground/js/last_modified_controller.js b/ui/file_manager/file_manager/foreground/js/last_modified_controller.js index 33fe4b4..0b0f6c7 100644 --- a/ui/file_manager/file_manager/foreground/js/last_modified_controller.js +++ b/ui/file_manager/file_manager/foreground/js/last_modified_controller.js
@@ -4,36 +4,35 @@ /** * Controls last modified column in the file table. - * @param {!FileTable} fileTable File table UI. - * @param {!DirectoryModel} directoryModel Directory model. - * @constructor - * @struct */ -function LastModifiedController(fileTable, directoryModel) { +class LastModifiedController { /** - * @private {!FileTable} + * @param {!FileTable} fileTable File table UI. + * @param {!DirectoryModel} directoryModel Directory model. */ - this.fileTable_ = fileTable; + constructor(fileTable, directoryModel) { + /** @private @const {!FileTable} */ + this.fileTable_ = fileTable; + + /** @private @const {!DirectoryModel} */ + this.directoryModel_ = directoryModel; + + this.directoryModel_.addEventListener( + 'scan-started', this.onScanStarted_.bind(this)); + } /** - * @private {!DirectoryModel} + * Handles directory scan start. + * @private */ - this.directoryModel_ = directoryModel; - - this.directoryModel_.addEventListener( - 'scan-started', this.onScanStarted_.bind(this)); + onScanStarted_() { + // If the current directory is Recent root, request FileTable to use + // modificationByMeTime instead of modificationTime in last modified column. + const useModificationByMeTime = + this.directoryModel_.getCurrentRootType() === + VolumeManagerCommon.RootType.RECENT; + this.fileTable_.setUseModificationByMeTime(useModificationByMeTime); + this.directoryModel_.getFileList().setUseModificationByMeTime( + useModificationByMeTime); + } } - -/** - * Handles directory scan start. - * @private - */ -LastModifiedController.prototype.onScanStarted_ = function() { - // If the current directory is Recent root, request FileTable to use - // modificationByMeTime instead of modificationTime in last modified column. - const useModificationByMeTime = this.directoryModel_.getCurrentRootType() === - VolumeManagerCommon.RootType.RECENT; - this.fileTable_.setUseModificationByMeTime(useModificationByMeTime); - this.directoryModel_.getFileList().setUseModificationByMeTime( - useModificationByMeTime); -};
diff --git a/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js b/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js index fd621cc..2042e6de 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js +++ b/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js
@@ -4,124 +4,114 @@ /** * Controller for list contents update. - * @param {!ListContainer} listContainer - * @param {!DirectoryModel} directoryModel - * @param {!MetadataModel} metadataModel - * @param {!FileMetadataFormatter} fileMetadataFormatter - * @constructor - * @struct */ -function MetadataUpdateController( - listContainer, directoryModel, metadataModel, fileMetadataFormatter) { +class MetadataUpdateController { /** - * @private {!DirectoryModel} - * @const + * @param {!ListContainer} listContainer + * @param {!DirectoryModel} directoryModel + * @param {!MetadataModel} metadataModel + * @param {!FileMetadataFormatter} fileMetadataFormatter */ - this.directoryModel_ = directoryModel; + constructor( + listContainer, directoryModel, metadataModel, fileMetadataFormatter) { + /** @private @const {!DirectoryModel} */ + this.directoryModel_ = directoryModel; + + /** @private @const {!MetadataModel} */ + this.metadataModel_ = metadataModel; + + /** @private @const {!ListContainer} */ + this.listContainer_ = listContainer; + + /** @private @const {!FileMetadataFormatter} */ + this.fileMetadataFormatter_ = fileMetadataFormatter; + + chrome.fileManagerPrivate.onPreferencesChanged.addListener( + this.onPreferencesChanged_.bind(this)); + this.onPreferencesChanged_(); + metadataModel.addEventListener( + 'update', this.onCachedMetadataUpdate_.bind(this)); + + // Update metadata to change 'Today' and 'Yesterday' dates. + const today = new Date(); + today.setHours(0); + today.setMinutes(0); + today.setSeconds(0); + today.setMilliseconds(0); + setTimeout( + this.dailyUpdateModificationTime_.bind(this), + today.getTime() + MetadataUpdateController.MILLISECONDS_IN_DAY_ - + Date.now() + 1000); + } /** - * @private {!MetadataModel} - * @const + * Clears metadata cache for the current directory and its decendents. */ - this.metadataModel_ = metadataModel; + refreshCurrentDirectoryMetadata() { + const entries = this.directoryModel_.getFileList().slice(); + const directoryEntry = this.directoryModel_.getCurrentDirEntry(); + if (!directoryEntry) { + return; + } + + // TODO(dgozman): refresh content metadata only when modificationTime + // changed. + const isFakeEntry = util.isFakeEntry(directoryEntry); + const changedEntries = + (isFakeEntry ? [] : [directoryEntry]).concat(entries); + this.metadataModel_.notifyEntriesChanged(changedEntries); + + // We don't pass callback here. When new metadata arrives, we have an + // observer registered to update the UI. + this.metadataModel_.get( + changedEntries, this.directoryModel_.getPrefetchPropertyNames()); + } /** - * @private {!ListContainer} - * @const + * Handles local metadata changes in the currect directory. + * @param {Event} event Change event. + * @private */ - this.listContainer_ = listContainer; + onCachedMetadataUpdate_(event) { + // TODO(hirono): Specify property name instead of metadata type. + this.listContainer_.currentView.updateListItemsMetadata( + 'filesystem', event.entries); + this.listContainer_.currentView.updateListItemsMetadata( + 'external', event.entries); + } /** - * @private {!FileMetadataFormatter} - * @const + * @private */ - this.fileMetadataFormatter_ = fileMetadataFormatter; + dailyUpdateModificationTime_() { + const entries = /** @type {!Array<!Entry>} */ ( + this.directoryModel_.getFileList().slice()); + this.metadataModel_.get(entries, ['modificationTime']).then(() => { + this.listContainer_.currentView.updateListItemsMetadata( + 'filesystem', entries); + }); + setTimeout( + this.dailyUpdateModificationTime_.bind(this), + MetadataUpdateController.MILLISECONDS_IN_DAY_); + } - chrome.fileManagerPrivate.onPreferencesChanged.addListener( - this.onPreferencesChanged_.bind(this)); - this.onPreferencesChanged_(); - metadataModel.addEventListener( - 'update', this.onCachedMetadataUpdate_.bind(this)); - - // Update metadata to change 'Today' and 'Yesterday' dates. - const today = new Date(); - today.setHours(0); - today.setMinutes(0); - today.setSeconds(0); - today.setMilliseconds(0); - setTimeout( - this.dailyUpdateModificationTime_.bind(this), - today.getTime() + MetadataUpdateController.MILLISECONDS_IN_DAY_ - - Date.now() + 1000); + /** + * @private + */ + onPreferencesChanged_() { + chrome.fileManagerPrivate.getPreferences(prefs => { + const use12hourClock = !prefs.use24hourClock; + this.fileMetadataFormatter_.setDateTimeFormat(use12hourClock); + // TODO(oka): Remove these two lines, and add fileMetadataFormatter to + // constructor for each field instead. + this.listContainer_.table.setDateTimeFormat(use12hourClock); + this.refreshCurrentDirectoryMetadata(); + }); + } } /** * Number of milliseconds in a day. - * @const {number} + * @private @const {number} */ MetadataUpdateController.MILLISECONDS_IN_DAY_ = 24 * 60 * 60 * 1000; - -/** - * Clears metadata cache for the current directory and its decendents. - */ -MetadataUpdateController.prototype.refreshCurrentDirectoryMetadata = - function() { - const entries = this.directoryModel_.getFileList().slice(); - const directoryEntry = this.directoryModel_.getCurrentDirEntry(); - if (!directoryEntry) { - return; - } - - // TODO(dgozman): refresh content metadata only when modificationTime - // changed. - const isFakeEntry = util.isFakeEntry(directoryEntry); - const changedEntries = (isFakeEntry ? [] : [directoryEntry]).concat(entries); - this.metadataModel_.notifyEntriesChanged(changedEntries); - - // We don't pass callback here. When new metadata arrives, we have an - // observer registered to update the UI. - this.metadataModel_.get( - changedEntries, this.directoryModel_.getPrefetchPropertyNames()); -}; - -/** - * Handles local metadata changes in the currect directory. - * @param {Event} event Change event. - * @private - */ -MetadataUpdateController.prototype.onCachedMetadataUpdate_ = function(event) { - // TODO(hirono): Specify property name instead of metadata type. - this.listContainer_.currentView.updateListItemsMetadata( - 'filesystem', event.entries); - this.listContainer_.currentView.updateListItemsMetadata( - 'external', event.entries); -}; - -/** - * @private - */ -MetadataUpdateController.prototype.dailyUpdateModificationTime_ = function() { - const entries = /** @type {!Array<!Entry>} */ ( - this.directoryModel_.getFileList().slice()); - this.metadataModel_.get(entries, ['modificationTime']).then(() => { - this.listContainer_.currentView.updateListItemsMetadata( - 'filesystem', entries); - }); - setTimeout( - this.dailyUpdateModificationTime_.bind(this), - MetadataUpdateController.MILLISECONDS_IN_DAY_); -}; - -/** - * @private - */ -MetadataUpdateController.prototype.onPreferencesChanged_ = function() { - chrome.fileManagerPrivate.getPreferences(prefs => { - const use12hourClock = !prefs.use24hourClock; - this.fileMetadataFormatter_.setDateTimeFormat(use12hourClock); - // TODO(oka): Remove these two lines, and add fileMetadataFormatter to - // constructor for each field instead. - this.listContainer_.table.setDateTimeFormat(use12hourClock); - this.refreshCurrentDirectoryMetadata(); - }); -};
diff --git a/ui/file_manager/file_manager/foreground/js/naming_controller.js b/ui/file_manager/file_manager/foreground/js/naming_controller.js index d534e4b..d9dc155a 100644 --- a/ui/file_manager/file_manager/foreground/js/naming_controller.js +++ b/ui/file_manager/file_manager/foreground/js/naming_controller.js
@@ -4,362 +4,339 @@ /** * Controller to handle naming. - * - * @param {!ListContainer} listContainer - * @param {!cr.ui.dialogs.AlertDialog} alertDialog - * @param {!cr.ui.dialogs.ConfirmDialog} confirmDialog - * @param {!DirectoryModel} directoryModel - * @param {!FileFilter} fileFilter - * @param {!FileSelectionHandler} selectionHandler - * @constructor - * @struct */ -function NamingController( - listContainer, alertDialog, confirmDialog, directoryModel, fileFilter, - selectionHandler) { +class NamingController { /** - * @type {!ListContainer} - * @const - * @private + * @param {!ListContainer} listContainer + * @param {!cr.ui.dialogs.AlertDialog} alertDialog + * @param {!cr.ui.dialogs.ConfirmDialog} confirmDialog + * @param {!DirectoryModel} directoryModel + * @param {!FileFilter} fileFilter + * @param {!FileSelectionHandler} selectionHandler */ - this.listContainer_ = listContainer; + constructor( + listContainer, alertDialog, confirmDialog, directoryModel, fileFilter, + selectionHandler) { + /** @private @const {!ListContainer} */ + this.listContainer_ = listContainer; + + /** @private @const {!cr.ui.dialogs.AlertDialog} */ + this.alertDialog_ = alertDialog; + + /** @private @const {!cr.ui.dialogs.ConfirmDialog} */ + this.confirmDialog_ = confirmDialog; + + /** @private @const {!DirectoryModel} */ + this.directoryModel_ = directoryModel; + + /** @private @const {!FileFilter} */ + this.fileFilter_ = fileFilter; + + /** @private @const {!FileSelectionHandler} */ + this.selectionHandler_ = selectionHandler; + + // Register events. + this.listContainer_.renameInput.addEventListener( + 'keydown', this.onRenameInputKeyDown_.bind(this)); + this.listContainer_.renameInput.addEventListener( + 'blur', this.onRenameInputBlur_.bind(this)); + } /** - * @type {!cr.ui.dialogs.AlertDialog} - * @const - * @private + * Verifies the user entered name for file or folder to be created or + * renamed to. See also util.validateFileName. + * + * @param {!DirectoryEntry} parentEntry The URL of the parent directory entry. + * @param {string} name New file or folder name. + * @param {function(boolean)} onDone Function to invoke when user closes the + * warning box or immediately if file name is correct. If the name was + * valid it is passed true, and false otherwise. */ - this.alertDialog_ = alertDialog; - - /** - * @type {!cr.ui.dialogs.ConfirmDialog} - * @const - * @private - */ - this.confirmDialog_ = confirmDialog; - - /** - * @type {!DirectoryModel} - * @const - * @private - */ - this.directoryModel_ = directoryModel; - - /** - * @type {!FileFilter} - * @const - * @private - */ - this.fileFilter_ = fileFilter; - - /** - * @type {!FileSelectionHandler} - * @const - * @private - */ - this.selectionHandler_ = selectionHandler; - - // Register events. - this.listContainer_.renameInput.addEventListener( - 'keydown', this.onRenameInputKeyDown_.bind(this)); - this.listContainer_.renameInput.addEventListener( - 'blur', this.onRenameInputBlur_.bind(this)); -} - -/** - * Verifies the user entered name for file or folder to be created or - * renamed to. See also util.validateFileName. - * - * @param {!DirectoryEntry} parentEntry The URL of the parent directory entry. - * @param {string} name New file or folder name. - * @param {function(boolean)} onDone Function to invoke when user closes the - * warning box or immediatelly if file name is correct. If the name was - * valid it is passed true, and false otherwise. - */ -NamingController.prototype.validateFileName = function( - parentEntry, name, onDone) { - const fileNameErrorPromise = util.validateFileName( - parentEntry, name, !this.fileFilter_.isHiddenFilesVisible()); - fileNameErrorPromise - .then( - onDone.bind(null, true), - message => { - this.alertDialog_.show( - /** @type {string} */ (message), onDone.bind(null, false)); - }) - .catch(error => { - console.error(error.stack || error); - }); -}; - -/** - * @param {string} filename - * @return {Promise<string>} - */ -NamingController.prototype.validateFileNameForSaving = function(filename) { - const directory = - /** @type {DirectoryEntry} */ (this.directoryModel_.getCurrentDirEntry()); - const currentDirUrl = directory.toURL().replace(/\/?$/, '/'); - const fileUrl = currentDirUrl + encodeURIComponent(filename); - - return new Promise(this.validateFileName.bind(this, directory, filename)) - .then(isValid => { - if (!isValid) { - return Promise.reject('Invalid filename.'); - } - - if (directory && util.isFakeEntry(directory)) { - // Can't save a file into a fake directory. - return Promise.reject('Cannot save into fake entry.'); - } - - return new Promise( - directory.getFile.bind(directory, filename, {create: false})); - }) - .then( - () => { - // An existing file is found. Show confirmation dialog to - // overwrite it. If the user select "OK" on the dialog, save it. - return new Promise((fulfill, reject) => { - this.confirmDialog_.show( - strf('CONFIRM_OVERWRITE_FILE', filename), - fulfill.bind(null, fileUrl), reject.bind(null, 'Cancelled'), - () => {}); - }); - }, - error => { - if (error.name == util.FileError.NOT_FOUND_ERR) { - // The file does not exist, so it should be ok to create a - // new file. - return fileUrl; - } - - if (error.name == util.FileError.TYPE_MISMATCH_ERR) { - // An directory is found. - // Do not allow to overwrite directory. + validateFileName(parentEntry, name, onDone) { + const fileNameErrorPromise = util.validateFileName( + parentEntry, name, !this.fileFilter_.isHiddenFilesVisible()); + fileNameErrorPromise + .then( + onDone.bind(null, true), + message => { this.alertDialog_.show( - strf('DIRECTORY_ALREADY_EXISTS', filename)); + /** @type {string} */ (message), onDone.bind(null, false)); + }) + .catch(error => { + console.error(error.stack || error); + }); + } + + /** + * @param {string} filename + * @return {Promise<string>} + */ + validateFileNameForSaving(filename) { + const directory = + /** @type {DirectoryEntry} */ ( + this.directoryModel_.getCurrentDirEntry()); + const currentDirUrl = directory.toURL().replace(/\/?$/, '/'); + const fileUrl = currentDirUrl + encodeURIComponent(filename); + + return new Promise(this.validateFileName.bind(this, directory, filename)) + .then(isValid => { + if (!isValid) { + return Promise.reject('Invalid filename.'); + } + + if (directory && util.isFakeEntry(directory)) { + // Can't save a file into a fake directory. + return Promise.reject('Cannot save into fake entry.'); + } + + return new Promise( + directory.getFile.bind(directory, filename, {create: false})); + }) + .then( + () => { + // An existing file is found. Show confirmation dialog to + // overwrite it. If the user select "OK" on the dialog, save it. + return new Promise((fulfill, reject) => { + this.confirmDialog_.show( + strf('CONFIRM_OVERWRITE_FILE', filename), + fulfill.bind(null, fileUrl), reject.bind(null, 'Cancelled'), + () => {}); + }); + }, + error => { + if (error.name == util.FileError.NOT_FOUND_ERR) { + // The file does not exist, so it should be ok to create a + // new file. + return fileUrl; + } + + if (error.name == util.FileError.TYPE_MISMATCH_ERR) { + // An directory is found. + // Do not allow to overwrite directory. + this.alertDialog_.show( + strf('DIRECTORY_ALREADY_EXISTS', filename)); + return Promise.reject(error); + } + + // Unexpected error. + console.error('File save failed: ' + error.code); return Promise.reject(error); - } - - // Unexpected error. - console.error('File save failed: ' + error.code); - return Promise.reject(error); - }); -}; - -/** - * @return {boolean} - */ -NamingController.prototype.isRenamingInProgress = function() { - return !!this.listContainer_.renameInput.currentEntry; -}; - -NamingController.prototype.initiateRename = function() { - const item = this.listContainer_.currentList.ensureLeadItemExists(); - if (!item) { - return; - } - const label = item.querySelector('.filename-label'); - const input = this.listContainer_.renameInput; - const currentEntry = - this.listContainer_.currentList.dataModel.item(item.listIndex); - - input.value = label.textContent; - item.setAttribute('renaming', ''); - label.parentNode.appendChild(input); - input.focus(); - - const selectionEnd = input.value.lastIndexOf('.'); - if (currentEntry.isFile && selectionEnd !== -1) { - input.selectionStart = 0; - input.selectionEnd = selectionEnd; - } else { - input.select(); + }); } - // This has to be set late in the process so we don't handle spurious - // blur events. - input.currentEntry = currentEntry; - this.listContainer_.startBatchUpdates(); -}; - -/** - * Restores the item which is being renamed while refreshing the file list. Do - * nothing if no item is being renamed or such an item disappeared. - * - * While refreshing file list it gets repopulated with new file entries. - * There is not a big difference whether DOM items stay the same or not. - * Except for the item that the user is renaming. - */ -NamingController.prototype.restoreItemBeingRenamed = function() { - if (!this.isRenamingInProgress()) { - return; + /** + * @return {boolean} + */ + isRenamingInProgress() { + return !!this.listContainer_.renameInput.currentEntry; } - const dm = this.directoryModel_; - const leadIndex = dm.getFileListSelection().leadIndex; - if (leadIndex < 0) { - return; + initiateRename() { + const item = this.listContainer_.currentList.ensureLeadItemExists(); + if (!item) { + return; + } + const label = item.querySelector('.filename-label'); + const input = this.listContainer_.renameInput; + const currentEntry = + this.listContainer_.currentList.dataModel.item(item.listIndex); + + input.value = label.textContent; + item.setAttribute('renaming', ''); + label.parentNode.appendChild(input); + input.focus(); + + const selectionEnd = input.value.lastIndexOf('.'); + if (currentEntry.isFile && selectionEnd !== -1) { + input.selectionStart = 0; + input.selectionEnd = selectionEnd; + } else { + input.select(); + } + + // This has to be set late in the process so we don't handle spurious + // blur events. + input.currentEntry = currentEntry; + this.listContainer_.startBatchUpdates(); } - const leadEntry = /** @type {Entry} */ (dm.getFileList().item(leadIndex)); - if (!util.isSameEntry( - this.listContainer_.renameInput.currentEntry, leadEntry)) { - return; - } - - const leadListItem = - this.listContainer_.findListItemForNode(this.listContainer_.renameInput); - if (this.listContainer_.currentListType == ListContainer.ListType.DETAIL) { - this.listContainer_.table.updateFileMetadata(leadListItem, leadEntry); - } - this.listContainer_.currentList.restoreLeadItem(leadListItem); -}; - -/** - * @param {Event} event Key event. - * @private - */ -NamingController.prototype.onRenameInputKeyDown_ = function(event) { - // Ignore key events if event.keyCode is VK_PROCESSKEY(229). - // TODO(fukino): Remove this workaround once crbug.com/644140 is fixed. - if (event.keyCode === 229) { - return; - } - - if (!this.isRenamingInProgress()) { - return; - } - - // Do not move selection or lead item in list during rename. - if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { - event.stopPropagation(); - } - - switch (util.getKeyModifiers(event) + event.key) { - case 'Escape': - this.cancelRename_(); - event.preventDefault(); - break; - - case 'Enter': - this.commitRename_(); - event.preventDefault(); - break; - } -}; - -/** - * @param {Event} event Blur event. - * @private - */ -NamingController.prototype.onRenameInputBlur_ = function(event) { - if (this.isRenamingInProgress() && - !this.listContainer_.renameInput.validation_) { - this.commitRename_(); - } -}; - -/** - * @private - */ -NamingController.prototype.commitRename_ = function() { - const input = this.listContainer_.renameInput; - const entry = input.currentEntry; - const newName = input.value; - - if (!newName || newName == entry.name) { - this.cancelRename_(); - return; - } - - const renamedItemElement = - this.listContainer_.findListItemForNode(this.listContainer_.renameInput); - const nameNode = renamedItemElement.querySelector('.filename-label'); - - input.validation_ = true; - const validationDone = valid => { - input.validation_ = false; - - if (!valid) { - // Cancel rename if it fails to restore focus from alert dialog. - // Otherwise, just cancel the commitment and continue to rename. - if (document.activeElement != input) { - this.cancelRename_(); - } + /** + * Restores the item which is being renamed while refreshing the file list. Do + * nothing if no item is being renamed or such an item disappeared. + * + * While refreshing file list it gets repopulated with new file entries. + * There is not a big difference whether DOM items stay the same or not. + * Except for the item that the user is renaming. + */ + restoreItemBeingRenamed() { + if (!this.isRenamingInProgress()) { return; } - // Validation succeeded. Do renaming. - this.listContainer_.renameInput.currentEntry = null; - if (this.listContainer_.renameInput.parentNode) { - this.listContainer_.renameInput.parentNode.removeChild( - this.listContainer_.renameInput); + const dm = this.directoryModel_; + const leadIndex = dm.getFileListSelection().leadIndex; + if (leadIndex < 0) { + return; } - renamedItemElement.setAttribute('renaming', 'provisional'); - // Optimistically apply new name immediately to avoid flickering in - // case of success. - nameNode.textContent = newName; + const leadEntry = /** @type {Entry} */ (dm.getFileList().item(leadIndex)); + if (!util.isSameEntry( + this.listContainer_.renameInput.currentEntry, leadEntry)) { + return; + } - util.rename( - entry, newName, - newEntry => { - this.directoryModel_.onRenameEntry(entry, assert(newEntry), () => { - // Select new entry. - this.listContainer_.currentList.selectionModel.selectedIndex = - this.directoryModel_.getFileList().indexOf(newEntry); - // Force to update selection immediately. - this.selectionHandler_.onFileSelectionChanged(); + const leadListItem = this.listContainer_.findListItemForNode( + this.listContainer_.renameInput); + if (this.listContainer_.currentListType == ListContainer.ListType.DETAIL) { + this.listContainer_.table.updateFileMetadata(leadListItem, leadEntry); + } + this.listContainer_.currentList.restoreLeadItem(leadListItem); + } + /** + * @param {Event} event Key event. + * @private + */ + onRenameInputKeyDown_(event) { + // Ignore key events if event.keyCode is VK_PROCESSKEY(229). + // TODO(fukino): Remove this workaround once crbug.com/644140 is fixed. + if (event.keyCode === 229) { + return; + } + + if (!this.isRenamingInProgress()) { + return; + } + + // Do not move selection or lead item in list during rename. + if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { + event.stopPropagation(); + } + + switch (util.getKeyModifiers(event) + event.key) { + case 'Escape': + this.cancelRename_(); + event.preventDefault(); + break; + + case 'Enter': + this.commitRename_(); + event.preventDefault(); + break; + } + } + + /** + * @param {Event} event Blur event. + * @private + */ + onRenameInputBlur_(event) { + if (this.isRenamingInProgress() && + !this.listContainer_.renameInput.validation_) { + this.commitRename_(); + } + } + + /** + * @private + */ + commitRename_() { + const input = this.listContainer_.renameInput; + const entry = input.currentEntry; + const newName = input.value; + + if (!newName || newName == entry.name) { + this.cancelRename_(); + return; + } + + const renamedItemElement = this.listContainer_.findListItemForNode( + this.listContainer_.renameInput); + const nameNode = renamedItemElement.querySelector('.filename-label'); + + input.validation_ = true; + const validationDone = valid => { + input.validation_ = false; + + if (!valid) { + // Cancel rename if it fails to restore focus from alert dialog. + // Otherwise, just cancel the commitment and continue to rename. + if (document.activeElement != input) { + this.cancelRename_(); + } + return; + } + + // Validation succeeded. Do renaming. + this.listContainer_.renameInput.currentEntry = null; + if (this.listContainer_.renameInput.parentNode) { + this.listContainer_.renameInput.parentNode.removeChild( + this.listContainer_.renameInput); + } + renamedItemElement.setAttribute('renaming', 'provisional'); + + // Optimistically apply new name immediately to avoid flickering in + // case of success. + nameNode.textContent = newName; + + util.rename( + entry, newName, + newEntry => { + this.directoryModel_.onRenameEntry(entry, assert(newEntry), () => { + // Select new entry. + this.listContainer_.currentList.selectionModel.selectedIndex = + this.directoryModel_.getFileList().indexOf(newEntry); + // Force to update selection immediately. + this.selectionHandler_.onFileSelectionChanged(); + + renamedItemElement.removeAttribute('renaming'); + this.listContainer_.endBatchUpdates(); + + // Focus may go out of the list. Back it to the list. + this.listContainer_.currentList.focus(); + }); + }, + error => { + // Write back to the old name. + nameNode.textContent = entry.name; renamedItemElement.removeAttribute('renaming'); this.listContainer_.endBatchUpdates(); - // Focus may go out of the list. Back it to the list. - this.listContainer_.currentList.focus(); + // Show error dialog. + const message = util.getRenameErrorMessage(error, entry, newName); + this.alertDialog_.show(message); }); - }, - error => { - // Write back to the old name. - nameNode.textContent = entry.name; - renamedItemElement.removeAttribute('renaming'); - this.listContainer_.endBatchUpdates(); + }; - // Show error dialog. - const message = util.getRenameErrorMessage(error, entry, newName); - this.alertDialog_.show(message); - }); - }; - - // TODO(mtomasz): this.getCurrentDirectoryEntry() might not return the actual - // parent if the directory content is a search result. Fix it to do proper - // validation. - this.validateFileName( - /** @type {!DirectoryEntry} */ ( - this.directoryModel_.getCurrentDirEntry()), - newName, validationDone.bind(this)); -}; - -/** - * @private - */ -NamingController.prototype.cancelRename_ = function() { - this.listContainer_.renameInput.currentEntry = null; - - const item = - this.listContainer_.findListItemForNode(this.listContainer_.renameInput); - if (item) { - item.removeAttribute('renaming'); + // TODO(mtomasz): this.getCurrentDirectoryEntry() might not return the + // actual parent if the directory content is a search result. Fix it to do + // proper validation. + this.validateFileName( + /** @type {!DirectoryEntry} */ ( + this.directoryModel_.getCurrentDirEntry()), + newName, validationDone.bind(this)); } - const parent = this.listContainer_.renameInput.parentNode; - if (parent) { - parent.removeChild(this.listContainer_.renameInput); + /** + * @private + */ + cancelRename_() { + this.listContainer_.renameInput.currentEntry = null; + + const item = this.listContainer_.findListItemForNode( + this.listContainer_.renameInput); + if (item) { + item.removeAttribute('renaming'); + } + + const parent = this.listContainer_.renameInput.parentNode; + if (parent) { + parent.removeChild(this.listContainer_.renameInput); + } + + this.listContainer_.endBatchUpdates(); + + // Focus may go out of the list. Back it to the list. + this.listContainer_.currentList.focus(); } - - this.listContainer_.endBatchUpdates(); - - // Focus may go out of the list. Back it to the list. - this.listContainer_.currentList.focus(); -}; +}
diff --git a/ui/file_manager/file_manager/foreground/js/providers_model.js b/ui/file_manager/file_manager/foreground/js/providers_model.js index 42f3b8c..5066dc2 100644 --- a/ui/file_manager/file_manager/foreground/js/providers_model.js +++ b/ui/file_manager/file_manager/foreground/js/providers_model.js
@@ -5,105 +5,83 @@ /** * An item in the model. Represents a single providing extension. - * - * @param {string} providerId - * @param {!chrome.fileManagerPrivate.IconSet} iconSet - * @param {string} name - * @param {boolean} configurable - * @param {boolean} watchable - * @param {boolean} multipleMounts - * @param {string} source - * @constructor - * @struct */ -function ProvidersModelItem( - providerId, iconSet, name, configurable, watchable, multipleMounts, - source) { +class ProvidersModelItem { /** - * @private {string} - * @const + * @param {string} providerId + * @param {!chrome.fileManagerPrivate.IconSet} iconSet + * @param {string} name + * @param {boolean} configurable + * @param {boolean} watchable + * @param {boolean} multipleMounts + * @param {string} source */ - this.providerId_ = providerId; + constructor( + providerId, iconSet, name, configurable, watchable, multipleMounts, + source) { + /** @private @const {string} */ + this.providerId_ = providerId; - /** - * @private {!chrome.fileManagerPrivate.IconSet} - * @const - */ - this.iconSet_ = iconSet; + /** @private @const {!chrome.fileManagerPrivate.IconSet} */ + this.iconSet_ = iconSet; - /** - * @private {string} - * @const - */ - this.name_ = name; + /** @private @const {string} */ + this.name_ = name; - /** - * @private {boolean} - * @const - */ - this.configurable_ = configurable; + /** @private @const {boolean} */ + this.configurable_ = configurable; - /** - * @private {boolean} - * @const - */ - this.watchable_ = watchable; + /** @private @const {boolean} */ + this.watchable_ = watchable; - /** - * @private {boolean} - * @const - */ - this.multipleMounts_ = multipleMounts; + /** @private @const {boolean} */ + this.multipleMounts_ = multipleMounts; - /** - * @private {string} - * @const - */ - this.source_ = source; -} + /** @private @const {string} */ + this.source_ = source; + } -ProvidersModelItem.prototype = { /** * @return {string} */ get providerId() { return this.providerId_; - }, + } /** * @return {!chrome.fileManagerPrivate.IconSet} */ get iconSet() { return this.iconSet_; - }, + } /** * @return {string} */ get name() { return this.name_; - }, + } /** * @return {boolean} */ get configurable() { return this.configurable_; - }, + } /** * @return {boolean} */ get watchable() { return this.watchable_; - }, + } /** * @return {boolean} */ get multipleMounts() { return this.multipleMounts_; - }, + } /** * @return {string} @@ -111,76 +89,74 @@ get source() { return this.source_; } -}; +} /** * Model for providing extensions. Providers methods for fetching lists of * providing extensions as well as performing operations on them, such as * requesting a new mount point. - * - * @param {!VolumeManager} volumeManager - * @constructor - * @struct */ -function ProvidersModel(volumeManager) { +class ProvidersModel { /** - * @private {!VolumeManager} - * @const + * @param {!VolumeManager} volumeManager */ - this.volumeManager_ = volumeManager; -} + constructor(volumeManager) { + /** @private @const {!VolumeManager} */ + this.volumeManager_ = volumeManager; + } -/** - * @return {!Promise<Array<ProvidersModelItem>>} - */ -ProvidersModel.prototype.getInstalledProviders = () => { - return new Promise((fulfill, reject) => { - chrome.fileManagerPrivate.getProviders(providers => { - if (chrome.runtime.lastError) { - reject(chrome.runtime.lastError.message); - return; - } - const results = []; - providers.forEach(provider => { - results.push(new ProvidersModelItem( - provider.providerId, provider.iconSet, provider.name, - provider.configurable, provider.watchable, provider.multipleMounts, - provider.source)); + /** + * @return {!Promise<Array<ProvidersModelItem>>} + */ + getInstalledProviders() { + return new Promise((fulfill, reject) => { + chrome.fileManagerPrivate.getProviders(providers => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError.message); + return; + } + const results = []; + providers.forEach(provider => { + results.push(new ProvidersModelItem( + provider.providerId, provider.iconSet, provider.name, + provider.configurable, provider.watchable, + provider.multipleMounts, provider.source)); + }); + fulfill(results); }); - fulfill(results); }); - }); -}; + } -/** - * @return {!Promise<Array<ProvidersModelItem>>} - */ -ProvidersModel.prototype.getMountableProviders = function() { - return this.getInstalledProviders().then(providers => { - const mountedProviders = {}; - for (let i = 0; i < this.volumeManager_.volumeInfoList.length; i++) { - const volumeInfo = this.volumeManager_.volumeInfoList.item(i); - if (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.PROVIDED) { - mountedProviders[volumeInfo.providerId] = true; + /** + * @return {!Promise<Array<ProvidersModelItem>>} + */ + getMountableProviders() { + return this.getInstalledProviders().then(providers => { + const mountedProviders = {}; + for (let i = 0; i < this.volumeManager_.volumeInfoList.length; i++) { + const volumeInfo = this.volumeManager_.volumeInfoList.item(i); + if (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.PROVIDED) { + mountedProviders[volumeInfo.providerId] = true; + } } - } - return providers.filter(item => { - // File systems handling files are mounted via file handlers. Device - // handlers are mounted when a device is inserted. Only network file - // systems are mounted manually by user via a menu. - return item.source === 'network' && - (!mountedProviders[item.providerId] || item.multipleMounts); + return providers.filter(item => { + // File systems handling files are mounted via file handlers. Device + // handlers are mounted when a device is inserted. Only network file + // systems are mounted manually by user via a menu. + return item.source === 'network' && + (!mountedProviders[item.providerId] || item.multipleMounts); + }); }); - }); -}; + } -/** - * @param {string} providerId - */ -ProvidersModel.prototype.requestMount = providerId => { - chrome.fileManagerPrivate.addProvidedFileSystem(assert(providerId), () => { - if (chrome.runtime.lastError) { - console.error(chrome.runtime.lastError.message); - } - }); -}; + /** + * @param {string} providerId + */ + requestMount(providerId) { + chrome.fileManagerPrivate.addProvidedFileSystem(assert(providerId), () => { + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError.message); + } + }); + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js b/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js index d815266..671168334 100644 --- a/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js +++ b/ui/file_manager/file_manager/foreground/js/thumbnail_loader.js
@@ -6,110 +6,479 @@ * Loads a thumbnail using provided url. In CANVAS mode, loaded images * are attached as <canvas> element, while in IMAGE mode as <img>. * <canvas> renders faster than <img>, however has bigger memory overhead. - * - * @param {Entry} entry File entry. - * @param {ThumbnailLoader.LoaderType=} opt_loaderType Canvas or Image loader, - * default: IMAGE. - * @param {Object=} opt_metadata Metadata object. - * @param {string=} opt_mediaType Media type. - * @param {Array<ThumbnailLoader.LoadTarget>=} opt_loadTargets The list of load - * targets in preferential order. The default value is [CONTENT_METADATA, - * EXTERNAL_METADATA, FILE_ENTRY]. - * @param {number=} opt_priority Priority, the highest is 0. default: 2. - * @constructor */ -function ThumbnailLoader( - entry, opt_loaderType, opt_metadata, opt_mediaType, opt_loadTargets, - opt_priority) { - const loadTargets = opt_loadTargets || [ - ThumbnailLoader.LoadTarget.CONTENT_METADATA, - ThumbnailLoader.LoadTarget.EXTERNAL_METADATA, - ThumbnailLoader.LoadTarget.FILE_ENTRY - ]; - +class ThumbnailLoader { /** - * @private {Entry} - * @const + * @param {!Entry} entry File entry. + * @param {!ThumbnailLoader.LoaderType=} opt_loaderType Canvas or Image + * loader, default: IMAGE. + * @param {?Object=} opt_metadata Metadata object. + * @param {string=} opt_mediaType Media type. + * @param {!Array<ThumbnailLoader.LoadTarget>=} opt_loadTargets The list of + * load targets in preferential order. The default value is + * [CONTENT_METADATA, EXTERNAL_METADATA, FILE_ENTRY]. + * @param {number=} opt_priority Priority, the highest is 0. default: 2. */ - this.entry_ = entry; + constructor( + entry, opt_loaderType, opt_metadata, opt_mediaType, opt_loadTargets, + opt_priority) { + /** @private {boolean} */ + this.canvasUpToDate_ = false; - this.mediaType_ = opt_mediaType || FileType.getMediaType(entry); - this.loaderType_ = opt_loaderType || ThumbnailLoader.LoaderType.IMAGE; - this.metadata_ = opt_metadata; - this.priority_ = (opt_priority !== undefined) ? opt_priority : 2; + /** @private {?Image} */ + this.image_ = null; + + /** @private {?number} */ + this.taskId_ = null; + + /** @private {?HTMLCanvasElement} */ + this.canvas_ = null; + + const loadTargets = opt_loadTargets || [ + ThumbnailLoader.LoadTarget.CONTENT_METADATA, + ThumbnailLoader.LoadTarget.EXTERNAL_METADATA, + ThumbnailLoader.LoadTarget.FILE_ENTRY + ]; + + /** @private @const {!Entry} */ + this.entry_ = entry; + + /** @private @const {string} */ + this.mediaType_ = opt_mediaType || FileType.getMediaType(entry); + + /** @private @const {!ThumbnailLoader.LoaderType} */ + this.loaderType_ = opt_loaderType || ThumbnailLoader.LoaderType.IMAGE; + + /** @private @const {?Object|undefined} */ + this.metadata_ = opt_metadata; + + /** @private @const {number} */ + this.priority_ = (opt_priority !== undefined) ? opt_priority : 2; + + /** + * The image transform from metadata. + * + * TODO(tapted): I suspect this actually needs to be more complicated, but + * it can't be properly type-checked so long as |opt_metadata| is passed in + * merely as "{Object}". + * + * @private {?ImageTransformParam} + */ + this.transform_ = null; + + /** @private {?ThumbnailLoader.LoadTarget} */ + this.loadTarget_ = null; + + if (!opt_metadata) { + this.thumbnailUrl_ = entry.toURL(); // Use the URL directly. + this.loadTarget_ = ThumbnailLoader.LoadTarget.FILE_ENTRY; + return; + } + + this.fallbackUrl_ = null; + this.thumbnailUrl_ = null; + if (opt_metadata.external && opt_metadata.external.customIconUrl) { + this.fallbackUrl_ = opt_metadata.external.customIconUrl; + } + const mimeType = opt_metadata && opt_metadata.contentMimeType; + + for (let i = 0; i < loadTargets.length; i++) { + switch (loadTargets[i]) { + case ThumbnailLoader.LoadTarget.CONTENT_METADATA: + if (opt_metadata.thumbnail && opt_metadata.thumbnail.url) { + this.thumbnailUrl_ = opt_metadata.thumbnail.url; + this.transform_ = + opt_metadata.thumbnail && opt_metadata.thumbnail.transform; + this.loadTarget_ = ThumbnailLoader.LoadTarget.CONTENT_METADATA; + } + break; + case ThumbnailLoader.LoadTarget.EXTERNAL_METADATA: + if (opt_metadata.external && opt_metadata.external.thumbnailUrl && + (!opt_metadata.external.present || + !FileType.isImage(entry, mimeType))) { + this.thumbnailUrl_ = opt_metadata.external.thumbnailUrl; + this.croppedThumbnailUrl_ = + opt_metadata.external.croppedThumbnailUrl; + this.loadTarget_ = ThumbnailLoader.LoadTarget.EXTERNAL_METADATA; + } + break; + case ThumbnailLoader.LoadTarget.FILE_ENTRY: + if (FileType.isImage(entry, mimeType) || + FileType.isVideo(entry, mimeType) || + FileType.isRaw(entry, mimeType)) { + this.thumbnailUrl_ = entry.toURL(); + this.transform_ = + opt_metadata.media && opt_metadata.media.imageTransform; + this.loadTarget_ = ThumbnailLoader.LoadTarget.FILE_ENTRY; + } + break; + default: + assertNotReached('Unkonwn load type: ' + loadTargets[i]); + } + if (this.thumbnailUrl_) { + break; + } + } + + if (!this.thumbnailUrl_ && this.fallbackUrl_) { + // Use fallback as the primary thumbnail. + this.thumbnailUrl_ = this.fallbackUrl_; + this.fallbackUrl_ = null; + } // else the generic thumbnail based on the media type will be used. + } /** - * The image transform from metadata. - * - * TODO(tapted): I suspect this actually needs to be more complicated, but - * it can't be properly type-checked so long as |opt_metadata| is passed in - * merely as "{Object}". - * - * @type {?ImageTransformParam} + * Returns the target of loading. + * @return {?ThumbnailLoader.LoadTarget} */ - this.transform_ = null; + getLoadTarget() { + return this.loadTarget_; + } /** - * @type {?ThumbnailLoader.LoadTarget} + * Loads and attaches an image. + * + * @param {!Element} box Container element. + * @param {ThumbnailLoader.FillMode} fillMode Fill mode. + * @param {function(Image)} onSuccess Success callback, accepts the image. + * @param {number} autoFillThreshold Auto fill threshold. + * @param {number} boxWidth Container box's width. + * @param {number} boxHeight Container box's height. + */ + load(box, fillMode, onSuccess, autoFillThreshold, boxWidth, boxHeight) { + if (!this.thumbnailUrl_) { + // Relevant CSS rules are in file_types.css. + box.setAttribute('generic-thumbnail', this.mediaType_); + return; + } + + this.cancel(); + this.canvasUpToDate_ = false; + this.image_ = new Image(); + this.image_.setAttribute('alt', this.entry_.name); + this.image_.onload = () => { + this.attachImage_(box, fillMode, autoFillThreshold, boxWidth, boxHeight); + onSuccess(this.image_); + }; + this.image_.onerror = () => { + if (this.fallbackUrl_) { + this.thumbnailUrl_ = this.fallbackUrl_; + this.fallbackUrl_ = null; + this.load( + box, fillMode, onSuccess, + ThumbnailLoader.AUTO_FILL_THRESHOLD_DEFAULT_VALUE, box.clientWidth, + box.clientHeight); + } else { + box.setAttribute('generic-thumbnail', this.mediaType_); + } + }; + + if (this.image_.src) { + console.warn('Thumbnail already loaded: ' + this.thumbnailUrl_); + return; + } + + // TODO(mtomasz): Smarter calculation of the requested size. + const wasAttached = box.ownerDocument.contains(box); + const modificationTime = this.metadata_ && this.metadata_.filesystem && + this.metadata_.filesystem.modificationTime && + this.metadata_.filesystem.modificationTime.getTime(); + this.taskId_ = ImageLoaderClient.loadToImage( + LoadImageRequest.createRequest({ + url: this.thumbnailUrl_, + maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, + maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, + cache: true, + priority: this.priority_, + timestamp: modificationTime, + orientation: this.transform_ + }), + this.image_, () => {}, () => { + this.image_.onerror(new Event('load-error')); + }); + } + + /** + * Loads thumbnail as data url. If data url of thumbnail can be fetched from + * metadata, this fetches it from it. Otherwise, this tries to load it from + * thumbnail loader. + * Compared with ThumbnailLoader.load, this method does not provide a + * functionality to fit image to a box. + * + * @param {ThumbnailLoader.FillMode} fillMode Only FIT and OVER_FILL is + * supported. This takes effect only when external thumbnail source is + * used. + * @return {!Promise<{data:string, width:number, height:number}>} A promise + * which is resolved when data url is fetched. + * + * TODO(yawano): Support cancel operation. + */ + loadAsDataUrl(fillMode) { + assert( + fillMode === ThumbnailLoader.FillMode.FIT || + fillMode === ThumbnailLoader.FillMode.OVER_FILL); + + return new Promise((resolve, reject) => { + // Load by using ImageLoaderClient. + const modificationTime = this.metadata_ && this.metadata_.filesystem && + this.metadata_.filesystem.modificationTime && + this.metadata_.filesystem.modificationTime.getTime(); + let request = LoadImageRequest.createRequest({ + url: this.thumbnailUrl_, + maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, + maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, + cache: true, + priority: this.priority_, + timestamp: modificationTime, + orientation: this.transform_ + }); + + if (fillMode === ThumbnailLoader.FillMode.OVER_FILL) { + // Use cropped thumbnail url if available. + request.url = this.croppedThumbnailUrl_ ? this.croppedThumbnailUrl_ : + this.thumbnailUrl_; + + // Set crop option to image loader. Since image of croppedThumbnailUrl_ + // is 360x360 with current implementation, it's no problem to crop it. + request.width = 360; + request.height = 360; + request.crop = true; + } + + ImageLoaderClient.getInstance().load(request, result => { + if (result.status === LoadImageResponseStatus.SUCCESS) { + resolve(result); + } else { + reject(result); + } + }); + }); + } + + /** + * Cancels loading the current image. + */ + cancel() { + if (this.taskId_) { + this.image_.onload = () => {}; + this.image_.onerror = () => {}; + ImageLoaderClient.getInstance().cancel(this.taskId_); + this.taskId_ = null; + } + } + + /** + * @return {boolean} True if a valid image is loaded. + */ + hasValidImage() { + return !!(this.image_ && this.image_.width && this.image_.height); + } + + /** + * @return {number} Image width. + */ + getWidth() { + return this.image_.width; + } + + /** + * @return {number} Image height. + */ + getHeight() { + return this.image_.height; + } + + /** + * Load an image but do not attach it. + * + * @param {function(boolean)} callback Callback, parameter is true if the + * image has loaded successfully or a stock icon has been used. + */ + loadDetachedImage(callback) { + if (!this.thumbnailUrl_) { + callback(true); + return; + } + + this.cancel(); + this.canvasUpToDate_ = false; + this.image_ = new Image(); + this.image_.onload = callback.bind(null, true); + this.image_.onerror = callback.bind(null, false); + + // TODO(mtomasz): Smarter calculation of the requested size. + const modificationTime = this.metadata_ && this.metadata_.filesystem && + this.metadata_.filesystem.modificationTime && + this.metadata_.filesystem.modificationTime.getTime(); + this.taskId_ = ImageLoaderClient.loadToImage( + LoadImageRequest.createRequest({ + url: this.thumbnailUrl_, + maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, + maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, + cache: true, + priority: this.priority_, + timestamp: modificationTime, + orientation: this.transform_ + }), + this.image_, () => {}, () => { + this.image_.onerror(new Event('load-error')); + }); + } + + /** + * Renders the thumbnail into either canvas or an image element. * @private */ - this.loadTarget_ = null; - - if (!opt_metadata) { - this.thumbnailUrl_ = entry.toURL(); // Use the URL directly. - this.loadTarget_ = ThumbnailLoader.LoadTarget.FILE_ENTRY; - return; - } - - this.fallbackUrl_ = null; - this.thumbnailUrl_ = null; - if (opt_metadata.external && opt_metadata.external.customIconUrl) { - this.fallbackUrl_ = opt_metadata.external.customIconUrl; - } - const mimeType = opt_metadata && opt_metadata.contentMimeType; - - for (let i = 0; i < loadTargets.length; i++) { - switch (loadTargets[i]) { - case ThumbnailLoader.LoadTarget.CONTENT_METADATA: - if (opt_metadata.thumbnail && opt_metadata.thumbnail.url) { - this.thumbnailUrl_ = opt_metadata.thumbnail.url; - this.transform_ = - opt_metadata.thumbnail && opt_metadata.thumbnail.transform; - this.loadTarget_ = ThumbnailLoader.LoadTarget.CONTENT_METADATA; - } - break; - case ThumbnailLoader.LoadTarget.EXTERNAL_METADATA: - if (opt_metadata.external && opt_metadata.external.thumbnailUrl && - (!opt_metadata.external.present || - !FileType.isImage(entry, mimeType))) { - this.thumbnailUrl_ = opt_metadata.external.thumbnailUrl; - this.croppedThumbnailUrl_ = opt_metadata.external.croppedThumbnailUrl; - this.loadTarget_ = ThumbnailLoader.LoadTarget.EXTERNAL_METADATA; - } - break; - case ThumbnailLoader.LoadTarget.FILE_ENTRY: - if (FileType.isImage(entry, mimeType) || - FileType.isVideo(entry, mimeType) || - FileType.isRaw(entry, mimeType)) { - this.thumbnailUrl_ = entry.toURL(); - this.transform_ = - opt_metadata.media && opt_metadata.media.imageTransform; - this.loadTarget_ = ThumbnailLoader.LoadTarget.FILE_ENTRY; - } - break; - default: - assertNotReached('Unkonwn load type: ' + loadTargets[i]); + renderMedia_() { + if (this.loaderType_ !== ThumbnailLoader.LoaderType.CANVAS) { + return; } - if (this.thumbnailUrl_) { - break; + + if (!this.canvas_) { + this.canvas_ = + /** @type {HTMLCanvasElement} */ (document.createElement('canvas')); + } + + // Copy the image to a canvas if the canvas is outdated. + // At this point, image transformation is not applied because we attach + // style attribute to an img element in attachImage() instead. + if (!this.canvasUpToDate_) { + this.canvas_.width = this.image_.width; + this.canvas_.height = this.image_.height; + const context = this.canvas_.getContext('2d'); + context.drawImage(this.image_, 0, 0); + this.canvasUpToDate_ = true; } } - if (!this.thumbnailUrl_ && this.fallbackUrl_) { - // Use fallback as the primary thumbnail. - this.thumbnailUrl_ = this.fallbackUrl_; - this.fallbackUrl_ = null; - } // else the generic thumbnail based on the media type will be used. + /** + * Attach the image to a given element. + * @param {!Element} box Container element. + * @param {ThumbnailLoader.FillMode} fillMode Fill mode. + * @param {number} autoFillThreshold Threshold value which is used for fill + * mode auto. + * @param {number} boxWidth Container box's width. + * @param {number} boxHeight Container box's height. + * @private + */ + attachImage_(box, fillMode, autoFillThreshold, boxWidth, boxHeight) { + if (!this.hasValidImage()) { + box.setAttribute('generic-thumbnail', this.mediaType_); + return; + } + + this.renderMedia_(); + const attachableMedia = + this.loaderType_ === ThumbnailLoader.LoaderType.CANVAS ? this.canvas_ : + this.image_; + + ThumbnailLoader.centerImage_( + box, attachableMedia, fillMode, autoFillThreshold, boxWidth, boxHeight); + + if (attachableMedia.parentNode !== box) { + box.textContent = ''; + box.appendChild(attachableMedia); + } + + if (!this.taskId_) { + attachableMedia.classList.add('cached'); + } + } + + /** + * Gets the loaded image. + * + * @return {Image|HTMLCanvasElement} Either image or a canvas object. + */ + getImage() { + this.renderMedia_(); + return (this.loaderType_ === ThumbnailLoader.LoaderType.IMAGE) ? + this.image_ : + this.canvas_; + } + + /** + * Updates the image style to fit/fill the container. + * + * Using webkit center packing does not align the image properly, so we need + * to wait until the image loads and its dimensions are known, then manually + * position it at the center. + * + * @param {Element} box Containing element. + * @param {Image|HTMLCanvasElement} img Element containing an image. + * @param {ThumbnailLoader.FillMode} fillMode Fill mode. + * @param {number} autoFillThreshold Threshold value which is used for fill + * mode auto. + * @param {number} boxWidth Container box's width. + * @param {number} boxHeight Container box's height. + * @private + */ + static centerImage_( + box, img, fillMode, autoFillThreshold, boxWidth, boxHeight) { + const imageWidth = img.width; + const imageHeight = img.height; + + let fractionX; + let fractionY; + + let fill; + switch (fillMode) { + case ThumbnailLoader.FillMode.FILL: + case ThumbnailLoader.FillMode.OVER_FILL: + fill = true; + break; + case ThumbnailLoader.FillMode.FIT: + fill = false; + break; + case ThumbnailLoader.FillMode.AUTO: + const imageRatio = imageWidth / imageHeight; + let boxRatio = 1.0; + if (boxWidth && boxHeight) { + boxRatio = boxWidth / boxHeight; + } + // Cropped area in percents. + const ratioFactor = boxRatio / imageRatio; + fill = (ratioFactor >= 1.0 - autoFillThreshold) && + (ratioFactor <= 1.0 + autoFillThreshold); + break; + } + + if (boxWidth && boxHeight) { + // When we know the box size we can position the image correctly even + // in a non-square box. + const fitScaleX = boxWidth / imageWidth; + const fitScaleY = boxHeight / imageHeight; + + let scale = fill ? Math.max(fitScaleX, fitScaleY) : + Math.min(fitScaleX, fitScaleY); + + if (fillMode !== ThumbnailLoader.FillMode.OVER_FILL) { + scale = Math.min(scale, 1); // Never overscale. + } + + fractionX = imageWidth * scale / boxWidth; + fractionY = imageHeight * scale / boxHeight; + } else { + // We do not know the box size so we assume it is square. + // Compute the image position based only on the image dimensions. + // First try vertical fit or horizontal fill. + fractionX = imageWidth / imageHeight; + fractionY = 1; + if ((fractionX < 1) === !!fill) { // Vertical fill or horizontal fit. + fractionY = 1 / fractionX; + fractionX = 1; + } + } + + function percent(fraction) { + return (fraction * 100).toFixed(2) + '%'; + } + + img.style.width = percent(fractionX); + img.style.height = percent(fractionY); + img.style.left = percent((1 - fractionX) / 2); + img.style.top = percent((1 - fractionY) / 2); + } } /** @@ -166,355 +535,3 @@ * @type {number} */ ThumbnailLoader.THUMBNAIL_MAX_HEIGHT = 500; - -/** - * Returns the target of loading. - * @return {?ThumbnailLoader.LoadTarget} - */ -ThumbnailLoader.prototype.getLoadTarget = function() { - return this.loadTarget_; -}; - -/** - * Loads and attaches an image. - * - * @param {!Element} box Container element. - * @param {ThumbnailLoader.FillMode} fillMode Fill mode. - * @param {function(Image)} onSuccess Success callback, accepts the image. - * @param {number} autoFillThreshold Auto fill threshold. - * @param {number} boxWidth Container box's width. - * @param {number} boxHeight Container box's height. - */ -ThumbnailLoader.prototype.load = function( - box, fillMode, onSuccess, autoFillThreshold, boxWidth, boxHeight) { - if (!this.thumbnailUrl_) { - // Relevant CSS rules are in file_types.css. - box.setAttribute('generic-thumbnail', this.mediaType_); - return; - } - - this.cancel(); - this.canvasUpToDate_ = false; - this.image_ = new Image(); - this.image_.setAttribute('alt', this.entry_.name); - this.image_.onload = () => { - this.attachImage_(box, fillMode, autoFillThreshold, boxWidth, boxHeight); - onSuccess(this.image_); - }; - this.image_.onerror = () => { - if (this.fallbackUrl_) { - this.thumbnailUrl_ = this.fallbackUrl_; - this.fallbackUrl_ = null; - this.load( - box, fillMode, onSuccess, - ThumbnailLoader.AUTO_FILL_THRESHOLD_DEFAULT_VALUE, box.clientWidth, - box.clientHeight); - } else { - box.setAttribute('generic-thumbnail', this.mediaType_); - } - }; - - if (this.image_.src) { - console.warn('Thumbnail already loaded: ' + this.thumbnailUrl_); - return; - } - - // TODO(mtomasz): Smarter calculation of the requested size. - const wasAttached = box.ownerDocument.contains(box); - const modificationTime = this.metadata_ && this.metadata_.filesystem && - this.metadata_.filesystem.modificationTime && - this.metadata_.filesystem.modificationTime.getTime(); - this.taskId_ = ImageLoaderClient.loadToImage( - LoadImageRequest.createRequest({ - url: this.thumbnailUrl_, - maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, - maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, - cache: true, - priority: this.priority_, - timestamp: modificationTime, - orientation: this.transform_ - }), - this.image_, () => {}, () => { - this.image_.onerror(new Event('load-error')); - }); -}; - -/** - * Loads thumbnail as data url. If data url of thumbnail can be fetched from - * metadata, this fetches it from it. Otherwise, this tries to load it from - * thumbnail loader. - * Compared with ThumbnailLoader.load, this method does not provide a - * functionality to fit image to a box. - * - * @param {ThumbnailLoader.FillMode} fillMode Only FIT and OVER_FILL is - * supported. This takes effect only when external thumbnail source is used. - * @return {!Promise<{data:string, width:number, height:number}>} A promise - * which is resolved when data url is fetched. - * - * TODO(yawano): Support cancel operation. - */ -ThumbnailLoader.prototype.loadAsDataUrl = function(fillMode) { - assert( - fillMode === ThumbnailLoader.FillMode.FIT || - fillMode === ThumbnailLoader.FillMode.OVER_FILL); - - return new Promise((resolve, reject) => { - // Load by using ImageLoaderClient. - const modificationTime = this.metadata_ && this.metadata_.filesystem && - this.metadata_.filesystem.modificationTime && - this.metadata_.filesystem.modificationTime.getTime(); - let request = LoadImageRequest.createRequest({ - url: this.thumbnailUrl_, - maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, - maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, - cache: true, - priority: this.priority_, - timestamp: modificationTime, - orientation: this.transform_ - }); - - if (fillMode === ThumbnailLoader.FillMode.OVER_FILL) { - // Use cropped thumbnail url if available. - request.url = this.croppedThumbnailUrl_ ? this.croppedThumbnailUrl_ : - this.thumbnailUrl_; - - // Set crop option to image loader. Since image of croppedThumbnailUrl_ is - // 360x360 with current implementation, it's no problem to crop it. - request.width = 360; - request.height = 360; - request.crop = true; - } - - ImageLoaderClient.getInstance().load(request, result => { - if (result.status === LoadImageResponseStatus.SUCCESS) { - resolve(result); - } else { - reject(result); - } - }); - }); -}; - -/** - * Cancels loading the current image. - */ -ThumbnailLoader.prototype.cancel = function() { - if (this.taskId_) { - this.image_.onload = () => {}; - this.image_.onerror = () => {}; - ImageLoaderClient.getInstance().cancel(this.taskId_); - this.taskId_ = null; - } -}; - -/** - * @return {boolean} True if a valid image is loaded. - */ -ThumbnailLoader.prototype.hasValidImage = function() { - return !!(this.image_ && this.image_.width && this.image_.height); -}; - -/** - * @return {number} Image width. - */ -ThumbnailLoader.prototype.getWidth = function() { - return this.image_.width; -}; - -/** - * @return {number} Image height. - */ -ThumbnailLoader.prototype.getHeight = function() { - return this.image_.height; -}; - -/** - * Load an image but do not attach it. - * - * @param {function(boolean)} callback Callback, parameter is true if the image - * has loaded successfully or a stock icon has been used. - */ -ThumbnailLoader.prototype.loadDetachedImage = function(callback) { - if (!this.thumbnailUrl_) { - callback(true); - return; - } - - this.cancel(); - this.canvasUpToDate_ = false; - this.image_ = new Image(); - this.image_.onload = callback.bind(null, true); - this.image_.onerror = callback.bind(null, false); - - // TODO(mtomasz): Smarter calculation of the requested size. - const modificationTime = this.metadata_ && this.metadata_.filesystem && - this.metadata_.filesystem.modificationTime && - this.metadata_.filesystem.modificationTime.getTime(); - this.taskId_ = ImageLoaderClient.loadToImage( - LoadImageRequest.createRequest({ - url: this.thumbnailUrl_, - maxWidth: ThumbnailLoader.THUMBNAIL_MAX_WIDTH, - maxHeight: ThumbnailLoader.THUMBNAIL_MAX_HEIGHT, - cache: true, - priority: this.priority_, - timestamp: modificationTime, - orientation: this.transform_ - }), - this.image_, () => {}, () => { - this.image_.onerror(new Event('load-error')); - }); -}; - -/** - * Renders the thumbnail into either canvas or an image element. - * @private - */ -ThumbnailLoader.prototype.renderMedia_ = function() { - if (this.loaderType_ !== ThumbnailLoader.LoaderType.CANVAS) { - return; - } - - if (!this.canvas_) { - this.canvas_ = document.createElement('canvas'); - } - - // Copy the image to a canvas if the canvas is outdated. - // At this point, image transformation is not applied because we attach style - // attribute to an img element in attachImage() instead. - if (!this.canvasUpToDate_) { - this.canvas_.width = this.image_.width; - this.canvas_.height = this.image_.height; - const context = this.canvas_.getContext('2d'); - context.drawImage(this.image_, 0, 0); - this.canvasUpToDate_ = true; - } -}; - -/** - * Attach the image to a given element. - * @param {!Element} box Container element. - * @param {ThumbnailLoader.FillMode} fillMode Fill mode. - * @param {number} autoFillThreshold Threshold value which is used for fill - * mode auto. - * @param {number} boxWidth Container box's width. - * @param {number} boxHeight Container box's height. - * @private - */ -ThumbnailLoader.prototype.attachImage_ = function( - box, fillMode, autoFillThreshold, boxWidth, boxHeight) { - if (!this.hasValidImage()) { - box.setAttribute('generic-thumbnail', this.mediaType_); - return; - } - - this.renderMedia_(); - const attachableMedia = - this.loaderType_ === ThumbnailLoader.LoaderType.CANVAS ? this.canvas_ : - this.image_; - - ThumbnailLoader.centerImage_( - box, attachableMedia, fillMode, autoFillThreshold, boxWidth, boxHeight); - - if (attachableMedia.parentNode !== box) { - box.textContent = ''; - box.appendChild(attachableMedia); - } - - if (!this.taskId_) { - attachableMedia.classList.add('cached'); - } -}; - -/** - * Gets the loaded image. - * - * @return {Image|HTMLCanvasElement} Either image or a canvas object. - */ -ThumbnailLoader.prototype.getImage = function() { - this.renderMedia_(); - return (this.loaderType_ === ThumbnailLoader.LoaderType.IMAGE) ? this.image_ : - this.canvas_; -}; - -/** - * Update the image style to fit/fill the container. - * - * Using webkit center packing does not align the image properly, so we need - * to wait until the image loads and its dimensions are known, then manually - * position it at the center. - * - * @param {Element} box Containing element. - * @param {Image|HTMLCanvasElement} img Element containing an image. - * @param {ThumbnailLoader.FillMode} fillMode Fill mode. - * @param {number} autoFillThreshold Threshold value which is used for fill mode - * auto. - * @param {number} boxWidth Container box's width. - * @param {number} boxHeight Container box's height. - * @private - */ -ThumbnailLoader.centerImage_ = - (box, img, fillMode, autoFillThreshold, boxWidth, boxHeight) => { - const imageWidth = img.width; - const imageHeight = img.height; - - let fractionX; - let fractionY; - - let fill; - switch (fillMode) { - case ThumbnailLoader.FillMode.FILL: - case ThumbnailLoader.FillMode.OVER_FILL: - fill = true; - break; - case ThumbnailLoader.FillMode.FIT: - fill = false; - break; - case ThumbnailLoader.FillMode.AUTO: - const imageRatio = imageWidth / imageHeight; - let boxRatio = 1.0; - if (boxWidth && boxHeight) { - boxRatio = boxWidth / boxHeight; - } - // Cropped area in percents. - const ratioFactor = boxRatio / imageRatio; - fill = (ratioFactor >= 1.0 - autoFillThreshold) && - (ratioFactor <= 1.0 + autoFillThreshold); - break; - } - - if (boxWidth && boxHeight) { - // When we know the box size we can position the image correctly even - // in a non-square box. - const fitScaleX = boxWidth / imageWidth; - const fitScaleY = boxHeight / imageHeight; - - let scale = fill ? Math.max(fitScaleX, fitScaleY) : - Math.min(fitScaleX, fitScaleY); - - if (fillMode !== ThumbnailLoader.FillMode.OVER_FILL) { - scale = Math.min(scale, 1); // Never overscale. - } - - fractionX = imageWidth * scale / boxWidth; - fractionY = imageHeight * scale / boxHeight; - } else { - // We do not know the box size so we assume it is square. - // Compute the image position based only on the image dimensions. - // First try vertical fit or horizontal fill. - fractionX = imageWidth / imageHeight; - fractionY = 1; - if ((fractionX < 1) === !!fill) { // Vertical fill or horizontal fit. - fractionY = 1 / fractionX; - fractionX = 1; - } - } - - function percent(fraction) { - return (fraction * 100).toFixed(2) + '%'; - } - - img.style.width = percent(fractionX); - img.style.height = percent(fractionY); - img.style.left = percent((1 - fractionX) / 2); - img.style.top = percent((1 - fractionY) / 2); - };
diff --git a/ui/file_manager/file_manager/foreground/js/toolbar_controller.js b/ui/file_manager/file_manager/foreground/js/toolbar_controller.js index e514651..bc1ab7b 100644 --- a/ui/file_manager/file_manager/foreground/js/toolbar_controller.js +++ b/ui/file_manager/file_manager/foreground/js/toolbar_controller.js
@@ -17,10 +17,11 @@ * the toolbar. * @param {!FileSelectionHandler} selectionHandler * @param {!DirectoryModel} directoryModel + * @param {!VolumeManager} volumeManager */ constructor( toolbar, navigationList, listContainer, locationLine, selectionHandler, - directoryModel) { + directoryModel, volumeManager) { /** * @private {!HTMLElement} * @const @@ -100,6 +101,12 @@ */ this.directoryModel_ = directoryModel; + /** + * @private {!VolumeManager} + * @const + */ + this.volumeManager_ = volumeManager; + this.selectionHandler_.addEventListener( FileSelectionHandler.EventType.CHANGE, this.onSelectionChanged_.bind(this)); @@ -114,7 +121,7 @@ 'relayout', this.onNavigationListRelayout_.bind(this)); this.directoryModel_.addEventListener( - 'directory-change', this.updateCurrentDirectoryButtons_.bind(this)); + 'directory-changed', this.updateCurrentDirectoryButtons_.bind(this)); // Watch visibility of toolbar buttons to update the width of location line. const observer = @@ -172,10 +179,8 @@ this.deleteButton_.hidden = (selection.totalCount === 0 || this.directoryModel_.isReadOnly() || selection.hasReadOnlyEntry() || - (util.isMyFilesVolumeEnabled() && - this.directoryModel_.getCurrentRootType() == - VolumeManagerCommon.RootType.DOWNLOADS && - selection.entries.some(entry => entry.fullPath === '/Downloads'))); + selection.entries.some( + entry => util.isNonModifiable(this.volumeManager_, entry))); // Set .selecting class to containing element to change the view // accordingly.
diff --git a/ui/file_manager/integration_tests/file_manager/my_files.js b/ui/file_manager/integration_tests/file_manager/my_files.js index 704cb37..e984cbe 100644 --- a/ui/file_manager/integration_tests/file_manager/my_files.js +++ b/ui/file_manager/integration_tests/file_manager/my_files.js
@@ -1,6 +1,28 @@ // Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +/** + * Select My files in directory tree and wait for load. + * + * @param {string} appId ID of the app window. + */ +async function selectMyFiles(appId) { + // Select My Files folder. + const myFilesQuery = '#directory-tree [entry-label="My files"]'; + const isDriveQuery = false; + chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( + 'selectInDirectoryTree', appId, [myFilesQuery, isDriveQuery])); + + // Wait for file list to display Downloads and Crostini. + const downloadsRow = ['Downloads', '--', 'Folder']; + const playFilesRow = ['Play files', '--', 'Folder']; + const crostiniRow = ['Linux files', '--', 'Folder']; + await remoteCall.waitForFiles( + appId, [downloadsRow, playFilesRow, crostiniRow], + {ignoreFileSize: true, ignoreLastModifiedTime: true}); +} + /** * Tests if MyFiles is displayed when flag is true. */ @@ -72,11 +94,8 @@ chrome.test.assertEq(1, buttonElements.length); chrome.test.assertFalse(buttonElements[0].hidden); - // Select My Files folder. - const myFilesQuery = '#directory-tree [entry-label="My files"]'; - const isDriveQuery = false; - chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - 'selectInDirectoryTree', appId, [myFilesQuery, isDriveQuery])); + // Select My files in directory tree. + await selectMyFiles(appId); // Get the search button element. buttonElements = await remoteCall.callRemoteTestUtil( @@ -122,19 +141,8 @@ const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); - // Select My Files folder. - const myFilesQuery = '#directory-tree [entry-label="My files"]'; - const isDriveQuery = false; - chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( - 'selectInDirectoryTree', appId, [myFilesQuery, isDriveQuery])); - - // Wait for file list to display Downloads and Crostini. - const downloadsRow = ['Downloads', '--', 'Folder']; - const playFilesRow = ['Play files', '--', 'Folder']; - const crostiniRow = ['Linux files', '--', 'Folder']; - await remoteCall.waitForFiles( - appId, [downloadsRow, playFilesRow, crostiniRow], - {ignoreFileSize: true, ignoreLastModifiedTime: true}); + // Select My files in directory tree. + await selectMyFiles(appId); // Double click on Download on file list. const downloadsFileListQuery = '#file-list [file-name="Downloads"]'; @@ -228,23 +236,8 @@ const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.photos], []); - // Select "My files" folder via directory tree. - const myFilesQuery = '#directory-tree [entry-label="My files"]'; - const isDriveQuery = false; - chrome.test.assertTrue( - !!await remoteCall.callRemoteTestUtil( - 'selectInDirectoryTree', appId, [myFilesQuery, isDriveQuery]), - 'selectInDirectoryTree failed'); - - // Wait for Downloads to load. - const expectedRows = [ - ['Downloads', '--', 'Folder'], - ['Play files', '--', 'Folder'], - ['Linux files', '--', 'Folder'], - ]; - await remoteCall.waitForFiles( - appId, expectedRows, - {ignoreFileSize: true, ignoreLastModifiedTime: true}); + // Select My files in directory tree. + await selectMyFiles(appId); // Select Downloads via file list. const downloads = ['Downloads']; @@ -386,3 +379,43 @@ chrome.test.assertTrue( !!await remoteCall.waitForElementLost(appId, playFilesTreeItem)); }; + +/** + * Tests that toolbar delete is not shown for Downloads, or Linux files. + */ +testcase.myFilesToolbarDelete = async () => { + // Open Files app on local Downloads. + const appId = + await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.beautiful], []); + + // Select My files in directory tree. + await selectMyFiles(appId); + + // Select Downloads folder in list. + chrome.test.assertTrue( + await remoteCall.callRemoteTestUtil('selectFile', appId, ['Downloads'])); + + // Test that the delete button isn't visible. + const hiddenDeleteButton = '#delete-button[hidden]'; + await remoteCall.waitForElement(appId, hiddenDeleteButton); + + // Select fake entry Linux files folder in list. + chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( + 'selectFile', appId, ['Linux files'])); + + // Test that the delete button isn't visible. + await remoteCall.waitForElement(appId, hiddenDeleteButton); + + // Mount crostini and test real root entry. + await mountCrostini(appId); + + // Select My files in directory tree. + await selectMyFiles(appId); + + // Select real Linux files folder in list. + chrome.test.assertTrue(await remoteCall.callRemoteTestUtil( + 'selectFile', appId, ['Linux files'])); + + // Test that the delete button isn't visible. + await remoteCall.waitForElement(appId, hiddenDeleteButton); +};
diff --git a/ui/native_theme/native_theme_mac.mm b/ui/native_theme/native_theme_mac.mm index 40e5cb5..7c3ffa8c 100644 --- a/ui/native_theme/native_theme_mac.mm +++ b/ui/native_theme/native_theme_mac.mm
@@ -19,7 +19,6 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/skia_util.h" #include "ui/native_theme/common_theme.h" -#include "ui/native_theme/native_theme_aura.h" namespace { @@ -153,8 +152,6 @@ // static NativeTheme* NativeTheme::GetInstanceForWeb() { - if (features::IsFormControlsRefreshEnabled()) - return NativeThemeAura::web_instance(); return NativeThemeMac::instance(); }
diff --git a/ui/views/DEPS b/ui/views/DEPS index 07b7bc43..4959057 100644 --- a/ui/views/DEPS +++ b/ui/views/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+cc/paint", "+components/crash/core/common/crash_key.h", + "+components/remote_cocoa", "+components/vector_icons", "+mojo/public/cpp/bindings", "+services/ws/public/mojom", @@ -21,7 +22,6 @@ "+ui/resources/grit/ui_resources.h", "+ui/strings/grit/ui_strings.h", "+ui/touch_selection", - "+ui/views_bridge_mac", "+ui/wm/core", "+ui/wm/public",
diff --git a/ui/views/cocoa/DEPS b/ui/views/cocoa/DEPS index e6cea14f..d4cfbf0 100644 --- a/ui/views/cocoa/DEPS +++ b/ui/views/cocoa/DEPS
@@ -1,5 +1,4 @@ include_rules = [ - "+components/remote_cocoa/common", + "+components/remote_cocoa", "+ui/accelerated_widget_mac", - "+ui/views_bridge_mac", ]
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.h b/ui/views/cocoa/bridged_native_widget_host_impl.h index 32bd7be..eddecb59 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.h +++ b/ui/views/cocoa/bridged_native_widget_host_impl.h
@@ -10,6 +10,7 @@ #include "base/mac/scoped_nsobject.h" #include "base/macros.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h" #include "components/remote_cocoa/common/bridged_native_widget.mojom.h" #include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h" @@ -25,7 +26,6 @@ #include "ui/views/views_export.h" #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_observer.h" -#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h" @class NativeWidgetMacNSWindow; @class NSAccessibilityRemoteUIElement;
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm index 865faa3..b51ced5 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.mm +++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -8,6 +8,9 @@ #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" +#include "components/remote_cocoa/app_shim/mouse_capture.h" +#include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" #include "mojo/public/cpp/bindings/strong_associated_binding.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/cocoa/animation_utils.h" @@ -33,9 +36,6 @@ #include "ui/views/window/dialog_client_view.h" #include "ui/views/window/dialog_delegate.h" #include "ui/views/word_lookup_client.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" -#include "ui/views_bridge_mac/cocoa_mouse_capture.h" -#include "ui/views_bridge_mac/native_widget_mac_nswindow.h" using views_bridge_mac::mojom::BridgedNativeWidgetInitParams; using views_bridge_mac::mojom::WindowVisibilityState;
diff --git a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm index 0dce22e..20ee2294 100644 --- a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm +++ b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #import <Cocoa/Cocoa.h>
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm index 9ca1972..8a871ad 100644 --- a/ui/views/cocoa/bridged_native_widget_unittest.mm +++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #import <Cocoa/Cocoa.h> #include <objc/runtime.h> @@ -19,6 +19,9 @@ #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_task_environment.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" +#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h" #import "testing/gtest_mac.h" #import "ui/base/cocoa/window_size_constants.h" #include "ui/base/ime/input_method.h" @@ -37,9 +40,6 @@ #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" -#import "ui/views_bridge_mac/views_nswindow_delegate.h" using base::ASCIIToUTF16; using base::SysNSStringToUTF8;
diff --git a/ui/views/cocoa/cocoa_mouse_capture_unittest.mm b/ui/views/cocoa/cocoa_mouse_capture_unittest.mm index 68dad9f..c1a75f27 100644 --- a/ui/views/cocoa/cocoa_mouse_capture_unittest.mm +++ b/ui/views/cocoa/cocoa_mouse_capture_unittest.mm
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ui/views_bridge_mac/cocoa_mouse_capture.h" +#import "components/remote_cocoa/app_shim/mouse_capture.h" #import <Cocoa/Cocoa.h> #import "base/mac/scoped_nsobject.h" #include "base/macros.h" +#import "components/remote_cocoa/app_shim/mouse_capture_delegate.h" #import "ui/base/test/cocoa_helper.h" #import "ui/events/test/cocoa_test_event_utils.h" -#import "ui/views_bridge_mac/cocoa_mouse_capture_delegate.h" // Simple test view that counts calls to -[NSView mouseDown:]. @interface CocoaMouseCaptureTestView : NSView {
diff --git a/ui/views/cocoa/drag_drop_client_mac.h b/ui/views/cocoa/drag_drop_client_mac.h index d952728..326650c 100644 --- a/ui/views/cocoa/drag_drop_client_mac.h +++ b/ui/views/cocoa/drag_drop_client_mac.h
@@ -11,11 +11,11 @@ #include "base/callback.h" #include "base/macros.h" +#include "components/remote_cocoa/app_shim/drag_drop_client.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/views/views_export.h" #include "ui/views/widget/drop_helper.h" -#include "ui/views_bridge_mac/drag_drop_client.h" namespace gfx { class Point;
diff --git a/ui/views/cocoa/drag_drop_client_mac.mm b/ui/views/cocoa/drag_drop_client_mac.mm index da67163..ac1c1b5 100644 --- a/ui/views/cocoa/drag_drop_client_mac.mm +++ b/ui/views/cocoa/drag_drop_client_mac.mm
@@ -7,12 +7,12 @@ #include "base/mac/mac_util.h" #include "base/run_loop.h" #include "base/strings/sys_string_conversions.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #import "ui/base/dragdrop/os_exchange_data_provider_mac.h" #include "ui/gfx/image/image_skia_util_mac.h" #include "ui/views/drag_utils.h" #include "ui/views/widget/native_widget_mac.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views {
diff --git a/ui/views/cocoa/drag_drop_client_mac_unittest.mm b/ui/views/cocoa/drag_drop_client_mac_unittest.mm index 94f0eea..e19072b0 100644 --- a/ui/views/cocoa/drag_drop_client_mac_unittest.mm +++ b/ui/views/cocoa/drag_drop_client_mac_unittest.mm
@@ -12,6 +12,7 @@ #include "base/mac/sdk_forward_declarations.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #import "ui/base/clipboard/clipboard_util_mac.h" #include "ui/gfx/image/image_unittest_util.h" #import "ui/views/cocoa/bridged_native_widget_host_impl.h" @@ -19,7 +20,6 @@ #include "ui/views/view.h" #include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/widget.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" using base::ASCIIToUTF16;
diff --git a/ui/views/cocoa/text_input_host.mm b/ui/views/cocoa/text_input_host.mm index dbe86f72..c1bbbe0ce 100644 --- a/ui/views/cocoa/text_input_host.mm +++ b/ui/views/cocoa/text_input_host.mm
@@ -4,11 +4,11 @@ #include "ui/views/cocoa/text_input_host.h" +#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/views/cocoa/bridged_native_widget_host_impl.h" -#include "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace {
diff --git a/ui/views/cocoa/tooltip_manager_mac.mm b/ui/views/cocoa/tooltip_manager_mac.mm index cbf12b14..de37a7a8 100644 --- a/ui/views/cocoa/tooltip_manager_mac.mm +++ b/ui/views/cocoa/tooltip_manager_mac.mm
@@ -5,11 +5,11 @@ #include "ui/views/cocoa/tooltip_manager_mac.h" #include "base/no_destructor.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "ui/base/cocoa/cocoa_base_utils.h" #include "ui/gfx/font_list.h" #import "ui/gfx/mac/coordinate_conversion.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace {
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/ui/views/controls/scrollbar/cocoa_scroll_bar.h index b4ae90e..a839959 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.h +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -8,11 +8,11 @@ #import "base/mac/scoped_nsobject.h" #include "base/macros.h" #include "base/timer/timer.h" +#import "components/remote_cocoa/app_shim/views_scrollbar_bridge.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/views/controls/scrollbar/scroll_bar.h" #include "ui/views/views_export.h" -#import "ui/views_bridge_mac/views_scrollbar_bridge.h" namespace views {
diff --git a/ui/views/test/platform_test_helper_cocoa.mm b/ui/views/test/platform_test_helper_cocoa.mm index 98d5872..4a0831b 100644 --- a/ui/views/test/platform_test_helper_cocoa.mm +++ b/ui/views/test/platform_test_helper_cocoa.mm
@@ -9,9 +9,9 @@ #import "base/mac/scoped_nsobject.h" #import "base/mac/scoped_objc_class_swizzler.h" #include "base/macros.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/widget.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views {
diff --git a/ui/views/test/widget_test_mac.mm b/ui/views/test/widget_test_mac.mm index e936011..6414d67 100644 --- a/ui/views/test/widget_test_mac.mm +++ b/ui/views/test/widget_test_mac.mm
@@ -9,10 +9,10 @@ #import "base/mac/scoped_nsobject.h" #import "base/mac/scoped_objc_class_swizzler.h" #include "base/macros.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" #include "ui/views/cocoa/bridged_native_widget_host_impl.h" #include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/root_view.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" namespace views { namespace test {
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index 4b1b2c4..ccb81cf 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -14,6 +14,10 @@ #include "base/strings/sys_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "components/crash/core/common/crash_key.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" +#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h" #import "ui/base/cocoa/constrained_window/constrained_window_animation.h" #import "ui/base/cocoa/window_size_constants.h" #include "ui/display/display.h" @@ -29,10 +33,6 @@ #include "ui/views/widget/drop_helper.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/window/native_frame_view.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" -#import "ui/views_bridge_mac/views_nswindow_delegate.h" using views_bridge_mac::mojom::WindowVisibilityState;
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm index 340fe7a..ce14d4c 100644 --- a/ui/views/widget/native_widget_mac_unittest.mm +++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -19,6 +19,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_task_runner_handle.h" +#import "components/remote_cocoa/app_shim/bridged_content_view.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" #import "testing/gtest_mac.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -42,9 +45,6 @@ #include "ui/views/widget/native_widget_private.h" #include "ui/views/window/dialog_client_view.h" #include "ui/views/window/dialog_delegate.h" -#import "ui/views_bridge_mac/bridged_content_view.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" // Donates an implementation of -[NSAnimation stopAnimation] which calls the // original implementation, then quits a nested run loop.
diff --git a/ui/views/widget/widget_utils_mac.mm b/ui/views/widget/widget_utils_mac.mm index 6dbf0d1..8d843b83 100644 --- a/ui/views/widget/widget_utils_mac.mm +++ b/ui/views/widget/widget_utils_mac.mm
@@ -4,7 +4,7 @@ #include "ui/views/widget/widget_utils_mac.h" -#import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h" namespace views {
diff --git a/ui/views_bridge_mac/browser_native_widget_window_mac.h b/ui/views_bridge_mac/browser_native_widget_window_mac.h deleted file mode 100644 index 6b7004a9..0000000 --- a/ui/views_bridge_mac/browser_native_widget_window_mac.h +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_VIEWS_BRIDGE_MAC_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_ -#define UI_VIEWS_BRIDGE_MAC_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_ - -#import "ui/views_bridge_mac/native_widget_mac_nswindow.h" - -@interface BrowserNativeWidgetWindow : NativeWidgetMacNSWindow -@end - -#endif // UI_VIEWS_BRIDGE_MAC_BROWSER_NATIVE_WIDGET_WINDOW_MAC_H_
diff --git a/ui/views_bridge_mac/views_bridge_mac_export.h b/ui/views_bridge_mac/views_bridge_mac_export.h deleted file mode 100644 index 6a44a0d..0000000 --- a/ui/views_bridge_mac/views_bridge_mac_export.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_VIEWS_BRIDGE_MAC_VIEWS_BRIDGE_MAC_EXPORT_H_ -#define UI_VIEWS_BRIDGE_MAC_VIEWS_BRIDGE_MAC_EXPORT_H_ - -// Defines VIEWS_BRIDGE_MAC_EXPORT so that functionality implemented by the -// RemoteMacViews module can be exported to consumers. - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION) -#define VIEWS_BRIDGE_MAC_EXPORT __declspec(dllexport) -#else -#define VIEWS_BRIDGE_MAC_EXPORT __declspec(dllimport) -#endif // defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION) -#define VIEWS_BRIDGE_MAC_EXPORT __attribute__((visibility("default"))) -#else -#define VIEWS_BRIDGE_MAC_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define VIEWS_BRIDGE_MAC_EXPORT -#endif - -#endif // UI_VIEWS_BRIDGE_MAC_VIEWS_BRIDGE_MAC_EXPORT_H_