diff --git a/BUILD.gn b/BUILD.gn index a310f481..3c4534f 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -38,19 +38,11 @@ assert(!is_component_build) } -# This file defines the following five main targets: -# -# "both_gn_and_gyp" should list every root target (target that nothing else -# depends on) built by GN that is also built in the GYP build. +# This file defines the following three main targets: # # "gn_all" should (transitively) cause everything to be built; if you run # 'ninja gn_all' and then 'ninja all', the second build should do no work. # -# "gn_only" should list every root target that is *not* intended to be built in -# a GYP build. Because GN has different rules for deciding what an 'all' build -# is, this may end up including targets that are actually defined in a GYP -# build but not dependencies of GYP's "all" (and so not actually built). -# # "gn_visibility": targets that are normally not visible to top-level targets, # but are built anyway by "all". Since we don't want any such targets, we have # this placeholder to make sure hidden targets that aren't otherwise depended @@ -63,8 +55,8 @@ # wildcards. # # Lastly, none of these targets are guaranteed to be the same as what ninja -# will build with "all". For more on how "all" works and the differences in how -# GYP and GN determine "all", see crbug.com/503241. +# will build with "all". For more on how "all" works and how GN determines +# "all", see crbug.com/503241. # # TODO(GYP_GONE): crbug.com/481694. Make sure that the above is true and there # are scripts run on the bots that enforce this. Once the GYP migration is @@ -155,8 +147,6 @@ } if (!is_ios) { - # TODO(GYP): Figure out which of these should actually build on iOS, - # and whether there should be other targets that are iOS-only and missing. deps += [ "//cc:cc_unittests", "//chrome/test:telemetry_perf_unittests", @@ -549,10 +539,6 @@ "//third_party/tcmalloc:addr2line-pdb", "//tools/win/chromeexts:chromeexts", ] - deps -= [ - "//crypto:crypto_unittests", # TODO(GYP) - "//net:net_unittests", # TODO(GYP) - ] if (!(is_component_build && is_debug && target_cpu == "x86")) { deps += @@ -625,7 +611,6 @@ # TODO(GYP): Figure out if any of these should be in gn_all # and figure out how cross-platform they are deps += [ - ":gn_mojo_targets", "//chrome/installer/util:strings", "//chrome/tools/convert_dict", "//components/constrained_window:unit_tests", @@ -828,19 +813,6 @@ } } -group("gn_mojo_targets") { - testonly = true - if (is_linux && !is_chromeos) { - # TODO(GYP): Figure out if any of these should be in gn_all - # and figure out how cross-platform they are - deps = [ - "//ipc:ipc_tests", - "//mojo:tests", - "//services:service_unittests", - ] - } -} - group("gn_visibility") { deps = [ "//build/config/sanitizers:options_sources",
diff --git a/DEPS b/DEPS index 86df34d..a26d3020 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'ec6ae52168ae4803c2312c362280f7f79e0d380e', + 'skia_revision': 'a2fc16e677c213d9efcc9e857effde0ed249b54d', # 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': 'ceafe3118264d8a896412f5e7a0affe1a62de046', + 'v8_revision': 'fa3a1c7570ad09f941c31714d7d54c87439f4c39', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '00ab92f4c6cd045904a0f26d7e2c227217758f02', + 'pdfium_revision': '1fe7d8c3819f6c6fdbf34a92146587a2eee8296a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'b2c22b39ba7df300abaa789fb7ea0292d62044d3', + 'catapult_revision': '380124f4ad9d972449c81462ec99a4c916fcd2d8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java index 28e7c26..5c824d2 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsTest.java
@@ -32,8 +32,8 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.parameter.ParameterizedTest; import org.chromium.content.browser.BindingManager; -import org.chromium.content.browser.ChildProcessConnection; import org.chromium.content.browser.ChildProcessLauncher; +import org.chromium.content.browser.ManagedChildProcessConnection; import org.chromium.content_public.common.ContentUrlConstants; import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.util.TestWebServer; @@ -585,7 +585,7 @@ } @Override - public void addNewConnection(int pid, ChildProcessConnection connection) { + public void addNewConnection(int pid, ManagedChildProcessConnection connection) { mIsChildProcessCreated = true; } @@ -607,12 +607,7 @@ public void onBroughtToForeground() {} @Override - public boolean isOomProtected(int pid) { - return false; - } - - @Override - public void clearConnection(int pid) {} + public void removeConnection(int pid) {} @Override public void startModerateBindingManagement(Context context, int maxSize) {}
diff --git a/ash/app_list/app_list_presenter_delegate.cc b/ash/app_list/app_list_presenter_delegate.cc index 3a1f918c..dbc28e6 100644 --- a/ash/app_list/app_list_presenter_delegate.cc +++ b/ash/app_list/app_list_presenter_delegate.cc
@@ -99,13 +99,11 @@ aura::Window* root_window = wm_root_window->aura_window(); aura::Window* container = GetRootWindowController(root_window) ->GetContainer(kShellWindowId_AppListContainer); + view->InitAsBubble(container, current_apps_page); + // The app list is centered over the display. + view->SetAnchorPoint(GetCenterOfDisplayForWindow( + wm_root_window, GetMinimumBoundsHeightForAppList(view))); - view->Initialize(container, current_apps_page); - - if (!app_list::switches::IsFullscreenAppListEnabled()) { - view->MaybeSetAnchorPoint(GetCenterOfDisplayForWindow( - wm_root_window, GetMinimumBoundsHeightForAppList(view))); - } keyboard::KeyboardController* keyboard_controller = keyboard::KeyboardController::GetInstance(); if (keyboard_controller) @@ -150,7 +148,7 @@ return; view_->UpdateBounds(); - view_->MaybeSetAnchorPoint(GetCenterOfDisplayForWindow( + view_->SetAnchorPoint(GetCenterOfDisplayForWindow( WmWindow::Get(view_->GetWidget()->GetNativeWindow()), GetMinimumBoundsHeightForAppList(view_))); }
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 00525dc..d554816 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -4,7 +4,6 @@ #include <memory> -#include "ash/ash_switches.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" #include "ash/shell_port.h" @@ -12,9 +11,7 @@ #include "ash/test/test_app_list_view_presenter_impl.h" #include "ash/wm/window_util.h" #include "ash/wm_window.h" -#include "base/command_line.h" #include "base/macros.h" -#include "ui/app_list/app_list_switches.h" #include "ui/app_list/views/app_list_view.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" @@ -29,15 +26,9 @@ return display::Screen::GetScreen()->GetPrimaryDisplay().id(); } -void SetFullscreenAppListSwitch() { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - app_list::switches::kEnableFullscreenAppList); -} - } // namespace -class AppListPresenterDelegateTest : public test::AshTestBase, - public testing::WithParamInterface<bool> { +class AppListPresenterDelegateTest : public test::AshTestBase { public: AppListPresenterDelegateTest() {} ~AppListPresenterDelegateTest() override {} @@ -50,29 +41,18 @@ void SetUp() override { AshTestBase::SetUp(); - // If the current test is parameterized. - if (testing::UnitTest::GetInstance()->current_test_info()->value_param()) { - test_with_fullscreen_ = GetParam(); - if (test_with_fullscreen_) - SetFullscreenAppListSwitch(); - } // Make the display big enough to hold the app list. UpdateDisplay("1024x768"); } private: test::TestAppListViewPresenterImpl app_list_presenter_impl_; - bool test_with_fullscreen_; DISALLOW_COPY_AND_ASSIGN(AppListPresenterDelegateTest); }; -// Instantiate the Boolean which is used to toggle the Fullscreen app list in -// the parameterized tests. -INSTANTIATE_TEST_CASE_P(, AppListPresenterDelegateTest, testing::Bool()); - // Tests that app launcher hides when focus moves to a normal window. -TEST_P(AppListPresenterDelegateTest, HideOnFocusOut) { +TEST_F(AppListPresenterDelegateTest, HideOnFocusOut) { app_list_presenter_impl()->Show(GetPrimaryDisplayId()); EXPECT_TRUE(app_list_presenter_impl()->GetTargetVisibility()); @@ -84,7 +64,7 @@ // Tests that app launcher remains visible when focus is moved to a different // window in kShellWindowId_AppListContainer. -TEST_P(AppListPresenterDelegateTest, +TEST_F(AppListPresenterDelegateTest, RemainVisibleWhenFocusingToApplistContainer) { app_list_presenter_impl()->Show(GetPrimaryDisplayId()); EXPECT_TRUE(app_list_presenter_impl()->GetTargetVisibility()); @@ -142,7 +122,7 @@ // Tests opening the app launcher on a non-primary display, then deleting the // display. -TEST_P(AppListPresenterDelegateTest, NonPrimaryDisplay) { +TEST_F(AppListPresenterDelegateTest, NonPrimaryDisplay) { // Set up a screen with two displays (horizontally adjacent). UpdateDisplay("1024x768,1024x768"); @@ -176,12 +156,10 @@ // from the anchor (center) and height. There isn't a bounds rect that gives // the actual app list position (the widget bounds include the bubble border // which is much bigger than the actual app list size). - app_list::AppListView* app_list = app_list_presenter_impl()->GetView(); int app_list_view_top = app_list->anchor_rect().y() - app_list->bounds().height() / 2; const int kMinimalAppListMargin = 10; - EXPECT_GE(app_list_view_top, kMinimalAppListMargin); }
diff --git a/ash/system/audio/audio_detailed_view.cc b/ash/system/audio/audio_detailed_view.cc index 2bcfc8b..bf378b6 100644 --- a/ash/system/audio/audio_detailed_view.cc +++ b/ash/system/audio/audio_detailed_view.cc
@@ -13,10 +13,7 @@ #include "chromeos/audio/cras_audio_handler.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/color_palette.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/native_theme/native_theme.h" #include "ui/views/controls/image_view.h" -#include "ui/views/controls/label.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/separator.h" @@ -73,47 +70,10 @@ Layout(); } -void AudioDetailedView::AddInputHeader() { - AddScrollListInfoItem(IDS_ASH_STATUS_TRAY_AUDIO_INPUT, - kSystemMenuAudioInputIcon); -} - -void AudioDetailedView::AddOutputHeader() { - AddScrollListInfoItem(IDS_ASH_STATUS_TRAY_AUDIO_OUTPUT, - kSystemMenuAudioOutputIcon); -} - -void AudioDetailedView::AddScrollListInfoItem(int text_id, - const gfx::VectorIcon& icon) { - TriView* header = TrayPopupUtils::CreateDefaultRowView(); - TrayPopupUtils::ConfigureAsStickyHeader(header); - views::ImageView* image_view = TrayPopupUtils::CreateMainImageView(); - image_view->SetImage(gfx::CreateVectorIcon( - icon, GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_ProminentButtonColor))); - header->AddView(TriView::Container::START, image_view); - - views::Label* label = TrayPopupUtils::CreateDefaultLabel(); - label->SetText(l10n_util::GetStringUTF16(text_id)); - TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::SUB_HEADER); - style.SetupLabel(label); - header->AddView(TriView::Container::CENTER, label); - +void AudioDetailedView::AddAudioSubHeader(const gfx::VectorIcon& icon, + int text_id) { + TriView* header = AddScrollListSubHeader(icon, text_id); header->SetContainerVisible(TriView::Container::END, false); - scroll_content()->AddChildView(header); -} - -HoverHighlightView* AudioDetailedView::AddScrollListItem( - const base::string16& text, - bool highlight, - bool checked) { - HoverHighlightView* container = new HoverHighlightView(this); - - container->AddLabelRow(text); - TrayPopupUtils::InitializeAsCheckableRow(container, checked); - - scroll_content()->AddChildView(container); - return container; } void AudioDetailedView::CreateItems() { @@ -129,21 +89,20 @@ audio_handler->GetAudioDevices(&devices); bool has_dual_internal_mic = audio_handler->HasDualInternalMic(); bool is_front_or_rear_mic_active = false; - for (size_t i = 0; i < devices.size(); ++i) { + for (const auto& device : devices) { // Don't display keyboard mic or aokr type. - if (!devices[i].is_for_simple_usage()) + if (!device.is_for_simple_usage()) continue; - if (devices[i].is_input) { + if (device.is_input) { // Do not expose the internal front and rear mic to UI. - if (has_dual_internal_mic && - audio_handler->IsFrontOrRearMic(devices[i])) { - if (devices[i].active) + if (has_dual_internal_mic && audio_handler->IsFrontOrRearMic(device)) { + if (device.active) is_front_or_rear_mic_active = true; continue; } - input_devices_.push_back(devices[i]); + input_devices_.push_back(device); } else { - output_devices_.push_back(devices[i]); + output_devices_.push_back(device); } } @@ -168,14 +127,15 @@ // Add audio output devices. const bool has_output_devices = output_devices_.size() > 0; - if (has_output_devices) - AddOutputHeader(); + if (has_output_devices) { + AddAudioSubHeader(kSystemMenuAudioOutputIcon, + IDS_ASH_STATUS_TRAY_AUDIO_OUTPUT); + } - for (size_t i = 0; i < output_devices_.size(); ++i) { - HoverHighlightView* container = AddScrollListItem( - GetAudioDeviceName(output_devices_[i]), false /* highlight */, - output_devices_[i].active); /* checkmark if active */ - device_map_[container] = output_devices_[i]; + for (const auto& device : output_devices_) { + HoverHighlightView* container = + AddScrollListCheckableItem(GetAudioDeviceName(device), device.active); + device_map_[container] = device; } if (has_output_devices) { @@ -185,14 +145,15 @@ // Add audio input devices. const bool has_input_devices = input_devices_.size() > 0; - if (has_input_devices) - AddInputHeader(); + if (has_input_devices) { + AddAudioSubHeader(kSystemMenuAudioInputIcon, + IDS_ASH_STATUS_TRAY_AUDIO_INPUT); + } - for (size_t i = 0; i < input_devices_.size(); ++i) { - HoverHighlightView* container = AddScrollListItem( - GetAudioDeviceName(input_devices_[i]), false /* highlight */, - input_devices_[i].active); /* checkmark if active */ - device_map_[container] = input_devices_[i]; + for (const auto& device : input_devices_) { + HoverHighlightView* container = + AddScrollListCheckableItem(GetAudioDeviceName(device), device.active); + device_map_[container] = device; } scroll_content()->SizeToPreferredSize();
diff --git a/ash/system/audio/audio_detailed_view.h b/ash/system/audio/audio_detailed_view.h index 5e2d3fd..7478ba8 100644 --- a/ash/system/audio/audio_detailed_view.h +++ b/ash/system/audio/audio_detailed_view.h
@@ -15,13 +15,7 @@ struct VectorIcon; } -namespace views { -class View; -} - namespace ash { -class HoverHighlightView; - namespace tray { class AudioDetailedView : public TrayDetailsView { @@ -33,15 +27,9 @@ void Update(); private: - // Helper functions to add non-clickable header rows within the scrollable + // Helper function to add non-clickable header rows within the scrollable // list. - void AddInputHeader(); - void AddOutputHeader(); - void AddScrollListInfoItem(int text_id, const gfx::VectorIcon& icon); - - HoverHighlightView* AddScrollListItem(const base::string16& text, - bool highlight, - bool checked); + void AddAudioSubHeader(const gfx::VectorIcon& icon, int text_id); void CreateItems();
diff --git a/ash/system/bluetooth/tray_bluetooth.cc b/ash/system/bluetooth/tray_bluetooth.cc index 962a3ff..26625a6 100644 --- a/ash/system/bluetooth/tray_bluetooth.cc +++ b/ash/system/bluetooth/tray_bluetooth.cc
@@ -24,10 +24,10 @@ #include "ash/system/tray/tri_view.h" #include "device/bluetooth/bluetooth_common.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/vector_icon_types.h" #include "ui/views/controls/button/toggle_button.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" @@ -119,11 +119,10 @@ void Update() { TrayBluetoothHelper* helper = Shell::Get()->tray_bluetooth_helper(); if (helper->GetBluetoothAvailable()) { - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - const base::string16 label = - rb.GetLocalizedString(helper->GetBluetoothEnabled() - ? IDS_ASH_STATUS_TRAY_BLUETOOTH_ENABLED - : IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED); + const base::string16 label = l10n_util::GetStringUTF16( + helper->GetBluetoothEnabled() + ? IDS_ASH_STATUS_TRAY_BLUETOOTH_ENABLED + : IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED); SetLabel(label); SetAccessibleName(label); SetVisible(true); @@ -163,8 +162,8 @@ bool has_connected_device = false; BluetoothDeviceList list = helper->GetAvailableBluetoothDevices(); - for (size_t i = 0; i < list.size(); ++i) { - if (list[i].connected) { + for (const auto& device : list) { + if (device.connected) { has_connected_device = true; break; } @@ -235,21 +234,20 @@ BluetoothDeviceList list = Shell::Get()->tray_bluetooth_helper()->GetAvailableBluetoothDevices(); - for (size_t i = 0; i < list.size(); ++i) { - if (list[i].connecting) { - new_connecting_devices.insert(list[i].address); - UpdateBluetoothDeviceListHelper(&connecting_devices_, list[i]); - } else if (list[i].connected && list[i].paired) { - new_connected_devices.insert(list[i].address); - UpdateBluetoothDeviceListHelper(&connected_devices_, list[i]); - } else if (list[i].paired) { - new_paired_not_connected_devices.insert(list[i].address); - UpdateBluetoothDeviceListHelper(&paired_not_connected_devices_, - list[i]); + for (const auto& device : list) { + if (device.connecting) { + new_connecting_devices.insert(device.address); + UpdateBluetoothDeviceListHelper(&connecting_devices_, device); + } else if (device.connected && device.paired) { + new_connected_devices.insert(device.address); + UpdateBluetoothDeviceListHelper(&connected_devices_, device); + } else if (device.paired) { + new_paired_not_connected_devices.insert(device.address); + UpdateBluetoothDeviceListHelper(&paired_not_connected_devices_, device); } else { - new_discovered_not_paired_devices.insert(list[i].address); + new_discovered_not_paired_devices.insert(device.address); UpdateBluetoothDeviceListHelper(&discovered_not_paired_devices_, - list[i]); + device); } } RemoveObsoleteBluetoothDevicesFromList(&connecting_devices_, @@ -293,7 +291,7 @@ connecting_devices_.size() + paired_not_connected_devices_.size(); if (num_paired_devices > 0) { - AddSubHeader(IDS_ASH_STATUS_TRAY_BLUETOOTH_PAIRED_DEVICES); + AddScrollListSubHeader(IDS_ASH_STATUS_TRAY_BLUETOOTH_PAIRED_DEVICES); AppendSameTypeDevicesToScrollList(connected_devices_, true, true, bluetooth_enabled); AppendSameTypeDevicesToScrollList(connecting_devices_, true, false, @@ -306,7 +304,7 @@ // present, also add a section header above the unpaired devices. if (discovered_not_paired_devices_.size() > 0) { if (num_paired_devices > 0) - AddSubHeader(IDS_ASH_STATUS_TRAY_BLUETOOTH_UNPAIRED_DEVICES); + AddScrollListSubHeader(IDS_ASH_STATUS_TRAY_BLUETOOTH_UNPAIRED_DEVICES); AppendSameTypeDevicesToScrollList(discovered_not_paired_devices_, false, false, bluetooth_enabled); } @@ -328,83 +326,41 @@ bool highlight, bool checked, bool enabled) { - for (size_t i = 0; i < list.size(); ++i) { - HoverHighlightView* container = nullptr; - gfx::ImageSkia icon_image = CreateVectorIcon( - GetBluetoothDeviceIcon(list[i].device_type, list[i].connected), - kMenuIconColor); - container = AddScrollListItem(list[i].display_name, icon_image, - list[i].connected, list[i].connecting); - device_map_[container] = list[i].address; + for (const auto& device : list) { + const gfx::VectorIcon& icon = + GetBluetoothDeviceIcon(device.device_type, device.connected); + HoverHighlightView* container = + AddScrollListItem(icon, device.display_name); + if (device.connected) + SetupConnectedItem(container); + else if (device.connecting) + SetupConnectingItem(container); + device_map_[container] = device.address; } } - HoverHighlightView* AddScrollListItem(const base::string16& text, - const gfx::ImageSkia& image, - bool connected, - bool connecting) { - HoverHighlightView* container = new HoverHighlightView(this); - if (connected) { - SetupConnectedItem(container, text, image); - } else if (connecting) { - SetupConnectingItem(container, text, image); - } else { - container->AddIconAndLabel(image, text); - } - scroll_content()->AddChildView(container); - return container; - } - - void AddSubHeader(int message_id) { - TriView* header = TrayPopupUtils::CreateSubHeaderRowView(); - TrayPopupUtils::ConfigureAsStickyHeader(header); - - views::Label* label = TrayPopupUtils::CreateDefaultLabel(); - label->SetText(l10n_util::GetStringUTF16(message_id)); - TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::SUB_HEADER); - style.SetupLabel(label); - header->AddView(TriView::Container::CENTER, label); - - scroll_content()->AddChildView(header); - } - - void SetupConnectedItem(HoverHighlightView* container, - const base::string16& text, - const gfx::ImageSkia& image) { - container->AddIconAndLabels( - image, text, l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED)); + void SetupConnectedItem(HoverHighlightView* container) { + container->SetSubText(l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED)); TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::CAPTION); style.set_color_style(TrayPopupItemStyle::ColorStyle::CONNECTED); style.SetupLabel(container->sub_text_label()); } - void SetupConnectingItem(HoverHighlightView* container, - const base::string16& text, - const gfx::ImageSkia& image) { - container->AddIconAndLabels( - image, text, l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTING)); + void SetupConnectingItem(HoverHighlightView* container) { + container->SetSubText(l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTING)); ThrobberView* throbber = new ThrobberView; throbber->Start(); container->AddRightView(throbber); } - // Returns true if the device with |device_id| is found in |device_list|, - // and the display_name of the device will be returned in |display_name| if - // it's not NULL. + // Returns true if the device with |device_id| is found in |device_list|. bool FoundDevice(const std::string& device_id, - const BluetoothDeviceList& device_list, - base::string16* display_name, - device::BluetoothDeviceType* device_type) { - for (size_t i = 0; i < device_list.size(); ++i) { - if (device_list[i].address == device_id) { - if (display_name) - *display_name = device_list[i].display_name; - if (device_type) - *device_type = device_list[i].device_type; + const BluetoothDeviceList& device_list) { + for (const auto& device : device_list) { + if (device.address == device_id) return true; - } } return false; } @@ -413,18 +369,10 @@ // or disconnected if such an operation is going to be performed underway. void UpdateClickedDevice(const std::string& device_id, views::View* item_container) { - base::string16 display_name; - device::BluetoothDeviceType device_type; - if (FoundDevice(device_id, paired_not_connected_devices_, &display_name, - &device_type)) { - item_container->RemoveAllChildViews(true); + if (FoundDevice(device_id, paired_not_connected_devices_)) { HoverHighlightView* container = static_cast<HoverHighlightView*>(item_container); - TrayPopupItemStyle style( - TrayPopupItemStyle::FontStyle::DETAILED_VIEW_LABEL); - gfx::ImageSkia icon_image = CreateVectorIcon( - GetBluetoothDeviceIcon(device_type, false), style.GetIconColor()); - SetupConnectingItem(container, display_name, icon_image); + SetupConnectingItem(container); scroll_content()->SizeToPreferredSize(); scroller()->Layout(); } @@ -442,7 +390,7 @@ return; const std::string device_id = find->second; - if (FoundDevice(device_id, connecting_devices_, nullptr, nullptr)) + if (FoundDevice(device_id, connecting_devices_)) return; UpdateClickedDevice(device_id, view); @@ -536,8 +484,7 @@ container->AddChildView(image_view); views::Label* label = new views::Label( - ui::ResourceBundle::GetSharedInstance().GetLocalizedString( - IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED)); + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED)); style.SetupLabel(label); label->SetBorder(views::CreateEmptyBorder( kDisabledPanelLabelBaselineY - label->GetBaseline(), 0, 0, 0));
diff --git a/ash/system/cast/tray_cast.cc b/ash/system/cast/tray_cast.cc index 899b4d0..70678868 100644 --- a/ash/system/cast/tray_cast.cc +++ b/ash/system/cast/tray_cast.cc
@@ -315,7 +315,6 @@ void CreateItems(); void UpdateReceiverListFromCachedData(); - views::View* AddToReceiverList(const mojom::SinkAndRoutePtr& sink_route); // TrayDetailsView: void HandleViewClicked(views::View* view) override; @@ -388,7 +387,8 @@ // Add a view for each receiver. for (auto& it : sinks_and_routes_) { const ash::mojom::SinkAndRoutePtr& sink_route = it.second; - views::View* container = AddToReceiverList(sink_route); + const base::string16 name = base::UTF8ToUTF16(sink_route->sink->name); + views::View* container = AddScrollListItem(kSystemMenuCastDeviceIcon, name); view_to_sink_map_[container] = sink_route->sink.Clone(); } @@ -396,18 +396,6 @@ scroller()->Layout(); } -views::View* CastDetailedView::AddToReceiverList( - const ash::mojom::SinkAndRoutePtr& sink_route) { - const gfx::ImageSkia image = - gfx::CreateVectorIcon(kSystemMenuCastDeviceIcon, kMenuIconColor); - - HoverHighlightView* container = new HoverHighlightView(this); - container->AddIconAndLabel(image, base::UTF8ToUTF16(sink_route->sink->name)); - - scroll_content()->AddChildView(container); - return container; -} - void CastDetailedView::HandleViewClicked(views::View* view) { // Find the receiver we are going to cast to. auto it = view_to_sink_map_.find(view);
diff --git a/ash/system/ime_menu/ime_list_view.cc b/ash/system/ime_menu/ime_list_view.cc index 334b42e..4d9cf07a 100644 --- a/ash/system/ime_menu/ime_list_view.cc +++ b/ash/system/ime_menu/ime_list_view.cc
@@ -112,8 +112,8 @@ void OnFocus() override { ActionableView::OnFocus(); - if (ime_list_view_ && ime_list_view_->scroll_content()) - ime_list_view_->scroll_content()->ScrollRectToVisible(bounds()); + if (ime_list_view_) + ime_list_view_->ScrollItemToVisible(this); } void GetAccessibleNodeData(ui::AXNodeData* node_data) override { @@ -221,7 +221,7 @@ last_item_selected_with_keyboard_) { FocusCurrentImeIfNeeded(); } else if (current_ime_view_) { - scroll_content()->ScrollRectToVisible(current_ime_view_->bounds()); + ScrollItemToVisible(current_ime_view_); } } @@ -232,6 +232,11 @@ current_ime_view_ = nullptr; } +void ImeListView::ScrollItemToVisible(views::View* item_view) { + if (scroll_content()) + scroll_content()->ScrollRectToVisible(item_view->bounds()); +} + void ImeListView::CloseImeListView() { last_selected_item_id_.clear(); current_ime_view_ = nullptr; @@ -324,7 +329,7 @@ return; } - scroll_content()->ScrollRectToVisible(current_ime_view_->bounds()); + ScrollItemToVisible(current_ime_view_); } void ImeListView::FocusCurrentImeIfNeeded() {
diff --git a/ash/system/ime_menu/ime_list_view.h b/ash/system/ime_menu/ime_list_view.h index 2acb4e0b..b0c9d9f 100644 --- a/ash/system/ime_menu/ime_list_view.h +++ b/ash/system/ime_menu/ime_list_view.h
@@ -44,6 +44,9 @@ // Closes the view. void CloseImeListView(); + // Scrolls contents such that |item_view| is visible. + void ScrollItemToVisible(views::View* item_view); + void set_last_item_selected_with_keyboard( bool last_item_selected_with_keyboard) { last_item_selected_with_keyboard_ = last_item_selected_with_keyboard;
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc index 735903f..f0f1a929 100644 --- a/ash/system/network/network_list.cc +++ b/ash/system/network/network_list.cc
@@ -135,7 +135,7 @@ void InitializeLayout() { TrayPopupUtils::ConfigureAsStickyHeader(this); SetLayoutManager(new views::FillLayout); - container_ = TrayPopupUtils::CreateSubHeaderRowView(); + container_ = TrayPopupUtils::CreateSubHeaderRowView(false); AddChildView(container_); views::Label* label = TrayPopupUtils::CreateDefaultLabel();
diff --git a/ash/system/network/vpn_list_view.cc b/ash/system/network/vpn_list_view.cc index 6b437ba7..e4c9df9 100644 --- a/ash/system/network/vpn_list_view.cc +++ b/ash/system/network/vpn_list_view.cc
@@ -88,7 +88,7 @@ : parent_(parent) { TrayPopupUtils::ConfigureAsStickyHeader(this); SetLayoutManager(new views::FillLayout); - TriView* tri_view = TrayPopupUtils::CreateSubHeaderRowView(); + TriView* tri_view = TrayPopupUtils::CreateSubHeaderRowView(false); AddChildView(tri_view); views::Label* label = TrayPopupUtils::CreateDefaultLabel();
diff --git a/ash/system/tray/hover_highlight_view.cc b/ash/system/tray/hover_highlight_view.cc index c3f7cfa3..e96272b6 100644 --- a/ash/system/tray/hover_highlight_view.cc +++ b/ash/system/tray/hover_highlight_view.cc
@@ -55,6 +55,19 @@ Layout(); } +void HoverHighlightView::SetSubText(const base::string16& sub_text) { + DCHECK(text_label_); + + if (!sub_text_label_) { + sub_text_label_ = TrayPopupUtils::CreateDefaultLabel(); + tri_view_->AddView(TriView::Container::CENTER, sub_text_label_); + } + TrayPopupItemStyle sub_style(TrayPopupItemStyle::FontStyle::CAPTION); + sub_style.set_color_style(TrayPopupItemStyle::ColorStyle::INACTIVE); + sub_style.SetupLabel(sub_text_label_); + sub_text_label_->SetText(sub_text); +} + void HoverHighlightView::AddIconAndLabel(const gfx::ImageSkia& image, const base::string16& text) { DoAddIconAndLabel(image, text, @@ -102,16 +115,9 @@ text_label_->SetEnabled(enabled()); TrayPopupItemStyle style(font_style); style.SetupLabel(text_label_); - tri_view_->AddView(TriView::Container::CENTER, text_label_); - if (!sub_text.empty()) { - sub_text_label_ = TrayPopupUtils::CreateDefaultLabel(); - sub_text_label_->SetText(sub_text); - TrayPopupItemStyle sub_style(TrayPopupItemStyle::FontStyle::CAPTION); - sub_style.set_color_style(TrayPopupItemStyle::ColorStyle::INACTIVE); - sub_style.SetupLabel(sub_text_label_); - tri_view_->AddView(TriView::Container::CENTER, sub_text_label_); - } + + SetSubText(sub_text); tri_view_->SetContainerVisible(TriView::Container::END, false);
diff --git a/ash/system/tray/hover_highlight_view.h b/ash/system/tray/hover_highlight_view.h index bdaf647..4283c53 100644 --- a/ash/system/tray/hover_highlight_view.h +++ b/ash/system/tray/hover_highlight_view.h
@@ -69,6 +69,10 @@ // Hide or show the right view. void SetRightViewVisible(bool visible); + // Sets text for the sub label. Precondition for this function is that + // |text_label_| is non-null. + void SetSubText(const base::string16& sub_text); + // Allows view to expand its height. Size of unexapandable view is fixed and // equals to kTrayPopupItemHeight. void SetExpandable(bool expandable);
diff --git a/ash/system/tray/tray_details_view.cc b/ash/system/tray/tray_details_view.cc index fee3c72..56f24b1 100644 --- a/ash/system/tray/tray_details_view.cc +++ b/ash/system/tray/tray_details_view.cc
@@ -6,6 +6,7 @@ #include "ash/ash_view_ids.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/system/tray/hover_highlight_view.h" #include "ash/system/tray/system_menu_button.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_item.h" @@ -16,13 +17,18 @@ #include "base/containers/adapters.h" #include "base/memory/ptr_util.h" #include "third_party/skia/include/core/SkDrawLooper.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/skia_paint_util.h" +#include "ui/gfx/vector_icon_types.h" #include "ui/views/background.h" #include "ui/views/border.h" +#include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/controls/progress_bar.h" #include "ui/views/controls/scroll_view.h" @@ -303,6 +309,60 @@ box_layout_->SetFlexForView(scroller_, 1); } +HoverHighlightView* TrayDetailsView::AddScrollListItem( + const gfx::VectorIcon& icon, + const base::string16& text) { + HoverHighlightView* item = new HoverHighlightView(this); + if (icon.is_empty()) + item->AddLabelRow(text); + else + item->AddIconAndLabel(gfx::CreateVectorIcon(icon, kMenuIconColor), text); + scroll_content_->AddChildView(item); + return item; +} + +HoverHighlightView* TrayDetailsView::AddScrollListCheckableItem( + const gfx::VectorIcon& icon, + const base::string16& text, + bool checked) { + HoverHighlightView* item = AddScrollListItem(icon, text); + TrayPopupUtils::InitializeAsCheckableRow(item, checked); + return item; +} + +HoverHighlightView* TrayDetailsView::AddScrollListCheckableItem( + const base::string16& text, + bool checked) { + return AddScrollListCheckableItem(gfx::kNoneIcon, text, checked); +} + +TriView* TrayDetailsView::AddScrollListSubHeader(const gfx::VectorIcon& icon, + int text_id) { + TriView* header = TrayPopupUtils::CreateSubHeaderRowView(!icon.is_empty()); + TrayPopupUtils::ConfigureAsStickyHeader(header); + + views::Label* label = TrayPopupUtils::CreateDefaultLabel(); + label->SetText(l10n_util::GetStringUTF16(text_id)); + TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::SUB_HEADER); + style.SetupLabel(label); + header->AddView(TriView::Container::CENTER, label); + + if (!icon.is_empty()) { + views::ImageView* image_view = TrayPopupUtils::CreateMainImageView(); + image_view->SetImage(gfx::CreateVectorIcon( + icon, GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_ProminentButtonColor))); + header->AddView(TriView::Container::START, image_view); + } + + scroll_content_->AddChildView(header); + return header; +} + +TriView* TrayDetailsView::AddScrollListSubHeader(int text_id) { + return AddScrollListSubHeader(gfx::kNoneIcon, text_id); +} + void TrayDetailsView::Reset() { RemoveAllChildViews(true); scroller_ = nullptr;
diff --git a/ash/system/tray/tray_details_view.h b/ash/system/tray/tray_details_view.h index f7f30f4..1822067 100644 --- a/ash/system/tray/tray_details_view.h +++ b/ash/system/tray/tray_details_view.h
@@ -15,6 +15,10 @@ #include "ui/views/controls/button/button.h" #include "ui/views/view.h" +namespace gfx { +struct VectorIcon; +} // namespace gfx + namespace views { class BoxLayout; class CustomButton; @@ -27,6 +31,7 @@ class TrayDetailsViewTest; } // namespace test +class HoverHighlightView; class ScrollBorder; class SystemTrayItem; class TriView; @@ -47,8 +52,6 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) final; SystemTrayItem* owner() { return owner_; } - views::ScrollView* scroller() { return scroller_; } - views::View* scroll_content() { return scroll_content_; } protected: // views::View: @@ -67,6 +70,29 @@ // any other view between the list and the footer row at the bottom. void CreateScrollableList(); + // Adds a targetable row to |scroll_content_| containing |icon| and |text|. + HoverHighlightView* AddScrollListItem(const gfx::VectorIcon& icon, + const base::string16& text); + + // Adds a targetable row to |scroll_content_| containing |icon|, |text|, and a + // checkbox. |checked| determines whether the checkbox is checked or not. + HoverHighlightView* AddScrollListCheckableItem(const gfx::VectorIcon& icon, + const base::string16& text, + bool checked); + + // Adds a targetable row to |scroll_content_| containing |text| and a + // checkbox. |checked| determines whether the checkbox is checked or not. + HoverHighlightView* AddScrollListCheckableItem(const base::string16& text, + bool checked); + + // Adds a sticky sub header to |scroll_content_| containing |icon| and a text + // represented by |text_id| resource id. + TriView* AddScrollListSubHeader(const gfx::VectorIcon& icon, int text_id); + + // Adds a sticky sub header to |scroll_content_| containing a text represented + // by |text_id| resource id. + TriView* AddScrollListSubHeader(int text_id); + // Removes (and destroys) all child views. void Reset(); @@ -82,6 +108,8 @@ views::CustomButton* CreateHelpButton(); TriView* tri_view() { return tri_view_; } + views::ScrollView* scroller() const { return scroller_; } + views::View* scroll_content() const { return scroll_content_; } private: friend class test::TrayDetailsViewTest;
diff --git a/ash/system/tray/tray_details_view_unittest.cc b/ash/system/tray/tray_details_view_unittest.cc index 49d3f3a0..cd13603 100644 --- a/ash/system/tray/tray_details_view_unittest.cc +++ b/ash/system/tray/tray_details_view_unittest.cc
@@ -43,6 +43,10 @@ void CreateScrollerViews() { CreateScrollableList(); } + views::View* scroll_content() const { + return TrayDetailsView::scroll_content(); + } + private: TrayPopupHeaderButton* tray_popup_header_button_;
diff --git a/ash/system/tray/tray_popup_utils.cc b/ash/system/tray/tray_popup_utils.cc index d5bdd0a6..d89c0d0 100644 --- a/ash/system/tray/tray_popup_utils.cc +++ b/ash/system/tray/tray_popup_utils.cc
@@ -48,8 +48,8 @@ // stretched horizontally and centered vertically. std::unique_ptr<views::LayoutManager> CreateDefaultCenterLayoutManager() { // TODO(bruthig): Use constants instead of magic numbers. - auto box_layout = - base::MakeUnique<views::BoxLayout>(views::BoxLayout::kVertical, 4, 8, 0); + auto box_layout = base::MakeUnique<views::BoxLayout>( + views::BoxLayout::kVertical, kTrayPopupLabelHorizontalPadding, 8, 0); box_layout->set_main_axis_alignment( views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); box_layout->set_cross_axis_alignment( @@ -174,13 +174,14 @@ return tri_view; } -TriView* TrayPopupUtils::CreateSubHeaderRowView() { - TriView* tri_view = CreateMultiTargetRowView(); - tri_view->SetInsets(gfx::Insets(0, kTrayPopupPaddingHorizontal, 0, 0)); - tri_view->SetContainerVisible(TriView::Container::START, false); - tri_view->SetContainerLayout( - TriView::Container::END, - CreateDefaultLayoutManager(TriView::Container::END)); +TriView* TrayPopupUtils::CreateSubHeaderRowView(bool start_visible) { + TriView* tri_view = CreateDefaultRowView(); + if (!start_visible) { + tri_view->SetInsets(gfx::Insets( + 0, kTrayPopupPaddingHorizontal - kTrayPopupLabelHorizontalPadding, 0, + 0)); + tri_view->SetContainerVisible(TriView::Container::START, false); + } return tri_view; }
diff --git a/ash/system/tray/tray_popup_utils.h b/ash/system/tray/tray_popup_utils.h index d674034..db268693 100644 --- a/ash/system/tray/tray_popup_utils.h +++ b/ash/system/tray/tray_popup_utils.h
@@ -54,13 +54,18 @@ // Creates a container view to be used by system menu sub-section header rows. // The caller takes over ownership of the created view. // - // The returned view consists of 2 regions: CENTER, and END having the same - // properties as when using |CreateMultiTargetRowView|. The START container is - // hidden. - // The END container has a fixed minimum width but can grow into the CENTER - // container if space is required and available. The CENTER container has a - // flexible width. - static TriView* CreateSubHeaderRowView(); + // The returned view contains at least CENTER and END regions having the same + // properties as when using |CreateMultiTargetRowView|. |start_visible| + // determines whether the START region should be visible or not. If START is + // not visible, extra padding is added to the left of the contents. + // + // The START (if visible) and END containers have a fixed minimum width but + // can grow into the CENTER container if space is required and available. The + // CENTER container has a flexible width. + // + // TODO(mohsen): Merge this into TrayDetailsView::AddScrollListSubHeader() + // once network and VPN alse use TrayDetailsView::AddScrollListSubHeader(). + static TriView* CreateSubHeaderRowView(bool start_visible); // Creates a view containing only a label (corresponding to |message_id|), // which is to be inserted as a non-targetable row within a system menu
diff --git a/ash/system/tray_accessibility.cc b/ash/system/tray_accessibility.cc index bf12a2d..643ea49 100644 --- a/ash/system/tray_accessibility.cc +++ b/ash/system/tray_accessibility.cc
@@ -215,58 +215,64 @@ CreateScrollableList(); AccessibilityDelegate* delegate = Shell::Get()->accessibility_delegate(); + spoken_feedback_enabled_ = delegate->IsSpokenFeedbackEnabled(); - spoken_feedback_view_ = AddScrollListItem( + spoken_feedback_view_ = AddScrollListCheckableItem( + kSystemMenuAccessibilityChromevoxIcon, l10n_util::GetStringUTF16( IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SPOKEN_FEEDBACK), - spoken_feedback_enabled_, kSystemMenuAccessibilityChromevoxIcon); + spoken_feedback_enabled_); high_contrast_enabled_ = delegate->IsHighContrastEnabled(); - high_contrast_view_ = AddScrollListItem( + high_contrast_view_ = AddScrollListCheckableItem( + kSystemMenuAccessibilityContrastIcon, l10n_util::GetStringUTF16( IDS_ASH_STATUS_TRAY_ACCESSIBILITY_HIGH_CONTRAST_MODE), - high_contrast_enabled_, kSystemMenuAccessibilityContrastIcon); + high_contrast_enabled_); + screen_magnifier_enabled_ = delegate->IsMagnifierEnabled(); - screen_magnifier_view_ = AddScrollListItem( + screen_magnifier_view_ = AddScrollListCheckableItem( + kSystemMenuAccessibilityScreenMagnifierIcon, l10n_util::GetStringUTF16( IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SCREEN_MAGNIFIER), - screen_magnifier_enabled_, kSystemMenuAccessibilityScreenMagnifierIcon); + screen_magnifier_enabled_); autoclick_enabled_ = delegate->IsAutoclickEnabled(); - autoclick_view_ = AddScrollListItem( + autoclick_view_ = AddScrollListCheckableItem( + kSystemMenuAccessibilityAutoClickIcon, l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_AUTOCLICK), - autoclick_enabled_, kSystemMenuAccessibilityAutoClickIcon); + autoclick_enabled_); virtual_keyboard_enabled_ = delegate->IsVirtualKeyboardEnabled(); - virtual_keyboard_view_ = - AddScrollListItem(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD), - virtual_keyboard_enabled_, kSystemMenuKeyboardIcon); + virtual_keyboard_view_ = AddScrollListCheckableItem( + kSystemMenuKeyboardIcon, + l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD), + virtual_keyboard_enabled_); scroll_content()->AddChildView( TrayPopupUtils::CreateListSubHeaderSeparator()); - AddSubHeader(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_ACCESSIBILITY_ADDITIONAL_SETTINGS)); + AddScrollListSubHeader(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_ADDITIONAL_SETTINGS); large_cursor_enabled_ = delegate->IsLargeCursorEnabled(); - large_cursor_view_ = AddScrollListItemWithoutIcon( + large_cursor_view_ = AddScrollListCheckableItem( l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_LARGE_CURSOR), large_cursor_enabled_); mono_audio_enabled_ = delegate->IsMonoAudioEnabled(); - mono_audio_view_ = AddScrollListItemWithoutIcon( + mono_audio_view_ = AddScrollListCheckableItem( l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_MONO_AUDIO), mono_audio_enabled_); caret_highlight_enabled_ = delegate->IsCaretHighlightEnabled(); - caret_highlight_view_ = AddScrollListItemWithoutIcon( + caret_highlight_view_ = AddScrollListCheckableItem( l10n_util::GetStringUTF16( IDS_ASH_STATUS_TRAY_ACCESSIBILITY_CARET_HIGHLIGHT), caret_highlight_enabled_); highlight_mouse_cursor_enabled_ = delegate->IsCursorHighlightEnabled(); - highlight_mouse_cursor_view_ = AddScrollListItemWithoutIcon( + highlight_mouse_cursor_view_ = AddScrollListCheckableItem( l10n_util::GetStringUTF16( IDS_ASH_STATUS_TRAY_ACCESSIBILITY_HIGHLIGHT_MOUSE_CURSOR), highlight_mouse_cursor_enabled_); @@ -275,59 +281,23 @@ // ChromeVox does its own focus highlighting. if (!spoken_feedback_enabled_) { highlight_keyboard_focus_enabled_ = delegate->IsFocusHighlightEnabled(); - highlight_keyboard_focus_view_ = AddScrollListItemWithoutIcon( + highlight_keyboard_focus_view_ = AddScrollListCheckableItem( l10n_util::GetStringUTF16( IDS_ASH_STATUS_TRAY_ACCESSIBILITY_HIGHLIGHT_KEYBOARD_FOCUS), highlight_keyboard_focus_enabled_); } sticky_keys_enabled_ = delegate->IsStickyKeysEnabled(); - sticky_keys_view_ = AddScrollListItemWithoutIcon( + sticky_keys_view_ = AddScrollListCheckableItem( l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_STICKY_KEYS), sticky_keys_enabled_); tap_dragging_enabled_ = delegate->IsTapDraggingEnabled(); - tap_dragging_view_ = AddScrollListItemWithoutIcon( + tap_dragging_view_ = AddScrollListCheckableItem( l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_TAP_DRAGGING), tap_dragging_enabled_); } -HoverHighlightView* AccessibilityDetailedView::AddScrollListItem( - const base::string16& text, - bool checked, - const gfx::VectorIcon& icon) { - HoverHighlightView* container = new HoverHighlightView(this); - gfx::ImageSkia image = CreateVectorIcon(icon, kMenuIconColor); - container->AddIconAndLabel(image, text); - TrayPopupUtils::InitializeAsCheckableRow(container, checked); - scroll_content()->AddChildView(container); - return container; -} - -HoverHighlightView* AccessibilityDetailedView::AddScrollListItemWithoutIcon( - const base::string16& text, - bool checked) { - HoverHighlightView* container = new HoverHighlightView(this); - container->AddLabelRow(text); - TrayPopupUtils::InitializeAsCheckableRow(container, checked); - scroll_content()->AddChildView(container); - return container; -} - -void AccessibilityDetailedView::AddSubHeader( - const base::string16& header_text) { - TriView* header = TrayPopupUtils::CreateSubHeaderRowView(); - TrayPopupUtils::ConfigureAsStickyHeader(header); - - views::Label* label = TrayPopupUtils::CreateDefaultLabel(); - label->SetText(header_text); - TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::SUB_HEADER); - style.SetupLabel(label); - header->AddView(TriView::Container::CENTER, label); - - scroll_content()->AddChildView(header); -} - void AccessibilityDetailedView::HandleViewClicked(views::View* view) { AccessibilityDelegate* delegate = Shell::Get()->accessibility_delegate(); UserMetricsAction user_action;
diff --git a/ash/system/tray_accessibility.h b/ash/system/tray_accessibility.h index e3a2e1a6..2e101f9 100644 --- a/ash/system/tray_accessibility.h +++ b/ash/system/tray_accessibility.h
@@ -8,7 +8,6 @@ #include <stdint.h> #include "ash/accessibility_delegate.h" -#include "ash/shell_observer.h" #include "ash/system/accessibility_observer.h" #include "ash/system/tray/tray_details_view.h" #include "ash/system/tray/tray_image_item.h" @@ -21,10 +20,6 @@ class TrayAccessibilityTest; } -namespace gfx { -struct VectorIcon; -} - namespace views { class Button; class CustomButton; @@ -33,7 +28,6 @@ } namespace ash { -class HoverHighlightView; class SystemTrayItem; namespace tray { @@ -60,8 +54,7 @@ }; // Create the detailed view of accessibility tray. -class AccessibilityDetailedView : public TrayDetailsView, - public ShellObserver { +class AccessibilityDetailedView : public TrayDetailsView { public: explicit AccessibilityDetailedView(SystemTrayItem* owner); ~AccessibilityDetailedView() override {} @@ -82,15 +75,6 @@ // Add the accessibility feature list. void AppendAccessibilityList(); - // Helper function to create entries in the detailed accessibility view. - HoverHighlightView* AddScrollListItem(const base::string16& text, - bool checked, - const gfx::VectorIcon& icon); - HoverHighlightView* AddScrollListItemWithoutIcon(const base::string16& text, - bool checked); - - void AddSubHeader(const base::string16& header_text); - views::View* spoken_feedback_view_ = nullptr; views::View* high_contrast_view_ = nullptr; views::View* screen_magnifier_view_ = nullptr;
diff --git a/base/BUILD.gn b/base/BUILD.gn index d096f012..b284bec 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2116,7 +2116,6 @@ "task_scheduler/task_scheduler_impl_unittest.cc", "task_scheduler/task_tracker_posix_unittest.cc", "task_scheduler/task_tracker_unittest.cc", - "task_scheduler/task_traits_unittest.cc", "task_scheduler/task_unittest.cc", "task_scheduler/test_task_factory.cc", "task_scheduler/test_task_factory.h",
diff --git a/base/containers/README.md b/base/containers/README.md index 33c2f32..e64e8f3 100644 --- a/base/containers/README.md +++ b/base/containers/README.md
@@ -1,5 +1,7 @@ # base/containers library +## What goes here + This directory contains some STL-like containers. Things should be moved here that are generally applicable across the code base. @@ -8,7 +10,7 @@ your component's directory and we can promote them here later if we feel there is broad applicability. -## Design and naming +### Design and naming Containers should adhere as closely to STL as possible. Functions and behaviors not present in STL should only be added when they are related to the specific @@ -18,3 +20,151 @@ when it may conflict with the style guide. So functions and class names should be lower case with underscores. Non-STL-like classes and functions should use Google naming. Be sure to use the base namespace. + +## Map and set selection + +### Usage advice + + * Generally avoid **std::unordered\_set** and **std::unordered\_map**. In the + common case, query performance is unlikely to be sufficiently higher than + std::map to make a difference, insert performance is slightly worse, and + the memory overhead is high. This makes sense mostly for large tables where + you expect a lot of lookups. + + * Most maps and sets in Chrome are small and contain objects that can be + moved efficiently. In this case, consider **base::flat\_map** and + **base::flat\_set**. You need to be aware of the maximum expected size of + the container since individual inserts and deletes are O(n), giving O(n^2) + construction time for the entire map. But because it avoids mallocs in most + cases, inserts are better or comparable to other containers even for + several dozen items, and efficiently-moved types are unlikely to have + performance problems for most cases until you have hundreds of items. If + your container can be constructed in one shot, the constructor from vector + gives O(n log n) construction times and it should be strictly better than + a std::map. + + * **base::small\_map** has better runtime memory usage without the poor + mutation performance of large containers that base::flat\_map has. But this + advantage is partially offset by additional code size. Prefer in cases + where you make many objects so that the code/heap tradeoff is good. + + * Use **std::map** and **std::set** if you can't decide. Even if they're not + great, they're unlikely to be bad or surprising. + +### Map and set details + +Sizes are on 64-bit platforms. Stable iterators aren't invalidated when the +container is mutated. + +| Container | Empty size | Per-item overhead | Stable iterators? | +|:---------------------------------------- |:--------------------- |:----------------- |:----------------- | +| std::map, std::set | 16 bytes | 32 bytes | Yes | +| std::unordered\_map, std::unordered\_set | 128 bytes | 16-24 bytes | No | +| base::flat\_map and base::flat\_set | 24 bytes | 0 (see notes) | No | +| base::small\_map | 24 bytes (see notes) | 32 bytes | No | + +**Takeaways:** std::unordered\_map and std::unordered\_map have high +overhead for small container sizes, prefer these only for larger workloads. + +Code size comparisons for a block of code (see appendix) on Windows using +strings as keys. + +| Container | Code size | +|:------------------- |:---------- | +| std::unordered\_map | 1646 bytes | +| std::map | 1759 bytes | +| base::flat\_map | 1872 bytes | +| base::small\_map | 2410 bytes | + +**Takeaways:** base::small\_map generates more code because of the inlining of +both brute-force and red-black tree searching. This makes it less attractive +for random one-off uses. But if your code is called frequently, the runtime +memory benefits will be more important. The code sizes of the other maps are +close enough it's not worth worrying about. + +### std::map and std::set + +A red-black tree. Each inserted item requires the memory allocation of a node +on the heap. Each node contains a left pointer, a right pointer, a parent +pointer, and a "color" for the red-black tree (32-bytes per item on 64-bits). + +### std::unordered\_map and std::unordered\_set + +A hash table. Implemented on Windows as a std::vector + std::list and in libc++ +as the equivalent of a std::vector + a std::forward\_list. Both implementations +allocate an 8-entry hash table (containing iterators into the list) on +initialization, and grow to 64 entries once 8 items are inserted. Above 64 +items, the size doubles every time the load factor exceeds 1. + +The empty size is sizeof(std::unordered\_map) = 64 + +the initial hash table size which is 8 pointers. The per-item overhead in the +table above counts the list node (2 pointers on Windows, 1 pointer in libc++), +plus amortizes the hash table assuming a 0.5 load factor on average. + +In a microbenchmark on Windows, inserts of 1M integers into a +std::unordered\_set took 1.07x the time of std::set, and queries took 0.67x the +time of std::set. For a typical 4-entry set (the statistical mode of map sizes +in the browser), query performance is identical to std::set and base::flat\_set. +On ARM, unordered\_set performance can be worse because integer division to +compute the bucket is slow, and a few "less than" operations can be faster than +computing a hash depending on the key type. The takeaway is that you should not +default to using unordered maps because "they're faster." + +### base::flat\_map and base::flat\_set + +A sorted std::vector. Seached via binary search, inserts in the middle require +moving elements to make room. Good cache locality. For large objects and large +set sizes, std::vector's doubling-when-full strategy can waste memory. + +Supports efficient construction from a vector of items which avoids the O(n^2) +insertion time of each element separately. + +The per-item overhead will depend on the underlying std::vector's reallocation +strategy and the memory access pattern. Assuming items are being linearly added, +one would expect it to be 3/4 full, so per-item overhead will be 0.25 * +sizeof(T). + +### base::small\_map + +A small inline buffer that is brute-force searched that overflows into a full +std::map or std::unordered\_map. This gives the memory benefit of +base::flat\_map for small data sizes without the degenerate insertion +performance for large container sizes. + +Since instantiations require both code for a std::map and a brute-force search +of the inline container, plus a fancy iterator to cover both cases, code size +is larger. + +The initial size in the above table is assuming a very small inline table. The +actual size will be sizeof(int) + min(sizeof(std::map), sizeof(T) * +inline\_size). + +## Appendix + +### Code for map code size comparison + +This just calls insert and query a number of times, with printfs that prevent +things from being dead-code eliminated. + +``` +TEST(Foo, Bar) { + base::small_map<std::map<std::string, Flubber>> foo; + foo.insert(std::make_pair("foo", Flubber(8, "bar"))); + foo.insert(std::make_pair("bar", Flubber(8, "bar"))); + foo.insert(std::make_pair("foo1", Flubber(8, "bar"))); + foo.insert(std::make_pair("bar1", Flubber(8, "bar"))); + foo.insert(std::make_pair("foo", Flubber(8, "bar"))); + foo.insert(std::make_pair("bar", Flubber(8, "bar"))); + auto found = foo.find("asdf"); + printf("Found is %d\n", (int)(found == foo.end())); + found = foo.find("foo"); + printf("Found is %d\n", (int)(found == foo.end())); + found = foo.find("bar"); + printf("Found is %d\n", (int)(found == foo.end())); + found = foo.find("asdfhf"); + printf("Found is %d\n", (int)(found == foo.end())); + found = foo.find("bar1"); + printf("Found is %d\n", (int)(found == foo.end())); +} +``` +
diff --git a/base/containers/flat_map.h b/base/containers/flat_map.h index bd0b1265..225052b 100644 --- a/base/containers/flat_map.h +++ b/base/containers/flat_map.h
@@ -14,7 +14,7 @@ namespace internal { -// An implementation of the flat_set GetKeyFromValue template parameter that +// An implementation of the flat_tree GetKeyFromValue template parameter that // extracts the key as the first element of a pair. template <class Key, class Mapped> struct GetKeyFromValuePairFirst { @@ -25,14 +25,30 @@ } // namespace internal -// OVERVIEW +// flat_map is a container with a std::map-like interface that stores its +// contents in a sorted vector. // -// This file implements flat_map container. It is an alternative to standard -// sorted containers that stores its elements in contiguous memory (a vector). +// Please see //base/containers/README.md for an overview of which container +// to select. // -// Additional documentation and usage advice is in flat_set.h. +// PROS // -// DOCUMENTATION +// - Good memory locality. +// - Low overhead, especially for smaller maps. +// - Performance is good for more workloads than you might expect (see +// overview link above). +// +// CONS +// +// - Inserts and removals are O(n). +// +// IMPORTANT NOTES +// +// - Iterators are invalidated across mutations. +// - If possible, construct a flat_map in one operation by inserting into +// a std::vector and moving that vector into the flat_map constructor. +// +// QUICK REFERENCE // // Most of the core functionality is inherited from flat_tree. Please see // flat_tree.h for more details for most of these functions. As a quick
diff --git a/base/containers/flat_set.h b/base/containers/flat_set.h index da19034f..13f44dd 100644 --- a/base/containers/flat_set.h +++ b/base/containers/flat_set.h
@@ -9,70 +9,31 @@ namespace base { -// Overview: -// This file implements flat_set container. It is an alternative to standard -// sorted containers that stores it's elements in contiguous memory using a -// std::vector. +// flat_set is a container with a std::set-like interface that stores its +// contents in a sorted vector. // -// Discussion that preceded introduction of this container can be found here: -// https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/vector$20based/chromium-dev/4uQMma9vj9w/HaQ-WvMOAwAJ +// Please see //base/containers/README.md for an overview of which container +// to select. // -// Motivation: -// Contiguous memory is very beneficial to iteration and copy speed at the cost -// of worse algorithmic complexity of insertion/erasure operations. They can -// be very fast for set operations and for small number of elements. +// PROS // -// Usage guidance: -// Prefer base::flat_set for: -// * Very small sets, something that is an easy fit for cache. Consider -// "very small" to be under 100 32bit integers. -// * Sets that are built once (using flat_set::flat_set(first, last)). Consider -// collecting all data in a vector and then building flat_set out of it. -// Using the constructor that takes a moved vector allows you to re-use -// storage. -// * Sets where mutating happens in big bulks: to erase multiple elements, use -// base::EraseIf() rather than repeated single-element removal. Insertion is -// harder - consider set operations or building a new vector. Set operations -// can be slow if one of the sets is considerably bigger. Also be aware that -// beating performance of sort + unique (implementation of flat_set's -// constructor) is hard, clever merge of many sets might not win. Generally -// avoid inserting into flat set without benchmarks. -// * Copying and iterating. -// * Set operations (union/intersect etc). +// - Good memory locality. +// - Low overhead, especially for smaller sets. +// - Performance is good for more workloads than you might expect (see +// overview link above). // -// Prefer to build a new flat_set from a std::vector (or similar) instead of -// calling insert() repeatedly, which would have O(size^2) complexity. The -// constructor that can accept a moved vector (not required to be sorted) is -// the most efficient. +// CONS // -// TODO(dyaroshev): develop standalone benchmarks to find performance boundaries -// for different types of sets crbug.com/682215. +// - Inserts and removals are O(n). // -// If you do write a benchmark that significantly depends on using sets please -// share your results at: -// https://groups.google.com/a/chromium.org/forum/#!searchin/chromium-dev/vector$20based/chromium-dev/4uQMma9vj9w/HaQ-WvMOAwAJ +// IMPORTANT NOTES // -// Important usability aspects: -// * flat_set implements std::set interface from C++11 where possible. It -// also has reserve(), capacity() and shrink_to_fit() from std::vector. -// * iteration invalidation rules differ: -// - all cases of std::vector::iterator invalidation also apply. -// - we ask (for now) to assume that move operations invalidate iterators. -// TODO(dyaroshev): Research the possibility of using a small buffer -// optimization crbug.com/682240. -// * allocator support is not implemented. -// * insert(first, last) and insert(std::initializer_list) are not -// implemented (see Notes section). +// - Iterators are invalidated across mutations. +// - If possible, construct a flat_set in one operation by inserting into +// a std::vector and moving that vector into the flat_set constructor. +// - For multiple removals use base::EraseIf() which is O(n) rather than +// O(n * removed_items). // -// Notes: -// Current implementation is based on boost::containers::flat_set, -// eastl::vector_set and folly::sorted_vector. All of these implementations do -// insert(first, last) as insertion one by one (some implementations with hints -// and/or reserve). Boost documentation claims this algorithm to be O(n*log(n)) -// but it seems to be a quadratic algorithm. For now we do not implement this -// method. -// TODO(dyaroshev): research an algorithm for range insertion crbug.com/682249. - // QUICK REFERENCE // // Most of the core functionality is inherited from flat_tree. Please see
diff --git a/base/containers/small_map.h b/base/containers/small_map.h index db27b88..0517ea6 100644 --- a/base/containers/small_map.h +++ b/base/containers/small_map.h
@@ -17,39 +17,32 @@ namespace base { -// An STL-like associative container which starts out backed by a simple -// array but switches to some other container type if it grows beyond a -// fixed size. +// small_map is a container with a std::map-like interface. It starts out +// backed by a unsorted array but switches to some other container type if it +// grows beyond this fixed size. // -// WHAT TYPE OF MAP SHOULD YOU USE? -// -------------------------------- +// Please see //base/containers/README.md for an overview of which container +// to select. // -// - std::map should be the default if you're not sure, since it's the most -// difficult to mess up. Generally this is backed by a red-black tree. It -// will generate a lot of code (if you use a common key type like int or -// string the linker will probably emiminate the duplicates). It will -// do heap allocations for each element. +// PROS // -// - If you only ever keep a couple of items and have very simple usage, -// use a base::flat_map. +// - Good memory locality and low overhead for smaller maps. +// - Handles large maps without the degenerate performance of flat_map. // -// - std::unordered_map should be used if you need O(1) lookups. It may waste -// space in the hash table, and it can be easy to write correct-looking -// code with the default hash function being wrong or poorly-behaving. +// CONS // -// - base::small_map combines the performance benefits of the -// brute-force-searched vector for small cases (no extra heap allocations), -// but can efficiently fall back if you end up adding many items. It will -// generate more code than std::map (at least 160 bytes for operator[]) -// which is bad if you have a "weird" key where map functions can't be -// duplicate-code-eliminated. If you have a one-off key and aren't in -// performance-critical code, this bloat may negate some of the benefits and -// you should consider on of the other options. +// - Larger code size than the alternatives. +// +// IMPORTANT NOTES +// +// - Iterators are invalidated across mutations. +// +// DETAILS // // base::small_map will pick up the comparator from the underlying map type. In -// std::map (and in MSVC additionally hash_map) only a "less" operator is -// defined, which requires us to do two comparisons per element when doing the -// brute-force search in the simple array. +// std::map only a "less" operator is defined, which requires us to do two +// comparisons per element when doing the brute-force search in the simple +// array. std::unordered_map has a key_equal function which will be used. // // We define default overrides for the common map types to avoid this // double-compare, but you should be aware of this if you use your own @@ -90,9 +83,6 @@ // days["thursday" ] = 4; // days["friday" ] = 5; // days["saturday" ] = 6; -// -// You should assume that small_map might invalidate all the iterators -// on any call to erase(), insert() and operator[]. namespace internal { @@ -147,7 +137,7 @@ // If we switch to using std::unordered_map for base::hash_map, then the // hash_map specialization can be removed. template <typename KeyType, typename ValueType> -struct select_equal_key< std::map<KeyType, ValueType>, false> { +struct select_equal_key<std::map<KeyType, ValueType>, false> { struct equal_key { bool operator()(const KeyType& left, const KeyType& right) { return left == right; @@ -155,7 +145,7 @@ }; }; template <typename KeyType, typename ValueType> -struct select_equal_key< base::hash_map<KeyType, ValueType>, false> { +struct select_equal_key<base::hash_map<KeyType, ValueType>, false> { struct equal_key { bool operator()(const KeyType& left, const KeyType& right) { return left == right;
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h index 6e5e796..06d4ba9 100644 --- a/base/process/process_metrics.h +++ b/base/process/process_metrics.h
@@ -167,10 +167,20 @@ bool GetCommittedAndWorkingSetKBytes(CommittedKBytes* usage, WorkingSetKBytes* ws_usage) const; - // Returns the physical footprint, only available on macOS 10.11+. This - // measures anonymous, non-discardable memory. Returns 0 on error, or if the - // measurement was unavailable. - size_t GetPhysicalFootprint() const; + struct TaskVMInfo { + // Only available on macOS 10.12+. + // Anonymous, non-discardable memory, including non-volatile IOKit. + // Measured in bytes. + uint64_t phys_footprint = 0; + + // Anonymous, non-discardable, non-compressed memory, excluding IOKit. + // Measured in bytes. + uint64_t internal = 0; + + // Compressed memory measured in bytes. + uint64_t compressed = 0; + }; + TaskVMInfo GetTaskVMInfo() const; // Returns private, shared, and total resident bytes. |locked_bytes| refers to // bytes that must stay resident. |locked_bytes| only counts bytes locked by
diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc index 5eda0d0..ad751e3 100644 --- a/base/process/process_metrics_mac.cc +++ b/base/process/process_metrics_mac.cc
@@ -287,18 +287,21 @@ return true; } -size_t ProcessMetrics::GetPhysicalFootprint() const { - if (mac::IsAtMostOS10_11()) - return 0; - +ProcessMetrics::TaskVMInfo ProcessMetrics::GetTaskVMInfo() const { + TaskVMInfo info; ChromeTaskVMInfo task_vm_info; mach_msg_type_number_t count = ChromeTaskVMInfoCount; kern_return_t result = task_info(TaskForPid(process_), TASK_VM_INFO, reinterpret_cast<task_info_t>(&task_vm_info), &count); if (result != KERN_SUCCESS) - return 0; - return task_vm_info.phys_footprint; + return info; + + info.internal = task_vm_info.internal; + info.compressed = task_vm_info.compressed; + if (count == ChromeTaskVMInfoCount) + info.phys_footprint = task_vm_info.phys_footprint; + return info; } #define TIME_VALUE_TO_TIMEVAL(a, r) do { \
diff --git a/base/task_scheduler/post_task.cc b/base/task_scheduler/post_task.cc index 6f9adae2..6da11bd8 100644 --- a/base/task_scheduler/post_task.cc +++ b/base/task_scheduler/post_task.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/logging.h" +#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h" #include "base/task_scheduler/task_scheduler.h" #include "base/threading/post_task_and_reply_impl.h" @@ -29,6 +30,15 @@ const TaskTraits traits_; }; +// Returns TaskTraits based on |traits|. If TaskPriority hasn't been set +// explicitly in |traits|, the returned TaskTraits have the current +// TaskPriority. +TaskTraits GetTaskTraitsWithExplicitPriority(const TaskTraits& traits) { + return traits.priority_set_explicitly() + ? traits + : TaskTraits(traits).WithPriority( + internal::GetTaskPriorityForCurrentThread()); +} } // namespace @@ -62,7 +72,8 @@ DCHECK(TaskScheduler::GetInstance()) << "Ref. Prerequisite section of post_task.h"; TaskScheduler::GetInstance()->PostDelayedTaskWithTraits( - from_here, traits, std::move(task), std::move(delay)); + from_here, GetTaskTraitsWithExplicitPriority(traits), std::move(task), + std::move(delay)); } void PostTaskWithTraitsAndReply(const tracked_objects::Location& from_here, @@ -76,7 +87,8 @@ scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(const TaskTraits& traits) { DCHECK(TaskScheduler::GetInstance()) << "Ref. Prerequisite section of post_task.h"; - return TaskScheduler::GetInstance()->CreateTaskRunnerWithTraits(traits); + return TaskScheduler::GetInstance()->CreateTaskRunnerWithTraits( + GetTaskTraitsWithExplicitPriority(traits)); } scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits( @@ -84,7 +96,7 @@ DCHECK(TaskScheduler::GetInstance()) << "Ref. Prerequisite section of post_task.h"; return TaskScheduler::GetInstance()->CreateSequencedTaskRunnerWithTraits( - traits); + GetTaskTraitsWithExplicitPriority(traits)); } scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits( @@ -92,7 +104,7 @@ DCHECK(TaskScheduler::GetInstance()) << "Ref. Prerequisite section of post_task.h"; return TaskScheduler::GetInstance()->CreateSingleThreadTaskRunnerWithTraits( - traits); + GetTaskTraitsWithExplicitPriority(traits)); } #if defined(OS_WIN) @@ -100,7 +112,8 @@ const TaskTraits& traits) { DCHECK(TaskScheduler::GetInstance()) << "Ref. Prerequisite section of post_task.h"; - return TaskScheduler::GetInstance()->CreateCOMSTATaskRunnerWithTraits(traits); + return TaskScheduler::GetInstance()->CreateCOMSTATaskRunnerWithTraits( + GetTaskTraitsWithExplicitPriority(traits)); } #endif // defined(OS_WIN)
diff --git a/base/task_scheduler/task_scheduler.cc b/base/task_scheduler/task_scheduler.cc index c1eb432..80359c3 100644 --- a/base/task_scheduler/task_scheduler.cc +++ b/base/task_scheduler/task_scheduler.cc
@@ -39,7 +39,7 @@ #if !defined(OS_NACL) // static -void TaskScheduler::CreateAndSetSimpleTaskScheduler(StringPiece name) { +void TaskScheduler::CreateAndStartWithDefaultParams(StringPiece name) { using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy; // Values were chosen so that: @@ -54,22 +54,32 @@ constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30); - CreateAndSetDefaultTaskScheduler( - name, {{StandbyThreadPolicy::LAZY, kBackgroundMaxThreads, - kSuggestedReclaimTime}, - {StandbyThreadPolicy::LAZY, kBackgroundBlockingMaxThreads, - kSuggestedReclaimTime}, - {StandbyThreadPolicy::LAZY, kForegroundMaxThreads, - kSuggestedReclaimTime}, - {StandbyThreadPolicy::LAZY, kForegroundBlockingMaxThreads, - kSuggestedReclaimTime}}); + Create(name); + GetInstance()->Start( + {{StandbyThreadPolicy::LAZY, kBackgroundMaxThreads, + kSuggestedReclaimTime}, + {StandbyThreadPolicy::LAZY, kBackgroundBlockingMaxThreads, + kSuggestedReclaimTime}, + {StandbyThreadPolicy::LAZY, kForegroundMaxThreads, + kSuggestedReclaimTime}, + {StandbyThreadPolicy::LAZY, kForegroundBlockingMaxThreads, + kSuggestedReclaimTime}}); +} + +// static +void TaskScheduler::CreateAndSetSimpleTaskScheduler(StringPiece name) { + CreateAndStartWithDefaultParams(name); } #endif // !defined(OS_NACL) +void TaskScheduler::Create(StringPiece name) { + SetInstance(MakeUnique<internal::TaskSchedulerImpl>(name)); +} + void TaskScheduler::CreateAndSetDefaultTaskScheduler( StringPiece name, const InitParams& init_params) { - SetInstance(MakeUnique<internal::TaskSchedulerImpl>(name)); + Create(name); GetInstance()->Start(init_params); }
diff --git a/base/task_scheduler/task_scheduler.h b/base/task_scheduler/task_scheduler.h index 3d3d5eb0..0bbfd5c 100644 --- a/base/task_scheduler/task_scheduler.h +++ b/base/task_scheduler/task_scheduler.h
@@ -134,28 +134,45 @@ // after this call. virtual void JoinForTesting() = 0; - // CreateAndSetSimpleTaskScheduler(), CreateAndSetDefaultTaskScheduler(), and - // SetInstance() register a TaskScheduler to handle tasks posted through the - // post_task.h API for this process. The registered TaskScheduler will only be - // deleted when a new TaskScheduler is registered and is leaked on shutdown. - // The methods must not be called when TaskRunners created by the previous - // TaskScheduler are still alive. The methods are not thread-safe; proper - // synchronization is required to use the post_task.h API after registering a - // new TaskScheduler. +// CreateAndStartWithDefaultParams(), Create(), and SetInstance() register a +// TaskScheduler to handle tasks posted through the post_task.h API for this +// process. +// +// Processes that need to initialize TaskScheduler with custom params or that +// need to allow tasks to be posted before the TaskScheduler creates its +// threads should use Create() followed by Start(). Other processes can use +// CreateAndStartWithDefaultParams(). +// +// A registered TaskScheduler is only deleted when a new TaskScheduler is +// registered. The last registered TaskScheduler is leaked on shutdown. The +// methods below must not be called when TaskRunners created by a previous +// TaskScheduler are still alive. The methods are not thread-safe; proper +// synchronization is required to use the post_task.h API after registering a +// new TaskScheduler. #if !defined(OS_NACL) - // Creates and sets a task scheduler using default params. |name| is used to + // Creates and starts a task scheduler using default params. |name| is used to // label threads and histograms. It should identify the component that calls - // this. CHECKs on failure. For tests, prefer base::test::ScopedTaskScheduler - // (ensures isolation). + // this. Start() is called by this method; it is invalid to call it again + // afterwards. CHECKs on failure. For tests, prefer + // base::test::ScopedTaskEnvironment (ensures isolation). + static void CreateAndStartWithDefaultParams(StringPiece name); + + // Deprecated. Use CreateAndStartWithDefaultParams() instead. + // TODO(fdoray): Redirect callers to CreateAndStartWithDefaultParams(). static void CreateAndSetSimpleTaskScheduler(StringPiece name); #endif // !defined(OS_NACL) - // Creates and sets a task scheduler using custom params. |name| is used to - // label threads and histograms. It should identify the component that creates - // the TaskScheduler. |init_params| is used to initialize the worker pools. - // CHECKs on failure. For tests, prefer base::test::ScopedTaskScheduler + // Creates a ready to start task scheduler. |name| is used to label threads + // and histograms. It should identify the component that creates the + // TaskScheduler. The task scheduler doesn't create threads until Start() is + // called. Tasks can be posted at any time but will not run until after + // Start() is called. For tests, prefer base::test::ScopedTaskEnvironment // (ensures isolation). + static void Create(StringPiece name); + + // Deprecated. Use Create() and Start() instead. + // TODO(fdoray): Redirect callers to Create() and Start(). static void CreateAndSetDefaultTaskScheduler(StringPiece name, const InitParams& init_params);
diff --git a/base/task_scheduler/task_traits.cc b/base/task_scheduler/task_traits.cc index 6acf324..c00ae6c4 100644 --- a/base/task_scheduler/task_traits.cc +++ b/base/task_scheduler/task_traits.cc
@@ -9,19 +9,10 @@ #include <ostream> #include "base/logging.h" -#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h" namespace base { -// Do not rely on defaults hard-coded below beyond the guarantees described in -// the header; anything else is subject to change. Tasks should explicitly -// request defaults if the behavior is critical to the task. -TaskTraits::TaskTraits() - : may_block_(false), - with_base_sync_primitives_(false), - priority_(internal::GetTaskPriorityForCurrentThread()), - shutdown_behavior_(TaskShutdownBehavior::SKIP_ON_SHUTDOWN) {} - +TaskTraits::TaskTraits() = default; TaskTraits::~TaskTraits() = default; TaskTraits& TaskTraits::MayBlock() { @@ -35,6 +26,7 @@ } TaskTraits& TaskTraits::WithPriority(TaskPriority priority) { + priority_set_explicitly_ = true; priority_ = priority; return *this; }
diff --git a/base/task_scheduler/task_traits.h b/base/task_scheduler/task_traits.h index 435fdac..04aea49 100644 --- a/base/task_scheduler/task_traits.h +++ b/base/task_scheduler/task_traits.h
@@ -142,6 +142,9 @@ // Returns true if tasks with these traits may use base/ sync primitives. bool with_base_sync_primitives() const { return with_base_sync_primitives_; } + // Returns true if the priority was set explicitly. + bool priority_set_explicitly() const { return priority_set_explicitly_; } + // Returns the priority of tasks with these traits. TaskPriority priority() const { return priority_; } @@ -149,10 +152,15 @@ TaskShutdownBehavior shutdown_behavior() const { return shutdown_behavior_; } private: - bool may_block_; - bool with_base_sync_primitives_; - TaskPriority priority_; - TaskShutdownBehavior shutdown_behavior_; + // Do not rely on defaults hard-coded below beyond the guarantees described on + // the constructor; anything else is subject to change. Tasks should + // explicitly request defaults if the behavior is critical to the task. + bool may_block_ = false; + bool with_base_sync_primitives_ = false; + bool priority_set_explicitly_ = false; + TaskPriority priority_ = TaskPriority::USER_VISIBLE; + TaskShutdownBehavior shutdown_behavior_ = + TaskShutdownBehavior::SKIP_ON_SHUTDOWN; }; // Returns string literals for the enums defined in this file. These methods
diff --git a/base/task_scheduler/task_traits_unittest.cc b/base/task_scheduler/task_traits_unittest.cc deleted file mode 100644 index fed3f99..0000000 --- a/base/task_scheduler/task_traits_unittest.cc +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/task_scheduler/task_traits.h" - -#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { - -// Verify that TaskTraits is initialized with the priority of the task running -// on the current thread. -TEST(TaskSchedulerTaskTraitsTest, DefaultPriority) { - { - internal::ScopedSetTaskPriorityForCurrentThread scope( - TaskPriority::BACKGROUND); - EXPECT_EQ(TaskPriority::BACKGROUND, TaskTraits().priority()); - } - { - internal::ScopedSetTaskPriorityForCurrentThread scope( - TaskPriority::USER_VISIBLE); - EXPECT_EQ(TaskPriority::USER_VISIBLE, TaskTraits().priority()); - } - { - internal::ScopedSetTaskPriorityForCurrentThread scope( - TaskPriority::USER_BLOCKING); - EXPECT_EQ(TaskPriority::USER_BLOCKING, TaskTraits().priority()); - } -} - -} // namespace base
diff --git a/base/trace_event/process_memory_totals.cc b/base/trace_event/process_memory_totals.cc index de27ab3d..d3cfad9 100644 --- a/base/trace_event/process_memory_totals.cc +++ b/base/trace_event/process_memory_totals.cc
@@ -14,8 +14,7 @@ ProcessMemoryTotals::ProcessMemoryTotals() : resident_set_bytes_(0), peak_resident_set_bytes_(0), - is_peak_rss_resetable_(false) { -} + is_peak_rss_resetable_(false) {} ProcessMemoryTotals::~ProcessMemoryTotals() {} @@ -35,6 +34,7 @@ void ProcessMemoryTotals::Clear() { resident_set_bytes_ = 0; + platform_private_footprint_ = PlatformPrivateFootprint(); } void ProcessMemoryTotals::SetExtraFieldInBytes(const char* name,
diff --git a/base/trace_event/process_memory_totals.h b/base/trace_event/process_memory_totals.h index 329967a6..207e398 100644 --- a/base/trace_event/process_memory_totals.h +++ b/base/trace_event/process_memory_totals.h
@@ -32,6 +32,30 @@ uint64_t resident_set_bytes() const { return resident_set_bytes_; } void set_resident_set_bytes(uint64_t value) { resident_set_bytes_ = value; } + // Platform-specific data that will be used to compute the + // PrivateMemoryFootprint. + struct PlatformPrivateFootprint { + // macOS 10.12+ + uint64_t phys_footprint_bytes = 0; + + // macOS [all versions] + uint64_t internal_bytes = 0; + uint64_t compressed_bytes = 0; + + // Linux, Android, ChromeOS + // TODO(hjd): https://crbug.com/707019 + uint64_t rss_anon_bytes = 0; + uint64_t vm_swap_bytes = 0; + + // On Windows, + // TBD: https://crbug.com/707022 + // On iOS, + // TBD: https://crbug.com/714961 + }; + PlatformPrivateFootprint& GetPlatformPrivateFootprint() { + return platform_private_footprint_; + } + uint64_t peak_resident_set_bytes() const { return peak_resident_set_bytes_; } void set_peak_resident_set_bytes(uint64_t value) { peak_resident_set_bytes_ = value; @@ -51,6 +75,10 @@ uint64_t peak_resident_set_bytes_; bool is_peak_rss_resetable_; + // Not emitted in the trace as this is intended to be an intermediary in + // computation of private memory footprint. + PlatformPrivateFootprint platform_private_footprint_; + // Extra metrics for OS-specific statistics. std::map<const char*, uint64_t> extra_fields_;
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index 026215d..099410c 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -451,6 +451,5 @@ <ignore regexp="chrome/android/java/src/org/chromium/chrome/browser/SSLClientCertificateRequest.java"/> <ignore regexp="chrome/android/java/src/org/chromium/chrome/browser/payments/ui/EditorView.java"/> <ignore regexp="chrome/android/java/src/org/chromium/chrome/browser/signin/SigninAndSyncView.java"/> - <ignore regexp="content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java"/> </issue> </lint>
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 6a495cc..092991d 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -512,12 +512,22 @@ ldflags += [ "-Wl,-all_load" ] } - # Allows the linker to apply ICF to the LTO object file. Also, when - # targeting ARM, without this flag, LTO produces a .text section that is - # larger than the maximum call displacement, preventing the linker from - # relocating calls (http://llvm.org/PR22999). + # Allows the linker to apply --gc-sections and ICF to the LTO object file. + # Also, when targeting ARM, without this flag, LTO produces a .text section + # that is larger than the maximum call displacement, preventing the linker + # from relocating calls (http://llvm.org/PR22999). if (is_linux) { - ldflags += [ "-Wl,-plugin-opt,-function-sections" ] + if (use_lld) { + ldflags += [ + "-Wl,-mllvm,-function-sections", + "-Wl,-mllvm,-data-sections", + ] + } else { + ldflags += [ + "-Wl,-plugin-opt,-function-sections", + "-Wl,-plugin-opt,-data-sections", + ] + } } }
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index f0343310..78166cbd 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn
@@ -277,12 +277,15 @@ cflags_cc = [] # Sanitizers need line table info for stack traces. They don't need type info - # or variable info, so we can leave that out to speed up the build. + # or variable info, so we can leave that out to speed up the build (unless + # it's explicitly asked for by setting |sanitizer_keep_symbols| to true). if (using_sanitizer) { assert(is_clang, "sanitizers only supported with clang") - cflags += [ - "-gline-tables-only", + if (!sanitizer_keep_symbols) { + cflags += [ "-gline-tables-only" ] + } + cflags += [ # Column info in debug data confuses Visual Studio's debugger, so don't # use this by default. However, clusterfuzz needs it for good attribution # of reports to CLs, so turn it on there.
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 6feef783..585a065 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -97,6 +97,12 @@ # Default value when unset and use_sanitizer_coverage=true: # edge,indirect-calls,8bit-counters sanitizer_coverage_flags = "" + + # Keep symbol level when building with sanitizers. When sanitizers are + # enabled, the default is to compile with the minimum debug info level + # necessary, overriding any other symbol level arguments that may be set. + # Setting this to true prevents this. + sanitizer_keep_symbols = false } # Disable sanitizers for non-default toolchains.
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index c2b244d..f7be83ed 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -11,7 +11,7 @@ import("//chrome/chrome_paks.gni") import("//chrome/common/features.gni") import("//chrome/process_version_rc_template.gni") # For branding_file_path. -import("//device/vr/features.gni") +import("//device/vr/features/features.gni") import("//testing/test.gni") import("//third_party/icu/config.gni") import("//third_party/protobuf/proto_library.gni")
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 f39d09d..ca0009bde 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1253,7 +1253,7 @@ WebContents webContents = currentTab.getWebContents(); RecordHistogram.recordBooleanHistogram( - "OfflinePages.SharedPageWasOffline", currentTab.isOfflinePage()); + "OfflinePages.SharedPageWasOffline", OfflinePageUtils.isOfflinePage(currentTab)); boolean canShareOfflinePage = OfflinePageBridge.isPageSharingEnabled(); // Share an empty blockingUri in place of screenshot file. The file ready notification is
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 93c8ddf..3417e128 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -31,10 +31,12 @@ import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; +import android.widget.PopupWindow.OnDismissListener; import org.chromium.base.ActivityState; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApplicationStatus; +import org.chromium.base.Callback; import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; import org.chromium.base.Log; @@ -63,6 +65,7 @@ import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.document.DocumentUtils; import org.chromium.chrome.browser.download.DownloadUtils; +import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory; import org.chromium.chrome.browser.firstrun.FirstRunActivity; import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer; import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; @@ -116,6 +119,9 @@ import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; import org.chromium.chrome.browser.widget.emptybackground.EmptyBackgroundViewWrapper; import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager; +import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble; +import org.chromium.components.feature_engagement_tracker.FeatureConstants; +import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker; import org.chromium.content.browser.ContentVideoView; import org.chromium.content.browser.ContentViewCore; import org.chromium.content.browser.crypto.CipherFactory; @@ -688,6 +694,15 @@ } mLayoutManager.hideOverview(false); + FeatureEngagementTracker tracker = + FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile( + Profile.getLastUsedProfile()); + tracker.addOnInitializedCallback(new Callback<Boolean>() { + @Override + public void onResult(Boolean result) { + showFeatureEngagementTextBubbleForDownloadHome(); + } + }); mUIInitialized = true; } finally { @@ -695,6 +710,34 @@ } } + private void showFeatureEngagementTextBubbleForDownloadHome() { + final FeatureEngagementTracker tracker = + FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile( + Profile.getLastUsedProfile()); + if (!tracker.shouldTriggerHelpUI(FeatureConstants.DOWNLOAD_HOME_FEATURE)) return; + + ViewAnchoredTextBubble textBubble = new ViewAnchoredTextBubble( + this, getToolbarManager().getMenuAnchor(), R.string.iph_download_home_text); + textBubble.setDismissOnTouchInteraction(true); + textBubble.addOnDismissListener(new OnDismissListener() { + @Override + public void onDismiss() { + mHandler.post(new Runnable() { + @Override + public void run() { + tracker.dismissed(); + getAppMenuHandler().setMenuHighlight(null); + } + }); + } + }); + getAppMenuHandler().setMenuHighlight(R.id.downloads_menu_id); + int yInsetPx = + getResources().getDimensionPixelOffset(R.dimen.text_bubble_menu_anchor_y_inset); + textBubble.setInsetPx(0, yInsetPx, 0, 0); + textBubble.show(); + } + private boolean isMainIntent(Intent intent) { return intent != null && TextUtils.equals(intent.getAction(), Intent.ACTION_MAIN); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java index 5fe243de..9fac8503 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -34,6 +34,10 @@ import org.chromium.chrome.browser.download.ui.BackendProvider; import org.chromium.chrome.browser.download.ui.DownloadHistoryAdapter; import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; +import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.components.feature_engagement_tracker.EventConstants; +import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker; import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.LegacyHelpers; import org.chromium.net.ConnectionType; @@ -1332,6 +1336,13 @@ mDownloadSnackbarController.onDownloadSucceeded( info, notificationId, systemDownloadId, canResolve, false); } + + Profile profile = info.isOffTheRecord() + ? Profile.getLastUsedProfile().getOffTheRecordProfile() + : Profile.getLastUsedProfile().getOriginalProfile(); + FeatureEngagementTracker tracker = + FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(profile); + tracker.notifyEvent(EventConstants.DOWNLOAD_COMPLETED); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java index 45fb196..f9313f625 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -42,7 +42,9 @@ import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory; import org.chromium.chrome.browser.offlinepages.DownloadUiActionFlags; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; +import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.offlinepages.downloads.OfflinePageDownloadBridge; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.document.TabDelegate; @@ -152,6 +154,11 @@ } } + Profile profile = (tab == null ? Profile.getLastUsedProfile() : tab.getProfile()); + FeatureEngagementTracker tracker = + FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(profile); + tracker.notifyEvent(EventConstants.DOWNLOAD_HOME_OPENED); + return true; } @@ -251,7 +258,7 @@ if (tab.isShowingInterstitialPage()) return false; // Don't allow re-downloading the currently displayed offline page. - if (tab.isOfflinePage()) return false; + if (OfflinePageUtils.isOfflinePage(tab)) return false; return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java index 8e9751e..f2f3542 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
@@ -233,8 +233,8 @@ @VisibleForTesting void onSuccessNotificationShown( final PendingNotificationInfo notificationInfo, final int notificationId) { - if (notificationInfo.downloadInfo != null - && !notificationInfo.downloadInfo.getIsOpenable()) { + if (notificationInfo.downloadInfo == null + || !notificationInfo.downloadInfo.getIsOpenable()) { return; } DownloadManagerService.getDownloadManagerService().onSuccessNotificationShown(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java index c73a508..8c09c2a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
@@ -19,6 +19,8 @@ import java.util.List; import java.util.Set; +import javax.annotation.Nullable; + /** * Access gate to C++ side offline pages functionalities. */ @@ -468,6 +470,25 @@ nativeScheduleDownload(mNativeOfflinePageBridge, webContents, nameSpace, url, uiAction); } + /** + * Checks if an offline page is shown for the webContents. + * @param webContents Web contents used to find the offline page. + * @return True if the offline page is opened. + */ + public boolean isOfflinePage(WebContents webContents) { + return nativeIsOfflinePage(mNativeOfflinePageBridge, webContents); + } + + /** + * Retrieves the offline page that is shown for the tab. + * @param webContents Web contents used to find the offline page. + * @return The offline page if tab currently displays it, null otherwise. + */ + @Nullable + public OfflinePageItem getOfflinePage(WebContents webContents) { + return nativeGetOfflinePage(mNativeOfflinePageBridge, webContents); + } + @VisibleForTesting static void setOfflineBookmarksEnabledForTesting(boolean enabled) { sOfflineBookmarksEnabled = enabled; @@ -573,4 +594,8 @@ long nativeOfflinePageBridge, WebContents webContents); private native void nativeScheduleDownload(long nativeOfflinePageBridge, WebContents webContents, String nameSpace, String url, int uiAction); + private native boolean nativeIsOfflinePage( + long nativeOfflinePageBridge, WebContents webContents); + private native OfflinePageItem nativeGetOfflinePage( + long nativeOfflinePageBridge, WebContents webContents); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java index 04015df1..c1dff32 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java
@@ -171,7 +171,7 @@ @Override public void onUrlUpdated(Tab tab) { Log.d(TAG, "onUrlUpdated"); - if (!tab.isOfflinePage()) { + if (!isOfflinePage(tab)) { stopObservingTab(tab); } else { if (isObservingTab(tab)) { @@ -184,7 +184,7 @@ } void startObservingTab(Tab tab) { - if (!tab.isOfflinePage()) return; + if (!isOfflinePage(tab)) return; mCurrentTab = tab; @@ -285,9 +285,14 @@ return OfflinePageUtils.isShowingOfflinePreview(tab); } + @VisibleForTesting + boolean isOfflinePage(Tab tab) { + return OfflinePageUtils.isOfflinePage(tab); + } + void maybeShowReloadSnackbar(Tab tab, boolean isNetworkEvent) { // Exclude Offline Previews, as there is a seperate UI for previews. - if (tab == null || tab.isFrozen() || tab.isHidden() || !tab.isOfflinePage() + if (tab == null || tab.isFrozen() || tab.isHidden() || !isOfflinePage(tab) || isShowingOfflinePreview(tab) || !isConnected() || !isLoadedTab(tab) || (wasSnackbarSeen(tab) && !isNetworkEvent)) { // Conditions to show a snackbar are not met.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java index 47709b4..39f86dd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -283,7 +283,7 @@ return; } - OfflinePageItem offlinePage = currentTab.getOfflinePage(); + OfflinePageItem offlinePage = offlinePageBridge.getOfflinePage(currentTab.getWebContents()); if (offlinePage != null) { // If we're currently on offline page get the saved file directly. prepareFileAndShare(shareDirectly, saveLastUsed, mainActivity, title, text, @@ -564,6 +564,28 @@ } /** + * Checks if an offline page is shown for the tab. + * @param tab The tab to be reloaded. + * @return True if the offline page is opened. + */ + public static boolean isOfflinePage(Tab tab) { + OfflinePageBridge offlinePageBridge = getInstance().getOfflinePageBridge(tab.getProfile()); + if (offlinePageBridge == null) return false; + return offlinePageBridge.isOfflinePage(tab.getWebContents()); + } + + /** + * Retrieves the offline page that is shown for the tab. + * @param tab The tab to be reloaded. + * @return The offline page if tab currently displays it, null otherwise. + */ + public static OfflinePageItem getOfflinePage(Tab tab) { + OfflinePageBridge offlinePageBridge = getInstance().getOfflinePageBridge(tab.getProfile()); + if (offlinePageBridge == null) return null; + return offlinePageBridge.getOfflinePage(tab.getWebContents()); + } + + /** * Reloads specified tab, which should allow to open an online version of the page. * @param tab The tab to be reloaded. */ @@ -698,7 +720,7 @@ // We first compute the bitwise tab restore context. int tabRestoreContext = 0; if (isConnected()) tabRestoreContext |= BIT_ONLINE; - OfflinePageItem page = tab.getOfflinePage(); + OfflinePageItem page = getOfflinePage(tab); if (page != null) { tabRestoreContext |= BIT_OFFLINE_PAGE; if (page.getClientId().getNamespace().equals(OfflinePageBridge.LAST_N_NAMESPACE)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index 8ef70af..a949e84f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -60,6 +60,7 @@ import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.ntp.NewTabPage.FakeboxDelegate; import org.chromium.chrome.browser.ntp.NewTabPageUma; +import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.omnibox.AutocompleteController.OnSuggestionsReceivedListener; import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxResultItem; import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxSuggestionDelegate; @@ -895,7 +896,8 @@ } @LocationBarButtonType private int getLocationBarButtonToShow() { - boolean isOffline = getCurrentTab() != null && getCurrentTab().isOfflinePage(); + boolean isOffline = + getCurrentTab() != null && OfflinePageUtils.isOfflinePage(getCurrentTab()); boolean isTablet = DeviceFormFactor.isTablet(getContext()); // The navigation icon type is only applicable on tablets. While smaller form factors do @@ -1342,7 +1344,8 @@ @Override public void updateSecurityIcon(int securityLevel) { boolean isSmallDevice = !DeviceFormFactor.isTablet(getContext()); - boolean isOfflinePage = getCurrentTab() != null && getCurrentTab().isOfflinePage(); + boolean isOfflinePage = + getCurrentTab() != null && OfflinePageUtils.isOfflinePage(getCurrentTab()); int id = getSecurityIconResource(securityLevel, isSmallDevice, isOfflinePage); if (id == 0) { mSecurityButton.setImageDrawable(null); @@ -1432,7 +1435,7 @@ // Because is offline page is cleared a bit slower, we also ensure that connection security // level is NONE or HTTP_SHOW_WARNING (http://crbug.com/671453). boolean verboseStatusVisible = !mUrlHasFocus && getCurrentTab() != null - && getCurrentTab().isOfflinePage() + && OfflinePageUtils.isOfflinePage(getCurrentTab()) && (getSecurityLevel() == ConnectionSecurityLevel.NONE || getSecurityLevel() == ConnectionSecurityLevel.HTTP_SHOW_WARNING);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java index cf3cc43..c44e6f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
@@ -995,7 +995,7 @@ String offlinePageCreationDate = null; - OfflinePageItem offlinePage = tab.getOfflinePage(); + OfflinePageItem offlinePage = OfflinePageUtils.getOfflinePage(tab); if (offlinePage != null) { // Get formatted creation date of the offline page. Date creationDate = new Date(offlinePage.getCreationTimeMs());
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 0775f97..6ffe223 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
@@ -66,7 +66,6 @@ import org.chromium.chrome.browser.media.ui.MediaSessionTabHelper; import org.chromium.chrome.browser.ntp.NativePageAssassin; import org.chromium.chrome.browser.ntp.NativePageFactory; -import org.chromium.chrome.browser.offlinepages.OfflinePageItem; import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.policy.PolicyAuditor; import org.chromium.chrome.browser.prerender.ExternalPrerenderHandler; @@ -836,7 +835,7 @@ */ public void reload() { // TODO(dtrainor): Should we try to rebuild the ContentView if it's frozen? - if (isOfflinePage()) { + if (OfflinePageUtils.isOfflinePage(this)) { // If current page is an offline page, reload it with custom behavior defined in extra // header respected. OfflinePageUtils.reload(this); @@ -2661,30 +2660,6 @@ } /** - * @return True if the offline page is opened. - */ - public boolean isOfflinePage() { - return isFrozen() ? false : nativeIsOfflinePage(mNativeTabAndroid); - } - - /** - * @return The offline page if tab currently displays it, null otherwise. - */ - public OfflinePageItem getOfflinePage() { - return isFrozen() ? null : nativeGetOfflinePage(mNativeTabAndroid); - } - - /** - * Shows the list of offline pages. This should only be hit when offline pages feature is - * enabled. - */ - @CalledByNative - public void showOfflinePages() { - // TODO(jianli): This is not currently used. Figure out what to do here. - // http://crbug.com/636574 - } - - /** * @return Original url of the tab, which is the original url from DOMDistiller. */ public String getOriginalUrl() { @@ -3094,8 +3069,6 @@ long nativeTabAndroid, int constraints, int current, boolean animate); private native void nativeLoadOriginalImage(long nativeTabAndroid); private native long nativeGetBookmarkId(long nativeTabAndroid, boolean onlyEditable); - private native boolean nativeIsOfflinePage(long nativeTabAndroid); - private native OfflinePageItem nativeGetOfflinePage(long nativeTabAndroid); private native void nativeSetInterceptNavigationDelegate(long nativeTabAndroid, InterceptNavigationDelegate delegate); private native void nativeAttachToTabContentManager(long nativeTabAndroid,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java index 0e9393df..c5bae347 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
@@ -41,6 +41,7 @@ import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils; import org.chromium.chrome.browser.ntp.NativePageFactory; import org.chromium.chrome.browser.ntp.NewTabPage; +import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.omnibox.LocationBar; import org.chromium.chrome.browser.omnibox.LocationBarLayout; import org.chromium.chrome.browser.omnibox.UrlBar; @@ -467,7 +468,8 @@ mSecurityIconType = securityLevel; boolean isSmallDevice = !DeviceFormFactor.isTablet(getContext()); - boolean isOfflinePage = getCurrentTab() != null && getCurrentTab().isOfflinePage(); + boolean isOfflinePage = + getCurrentTab() != null && OfflinePageUtils.isOfflinePage(getCurrentTab()); int id = LocationBarLayout.getSecurityIconResource( securityLevel, isSmallDevice, isOfflinePage);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java index cfd52f1..4ab12eac 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
@@ -115,7 +115,7 @@ displayText = DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl); } - } else if (mTab.isOfflinePage() + } else if (OfflinePageUtils.isOfflinePage(mTab) && mTab.getSecurityLevel() == ConnectionSecurityLevel.NONE) { String originalUrl = mTab.getOriginalUrl(); displayText = OfflinePageUtils.stripSchemeFromOnlineUrl(
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 1160091..e948a05 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2946,6 +2946,9 @@ <message name="IDS_IPH_DOWNLOAD_PAGE_FOR_OFFLINE_USAGE_TEXT" desc="The in-product-help message after a successful navigation prompting user to download the pages to view offline."> Download pages to use them offline </message> + <message name="IDS_IPH_DOWNLOAD_HOME_TEXT" desc="The in-product-help message to open download home after a restart."> + Find your files and pages in Downloads + </message> <!-- Search Widget strings --> <message name="IDS_SEARCH_WIDGET_DEFAULT" desc="Default text for the search widget">
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java index efa5df22..0441146 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java
@@ -26,8 +26,8 @@ import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.PrerenderTestHelper; import org.chromium.content.browser.BindingManager; -import org.chromium.content.browser.ChildProcessConnection; import org.chromium.content.browser.ChildProcessLauncher; +import org.chromium.content.browser.ManagedChildProcessConnection; import org.chromium.content.browser.test.ChildProcessAllocatorSettings; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; @@ -99,7 +99,7 @@ } @Override - public void addNewConnection(int pid, ChildProcessConnection connection) { + public void addNewConnection(int pid, ManagedChildProcessConnection connection) { synchronized (mVisibilityCallsMap) { mVisibilityCallsMap.put(pid, ""); } @@ -132,12 +132,7 @@ public void onBroughtToForeground() {} @Override - public boolean isOomProtected(int pid) { - return false; - } - - @Override - public void clearConnection(int pid) {} + public void removeConnection(int pid) {} @Override public void startModerateBindingManagement(Context context, int maxSize) {}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java index 42ae2e9a..6283b75 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java
@@ -169,7 +169,7 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - isOffline[0] = tab.isOfflinePage(); + isOffline[0] = OfflinePageUtils.isOfflinePage(tab); } }); return isOffline[0];
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java index 6eb6186..a901d25 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java
@@ -62,6 +62,7 @@ doReturn(false).when(observer).isShowingOfflinePreview(any(Tab.class)); // TODO(fgorski): This call has to be mocked out until we update OfflinePageUtils. doNothing().when(observer).showReloadSnackbar(any(Tab.class)); + doReturn(true).when(observer).isOfflinePage(any(Tab.class)); // Assert tab model observer was created. assertTrue(observer.getTabModelObserver() != null); return observer; @@ -76,7 +77,6 @@ doReturn(TAB_ID).when(mTab).getId(); doReturn(false).when(mTab).isFrozen(); doReturn(false).when(mTab).isHidden(); - doReturn(true).when(mTab).isOfflinePage(); doReturn(mActivity).when(mTab).getActivity(); // Setting up mock snackbar manager. @@ -130,14 +130,14 @@ public void testStartObservingTab() { OfflinePageTabObserver observer = createObserver(); - doReturn(false).when(mTab).isOfflinePage(); + doReturn(false).when(observer).isOfflinePage(any(Tab.class)); observer.startObservingTab(mTab); assertFalse(observer.isObservingNetworkChanges()); assertFalse(observer.isObservingTab(mTab)); verify(observer, times(0)).showReloadSnackbar(any(Tab.class)); - doReturn(true).when(mTab).isOfflinePage(); + doReturn(true).when(observer).isOfflinePage(any(Tab.class)); observer.startObservingTab(mTab); assertTrue(observer.isObservingNetworkChanges()); @@ -400,7 +400,7 @@ verify(mSnackbarManager, times(1)).dismissSnackbars(eq(mSnackbarController)); // URL updated and tab no longer shows offline page. - doReturn(false).when(mTab).isOfflinePage(); + doReturn(false).when(observer).isOfflinePage(any(Tab.class)); observer.onUrlUpdated(mTab); assertFalse(observer.isObservingTab(mTab)); @@ -432,7 +432,7 @@ observer.onPageLoadFinished(mTab); // URL updated and tab no longer shows offline page. - doReturn(false).when(mTab).isOfflinePage(); + doReturn(false).when(observer).isOfflinePage(any(Tab.class)); observer.onUrlUpdated(mTab); assertFalse(observer.isObservingTab(mTab));
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 8658bd43..9403dab 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6854,12 +6854,6 @@ <message name="IDS_PRINT_PREVIEW_OFFLINE" desc="Shown when printer is currently offline."> Currently offline </message> - <message name="IDS_PRINT_PREVIEW_FEDEX_TOS" desc="Terms-of-service for using the FedEx Office printer."> - By printing to FedEx Office, you accept their <ph name="START_LINK">$1</ph>terms of use<ph name="END_LINK">$2</ph>. - </message> - <message name="IDS_PRINT_PREVIEW_TOS_CHECKBOX_LABEL" desc="Label of the terms-of-service agreement checkbox."> - I agree - </message> <message name="IDS_PRINT_PREVIEW_NO_DESTS_PROMO_TITLE" desc="Title of promotion shown when user has no Google Cloud Print printers."> Add Printers </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index ae72f49f..2d402198 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -10,7 +10,7 @@ import("//chrome/common/features.gni") import("//components/os_crypt/features.gni") import("//components/spellcheck/spellcheck_build_features.gni") -import("//device/vr/features.gni") +import("//device/vr/features/features.gni") import("//extensions/features/features.gni") import("//media/media_options.gni") import("//net/features.gni") @@ -1608,7 +1608,7 @@ "//device/power_save_blocker", "//device/usb/mojo", "//device/usb/public/interfaces", - "//device/vr:features", + "//device/vr/features", "//extensions/features", "//gin:gin_features", "//google_apis",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index ca33be37..cb576af5 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -22,7 +22,7 @@ "+device/media_transfer_protocol", "+device/power_save_blocker", "+device/usb", - "+device/vr/features.h", + "+device/vr/features/features.h", "+extensions/browser", "+extensions/common", "+extensions/components/javascript_dialog_extensions_client",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index f0f52cf1..8b843be 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -76,7 +76,7 @@ #include "content/public/common/feature_h264_with_openh264_ffmpeg.h" #include "content/public/common/features.h" #include "device/base/features.h" -#include "device/vr/features.h" +#include "device/vr/features/features.h" #include "extensions/features/features.h" #include "gin/public/gin_features.h" #include "gpu/config/gpu_switches.h" @@ -706,6 +706,21 @@ }; #endif // !defined(OS_ANDROID) +const FeatureEntry::Choice kAutoplayPolicyChoices[] = { + {flags_ui::kGenericExperimentChoiceDefault, "", ""}, + {flag_descriptions::kAutoplayPolicyNoUserGestureRequired, + switches::kAutoplayPolicy, + switches::autoplay::kNoUserGestureRequiredPolicy}, +#if defined(OS_ANDROID) + {flag_descriptions::kAutoplayPolicyUserGestureRequired, + switches::kAutoplayPolicy, switches::autoplay::kUserGestureRequiredPolicy}, +#else + {flag_descriptions::kAutoplayPolicyCrossOriginUserGestureRequired, + switches::kAutoplayPolicy, + switches::autoplay::kCrossOriginUserGestureRequiredPolicy}, +#endif +}; + const FeatureEntry::FeatureParam kNoStatePrefetchEnabled[] = { {prerender::kNoStatePrefetchFeatureModeParameterName, prerender::kNoStatePrefetchFeatureModeParameterPrefetch}}; @@ -1437,15 +1452,6 @@ flag_descriptions::kGestureRequirementForMediaPlaybackDescription, kOsAll, SINGLE_DISABLE_VALUE_TYPE( switches::kDisableGestureRequirementForMediaPlayback)}, -#if !defined(OS_ANDROID) - {"cross-origin-media-playback-requires-user-gesture", - flag_descriptions::kCrossOriginMediaPlaybackRequiresUserGestureName, - flag_descriptions::kCrossOriginMediaPlaybackRequiresUserGestureDescription, - kOsDesktop, - FEATURE_VALUE_TYPE( - features::kCrossOriginMediaPlaybackRequiresUserGesture)}, -#endif // !defined(OS_ANDROID) - #if defined(OS_CHROMEOS) {"enable-virtual-keyboard", flag_descriptions::kVirtualKeyboardName, flag_descriptions::kVirtualKeyboardDescription, kOsCrOS, @@ -2763,6 +2769,10 @@ FEATURE_VALUE_TYPE(omnibox::kEnableClipboardProvider)}, #endif + {"autoplay-policy", flag_descriptions::kAutoplayPolicyName, + flag_descriptions::kAutoplayPolicyDescription, kOsAll, + MULTI_VALUE_TYPE(kAutoplayPolicyChoices)}, + // NOTE: Adding new command-line switches requires adding corresponding // entries to enum "LoginCustomFlags" in histograms.xml. See note in // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/DEPS b/chrome/browser/android/DEPS index 9da1a1a6..bb55a8c 100644 --- a/chrome/browser/android/DEPS +++ b/chrome/browser/android/DEPS
@@ -9,7 +9,7 @@ "+components/sync/test/fake_server/android", "+components/toolbar", "+components/web_contents_delegate_android", - "+device/vr/features.h", + "+device/vr/features/features.h", "+sandbox/linux/seccomp-bpf/sandbox_bpf.h", "+sandbox/sandbox_features.h", "+third_party/gvr-android-sdk",
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 9017b02..cdd7a13 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -190,7 +190,7 @@ #include "components/url_formatter/android/component_jni_registrar.h" #include "components/variations/android/component_jni_registrar.h" #include "components/web_contents_delegate_android/component_jni_registrar.h" -#include "device/vr/features.h" +#include "device/vr/features/features.h" #include "printing/features/features.h" #if BUILDFLAG(ENABLE_PRINTING) && !BUILDFLAG(ENABLE_PRINT_PREVIEW)
diff --git a/chrome/browser/android/offline_pages/offline_page_bridge.cc b/chrome/browser/android/offline_pages/offline_page_bridge.cc index 9819635..6f1dbe7 100644 --- a/chrome/browser/android/offline_pages/offline_page_bridge.cc +++ b/chrome/browser/android/offline_pages/offline_page_bridge.cc
@@ -631,6 +631,30 @@ static_cast<OfflinePageUtils::DownloadUIActionFlags>(ui_action)); } +jboolean OfflinePageBridge::IsOfflinePage( + JNIEnv* env, + const JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jobject>& j_web_contents) { + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(j_web_contents); + return offline_pages::OfflinePageUtils::GetOfflinePageFromWebContents( + web_contents) != nullptr; +} + +ScopedJavaLocalRef<jobject> OfflinePageBridge::GetOfflinePage( + JNIEnv* env, + const JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jobject>& j_web_contents) { + const offline_pages::OfflinePageItem* offline_page = + offline_pages::OfflinePageUtils::GetOfflinePageFromWebContents( + content::WebContents::FromJavaWebContents(j_web_contents)); + if (!offline_page) + return ScopedJavaLocalRef<jobject>(); + + return offline_pages::android::OfflinePageBridge::ConvertToJavaOfflinePage( + env, *offline_page); +} + void OfflinePageBridge::NotifyIfDoneLoading() const { if (!offline_page_model_->is_loaded()) return;
diff --git a/chrome/browser/android/offline_pages/offline_page_bridge.h b/chrome/browser/android/offline_pages/offline_page_bridge.h index c6a8b62..db898dfb 100644 --- a/chrome/browser/android/offline_pages/offline_page_bridge.h +++ b/chrome/browser/android/offline_pages/offline_page_bridge.h
@@ -144,6 +144,16 @@ base::android::ScopedJavaGlobalRef<jobject> java_ref() { return java_ref_; } + jboolean IsOfflinePage( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jobject>& j_web_contents); + + base::android::ScopedJavaLocalRef<jobject> GetOfflinePage( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jobject>& j_web_contents); + private: void NotifyIfDoneLoading() const;
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index e41f85a..0d71514 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc
@@ -15,9 +15,6 @@ #include "cc/layers/layer.h" #include "chrome/browser/android/compositor/tab_content_manager.h" #include "chrome/browser/android/metrics/uma_utils.h" -#include "chrome/browser/android/offline_pages/offline_page_bridge.h" -#include "chrome/browser/android/offline_pages/offline_page_model_factory.h" -#include "chrome/browser/android/offline_pages/offline_page_utils.h" #include "chrome/browser/android/tab_web_contents_delegate_android.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h" @@ -57,9 +54,6 @@ #include "components/favicon/content/content_favicon_driver.h" #include "components/navigation_interception/intercept_navigation_delegate.h" #include "components/navigation_interception/navigation_params.h" -#include "components/offline_pages/core/offline_page_feature.h" -#include "components/offline_pages/core/offline_page_item.h" -#include "components/offline_pages/core/offline_page_model.h" #include "components/sessions/content/content_live_tab.h" #include "components/sessions/core/tab_restore_service.h" #include "components/url_formatter/url_fixer.h" @@ -695,30 +689,6 @@ return -1; } -void TabAndroid::ShowOfflinePages() { - JNIEnv* env = base::android::AttachCurrentThread(); - Java_Tab_showOfflinePages(env, weak_java_tab_.get(env)); -} - -jboolean TabAndroid::IsOfflinePage(JNIEnv* env, - const JavaParamRef<jobject>& obj) { - return offline_pages::OfflinePageUtils::GetOfflinePageFromWebContents( - web_contents()) != nullptr; -} - -ScopedJavaLocalRef<jobject> TabAndroid::GetOfflinePage( - JNIEnv* env, - const JavaParamRef<jobject>& obj) { - const offline_pages::OfflinePageItem* offline_page = - offline_pages::OfflinePageUtils::GetOfflinePageFromWebContents( - web_contents()); - if (!offline_page) - return ScopedJavaLocalRef<jobject>(); - - return offline_pages::android::OfflinePageBridge::ConvertToJavaOfflinePage( - env, *offline_page); -} - bool TabAndroid::HasPrerenderedUrl(JNIEnv* env, const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& url) {
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h index dea06a6..1e3e4a8a 100644 --- a/chrome/browser/android/tab_android.h +++ b/chrome/browser/android/tab_android.h
@@ -117,8 +117,6 @@ bool HasPrerenderedUrl(GURL gurl); - void ShowOfflinePages(); - // Overridden from CoreTabHelperDelegate: void SwapTabContents(content::WebContents* old_contents, content::WebContents* new_contents, @@ -212,16 +210,6 @@ const base::android::JavaParamRef<jobject>& obj, jboolean only_editable); - jboolean HasOfflineCopy(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - - jboolean IsOfflinePage(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - - base::android::ScopedJavaLocalRef<jobject> GetOfflinePage( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - void SetInterceptNavigationDelegate( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/android/vr_shell/BUILD.gn b/chrome/browser/android/vr_shell/BUILD.gn index 5c9e0f87..dc166f9 100644 --- a/chrome/browser/android/vr_shell/BUILD.gn +++ b/chrome/browser/android/vr_shell/BUILD.gn
@@ -4,7 +4,7 @@ import("//build/config/android/rules.gni") import("//chrome/common/features.gni") -import("//device/vr/features.gni") +import("//device/vr/features/features.gni") import("//testing/test.gni") assert(enable_vr)
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc index 4bfebfb2..431f3a5 100644 --- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/test_timeouts.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" @@ -56,6 +57,51 @@ using guest_view::TestGuestViewManager; using guest_view::TestGuestViewManagerFactory; +#if defined(OS_MACOSX) +// The original TextInputClientMessageFilter is added during the initialization +// phase of RenderProcessHost. The only chance we have to add the test filter +// (so that it can receive the TextInputClientMac incoming IPC messages) is +// during the call to RenderProcessWillLaunch() on ContentBrowserClient. This +// class provides that for testing. The class also replaces the current client +// and will reset the client back to the original one upon destruction. +class BrowserClientForTextInputClientMac : public ChromeContentBrowserClient { + public: + BrowserClientForTextInputClientMac() + : old_client_(content::SetBrowserClientForTesting(this)) {} + ~BrowserClientForTextInputClientMac() override { + content::SetBrowserClientForTesting(old_client_); + } + + // ContentBrowserClient overrides. + void RenderProcessWillLaunch( + content::RenderProcessHost* process_host) override { + ChromeContentBrowserClient::RenderProcessWillLaunch(process_host); + filters_.push_back( + new content::TestTextInputClientMessageFilter(process_host)); + } + + // Retrieves the registered filter for the given RenderProcessHost. It will + // return false if the RenderProcessHost was initialized while a different + // instance of ContentBrowserClient was in action. + scoped_refptr<content::TestTextInputClientMessageFilter> + GetTextInputClientMessageFilterForProcess( + content::RenderProcessHost* process_host) const { + for (auto filter : filters_) { + if (filter->process() == process_host) + return filter; + } + return nullptr; + } + + private: + content::ContentBrowserClient* old_client_; + std::vector<scoped_refptr<content::TestTextInputClientMessageFilter>> + filters_; + + DISALLOW_COPY_AND_ASSIGN(BrowserClientForTextInputClientMac); +}; +#endif // OS_MACOSX + class WebViewInteractiveTestBase : public extensions::PlatformAppBrowserTest { public: WebViewInteractiveTestBase() @@ -1363,6 +1409,37 @@ ASSERT_TRUE(selected_text.size() >= 10u); ASSERT_EQ("AAAAAAAAAA", selected_text.substr(0, 10)); } + +// Verifies that asking for a word lookup from a guest will lead to a returned +// IPC from the renderer containing the right selected word. +IN_PROC_BROWSER_TEST_P(WebViewInteractiveTest, WordLookup) { + // BrowserClientForTextInputClientMac needs to replace the + // ChromeContentBrowserClient after most things are initialized but before the + // WebContents is created. + BrowserClientForTextInputClientMac browser_client; + + SetupTest("web_view/text_selection", + "/extensions/platform_apps/web_view/text_selection/guest.html"); + ASSERT_TRUE(guest_web_contents()); + ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(GetPlatformAppWindow())); + + auto guest_message_filter = + browser_client.GetTextInputClientMessageFilterForProcess( + guest_web_contents()->GetRenderProcessHost()); + ASSERT_TRUE(guest_message_filter); + + // Lookup some string through context menu. + ContextMenuNotificationObserver menu_observer(IDC_CONTENT_CONTEXT_LOOK_UP); + // Simulating a mouse click at a position to highlight text in guest and + // showing the context menu. + SimulateRWHMouseClick(guest_web_contents()->GetRenderViewHost()->GetWidget(), + blink::WebMouseEvent::Button::kRight, 20, 20); + // Wait for the response form the guest renderer. + guest_message_filter->WaitForStringFromRange(); + + // Sanity check. + ASSERT_EQ("AAAA", guest_message_filter->string_from_range().substr(0, 4)); +} #endif IN_PROC_BROWSER_TEST_P(WebViewFocusInteractiveTest, FocusAndVisibility) {
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 20b9634..499d61d 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -434,8 +434,6 @@ file="resources\print_preview\images\pdf.png" type="BINDATA" /> <include name="IDR_PRINT_PREVIEW_IMAGES_THIRD_PARTY" file="resources\print_preview\images\third_party.png" type="BINDATA" /> - <include name="IDR_PRINT_PREVIEW_IMAGES_THIRD_PARTY_FEDEX" - file="resources\print_preview\images\third_party_fedex.png" type="BINDATA" /> <include name="IDR_PRINT_PREVIEW_IMAGES_MOBILE" file="resources\print_preview\images\mobile.png" type="BINDATA" /> <include name="IDR_PRINT_PREVIEW_IMAGES_MOBILE_SHARED"
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 04b8048..7fdd922 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -660,17 +660,6 @@ "User gesture requirement for playing media elements. Disabling this " "will allow autoplay to work."; -#if !defined(OS_ANDROID) - -const char kCrossOriginMediaPlaybackRequiresUserGestureName[] = - "Media playback in cross-origin iframes requires user gesture"; - -const char kCrossOriginMediaPlaybackRequiresUserGestureDescription[] = - "Playing media elements in cross-origin iframes requires user gesture. " - "Disabling this will allow autoplay in cross-origin iframes to work."; - -#endif // !defined(OS_ANDROID) - const char kPassiveDocumentEventListenersDescription[] = "Forces touchstart, and touchmove event listeners on document level " "targets (which haven't requested otherwise) to be treated as passive."; @@ -3053,4 +3042,17 @@ #endif // defined(OS_ANDROID) +const char kAutoplayPolicyName[] = "Autoplay policy"; + +const char kAutoplayPolicyDescription[] = + "Policy used when deciding if audio or video is allowed to autoplay."; + +const char kAutoplayPolicyNoUserGestureRequired[] = + "No user gesture is required."; + +const char kAutoplayPolicyUserGestureRequired[] = "User gesture is required."; + +const char kAutoplayPolicyCrossOriginUserGestureRequired[] = + "User gesture is required for cross-origin iframes."; + } // namespace flag_descriptions
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index cc6bedd..2eeb915 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -721,16 +721,6 @@ // Description for the flag for gesture requiment for media playback extern const char kGestureRequirementForMediaPlaybackDescription[]; -#if !defined(OS_ANDROID) - -// Title for the flag for gesture requiment for media playback -extern const char kCrossOriginMediaPlaybackRequiresUserGestureName[]; - -// Description for the flag for gesture requiment for media playback -extern const char kCrossOriginMediaPlaybackRequiresUserGestureDescription[]; - -#endif // !defined(OS_ANDROID) - // Description for the flag to adjust the default behaviour for document level // passive touch listeners. extern const char kPassiveDocumentEventListenersDescription[]; @@ -3320,6 +3310,22 @@ #endif // defined(OS_ANDROID) +// Name of the autoplay policy flag. +extern const char kAutoplayPolicyName[]; + +// Description of the autoplay policy entry. +extern const char kAutoplayPolicyDescription[]; + +// Description of the autoplay policy that requires a user gesture on cross +// origin iframes. +extern const char kAutoplayPolicyCrossOriginUserGestureRequired[]; + +// Description of the autoplay policy that has no user gesture requirements. +extern const char kAutoplayPolicyNoUserGestureRequired[]; + +// Description of the autoplay policy that requires a user gesture. +extern const char kAutoplayPolicyUserGestureRequired[]; + } // namespace flag_descriptions #endif // CHROME_BROWSER_FLAG_DESCRIPTIONS_H_
diff --git a/chrome/browser/memory_details_mac.cc b/chrome/browser/memory_details_mac.cc index 36b77ff..2a7292f8 100644 --- a/chrome/browser/memory_details_mac.cc +++ b/chrome/browser/memory_details_mac.cc
@@ -62,7 +62,7 @@ base::ProcessMetrics::CreateProcessMetrics( pid, content::BrowserChildProcessHost::GetPortProvider()); metrics->GetCommittedAndWorkingSetKBytes(&info.committed, &info.working_set); - info.phys_footprint = metrics->GetPhysicalFootprint(); + info.phys_footprint = metrics->GetTaskVMInfo().phys_footprint; processes->push_back(info); }
diff --git a/chrome/browser/resources/md_bookmarks/shared_style.html b/chrome/browser/resources/md_bookmarks/shared_style.html index f242649..c8d75709 100644 --- a/chrome/browser/resources/md_bookmarks/shared_style.html +++ b/chrome/browser/resources/md_bookmarks/shared_style.html
@@ -1,12 +1,9 @@ <link rel="import" href="chrome://bookmarks/shared_vars.html"> +<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <dom-module id="shared-style"> <template> - <style> - [hidden] { - display: none !important; - } - + <style include="cr-hidden-style"> button.more-vert-button { height: 36px; padding: 8px;
diff --git a/chrome/browser/resources/md_downloads/item.html b/chrome/browser/resources/md_downloads/item.html index f057735..c4ed060 100644 --- a/chrome/browser/resources/md_downloads/item.html +++ b/chrome/browser/resources/md_downloads/item.html
@@ -1,4 +1,5 @@ <link rel="import" href="chrome://resources/cr_elements/icons.html"> +<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/html/action_link.html"> <link rel="import" href="chrome://resources/html/action_link_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> @@ -16,16 +17,12 @@ <dom-module id="downloads-item"> <template> - <style include="action-link"> + <style include="action-link cr-hidden-style"> :host { display: flex; flex-direction: column; } - [hidden] { - display: none !important; - } - paper-button { font-weight: 500; margin: 0;
diff --git a/chrome/browser/resources/md_downloads/manager.html b/chrome/browser/resources/md_downloads/manager.html index 34aa9e9..736d9d1 100644 --- a/chrome/browser/resources/md_downloads/manager.html +++ b/chrome/browser/resources/md_downloads/manager.html
@@ -1,3 +1,4 @@ +<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/cr/ui.html"> <link rel="import" href="chrome://resources/html/cr/ui/command.html"> @@ -13,7 +14,7 @@ <dom-module id="downloads-manager"> <template> - <style> + <style include="cr-hidden-style"> :host { display: flex; flex: 1 0; @@ -22,10 +23,6 @@ z-index: 0; } - [hidden] { - display: none !important; - } - @media screen and (max-width: 1024px) { :host { flex-basis: calc(
diff --git a/chrome/browser/resources/md_downloads/toolbar.html b/chrome/browser/resources/md_downloads/toolbar.html index bda557e..2b6bca652 100644 --- a/chrome/browser/resources/md_downloads/toolbar.html +++ b/chrome/browser/resources/md_downloads/toolbar.html
@@ -1,4 +1,5 @@ <link rel="import" href="chrome://downloads/action_service.html"> +<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/polymer.html"> @@ -12,7 +13,7 @@ <dom-module id="downloads-toolbar"> <template> - <style> + <style include="cr-hidden-style"> :host { align-items: center; background: var(--google-blue-700); @@ -21,10 +22,6 @@ min-height: 56px; } - [hidden] { - display: none !important; - } - #toolbar { --cr-toolbar-field-width: var(--downloads-card-width); flex: 1;
diff --git a/chrome/browser/resources/md_history/shared_style.html b/chrome/browser/resources/md_history/shared_style.html index f561acc..d428ea27 100644 --- a/chrome/browser/resources/md_history/shared_style.html +++ b/chrome/browser/resources/md_history/shared_style.html
@@ -1,12 +1,9 @@ <link rel="import" href="chrome://history/shared_vars.html"> +<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html"> <dom-module id="shared-style"> <template> - <style> - [hidden] { - display: none !important; - } - + <style include="cr-hidden-style"> a { color: var(--link-color); }
diff --git a/chrome/browser/resources/print_preview/cloud_print_interface.js b/chrome/browser/resources/print_preview/cloud_print_interface.js index abf3b96..e6c36722 100644 --- a/chrome/browser/resources/print_preview/cloud_print_interface.js +++ b/chrome/browser/resources/print_preview/cloud_print_interface.js
@@ -105,8 +105,6 @@ SEARCH_FAILED: 'cloudprint.CloudPrintInterface.SEARCH_FAILED', SUBMIT_DONE: 'cloudprint.CloudPrintInterface.SUBMIT_DONE', SUBMIT_FAILED: 'cloudprint.CloudPrintInterface.SUBMIT_FAILED', - UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED: - 'cloudprint.CloudPrintInterface.UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED' }; /** @@ -339,27 +337,6 @@ }, /** - * Sends a Google Cloud Print update API request to accept (or reject) the - * terms-of-service of the given printer. - * @param {!print_preview.Destination} destination Destination to accept ToS - * for. - * @param {boolean} isAccepted Whether the user accepted ToS or not. - */ - updatePrinterTosAcceptance: function(destination, isAccepted) { - var params = [ - new HttpParam('printerid', destination.id), - new HttpParam('is_tos_accepted', isAccepted) - ]; - this.sendOrQueueRequest_(this.buildRequest_( - 'POST', - 'update', - params, - destination.origin, - destination.account, - this.onUpdatePrinterTosAcceptanceDone_.bind(this))); - }, - - /** * Adds event listeners to relevant events. * @private */ @@ -759,21 +736,6 @@ this.dispatchEvent(errorEvent); } }, - - /** - * Called when the update printer TOS acceptance request completes. - * @param {!CloudPrintRequest} request Request that has been completed. - * @private - */ - onUpdatePrinterTosAcceptanceDone_: function(request) { - if (request.xhr.status == 200 && request.result['success']) { - // Do nothing. - } else { - var errorEvent = this.createErrorEvent_( - CloudPrintInterface.EventType.SUBMIT_FAILED, request); - this.dispatchEvent(errorEvent); - } - } }; /**
diff --git a/chrome/browser/resources/print_preview/data/cloud_parsers.js b/chrome/browser/resources/print_preview/data/cloud_parsers.js index d4d032e4..dc6236a 100644 --- a/chrome/browser/resources/print_preview/data/cloud_parsers.js +++ b/chrome/browser/resources/print_preview/data/cloud_parsers.js
@@ -19,7 +19,6 @@ DESCRIPTION: 'description', DISPLAY_NAME: 'displayName', ID: 'id', - IS_TOS_ACCEPTED: 'isTosAccepted', LAST_ACCESS: 'accessTime', TAGS: 'tags', TYPE: 'type' @@ -80,8 +79,6 @@ isOwned: arrayContains(tags, CloudDestinationParser.OWNED_TAG_), lastAccessTime: parseInt( json[CloudDestinationParser.Field_.LAST_ACCESS], 10) || Date.now(), - isTosAccepted: (id == print_preview.Destination.GooglePromotedId.FEDEX) ? - json[CloudDestinationParser.Field_.IS_TOS_ACCEPTED] : null, cloudID: id, description: json[CloudDestinationParser.Field_.DESCRIPTION] };
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js index 8eaa24f..5584e70 100644 --- a/chrome/browser/resources/print_preview/data/destination.js +++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -53,7 +53,6 @@ * isEnterprisePrinter: (boolean|undefined), * account: (string|undefined), * lastAccessTime: (number|undefined), - * isTosAccepted: (boolean|undefined), * cloudID: (string|undefined), * provisionalType: * (print_preview.Destination.ProvisionalType|undefined), @@ -153,14 +152,6 @@ Date.now(); /** - * Whether the user has accepted the terms-of-service for the print - * destination. Only applies to the FedEx Office cloud-based printer. - * {@code null} if terms-of-service does not apply to the print destination. - * @private {?boolean} - */ - this.isTosAccepted_ = !!(opt_params && opt_params.isTosAccepted); - - /** * Cloud ID for Privet printers. * @private {string} */ @@ -212,7 +203,6 @@ */ Destination.GooglePromotedId = { DOCS: '__google__docs', - FEDEX: '__google__fedex', SAVE_AS_PDF: 'Save as PDF' }; @@ -282,7 +272,6 @@ THIRD_PARTY: 'images/third_party.png', PDF: 'images/pdf.png', DOCS: 'images/google_doc.png', - FEDEX: 'images/third_party_fedex.png', ENTERPRISE: 'images/business.svg' }; @@ -391,8 +380,7 @@ * destination. */ get hint() { - if (this.id_ == Destination.GooglePromotedId.DOCS || - this.id_ == Destination.GooglePromotedId.FEDEX) { + if (this.id_ == Destination.GooglePromotedId.DOCS) { return this.account_; } return this.location || this.extensionName || this.description; @@ -492,9 +480,6 @@ if (this.id_ == Destination.GooglePromotedId.DOCS) { return Destination.IconUrl_.DOCS; } - if (this.id_ == Destination.GooglePromotedId.FEDEX) { - return Destination.IconUrl_.FEDEX; - } if (this.id_ == Destination.GooglePromotedId.SAVE_AS_PDF) { return Destination.IconUrl_.PDF; } @@ -517,24 +502,6 @@ }, /** - * @return {?boolean} Whether the user has accepted the terms-of-service of - * the print destination or {@code null} if a terms-of-service does not - * apply. - */ - get isTosAccepted() { - return this.isTosAccepted_; - }, - - /** - * @param {?boolean} isTosAccepted Whether the user has accepted the - * terms-of-service of the print destination or {@code null} if - * a terms-of-service does not apply. - */ - set isTosAccepted(isTosAccepted) { - this.isTosAccepted_ = isTosAccepted; - }, - - /** * @return {!Array<string>} Properties (besides display name) to match * search queries against. */
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index 34021ccf..e26fd39 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -89,8 +89,7 @@ destination.id); } return arrayContains( - [print_preview.Destination.GooglePromotedId.DOCS, - print_preview.Destination.GooglePromotedId.FEDEX], + [print_preview.Destination.GooglePromotedId.DOCS], destination.id); } }; @@ -1025,8 +1024,7 @@ // TODO: Move the logic to print_preview. return this.destinations_.every(function(dest) { return dest.isLocal || - dest.id == print_preview.Destination.GooglePromotedId.DOCS || - dest.id == print_preview.Destination.GooglePromotedId.FEDEX; + dest.id == print_preview.Destination.GooglePromotedId.DOCS; }); }, @@ -1056,13 +1054,6 @@ // Update and persist selected destination. this.selectedDestination_ = destination; this.selectedDestination_.isRecent = true; - if (destination.id == print_preview.Destination.GooglePromotedId.FEDEX && - !destination.isTosAccepted) { - assert(this.cloudPrintInterface_ != null, - 'Selected FedEx destination, but GCP API is not available'); - destination.isTosAccepted = true; - this.cloudPrintInterface_.updatePrinterTosAcceptance(destination, true); - } this.appState_.persistSelectedDestination(this.selectedDestination_); // Adjust metrics. if (destination.cloudID &&
diff --git a/chrome/browser/resources/print_preview/data/ticket_items/color.js b/chrome/browser/resources/print_preview/data/ticket_items/color.js index b1cbe38..2740501 100644 --- a/chrome/browser/resources/print_preview/data/ticket_items/color.js +++ b/chrome/browser/resources/print_preview/data/ticket_items/color.js
@@ -105,7 +105,6 @@ var dest = this.getSelectedDestInternal(); if (dest) { if (dest.id == print_preview.Destination.GooglePromotedId.DOCS || - dest.id == print_preview.Destination.GooglePromotedId.FEDEX || dest.type == print_preview.Destination.Type.MOBILE) { return true; }
diff --git a/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js b/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js index f48948c6..af17ce0 100644 --- a/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js +++ b/chrome/browser/resources/print_preview/data/ticket_items/vendor_items.js
@@ -66,8 +66,7 @@ this.destinationStore_.selectedDestination : null; if (!destination) return null; - if (destination.id == print_preview.Destination.GooglePromotedId.FEDEX || - destination.type == print_preview.Destination.Type.MOBILE) { + if (destination.type == print_preview.Destination.Type.MOBILE) { return null; } return (destination.capabilities &&
diff --git a/chrome/browser/resources/print_preview/images/third_party_fedex.png b/chrome/browser/resources/print_preview/images/third_party_fedex.png deleted file mode 100644 index 03d7da8..0000000 --- a/chrome/browser/resources/print_preview/images/third_party_fedex.png +++ /dev/null Binary files differ
diff --git a/chrome/browser/resources/print_preview/print_preview.html b/chrome/browser/resources/print_preview/print_preview.html index e32bbe93..30b3964 100644 --- a/chrome/browser/resources/print_preview/print_preview.html +++ b/chrome/browser/resources/print_preview/print_preview.html
@@ -36,7 +36,6 @@ <link rel="stylesheet" href="search/destination_list.css"> <link rel="stylesheet" href="search/destination_list_item.css"> <link rel="stylesheet" href="search/destination_search.css"> - <link rel="stylesheet" href="search/fedex_tos.css"> <link rel="stylesheet" href="search/provisional_destination_resolver.css"> <script src="chrome://resources/js/action_link.js"></script> @@ -108,7 +107,6 @@ <include src="previewarea/margin_control.html"> <include src="search/destination_list.html"> <include src="search/destination_list_item.html"> - <include src="search/fedex_tos.html"> <include src="search/provisional_destination_resolver.html"> <script src="chrome://resources/js/i18n_template.js"></script>
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js index a4b96fc..64526ba 100644 --- a/chrome/browser/resources/print_preview/print_preview.js +++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -716,11 +716,6 @@ this.cloudPrintInterface_, cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED, this.onCloudPrintError_.bind(this)); - this.tracker.add( - this.cloudPrintInterface_, - cloudprint.CloudPrintInterface.EventType. - UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED, - this.onCloudPrintError_.bind(this)); this.destinationStore_.setCloudPrintInterface(this.cloudPrintInterface_); this.invitationStore_.setCloudPrintInterface(this.cloudPrintInterface_); @@ -783,12 +778,6 @@ assert(this.uiState_ == PrintPreview.UiState_.PRINTING, 'Submited job to Google Cloud Print but not in printing state ' + this.uiState_); - if (this.destinationStore_.selectedDestination.id == - print_preview.Destination.GooglePromotedId.FEDEX) { - this.nativeLayer_.startForceOpenNewTab( - 'https://www.google.com/cloudprint/fedexcode.html?jobid=' + - event.jobId); - } this.close_(); }, @@ -799,12 +788,13 @@ * @private */ onCloudPrintError_: function(event) { + if (event.status == 0) { + return; // Ignore, the system does not have internet connectivity. + } if (event.status == 403) { if (!this.isInAppKioskMode_) { this.destinationSearch_.showCloudPrintPromo(); } - } else if (event.status == 0) { - return; // Ignore, the system does not have internet connectivity. } else { this.printHeader_.setErrorMessage(event.message); } @@ -1364,7 +1354,6 @@ // <include src="search/recent_destination_list.js"> // <include src="search/destination_list_item.js"> // <include src="search/destination_search.js"> -// <include src="search/fedex_tos.js"> // <include src="search/provisional_destination_resolver.js"> window.addEventListener('DOMContentLoaded', function() {
diff --git a/chrome/browser/resources/print_preview/search/cloud_destination_list.js b/chrome/browser/resources/print_preview/search/cloud_destination_list.js index e8c6710..71e5bc3 100644 --- a/chrome/browser/resources/print_preview/search/cloud_destination_list.js +++ b/chrome/browser/resources/print_preview/search/cloud_destination_list.js
@@ -26,18 +26,11 @@ /** @override */ updateDestinations: function(destinations) { // Change the action link from "Manage..." to "Setup..." if user only has - // Docs and FedEx printers. + // Docs printers. var docsId = print_preview.Destination.GooglePromotedId.DOCS; - var fedexId = print_preview.Destination.GooglePromotedId.FEDEX; - if ((destinations.length == 1 && destinations[0].id == docsId) || - (destinations.length == 2 && - ((destinations[0].id == docsId && destinations[1].id == fedexId) || - (destinations[0].id == fedexId && destinations[1].id == docsId)))) { - this.setActionLinkTextInternal( - loadTimeData.getString('setupCloudPrinters')); - } else { - this.setActionLinkTextInternal(loadTimeData.getString('manage')); - } + this.setActionLinkTextInternal( + destinations.length == 1 && destinations[0].id == docsId ? + 'setupCloudPrinters' : 'manage'); print_preview.DestinationList.prototype.updateDestinations.call( this, destinations); }
diff --git a/chrome/browser/resources/print_preview/search/destination_list_item.js b/chrome/browser/resources/print_preview/search/destination_list_item.js index b13dc54..20e3c2d 100644 --- a/chrome/browser/resources/print_preview/search/destination_list_item.js +++ b/chrome/browser/resources/print_preview/search/destination_list_item.js
@@ -38,14 +38,6 @@ * @private */ this.query_ = query; - - /** - * FedEx terms-of-service widget or {@code null} if this list item does not - * render the FedEx Office print destination. - * @type {print_preview.FedexTos} - * @private - */ - this.fedexTos_ = null; }; /** @@ -284,20 +276,8 @@ * @private */ onDestinationActivated_: function() { - if (this.destination_.id == - print_preview.Destination.GooglePromotedId.FEDEX && - !this.destination_.isTosAccepted) { - if (!this.fedexTos_) { - this.fedexTos_ = new print_preview.FedexTos(); - this.fedexTos_.render(this.getElement()); - this.tracker.add( - this.fedexTos_, - print_preview.FedexTos.EventType.AGREE, - this.onTosAgree_.bind(this)); - } - this.fedexTos_.setIsVisible(true); - } else if (this.destination_.connectionStatus != - print_preview.Destination.ConnectionStatus.UNREGISTERED) { + if (this.destination_.connectionStatus != + print_preview.Destination.ConnectionStatus.UNREGISTERED) { var selectEvt = new Event(DestinationListItem.EventType.SELECT); selectEvt.destination = this.destination_; this.eventTarget_.dispatchEvent(selectEvt); @@ -325,17 +305,6 @@ }, /** - * Called when the user agrees to the print destination's terms-of-service. - * Selects the print destination that was agreed to. - * @private - */ - onTosAgree_: function() { - var selectEvt = new Event(DestinationListItem.EventType.SELECT); - selectEvt.destination = this.destination_; - this.eventTarget_.dispatchEvent(selectEvt); - }, - - /** * Called when the registration promo is clicked. * @private */
diff --git a/chrome/browser/resources/print_preview/search/fedex_tos.css b/chrome/browser/resources/print_preview/search/fedex_tos.css deleted file mode 100644 index d239b69..0000000 --- a/chrome/browser/resources/print_preview/search/fedex_tos.css +++ /dev/null
@@ -1,18 +0,0 @@ -/* Copyright (c) 2012 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. */ - -.fedex-tos { - overflow: hidden; - padding: 0 36px; - text-align: center; - transition: height 300ms; -} - -.fedex-tos .tos-text { - padding: 8px 0; -} - -.fedex-tos .agreement-box { - padding-bottom: 8px; -}
diff --git a/chrome/browser/resources/print_preview/search/fedex_tos.html b/chrome/browser/resources/print_preview/search/fedex_tos.html deleted file mode 100644 index f3dcffc..0000000 --- a/chrome/browser/resources/print_preview/search/fedex_tos.html +++ /dev/null
@@ -1,12 +0,0 @@ -<div id="fedex-tos-template" class="fedex-tos" aria-hidden="false" - aria-live="polite" hidden style="height: 0;"> - <div class="height-helper"> - <div class="tos-text"></div> - <div class="agreement-box"> - <label> - <input class="agree-checkbox" type="checkbox"> - <span>$i18n{tosCheckboxLabel}</span> - </label> - </div> - </div> -</div>
diff --git a/chrome/browser/resources/print_preview/search/fedex_tos.js b/chrome/browser/resources/print_preview/search/fedex_tos.js deleted file mode 100644 index 7aa45f2..0000000 --- a/chrome/browser/resources/print_preview/search/fedex_tos.js +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright (c) 2012 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. - -cr.define('print_preview', function() { - 'use strict'; - - /** - * Widget that renders a terms-of-service agreement for using the FedEx Office - * print destination. - * @constructor - * @extends {print_preview.Component} - */ - function FedexTos() { - print_preview.Component.call(this); - }; - - /** - * Enumeration of event types dispatched by the widget. - * @enum {string} - */ - FedexTos.EventType = { - // Dispatched when the user agrees to the terms-of-service. - AGREE: 'print_preview.FedexTos.AGREE' - }; - - FedexTos.prototype = { - __proto__: print_preview.Component.prototype, - - /** @param {boolean} isVisible Whether the widget is visible. */ - setIsVisible: function(isVisible) { - if (isVisible) { - var heightHelperEl = this.getElement().querySelector('.height-helper'); - this.getElement().style.height = heightHelperEl.offsetHeight + 'px'; - } else { - this.getElement().style.height = 0; - } - }, - - /** @override */ - createDom: function() { - this.setElementInternal(this.cloneTemplateInternal('fedex-tos-template')); - var tosTextEl = this.getElement().querySelector('.tos-text'); - tosTextEl.innerHTML = loadTimeData.getStringF( - 'fedexTos', - '<a href="http://www.fedex.com/us/office/copyprint/online/' + - 'googlecloudprint/termsandconditions">', - '</a>'); - }, - - /** @override */ - enterDocument: function() { - var agreeCheckbox = this.getElement().querySelector('.agree-checkbox'); - this.tracker.add( - agreeCheckbox, 'click', this.onAgreeCheckboxClick_.bind(this)); - }, - - /** - * Called when the agree checkbox is clicked. Dispatches a AGREE event. - * @private - */ - onAgreeCheckboxClick_: function() { - cr.dispatchSimpleEvent(this, FedexTos.EventType.AGREE); - } - }; - - // Export - return { - FedexTos: FedexTos - }; -});
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html index 9a26583..10ad783 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -50,18 +50,19 @@ </if> <if expr="not chromeos"> - <div class="settings-box first two-line" on-tap="onMoreFeaturesTap_" - actionable> + <a class="settings-box first two-line inherit-color no-outline" + tabindex="-1" target="_blank" + href="https://chrome.google.com/webstore/category/collection/accessibility"> <div class="start"> $i18n{moreFeaturesLink} <div class="secondary" id="moreFeaturesSecondary"> $i18n{a11yWebStore} </div> </div> - <button class="icon-external" is="paper-icon-button-light" + <button class="icon-external" is="paper-icon-button-light" actionable aria-label="$i18n{moreFeaturesLink}" aria-describedby="moreFeaturesSecondary"></button> - </div> + </a> </if> </template>
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.js b/chrome/browser/resources/settings/a11y_page/a11y_page.js index 0bcbcbc..5f236ee 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.js +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.js
@@ -49,10 +49,4 @@ settings.navigateTo(settings.Route.MANAGE_ACCESSIBILITY); }, // </if> - - /** @private */ - onMoreFeaturesTap_: function() { - window.open( - 'https://chrome.google.com/webstore/category/collection/accessibility'); - }, });
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html index f00de249..31e0da37 100644 --- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -205,17 +205,19 @@ </div> <template is="dom-if" if="[[!isGuest_]]"> - <div class="settings-box two-line" on-tap="onMoreFeaturesTap_" actionable> + <a class="settings-box two-line inherit-color no-outline" tabindex="-1" + target="_blank" + href="https://chrome.google.com/webstore/category/collection/accessibility"> <div class="start"> $i18n{additionalFeaturesTitle} <div class="secondary" id="moreFeaturesSecondary"> $i18n{a11yWebStore} </div> </div> - <button class="icon-external" is="paper-icon-button-light" + <button class="icon-external" is="paper-icon-button-light" actionable aria-label="$i18n{additionalFeaturesTitle}" aria-describedby="moreFeaturesSecondary"></button> - </div> + </a> </template> </template> <script src="manage_a11y_page.js"></script>
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js index 84d2a77..848bd57 100644 --- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js +++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js
@@ -101,10 +101,4 @@ settings.Route.POINTERS, /* dynamicParams */ null, /* removeSearch */ true); }, - - /** @private */ - onMoreFeaturesTap_: function() { - window.open( - 'https://chrome.google.com/webstore/category/collection/accessibility'); - }, });
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index 06b4e12e..fdf0277e 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -61,7 +61,8 @@ <div class="settings-box two-line first" hidden="[[!pageVisibility.setTheme]]"> </if> - <div class="start two-line" on-tap="onThemesTap_" actionable> + <a class="start two-line inherit-color no-outline" tabindex="-1" + target="_blank" href$="[[getThemeHref_(themeUrl_)]]"> <div class="flex"> $i18n{themes} <div class="secondary" id="themesSecondary"> @@ -69,9 +70,9 @@ </div> </div> <button class="icon-external" is="paper-icon-button-light" - aria-label="$i18n{themes}" + actionable aria-label="$i18n{themes}" aria-describedby="themesSecondary"></button> - </div> + </a> <if expr="not is_linux or chromeos"> <template is="dom-if" if="[[prefs.extensions.theme.id.value]]"> <div class="secondary-action">
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chrome/browser/resources/settings/appearance_page/appearance_page.js index 5571b2d..37a6a96 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -94,6 +94,9 @@ themeSublabel_: String, /** @private */ + themeUrl_: String, + + /** @private */ useSystemTheme_: { type: Boolean, value: false, // Can only be true on Linux, but value exists everywhere. @@ -115,9 +118,6 @@ /** @private {?settings.AppearanceBrowserProxy} */ browserProxy_: null, - /** @private {string} */ - themeUrl_: '', - observers: [ 'defaultFontSizeChanged_(prefs.webkit.webprefs.default_font_size.value)', 'themeChanged_(prefs.extensions.theme.id.value, useSystemTheme_)', @@ -187,9 +187,13 @@ value - SIZE_DIFFERENCE_FIXED_STANDARD_); }, - /** @private */ - onThemesTap_: function() { - window.open(this.themeUrl_ || loadTimeData.getString('themesGalleryUrl')); + /** + * URL for either current theme or the theme gallery. + * @return {string} + * @private + */ + getThemeHref_: function() { + return this.themeUrl_ || loadTimeData.getString('themesGalleryUrl'); }, // <if expr="chromeos">
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js index 760db46b..ef74fd5 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -267,12 +267,24 @@ * @private */ getPropertiesCallback_: function(properties) { - this.networkProperties = properties; - if (!properties) { - // If |properties| is null, the network is no longer visible, close this. - console.error('Network no longer exists: ' + this.guid); + if (chrome.runtime.lastError) { + var message = chrome.runtime.lastError.message; + if (message == 'Error.InvalidNetworkGuid') { + console.error('Details page: GUID no longer exists: ' + this.guid); + } else { + console.error( + 'Unexpected networkingPrivate.getManagedProperties error: ' + + message + ' For: ' + this.guid); + } this.close_(); + return; } + if (!properties) { + console.error('No properties for: ' + this.guid); + this.close_(); + return; + } + this.networkProperties = properties; }, /**
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chrome/browser/resources/settings/internet_page/internet_subpage.js index 09126808..5ff70c3 100644 --- a/chrome/browser/resources/settings/internet_page/internet_subpage.js +++ b/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -417,11 +417,13 @@ this.networkingPrivate.startConnect(state.GUID, function() { if (chrome.runtime.lastError) { var message = chrome.runtime.lastError.message; - if (message != 'connecting') { - console.error( - 'Unexpected networkingPrivate.startConnect error: ' + message + - 'For: ' + state.GUID); + if (message == 'connecting' || message == 'connect-canceled' || + message == 'connected' || message == 'Error.InvalidNetworkGuid') { + return; } + console.error( + 'Unexpected networkingPrivate.startConnect error: ' + message + + ' For: ' + state.GUID); } }); },
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html index 9e488b3..8f7dbb5 100644 --- a/chrome/browser/resources/settings/people_page/people_page.html +++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -231,12 +231,14 @@ </if> <template is="dom-if" if="[[profileManagesSupervisedUsers_]]"> - <div id="manageSupervisedUsersContainer" class="settings-box" - on-tap="onManageSupervisedUsers_" actionable> + <a id="manageSupervisedUsersContainer" + class="settings-box inherit-color no-outline" tabindex="-1" + target="_blank" href="$i18n{supervisedUsersUrl}"> <div class="start">$i18n{manageSupervisedUsers}</div> <button class="icon-external" is="paper-icon-button-light" - aria-label="$i18n{manageSupervisedUsers}"></button> - </div> + actionable aria-label="$i18n{manageSupervisedUsers}"> + </button> + </a> </template> </neon-animatable> <template is="dom-if" route-path="/syncSetup"
diff --git a/chrome/browser/resources/settings/people_page/people_page.js b/chrome/browser/resources/settings/people_page/people_page.js index f587973..26fd9dc5 100644 --- a/chrome/browser/resources/settings/people_page/people_page.js +++ b/chrome/browser/resources/settings/people_page/people_page.js
@@ -343,11 +343,6 @@ // </if> }, - /** @private */ - onManageSupervisedUsers_: function() { - window.open(loadTimeData.getString('supervisedUsersUrl')); - }, - // <if expr="not chromeos"> /** * @private
diff --git a/chrome/browser/resources/settings/people_page/sync_browser_proxy.js b/chrome/browser/resources/settings/people_page/sync_browser_proxy.js index 1d332be..572dcb4 100644 --- a/chrome/browser/resources/settings/people_page/sync_browser_proxy.js +++ b/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
@@ -232,7 +232,6 @@ openActivityControlsUrl: function() { chrome.metricsPrivate.recordUserAction( 'Signin_AccountSettings_GoogleActivityControlsClicked'); - window.open(loadTimeData.getString('activityControlsUrl')); } };
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index 3761fa5..32bf38d 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -249,7 +249,8 @@ </div> </div> - <div class="settings-box two-line" actionable + <a class="settings-box two-line inherit-color no-outline" tabindex="-1" + target="_blank" href="$i18n{activityControlsUrl}" on-tap="onActivityControlsTap_"> <div class="start"> $i18n{personalizeGoogleServicesTitle} @@ -258,17 +259,18 @@ </div> </div> <button class="icon-external" is="paper-icon-button-light" - aria-label="$i18n{personalizeGoogleServicesTitle}" + actionable aria-label="$i18n{personalizeGoogleServicesTitle}" aria-describedby="activityControlsSecondary"></button> - </div> + </a> - <div class="settings-box" actionable on-tap="onManageSyncedDataTap_"> + <a class="settings-box inherit-color no-outline" tabindex="-1" + target="_blank" href="$i18n{syncDashboardUrl}"> <div class="start"> $i18n{manageSyncedDataTitle} </div> - <button class="icon-external" is="paper-icon-button-light" + <button class="icon-external" is="paper-icon-button-light" actionable aria-label="$i18n{manageSyncedDataTitle}"></button> - </div> + </a> <div id="encryptionDescription" hidden="[[syncPrefs.passphraseRequired]]" class="settings-box two-line single-column">
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js index ae28f92..3c99f727e 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.js +++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -269,11 +269,6 @@ this.browserProxy_.openActivityControlsUrl(); }, - /** @private */ - onManageSyncedDataTap_: function() { - window.open(loadTimeData.getString('syncDashboardUrl')); - }, - /** * Handler for when the autofill data type checkbox is changed. * @private
diff --git a/chrome/browser/resources/settings/printing_page/cloud_printers.html b/chrome/browser/resources/settings/printing_page/cloud_printers.html index d47403f..4a74eae 100644 --- a/chrome/browser/resources/settings/printing_page/cloud_printers.html +++ b/chrome/browser/resources/settings/printing_page/cloud_printers.html
@@ -20,13 +20,14 @@ label="$i18n{printingNotificationsLabel}"> </settings-toggle-button> </div> - <div class="settings-box" on-tap="onManageTap_" actionable> + <a class="settings-box inherit-color no-outline" tabindex="-1" + target="_blank" href="$i18n{devicesUrl}"> <div class="start"> $i18n{printingManageCloudPrintDevices} </div> - <button class="icon-external" is="paper-icon-button-light" + <button class="icon-external" is="paper-icon-button-light" actionable aria-label="$i18n{printingManageCloudPrintDevices}"></button> - </div> + </a> </template> <script src="cloud_printers.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/printing_page/cloud_printers.js b/chrome/browser/resources/settings/printing_page/cloud_printers.js index 3537e5d..1de17f79 100644 --- a/chrome/browser/resources/settings/printing_page/cloud_printers.js +++ b/chrome/browser/resources/settings/printing_page/cloud_printers.js
@@ -16,9 +16,4 @@ notify: true, }, }, - - /** @private */ - onManageTap_: function() { - window.open(loadTimeData.getString('devicesUrl')); - }, });
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index b6e0dce6..428ca86d 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -378,12 +378,13 @@ sub-option-secondary="$i18n{siteSettingsFlashAskBeforeSubtitle}"> </category-default-setting> <if expr="chromeos"> - <div actionable class="settings-box" - on-tap="onAdobeFlashStorageClicked_"> + <a class="settings-box inherit-color no-outline" tabindex="-1" + target="_blank" + href="https://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html"> <div class="start">$i18n{adobeFlashStorage}</div> <button class="icon-external" is="paper-icon-button-light" - aria-label="$i18n{adobeFlashStorage}"></button> - </div> + actionable aria-label="$i18n{adobeFlashStorage}"></button> + </a> </if> <category-setting-exceptions category="{{ContentSettingsTypes.PLUGINS}}">
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chrome/browser/resources/settings/privacy_page/privacy_page.js index a8ac950..5912a1b 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.js +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -246,12 +246,6 @@ }, /** @private */ - onHelpTap_: function() { - window.open( - 'https://support.google.com/chrome/?p=settings_manage_exceptions'); - }, - - /** @private */ onSberChange_: function() { var enabled = this.$.safeBrowsingExtendedReportingControl.checked; this.browserProxy_.setSafeBrowsingExtendedReportingEnabled(enabled); @@ -325,14 +319,6 @@ loadTimeData.getString('contentSettings'); }, -// <if expr="chromeos"> - /** @private */ - onAdobeFlashStorageClicked_: function() { - window.open('https://www.macromedia.com/support/' + - 'documentation/en/flashplayer/help/settings_manager07.html'); - }, -// </if> - /** @private */ getProtectedContentLabel_: function(value) { return value ? this.i18n('siteSettingsProtectedContentEnable')
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html index f19514a3..e87bb580 100644 --- a/chrome/browser/resources/settings/search_page/search_page.html +++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -106,8 +106,9 @@ </template> <template is="dom-if" if="[[hotwordInfo_.historyEnabled]]"> - <div class="settings-box two-line continuation indented" - on-tap="onManageAudioHistoryTap_" actionable> + <a class="settings-box two-line continuation indented inherit-color + no-outline" tabindex="-1" target="_blank" + href="$i18n{manageAudioHistoryUrl}"> <div class="start"> [[i18n('searchOkGoogleAudioHistoryLabel', hotwordInfo_.userName)]] @@ -115,11 +116,12 @@ $i18n{searchOkGoogleAudioHistorySubtext} </div> </div> - <button class="icon-external" is="paper-icon-button-light" + <button actionable class="icon-external" + is="paper-icon-button-light" aria-label$="[[i18n('searchOkGoogleAudioHistoryLabel', hotwordInfo_.userName)]]" aria-describedby="audioHistorySecondary"></button> - </div> + </a> </template> </template>
diff --git a/chrome/browser/resources/settings/search_page/search_page.js b/chrome/browser/resources/settings/search_page/search_page.js index a307f3d..41db7cb 100644 --- a/chrome/browser/resources/settings/search_page/search_page.js +++ b/chrome/browser/resources/settings/search_page/search_page.js
@@ -166,11 +166,6 @@ this.browserProxy_.setHotwordSearchEnabled(this.hotwordInfo_.enabled); }, - /** @private */ - onManageAudioHistoryTap_: function() { - window.open(loadTimeData.getString('manageAudioHistoryUrl')); - }, - /** * @param {Event} event * @private
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index 5204d006..1b42c64 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -5,12 +5,6 @@ <dom-module id="settings-shared"> <template> <style include="cr-shared-style"> - /* Included here so we don't have to include "iron-positioning" in every - * stylesheet. See crbug.com/498405. */ - [hidden] { - display: none !important; - } - :host-context([dir=rtl]) button[is='paper-icon-button-light'] { transform: scaleX(-1); /* Flip on the X axis (aka mirror). */ } @@ -75,8 +69,13 @@ text-decoration: none; } - /* There are three main button styles, .primary-button and - * .secondary-button. The primary is the action button (e.g. "edit", + /* For elements that are simple outlinks but dont look like anchors. */ + .inherit-color { + color: inherit !important; + } + + /* There are three main button styles, .primary-button, .secondary-button, + * and .tertiary-button. The primary is the action button (e.g. "edit", * "delete") while the secondary is often a "Cancel" button. A tertiary * button may be used to get more information or similar, that we expect * most users will not need. */
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.html b/chrome/browser/resources/settings/settings_ui/settings_ui.html index ac2d1330..a4d4207 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.html +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.html
@@ -25,7 +25,7 @@ :host { @apply(--layout-fit); -webkit-user-select: none; - color: var(--paper-grey-900); + color: var(--primary-text-color); display: flex; flex-direction: column; line-height: 154%; /* Apply 20px line-height to all texts by default. */
diff --git a/chrome/browser/resources/settings/settings_vars_css.html b/chrome/browser/resources/settings/settings_vars_css.html index 69e23ac..4a01124 100644 --- a/chrome/browser/resources/settings/settings_vars_css.html +++ b/chrome/browser/resources/settings/settings_vars_css.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/default-theme.html"> <!-- Common css variables for Material Design settings. --> <style is="custom-style">
diff --git a/chrome/browser/ui/ash/app_list/app_list_presenter_delegate_mus.cc b/chrome/browser/ui/ash/app_list/app_list_presenter_delegate_mus.cc index d82621b..1ca9e18 100644 --- a/chrome/browser/ui/ash/app_list/app_list_presenter_delegate_mus.cc +++ b/chrome/browser/ui/ash/app_list/app_list_presenter_delegate_mus.cc
@@ -64,9 +64,8 @@ // the only thing this is used for is choosing the right scale factor in // AppListMainView::PreloadIcons(), so we take care of that - perhaps by // passing the display_id or the scale factor directly - view->Initialize(nullptr /* parent */, current_apps_page); - - view->MaybeSetAnchorPoint( + view->InitAsBubble(nullptr /* parent */, current_apps_page); + view->SetAnchorPoint( GetCenterOfDisplay(display_id, GetMinimumBoundsHeightForAppList(view))); // TODO(mfomitchev): Setup updating bounds on keyboard bounds change.
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc index 25379e4..905fb90 100644 --- a/chrome/browser/ui/ash/session_controller_client.cc +++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -31,8 +31,10 @@ #include "content/public/browser/notification_service.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" +#include "mojo/public/cpp/bindings/equals_traits.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image_skia.h" using session_manager::Session; using session_manager::SessionManager; @@ -101,6 +103,20 @@ } // namespace +namespace mojo { + +// When comparing two mojom::UserSession objects we need to decide if the avatar +// images are changed. Consider them equal if they have the same storage rather +// than comparing the backing pixels. +template <> +struct EqualsTraits<gfx::ImageSkia> { + static bool Equals(const gfx::ImageSkia& a, const gfx::ImageSkia& b) { + return a.BackedBySameObjectAs(b); + } +}; + +} // namespace mojo + SessionControllerClient::SessionControllerClient() : binding_(this), weak_ptr_factory_(this) { SessionManager::Get()->AddObserver(this); @@ -392,10 +408,10 @@ if (!user_session) return; - // TODO(jamescook): Only send if it changed. This will require an Equals() - // method for gfx::ImageSkia to allow mojom::UserSession comparison. - // http://crbug.com/714689 - session_controller_->UpdateUserSession(std::move(user_session)); + if (user_session != last_sent_user_session_) { + last_sent_user_session_ = user_session->Clone(); + session_controller_->UpdateUserSession(std::move(user_session)); + } } void SessionControllerClient::SendUserSessionOrder() {
diff --git a/chrome/browser/ui/ash/session_controller_client.h b/chrome/browser/ui/ash/session_controller_client.h index 4241d84..9fffbe0 100644 --- a/chrome/browser/ui/ash/session_controller_client.h +++ b/chrome/browser/ui/ash/session_controller_client.h
@@ -95,6 +95,7 @@ static void FlushForTesting(); private: + FRIEND_TEST_ALL_PREFIXES(SessionControllerClientTest, SendUserSession); FRIEND_TEST_ALL_PREFIXES(SessionControllerClientTest, SupervisedUser); // Called when the login profile is ready. @@ -130,7 +131,9 @@ content::NotificationRegistrar registrar_; + // Used to suppress duplicate IPCs to ash. ash::mojom::SessionInfoPtr last_sent_session_info_; + ash::mojom::UserSessionPtr last_sent_user_session_; base::WeakPtrFactory<SessionControllerClient> weak_ptr_factory_;
diff --git a/chrome/browser/ui/ash/session_controller_client_unittest.cc b/chrome/browser/ui/ash/session_controller_client_unittest.cc index 1e5d0a5..2d0db44 100644 --- a/chrome/browser/ui/ash/session_controller_client_unittest.cc +++ b/chrome/browser/ui/ash/session_controller_client_unittest.cc
@@ -87,6 +87,8 @@ return last_user_session_.get(); } + int update_user_session_count() { return update_user_session_count_; } + // ash::mojom::SessionController: void SetClient(ash::mojom::SessionControllerClientPtr client) override {} void SetSessionInfo(ash::mojom::SessionInfoPtr info) override { @@ -94,6 +96,7 @@ } void UpdateUserSession(ash::mojom::UserSessionPtr user_session) override { last_user_session_ = user_session->Clone(); + update_user_session_count_++; } void SetUserSessionOrder( const std::vector<uint32_t>& user_session_order) override {} @@ -108,6 +111,7 @@ ash::mojom::SessionInfoPtr last_session_info_; ash::mojom::UserSessionPtr last_user_session_; + int update_user_session_count_ = 0; DISALLOW_COPY_AND_ASSIGN(TestSessionController); }; @@ -361,6 +365,36 @@ SessionControllerClient::GetAddUserSessionPolicy()); } +TEST_F(SessionControllerClientTest, SendUserSession) { + // Create an object to test and connect it to our test interface. + SessionControllerClient client; + TestSessionController session_controller; + client.session_controller_ = session_controller.CreateInterfacePtrAndBind(); + client.Init(); + SessionControllerClient::FlushForTesting(); + + // No user session sent yet. + EXPECT_EQ(0, session_controller.update_user_session_count()); + + // Simulate login. + const AccountId account_id(AccountId::FromUserEmail("user@test.com")); + user_manager()->AddUser(account_id); + session_manager_.CreateSession( + account_id, chromeos::ProfileHelper::GetUserIdHashByUserIdForTesting( + "user@test.com")); + SessionControllerClient::FlushForTesting(); + + // User session was sent. + EXPECT_EQ(1, session_controller.update_user_session_count()); + + // Simulate a request for an update where nothing changed. + client.SendUserSession(*user_manager()->GetLoggedInUsers()[0]); + SessionControllerClient::FlushForTesting(); + + // Session was not updated because nothing changed. + EXPECT_EQ(1, session_controller.update_user_session_count()); +} + TEST_F(SessionControllerClientTest, SupervisedUser) { // Create an object to test and connect it to our test interface. SessionControllerClient client;
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index b9df782..d7a5dd2 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -172,7 +172,7 @@ void UpdateAlertState(TabAlertState alert_state); // Returns the cocoa-world BrowserWindowController - BrowserWindowController* cocoa_controller() { return controller_; } + BrowserWindowController* cocoa_controller() const { return controller_; } // Returns window title based on the active tab title and the window's alert // state.
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 36f0ab7c..1e9353d9 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -333,10 +333,7 @@ if (!IsFullscreen()) return true; - // TODO(zijiehe): Retrieve the visibility of toolbar from - // FullscreenToolbarController. See http://crbug.com/702251 and - // http://crbug.com/680809. - return true; + return [cocoa_controller() isToolbarShowing] == YES; } void BrowserWindowCocoa::BookmarkBarStateChanged( @@ -734,13 +731,14 @@ return content::KeyboardEventProcessingResult::NOT_HANDLED; if (browser_->command_controller()->IsReservedCommandOrKey(id, event)) { + using Result = content::KeyboardEventProcessingResult; return [BrowserWindowUtils handleKeyboardEvent:event.os_event inWindow:window()] - ? content::KeyboardEventProcessingResult::HANDLED - : content::KeyboardEventProcessingResult::NOT_HANDLED; + ? Result::HANDLED + : Result::NOT_HANDLED_IS_SHORTCUT; } - return content::KeyboardEventProcessingResult::NOT_HANDLED_IS_SHORTCUT; + return content::KeyboardEventProcessingResult::NOT_HANDLED; } void BrowserWindowCocoa::HandleKeyboardEvent(
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h index d98a2b9..447add8 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.h +++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -404,6 +404,10 @@ // Invalidates the browser's touch bar. - (void)invalidateTouchBar; +// Indicates whether the toolbar is visible to the user. Toolbar is usually +// triggered by moving mouse cursor to the top of the monitor. +- (BOOL)isToolbarShowing; + @end // @interface BrowserWindowController
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 214d8ce4..7ca369af 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1919,6 +1919,10 @@ [[self window] performSelector:@selector(setTouchBar:) withObject:nil]; } +- (BOOL)isToolbarShowing { + return [fullscreenToolbarController_ mustShowFullscreenToolbar]; +} + @end // @implementation BrowserWindowController @implementation BrowserWindowController(Fullscreen)
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index 8da4f1c4..820b325 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -209,7 +209,7 @@ // Forces the opening of a new tab. |args| should consist of one element: the // URL to set the new tab to. // - // NOTE: This is needed to open FedEx confirmation window as a new tab. + // NOTE: This is needed to open register promo for Cloud Print as a new tab. // Javascript's "window.open" opens a new window popup (since initiated from // async HTTP request) and worse yet, on Windows and Chrome OS, the opened // window opens behind the initiator window.
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index af6bab18..955e77b 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -338,9 +338,6 @@ source->AddLocalizedString("offlineForWeek", IDS_PRINT_PREVIEW_OFFLINE_FOR_WEEK); source->AddLocalizedString("offline", IDS_PRINT_PREVIEW_OFFLINE); - source->AddLocalizedString("fedexTos", IDS_PRINT_PREVIEW_FEDEX_TOS); - source->AddLocalizedString("tosCheckboxLabel", - IDS_PRINT_PREVIEW_TOS_CHECKBOX_LABEL); source->AddLocalizedString("noDestsPromoTitle", IDS_PRINT_PREVIEW_NO_DESTS_PROMO_TITLE); source->AddLocalizedString("noDestsPromoBody", @@ -398,8 +395,6 @@ IDR_PRINT_PREVIEW_IMAGES_ENTERPRISE_PRINTER); source->AddResourcePath("images/third_party.png", IDR_PRINT_PREVIEW_IMAGES_THIRD_PARTY); - source->AddResourcePath("images/third_party_fedex.png", - IDR_PRINT_PREVIEW_IMAGES_THIRD_PARTY_FEDEX); source->AddResourcePath("images/google_doc.png", IDR_PRINT_PREVIEW_IMAGES_GOOGLE_DOC); source->AddResourcePath("images/pdf.png", IDR_PRINT_PREVIEW_IMAGES_PDF);
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc index f8cb64a..03abb0f 100644 --- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc +++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
@@ -22,7 +22,10 @@ g_browser_process->local_state()->FindPreference( prefs::kDefaultBrowserSettingEnabled); DCHECK(pref); - return pref->IsManaged() && !pref->GetValue(); + bool may_set_default_browser; + bool success = pref->GetValue()->GetAsBoolean(&may_set_default_browser); + DCHECK(success); + return pref->IsManaged() && !may_set_default_browser; } } // namespace
diff --git a/chrome/common/DEPS b/chrome/common/DEPS index b0596a6d..bc3c673 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS
@@ -28,7 +28,7 @@ "+components/translate/core/common", "+components/url_formatter", "+components/version_info", - "+device/vr/features.h", + "+device/vr/features/features.h", "+extensions/common", "+extensions/features", "+gin/public", # For profiling.cc
diff --git a/chrome/common/features.gni b/chrome/common/features.gni index 9364bd9..b302e5d7 100644 --- a/chrome/common/features.gni +++ b/chrome/common/features.gni
@@ -6,7 +6,7 @@ import("//build/config/chromecast_build.gni") import("//build/config/compiler/compiler.gni") import("//build/config/features.gni") -import("//device/vr/features.gni") +import("//device/vr/features/features.gni") import("//extensions/features/features.gni") import("//media/media_options.gni") import("//net/features.gni")
diff --git a/chrome/installer/mac/sign_app.sh.in b/chrome/installer/mac/sign_app.sh.in index d293a4e..5114af6 100644 --- a/chrome/installer/mac/sign_app.sh.in +++ b/chrome/installer/mac/sign_app.sh.in
@@ -71,13 +71,18 @@ # Verify everything. Check the framework and helper apps to make sure that the # signatures are present and weren't altered by the signing process. Use # --ignore-resources on the app mode loader because its signature only covers -# the main executable, not its containing .app bundle. Use --no-strict on the -# outermost browser .app because it uses custom resource rules. +# the main executable, not its containing .app bundle. Use --no-strict to +# verify items that use custom resource rules: +# - The outermost brrowser .app +# - The inner .framework, which has a nested component that uses them. codesign --verify --verbose=6 --deep --no-strict "${browser_app}" codesign --verify --verbose=6 --deep "${crashpad_handler}" codesign --verify --verbose=6 --ignore-resources "${app_mode_loader}" codesign --verify --verbose=6 --deep "${notification_service}" -codesign --verify --verbose=6 --deep "${framework}" +# Check the framework twice: once deep with no-strict, and once shallow with +# strict verification. +codesign --verify --verbose=6 --deep --no-strict "${framework}" +codesign --verify --verbose=6 --strict "${framework}" codesign --verify --verbose=6 --deep "${helper_app}" # Verify with spctl, which uses the same rules that Gatekeeper does for
diff --git a/chrome/installer/mac/sign_versioned_dir.sh.in b/chrome/installer/mac/sign_versioned_dir.sh.in index 2d03ee45..e4213f5 100644 --- a/chrome/installer/mac/sign_versioned_dir.sh.in +++ b/chrome/installer/mac/sign_versioned_dir.sh.in
@@ -109,5 +109,8 @@ codesign_display_and_verify "${crashpad_handler}" --deep codesign_display_and_verify "${app_mode_loader}" --ignore-resources codesign_display_and_verify "${notification_service}" --deep -codesign_display_and_verify "${framework}" --deep +# The framework contains KeystoneRegistration.framework, which uses +# custom resource rules, so use --no-strict to verify. +codesign_display_and_verify "${framework}" --deep --no-strict +codesign_display_and_verify "${framework}" --strict codesign_display_and_verify "${helper_app}" --deep
diff --git a/chrome/tools/build/mac/copy_keystone_framework.py b/chrome/tools/build/mac/copy_keystone_framework.py index 19b8f2f..513fdc91 100644 --- a/chrome/tools/build/mac/copy_keystone_framework.py +++ b/chrome/tools/build/mac/copy_keystone_framework.py
@@ -31,10 +31,7 @@ # dotfiles and the Headers directories. subprocess.check_call( ['rsync', '-acC', '--delete', - # TODO(rsesek): Exclude these directories again after they are marked as - # optional in the code signing resource rules, otherwise the code - # signature is invalidated. https://crbug.com/688076 - #'--exclude', 'Headers', '--exclude', 'PrivateHeaders', + '--exclude', 'Headers', '--exclude', 'PrivateHeaders', '--include', '*.so', os.path.join(args[1], 'Versions/Current/'), output_path])
diff --git a/chromecast/media/cma/decoder/BUILD.gn b/chromecast/media/cma/decoder/BUILD.gn index 5adf546..be40a3c 100644 --- a/chromecast/media/cma/decoder/BUILD.gn +++ b/chromecast/media/cma/decoder/BUILD.gn
@@ -4,9 +4,8 @@ source_set("decoder") { sources = [ + "cast_audio_decoder.cc", "cast_audio_decoder.h", - "cast_audio_decoder_android.cc", - "cast_audio_decoder_linux.cc", ] deps = [
diff --git a/chromecast/media/cma/decoder/cast_audio_decoder_linux.cc b/chromecast/media/cma/decoder/cast_audio_decoder.cc similarity index 100% rename from chromecast/media/cma/decoder/cast_audio_decoder_linux.cc rename to chromecast/media/cma/decoder/cast_audio_decoder.cc
diff --git a/chromecast/media/cma/decoder/cast_audio_decoder_android.cc b/chromecast/media/cma/decoder/cast_audio_decoder_android.cc deleted file mode 100644 index d011280..0000000 --- a/chromecast/media/cma/decoder/cast_audio_decoder_android.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2015 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 "chromecast/media/cma/decoder/cast_audio_decoder.h" - -#include "base/logging.h" - -namespace chromecast { -namespace media { - -// static -std::unique_ptr<CastAudioDecoder> CastAudioDecoder::Create( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - const media::AudioConfig& config, - OutputFormat output_format, - const InitializedCallback& initialized_callback) { - return std::unique_ptr<CastAudioDecoder>(); -} - -// static -int CastAudioDecoder::OutputFormatSizeInBytes( - CastAudioDecoder::OutputFormat format) { - switch (format) { - case CastAudioDecoder::OutputFormat::kOutputSigned16: - return 2; - case CastAudioDecoder::OutputFormat::kOutputPlanarFloat: - return 4; - } - NOTREACHED(); - return 1; -} - -} // namespace media -} // namespace chromecast
diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc index b2c4cd56..78abfb2 100644 --- a/chromeos/network/onc/onc_signature.cc +++ b/chromeos/network/onc/onc_signature.cc
@@ -57,10 +57,11 @@ {::onc::eap::kSaveCredentials, &kBoolSignature}, // Used internally. Not officially supported. {::onc::eap::kServerCAPEMs, &kStringListSignature}, + // Deprecated. {::onc::eap::kServerCARef, &kStringSignature}, {::onc::eap::kServerCARefs, &kStringListSignature}, - {::onc::eap::kUseSystemCAs, &kBoolSignature}, {::onc::eap::kUseProactiveKeyCaching, &kBoolSignature}, + {::onc::eap::kUseSystemCAs, &kBoolSignature}, {NULL}}; const OncFieldSignature ipsec_fields[] = {
diff --git a/components/feature_engagement_tracker/internal/feature_constants.cc b/components/feature_engagement_tracker/internal/feature_constants.cc index 581600e..d3f22bc4 100644 --- a/components/feature_engagement_tracker/internal/feature_constants.cc +++ b/components/feature_engagement_tracker/internal/feature_constants.cc
@@ -13,5 +13,7 @@ const base::Feature kIPHDownloadPageFeature{"IPH_DownloadPage", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kIPHDownloadHomeFeature{"IPH_DownloadHome", + base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/feature_list.cc b/components/feature_engagement_tracker/internal/feature_list.cc index 1cedb6b..39a92827 100644 --- a/components/feature_engagement_tracker/internal/feature_list.cc +++ b/components/feature_engagement_tracker/internal/feature_list.cc
@@ -11,7 +11,8 @@ namespace { -const base::Feature* kAllFeatures[] = {&kIPHDownloadPageFeature}; +const base::Feature* kAllFeatures[] = {&kIPHDownloadPageFeature, + &kIPHDownloadHomeFeature}; } // namespace
diff --git a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java b/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java index 6c54c7b..0f94cd801 100644 --- a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java +++ b/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java
@@ -19,6 +19,16 @@ public static final String DOWNLOAD_PAGE_STARTED = "download_page_started"; /** + * The download has completed successfully. + */ + public static final String DOWNLOAD_COMPLETED = "download_completed"; + + /** + * The download home was opened by the user (from toolbar menu or notifications). + */ + public static final String DOWNLOAD_HOME_OPENED = "download_home_opened"; + + /** * Do not instantiate. */ private EventConstants() {}
diff --git a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java b/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java index cf1ab1a8..5013839 100644 --- a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java +++ b/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java
@@ -10,6 +10,7 @@ */ public final class FeatureConstants { public static final String DOWNLOAD_PAGE_FEATURE = "IPH_DownloadPage"; + public static final String DOWNLOAD_HOME_FEATURE = "IPH_DownloadHome"; /** * Do not instantiate.
diff --git a/components/feature_engagement_tracker/public/feature_constants.h b/components/feature_engagement_tracker/public/feature_constants.h index 2bc24c5..215488bc 100644 --- a/components/feature_engagement_tracker/public/feature_constants.h +++ b/components/feature_engagement_tracker/public/feature_constants.h
@@ -16,6 +16,7 @@ // version: org.chromium.components.feature_engagement_tracker.FeatureConstants. extern const base::Feature kIPHDownloadPageFeature; +extern const base::Feature kIPHDownloadHomeFeature; } // namespace feature_engagement_tracker
diff --git a/components/onc/docs/onc_spec.md b/components/onc/docs/onc_spec.md index bafb102..c42e357c 100644 --- a/components/onc/docs/onc_spec.md +++ b/components/onc/docs/onc_spec.md
@@ -1085,6 +1085,11 @@ **SaveCredentials** is *false* is not allowed. +* **ServerCAPEMs** + * (optional) - **array of string** + * Non-empty list of CA certificates in PEM format, If this field is set, + **ServerCARef** and **ServerCARefs** must be unset. + * **ServerCARefs** * (optional) - **array of string** * Non-empty list of references to CA certificates in **Certificates** to be
diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index 36d169b..9e0c9d3 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc
@@ -1907,11 +1907,11 @@ #if BUILDFLAG(ENABLE_PRINT_PREVIEW) if (params.display_header_footer) { - // TODO(thestig): Figure out why Linux needs this. It is almost certainly - // |printingMinimumShrinkFactor| from Blink. #if defined(OS_WIN) const float fudge_factor = 1; #else + // TODO(thestig): Figure out why Linux needs this. It is almost certainly + // |kPrintingMinimumShrinkFactor| from Blink. const float fudge_factor = kPrintingMinimumShrinkFactor; #endif // |page_number| is 0-based, so 1 is added.
diff --git a/components/tracing/common/process_metrics_memory_dump_provider.cc b/components/tracing/common/process_metrics_memory_dump_provider.cc index 2936256..3f2abde 100644 --- a/components/tracing/common/process_metrics_memory_dump_provider.cc +++ b/components/tracing/common/process_metrics_memory_dump_provider.cc
@@ -614,6 +614,13 @@ pmd->process_totals()->SetExtraFieldInBytes("private_bytes", private_bytes); pmd->process_totals()->SetExtraFieldInBytes("shared_bytes", shared_bytes); pmd->process_totals()->SetExtraFieldInBytes("locked_bytes", locked_bytes); + + base::trace_event::ProcessMemoryTotals::PlatformPrivateFootprint& footprint = + pmd->process_totals()->GetPlatformPrivateFootprint(); + base::ProcessMetrics::TaskVMInfo info = process_metrics_->GetTaskVMInfo(); + footprint.phys_footprint_bytes = info.phys_footprint; + footprint.internal_bytes = info.internal; + footprint.compressed_bytes = info.compressed; #else uint64_t rss_bytes = process_metrics_->GetWorkingSetSize(); #endif // defined(OS_MACOSX)
diff --git a/components/viz/frame_sinks/mojo_frame_sink_manager.cc b/components/viz/frame_sinks/mojo_frame_sink_manager.cc index 71b56c6..a41c1a4 100644 --- a/components/viz/frame_sinks/mojo_frame_sink_manager.cc +++ b/components/viz/frame_sinks/mojo_frame_sink_manager.cc
@@ -18,17 +18,13 @@ namespace viz { -MojoFrameSinkManager::MojoFrameSinkManager( - bool use_surface_references, - DisplayProvider* display_provider, - cc::mojom::FrameSinkManagerRequest request, - cc::mojom::FrameSinkManagerClientPtr client) +MojoFrameSinkManager::MojoFrameSinkManager(bool use_surface_references, + DisplayProvider* display_provider) : manager_(use_surface_references ? cc::SurfaceManager::LifetimeType::REFERENCES : cc::SurfaceManager::LifetimeType::SEQUENCES), display_provider_(display_provider), - client_(std::move(client)), - binding_(this, std::move(request)) { + binding_(this) { manager_.AddObserver(this); } @@ -37,6 +33,14 @@ manager_.RemoveObserver(this); } +void MojoFrameSinkManager::Connect( + cc::mojom::FrameSinkManagerRequest request, + cc::mojom::FrameSinkManagerClientPtr client) { + DCHECK(!binding_.is_bound()); + binding_.Bind(std::move(request)); + client_ = std::move(client); +} + void MojoFrameSinkManager::CreateRootCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, gpu::SurfaceHandle surface_handle,
diff --git a/components/viz/frame_sinks/mojo_frame_sink_manager.h b/components/viz/frame_sinks/mojo_frame_sink_manager.h index 5fb8fa60..35db0ed4 100644 --- a/components/viz/frame_sinks/mojo_frame_sink_manager.h +++ b/components/viz/frame_sinks/mojo_frame_sink_manager.h
@@ -39,13 +39,15 @@ public NON_EXPORTED_BASE(cc::mojom::FrameSinkManager) { public: MojoFrameSinkManager(bool use_surface_references, - DisplayProvider* display_provider, - cc::mojom::FrameSinkManagerRequest request, - cc::mojom::FrameSinkManagerClientPtr client); + DisplayProvider* display_provider); ~MojoFrameSinkManager() override; cc::SurfaceManager* surface_manager() { return &manager_; } + // Binds to |request| and store connection back to |client|. + void Connect(cc::mojom::FrameSinkManagerRequest request, + cc::mojom::FrameSinkManagerClientPtr client); + // cc::mojom::FrameSinkManager implementation: void CreateRootCompositorFrameSink( const cc::FrameSinkId& frame_sink_id,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 7423578..eb0ac5e1 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -76,7 +76,7 @@ "//device/power_save_blocker", "//device/screen_orientation/public/interfaces", "//device/vr", - "//device/vr:features", + "//device/vr/features", "//device/wake_lock/public/interfaces", "//google_apis", "//gpu",
diff --git a/content/browser/compositor/frame_sink_manager_host.cc b/content/browser/compositor/frame_sink_manager_host.cc index 089abdb..ea57d32 100644 --- a/content/browser/compositor/frame_sink_manager_host.cc +++ b/content/browser/compositor/frame_sink_manager_host.cc
@@ -14,9 +14,7 @@ FrameSinkManagerHost::FrameSinkManagerHost() : binding_(this), frame_sink_manager_(false, // Use surface sequences. - nullptr, - MakeRequest(&frame_sink_manager_ptr_), - binding_.CreateInterfacePtrAndBind()) {} + nullptr) {} FrameSinkManagerHost::~FrameSinkManagerHost() {} @@ -24,11 +22,18 @@ return frame_sink_manager_.surface_manager(); } +void FrameSinkManagerHost::ConnectToFrameSinkManager() { + DCHECK(!frame_sink_manager_ptr_.is_bound()); + frame_sink_manager_.Connect(mojo::MakeRequest(&frame_sink_manager_ptr_), + binding_.CreateInterfacePtrAndBind()); +} + void FrameSinkManagerHost::CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id, cc::mojom::MojoCompositorFrameSinkRequest request, cc::mojom::MojoCompositorFrameSinkPrivateRequest private_request, cc::mojom::MojoCompositorFrameSinkClientPtr client) { + DCHECK(frame_sink_manager_ptr_.is_bound()); frame_sink_manager_ptr_->CreateCompositorFrameSink( frame_sink_id, std::move(request), std::move(private_request), std::move(client)); @@ -37,6 +42,7 @@ void FrameSinkManagerHost::RegisterFrameSinkHierarchy( const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& child_frame_sink_id) { + DCHECK(frame_sink_manager_ptr_.is_bound()); frame_sink_manager_ptr_->RegisterFrameSinkHierarchy(parent_frame_sink_id, child_frame_sink_id); } @@ -44,6 +50,7 @@ void FrameSinkManagerHost::UnregisterFrameSinkHierarchy( const cc::FrameSinkId& parent_frame_sink_id, const cc::FrameSinkId& child_frame_sink_id) { + DCHECK(frame_sink_manager_ptr_.is_bound()); frame_sink_manager_ptr_->UnregisterFrameSinkHierarchy(parent_frame_sink_id, child_frame_sink_id); }
diff --git a/content/browser/compositor/frame_sink_manager_host.h b/content/browser/compositor/frame_sink_manager_host.h index a439730..8c7865d 100644 --- a/content/browser/compositor/frame_sink_manager_host.h +++ b/content/browser/compositor/frame_sink_manager_host.h
@@ -5,10 +5,12 @@ #ifndef CONTENT_BROWSER_COMPOSITOR_FRAME_SINK_MANAGER_HOST_H_ #define CONTENT_BROWSER_COMPOSITOR_FRAME_SINK_MANAGER_HOST_H_ +#include "base/compiler_specific.h" #include "base/macros.h" #include "cc/ipc/frame_sink_manager.mojom.h" #include "cc/surfaces/frame_sink_id.h" #include "components/viz/frame_sinks/mojo_frame_sink_manager.h" +#include "content/common/content_export.h" #include "mojo/public/cpp/bindings/binding.h" namespace cc { @@ -19,14 +21,18 @@ namespace content { // Browser side implementation of mojom::FrameSinkManager. Manages frame sinks -// and is inteded to replace SurfaceManager. -class FrameSinkManagerHost : cc::mojom::FrameSinkManagerClient { +// and is intended to replace SurfaceManager. +class CONTENT_EXPORT FrameSinkManagerHost + : NON_EXPORTED_BASE(cc::mojom::FrameSinkManagerClient) { public: FrameSinkManagerHost(); ~FrameSinkManagerHost() override; cc::SurfaceManager* surface_manager(); + // Start Mojo connection to FrameSinkManager. Most tests won't need this. + void ConnectToFrameSinkManager(); + // See frame_sink_manager.mojom for descriptions. void CreateCompositorFrameSink( const cc::FrameSinkId& frame_sink_id,
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 25b59f06..dbd83c60 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -197,6 +197,7 @@ cc::SetClientNameForMetrics("Browser"); frame_sink_manager_host_ = base::MakeUnique<FrameSinkManagerHost>(); + frame_sink_manager_host_->ConnectToFrameSinkManager(); task_graph_runner_->Start("CompositorTileWorker1", base::SimpleThread::Options());
diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.cc b/content/browser/compositor/test/no_transport_image_transport_factory.cc index f326a4b2..51a04233 100644 --- a/content/browser/compositor/test/no_transport_image_transport_factory.cc +++ b/content/browser/compositor/test/no_transport_image_transport_factory.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/memory/ptr_util.h" #include "build/build_config.h" #include "cc/output/context_provider.h" #include "cc/surfaces/surface_manager.h" @@ -17,11 +18,12 @@ namespace content { NoTransportImageTransportFactory::NoTransportImageTransportFactory() - : surface_manager_(new cc::SurfaceManager), + : frame_sink_manager_host_(base::MakeUnique<FrameSinkManagerHost>()), // The context factory created here is for unit tests, thus passing in // true in constructor. - context_factory_( - new ui::InProcessContextFactory(true, surface_manager_.get())) {} + context_factory_(base::MakeUnique<ui::InProcessContextFactory>( + true, + frame_sink_manager_host_->surface_manager())) {} NoTransportImageTransportFactory::~NoTransportImageTransportFactory() { std::unique_ptr<display_compositor::GLHelper> lost_gl_helper = @@ -40,8 +42,7 @@ FrameSinkManagerHost* NoTransportImageTransportFactory::GetFrameSinkManagerHost() { - NOTIMPLEMENTED(); - return nullptr; + return frame_sink_manager_host_.get(); } display_compositor::GLHelper* NoTransportImageTransportFactory::GetGLHelper() {
diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.h b/content/browser/compositor/test/no_transport_image_transport_factory.h index 0b3a357..87551fa 100644 --- a/content/browser/compositor/test/no_transport_image_transport_factory.h +++ b/content/browser/compositor/test/no_transport_image_transport_factory.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "build/build_config.h" #include "cc/surfaces/surface_manager.h" +#include "content/browser/compositor/frame_sink_manager_host.h" #include "content/browser/compositor/image_transport_factory.h" namespace cc { @@ -41,7 +42,7 @@ #endif private: - std::unique_ptr<cc::SurfaceManager> surface_manager_; + std::unique_ptr<FrameSinkManagerHost> frame_sink_manager_host_; std::unique_ptr<ui::InProcessContextFactory> context_factory_; scoped_refptr<cc::ContextProvider> context_provider_; std::unique_ptr<display_compositor::GLHelper> gl_helper_;
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index c070f2df..b26cfd0 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -279,6 +279,7 @@ DCHECK(GetEntryCount() == 0 && !GetPendingEntry()); DCHECK(selected_navigation >= 0 && selected_navigation < static_cast<int>(entries->size())); + DCHECK_EQ(-1, pending_entry_index_); needs_reload_ = true; entries_.reserve(entries->size()); @@ -447,10 +448,14 @@ std::unique_ptr<NavigationEntryImpl> entry) { // Remember the last pending entry for which we haven't received a response // yet. This will be deleted in the NavigateToPendingEntry() function. + DCHECK_EQ(nullptr, last_pending_entry_); + DCHECK_EQ(-1, last_pending_entry_index_); last_pending_entry_ = pending_entry_; last_pending_entry_index_ = pending_entry_index_; last_transient_entry_index_ = transient_entry_index_; + pending_entry_ = nullptr; + pending_entry_index_ = -1; // When navigating to a new page, we don't know for sure if we will actually // end up leaving the current page. The new page load could for example // result in a download or a 'no content' response (e.g., a mailto: URL). @@ -462,6 +467,7 @@ std::unique_ptr<NavigationEntryImpl> entry) { DiscardNonCommittedEntriesInternal(); pending_entry_ = entry.release(); + DCHECK_EQ(-1, pending_entry_index_); NotificationService::current()->Notify( NOTIFICATION_NAV_ENTRY_PENDING, Source<NavigationController>(this), @@ -534,11 +540,16 @@ } int NavigationControllerImpl::GetLastCommittedEntryIndex() const { + // The last committed entry index must always be less than the number of + // entries. If there are no entries, it must be -1. However, there may be a + // transient entry while the last committed entry index is still -1. + DCHECK_LT(last_committed_entry_index_, GetEntryCount()); + DCHECK(GetEntryCount() || last_committed_entry_index_ == -1); return last_committed_entry_index_; } int NavigationControllerImpl::GetEntryCount() const { - DCHECK(entries_.size() <= max_entry_count()); + DCHECK_LE(entries_.size(), max_entry_count()); return static_cast<int>(entries_.size()); } @@ -615,11 +626,12 @@ DiscardNonCommittedEntries(); + DCHECK_EQ(nullptr, pending_entry_); + DCHECK_EQ(-1, pending_entry_index_); + pending_entry_ = entries_[index].get(); pending_entry_index_ = index; - entries_[pending_entry_index_]->SetTransitionType( - ui::PageTransitionFromInt( - entries_[pending_entry_index_]->GetTransitionType() | - ui::PAGE_TRANSITION_FORWARD_BACK)); + pending_entry_->SetTransitionType(ui::PageTransitionFromInt( + pending_entry_->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK)); NavigateToPendingEntry(ReloadType::NONE); } @@ -1734,10 +1746,22 @@ } NavigationEntryImpl* NavigationControllerImpl::GetPendingEntry() const { + // If there is no pending_entry_, there should be no pending_entry_index_. + DCHECK(pending_entry_ || pending_entry_index_ == -1); + + // If there is a pending_entry_index_, then pending_entry_ must be the entry + // at that index. + DCHECK(pending_entry_index_ == -1 || + pending_entry_ == GetEntryAtIndex(pending_entry_index_)); + return pending_entry_; } int NavigationControllerImpl::GetPendingEntryIndex() const { + // The pending entry index must always be less than the number of entries. + // If there are no entries, it must be exactly -1. + DCHECK_LT(pending_entry_index_, GetEntryCount()); + DCHECK(GetEntryCount() != 0 || pending_entry_index_ == -1); return pending_entry_index_; } @@ -1799,6 +1823,7 @@ } void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) { + DCHECK(pending_entry_); needs_reload_ = false; // If we were navigating to a slow-to-commit page, and the user performs @@ -1809,9 +1834,8 @@ // page from loading (which would normally happen during the navigation). if (pending_entry_index_ != -1 && pending_entry_index_ == last_committed_entry_index_ && - (entries_[pending_entry_index_]->restore_type() == RestoreType::NONE) && - (entries_[pending_entry_index_]->GetTransitionType() & - ui::PAGE_TRANSITION_FORWARD_BACK)) { + pending_entry_->restore_type() == RestoreType::NONE && + pending_entry_->GetTransitionType() & ui::PAGE_TRANSITION_FORWARD_BACK) { delegate_->Stop(); // If an interstitial page is showing, we want to close it to get back @@ -1840,10 +1864,12 @@ // Convert Enter-in-omnibox to a reload. This is what Blink does in // FrameLoader, but we want to handle it here so that if the navigation is // redirected or handled purely on the browser side in PlzNavigate we have the - // same behaviour as Blink would. Note that we don't want to convert to a - // reload for history navigations, so this must be above the retrieval of the - // pending_entry_ below when pending_entry_index_ is used. - if (reload_type == ReloadType::NONE && last_navigation && pending_entry_ && + // same behaviour as Blink would. + if (reload_type == ReloadType::NONE && last_navigation && + // When |pending_entry_index_| is different from -1, it means this is an + // history navigation. History navigation mustn't be converted to a + // reload. + pending_entry_index_ == -1 && // Please refer to the ShouldTreatNavigationAsReload() function for info // on which navigations are treated as reloads. In general navigating to // the last committed or pending entry via the address bar, clicking on @@ -1878,12 +1904,6 @@ last_pending_entry_ = nullptr; last_pending_entry_index_ = -1; - // For session history navigations only the pending_entry_index_ is set. - if (!pending_entry_) { - CHECK_NE(pending_entry_index_, -1); - pending_entry_ = entries_[pending_entry_index_].get(); - } - // Any renderer-side debug URLs or javascript: URLs should be ignored if the // renderer process is not live, unless it is the initial navigation of the // tab. @@ -2052,6 +2072,7 @@ if (pending_entry_) { NavigateToPendingEntry(ReloadType::NONE); } else if (last_committed_entry_index_ != -1) { + pending_entry_ = entries_[last_committed_entry_index_].get(); pending_entry_index_ = last_committed_entry_index_; NavigateToPendingEntry(ReloadType::NONE); } else { @@ -2099,10 +2120,12 @@ failed_pending_entry_id_ = 0; } - if (pending_entry_index_ == -1) - delete pending_entry_; - pending_entry_ = NULL; - pending_entry_index_ = -1; + if (pending_entry_) { + if (pending_entry_index_ == -1) + delete pending_entry_; + pending_entry_index_ = -1; + pending_entry_ = nullptr; + } } void NavigationControllerImpl::SetPendingNavigationSSLError(bool error) { @@ -2116,6 +2139,8 @@ entries_.erase(entries_.begin() + transient_entry_index_); if (last_committed_entry_index_ > transient_entry_index_) last_committed_entry_index_--; + if (pending_entry_index_ > transient_entry_index_) + pending_entry_index_--; transient_entry_index_ = -1; } @@ -2143,6 +2168,8 @@ DiscardTransientEntry(); entries_.insert(entries_.begin() + index, NavigationEntryImpl::FromNavigationEntry(std::move(entry))); + if (pending_entry_index_ >= index) + pending_entry_index_++; transient_entry_index_ = index; delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_ALL); } @@ -2162,6 +2189,8 @@ source.entries_[i]->Clone()); } } + DCHECK(pending_entry_index_ == -1 || + pending_entry_ == GetEntryAtIndex(pending_entry_index_)); } void NavigationControllerImpl::SetGetTimestampCallbackForTest(
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index 6d478e4f..b23fb01 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -5288,4 +5288,82 @@ main_test_rfh()->SimulateNavigationCommit(url_1); } +// Test to ensure that the pending entry index is updated when a transient entry +// is inserted or removed. +TEST_F(NavigationControllerTest, PendingEntryIndexUpdatedWithTransient) { + NavigationControllerImpl& controller = controller_impl(); + const GURL url_0("http://foo/0"); + const GURL url_1("http://foo/1"); + const GURL url_transient_1("http://foo/transient_1"); + const GURL url_transient_2("http://foo/transient_2"); + + NavigateAndCommit(url_0); + NavigateAndCommit(url_1); + controller.GoBack(); + contents()->CommitPendingNavigation(); + controller.GoForward(); + + // Check the state before the insertion of the transient entry. + // entries[0] = url_0 <- last committed entry. + // entries[1] = url_1 <- pending entry. + ASSERT_EQ(2, controller.GetEntryCount()); + EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(1, controller.GetPendingEntryIndex()); + EXPECT_EQ(controller.GetEntryAtIndex(1), controller.GetPendingEntry()); + EXPECT_EQ(url_0, controller.GetEntryAtIndex(0)->GetURL()); + EXPECT_EQ(url_1, controller.GetEntryAtIndex(1)->GetURL()); + + // Insert a transient entry before the pending one. It should increase the + // pending entry index by one (1 -> 2). + std::unique_ptr<NavigationEntry> transient_entry_1(new NavigationEntryImpl); + transient_entry_1->SetURL(url_transient_1); + controller.SetTransientEntry(std::move(transient_entry_1)); + + // Check the state after the insertion of the transient entry. + // entries[0] = url_0 <- last committed entry + // entries[1] = url_transient_1 <- transient entry + // entries[2] = url_1 <- pending entry + ASSERT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(2, controller.GetPendingEntryIndex()); + EXPECT_EQ(controller.GetEntryAtIndex(1), controller.GetTransientEntry()); + EXPECT_EQ(controller.GetEntryAtIndex(2), controller.GetPendingEntry()); + EXPECT_EQ(url_0, controller.GetEntryAtIndex(0)->GetURL()); + EXPECT_EQ(url_transient_1, controller.GetEntryAtIndex(1)->GetURL()); + EXPECT_EQ(url_1, controller.GetEntryAtIndex(2)->GetURL()); + + // Insert another transient entry. It should replace the previous one and this + // time the pending entry index should retain its value (i.e. 2). + std::unique_ptr<NavigationEntry> transient_entry_2(new NavigationEntryImpl); + transient_entry_2->SetURL(url_transient_2); + controller.SetTransientEntry(std::move(transient_entry_2)); + + // Check the state after the second insertion of a transient entry. + // entries[0] = url_0 <- last committed entry + // entries[1] = url_transient_2 <- transient entry + // entries[2] = url_1 <- pending entry + ASSERT_EQ(3, controller.GetEntryCount()); + EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(2, controller.GetPendingEntryIndex()); + EXPECT_EQ(controller.GetEntryAtIndex(1), controller.GetTransientEntry()); + EXPECT_EQ(controller.GetEntryAtIndex(2), controller.GetPendingEntry()); + EXPECT_EQ(url_0, controller.GetEntryAtIndex(0)->GetURL()); + EXPECT_EQ(url_transient_2, controller.GetEntryAtIndex(1)->GetURL()); + EXPECT_EQ(url_1, controller.GetEntryAtIndex(2)->GetURL()); + + // Commit the pending entry. + contents()->CommitPendingNavigation(); + + // Check the final state. + // entries[0] = url_0 + // entries[1] = url_1 <- last committed entry + ASSERT_EQ(2, controller.GetEntryCount()); + EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(-1, controller.GetPendingEntryIndex()); + EXPECT_EQ(nullptr, controller.GetPendingEntry()); + EXPECT_EQ(nullptr, controller.GetTransientEntry()); + EXPECT_EQ(url_0, controller.GetEntryAtIndex(0)->GetURL()); + EXPECT_EQ(url_1, controller.GetEntryAtIndex(1)->GetURL()); +} + } // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 45cf9cf..40b9c06 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -97,7 +97,7 @@ #include "content/public/common/url_constants.h" #include "content/public/common/url_utils.h" #include "device/geolocation/geolocation_service_context.h" -#include "device/vr/features.h" +#include "device/vr/features/features.h" #include "device/wake_lock/public/interfaces/wake_lock_context.mojom.h" #include "device/wake_lock/public/interfaces/wake_lock_service.mojom.h" #include "media/base/media_switches.h"
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc index d32665c..263113a 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -560,6 +560,10 @@ } void RenderWidgetHostViewChildFrame::ShowDefinitionForSelection() { + if (frame_connector_) { + frame_connector_->GetRootRenderWidgetHostView() + ->ShowDefinitionForSelection(); + } } bool RenderWidgetHostViewChildFrame::SupportsSpeech() const {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index efbd3eb8..c3e20e2d 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -95,7 +95,9 @@ }; struct CompositorDependencies { - CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) {} + CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) { + frame_sink_manager_host.ConnectToFrameSinkManager(); + } SingleThreadTaskGraphRunner task_graph_runner; FrameSinkManagerHost frame_sink_manager_host;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 1884d92a..ed09e523 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1685,6 +1685,7 @@ switches::kAllowLoopbackInPeerConnection, switches::kAndroidFontsPath, switches::kAudioBufferSize, + switches::kAutoplayPolicy, switches::kBlinkSettings, switches::kDefaultTileWidth, switches::kDefaultTileHeight,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index ba2cd466..db981b6 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -439,16 +439,19 @@ // On Android, user gestures are normally required, unless that requirement // is disabled with a command-line switch or the equivalent field trial is // is set to "Enabled". - prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch( - switches::kDisableGestureRequirementForMediaPlayback); + prefs.user_gesture_required_for_media_playback = + !command_line.HasSwitch( + switches::kDisableGestureRequirementForMediaPlayback) && + command_line.GetSwitchValueASCII(switches::kAutoplayPolicy) != + switches::autoplay::kNoUserGestureRequiredPolicy; prefs.progress_bar_completion = GetProgressBarCompletionPolicy(); prefs.use_solid_color_scrollbars = true; #else // defined(OS_ANDROID) prefs.cross_origin_media_playback_requires_user_gesture = - base::FeatureList::GetInstance()->IsEnabled( - features::kCrossOriginMediaPlaybackRequiresUserGesture); + command_line.GetSwitchValueASCII(switches::kAutoplayPolicy) == + switches::autoplay::kCrossOriginUserGestureRequiredPolicy; #endif // defined(OS_ANDROID) const std::string touch_enabled_switch =
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 4c7c8f1..3c7f850 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -484,6 +484,9 @@ // platform view for a guest). const TextInputManager::TextSelection* GetTextSelection(); + // Get the focused view that should be used for retrieving the text selection. + RenderWidgetHostViewBase* GetFocusedViewForTextSelection(); + private: friend class RenderWidgetHostViewMacTest; @@ -503,9 +506,6 @@ // Dispatches a TTS session. void SpeakText(const std::string& text); - // Get the focused view that should be used for retrieving the text selection. - RenderWidgetHostViewBase* GetFocusedViewForTextSelection(); - // Adds/Removes frame observer based on state. void UpdateNeedsBeginFramesInternal();
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 41d21d0..1e60855 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -542,24 +542,24 @@ ui::TextInputType RenderWidgetHostViewMac::GetTextInputType() { if (!GetActiveWidget()) return ui::TEXT_INPUT_TYPE_NONE; - return GetTextInputManager()->GetTextInputState()->type; + return text_input_manager_->GetTextInputState()->type; } RenderWidgetHostImpl* RenderWidgetHostViewMac::GetActiveWidget() { - return GetTextInputManager() ? GetTextInputManager()->GetActiveWidget() - : nullptr; + return text_input_manager_ ? text_input_manager_->GetActiveWidget() : nullptr; } const TextInputManager::CompositionRangeInfo* RenderWidgetHostViewMac::GetCompositionRangeInfo() { - return GetTextInputManager() ? text_input_manager_->GetCompositionRangeInfo() - : nullptr; + return text_input_manager_ ? text_input_manager_->GetCompositionRangeInfo() + : nullptr; } const TextInputManager::TextSelection* RenderWidgetHostViewMac::GetTextSelection() { - return text_input_manager_->GetTextSelection( - GetFocusedViewForTextSelection()); + return text_input_manager_ ? text_input_manager_->GetTextSelection( + GetFocusedViewForTextSelection()) + : nullptr; } /////////////////////////////////////////////////////////////////////////////// @@ -2421,41 +2421,32 @@ NSPerformService(@"Look Up in Dictionary", pasteboard->get()); return; } - dispatch_async(dispatch_get_main_queue(), ^{ - NSPoint flippedBaselinePoint = { - baselinePoint.x, [view frame].size.height - baselinePoint.y, - }; - [view showDefinitionForAttributedString:string - atPoint:flippedBaselinePoint]; - }); + NSPoint flippedBaselinePoint = { + baselinePoint.x, [view frame].size.height - baselinePoint.y, + }; + [view showDefinitionForAttributedString:string atPoint:flippedBaselinePoint]; } - (void)showLookUpDictionaryOverlayFromRange:(NSRange)range targetView:(NSView*)targetView { - RenderWidgetHostImpl* widgetHost = renderWidgetHostView_->render_widget_host_; - if (!widgetHost || !widgetHost->delegate()) + content::RenderWidgetHostViewBase* focusedView = + renderWidgetHostView_->GetFocusedViewForTextSelection(); + if (!focusedView) return; - widgetHost = widgetHost->delegate()->GetFocusedRenderWidgetHost(widgetHost); + RenderWidgetHostImpl* widgetHost = + RenderWidgetHostImpl::From(focusedView->GetRenderWidgetHost()); if (!widgetHost) return; - // TODO(ekaramad): The position reported by the renderer is with respect to - // |widgetHost|'s coordinate space with y-axis inverted to conform to AppKit - // coordinate system. The point will need to be transformed into root view's - // coordinate system (RenderWidgetHostViewMac in this case). However, since - // the callback is invoked on IO thread it will require some thread hopping to - // do so. For this reason, for now, we accept this non-ideal way of fixing the - // point offset manually from the view bounds. This should be revisited when - // fixing issues in TextInputClientMac (https://crbug.com/643233). - gfx::Rect root_box = renderWidgetHostView_->GetViewBounds(); - gfx::Rect view_box = widgetHost->GetView()->GetViewBounds(); - TextInputClientMac::GetInstance()->GetStringFromRange( widgetHost, range, ^(NSAttributedString* string, NSPoint baselinePoint) { - baselinePoint.x += view_box.origin().x() - root_box.origin().x(); - baselinePoint.y += - root_box.bottom_left().y() - view_box.bottom_left().y(); + if (auto* rwhv = widgetHost->GetView()) { + gfx::Point pointInRootView = rwhv->TransformPointToRootCoordSpace( + gfx::Point(baselinePoint.x, baselinePoint.y)); + baselinePoint.x = pointInRootView.x(); + baselinePoint.y = pointInRootView.y(); + } [self showLookUpDictionaryOverlayInternal:string baselinePoint:baselinePoint targetView:targetView]; @@ -2479,23 +2470,15 @@ if (!widgetHost) return; - // TODO(ekaramad): The position reported by the renderer is with respect to - // |widgetHost|'s coordinate space with y-axis inverted to conform to AppKit - // coordinate system. The point will need to be transformed into root view's - // coordinate system (RenderWidgetHostViewMac in this case). However, since - // the callback is invoked on IO thread it will require some thread hopping to - // do so. For this reason, for now, we accept this non-ideal way of fixing the - // point offset manually from the view bounds. This should be revisited when - // fixing issues in TextInputClientMac (https://crbug.com/643233). - gfx::Rect root_box = renderWidgetHostView_->GetViewBounds(); - gfx::Rect view_box = widgetHost->GetView()->GetViewBounds(); - TextInputClientMac::GetInstance()->GetStringAtPoint( widgetHost, transformedPoint, ^(NSAttributedString* string, NSPoint baselinePoint) { - baselinePoint.x += view_box.origin().x() - root_box.origin().x(); - baselinePoint.y += - root_box.bottom_left().y() - view_box.bottom_left().y(); + if (auto* rwhv = widgetHost->GetView()) { + gfx::Point pointInRootView = rwhv->TransformPointToRootCoordSpace( + gfx::Point(baselinePoint.x, baselinePoint.y)); + baselinePoint.x = pointInRootView.x(); + baselinePoint.y = pointInRootView.y(); + } [self showLookUpDictionaryOverlayInternal:string baselinePoint:baselinePoint targetView:self];
diff --git a/content/browser/renderer_host/text_input_client_message_filter.h b/content/browser/renderer_host/text_input_client_message_filter.h index 6968cd79..4ded7f33 100644 --- a/content/browser/renderer_host/text_input_client_message_filter.h +++ b/content/browser/renderer_host/text_input_client_message_filter.h
@@ -28,6 +28,8 @@ // BrowserMessageFilter override: bool OnMessageReceived(const IPC::Message& message) override; + void OverrideThreadForMessage(const IPC::Message& message, + BrowserThread::ID* thread) override; protected: ~TextInputClientMessageFilter() override;
diff --git a/content/browser/renderer_host/text_input_client_message_filter.mm b/content/browser/renderer_host/text_input_client_message_filter.mm index 7ab20e40..35d43000 100644 --- a/content/browser/renderer_host/text_input_client_message_filter.mm +++ b/content/browser/renderer_host/text_input_client_message_filter.mm
@@ -35,6 +35,17 @@ return handled; } +void TextInputClientMessageFilter::OverrideThreadForMessage( + const IPC::Message& message, + BrowserThread::ID* thread) { + switch (message.type()) { + case TextInputClientReplyMsg_GotStringAtPoint::ID: + case TextInputClientReplyMsg_GotStringForRange::ID: + *thread = BrowserThread::UI; + break; + } +} + TextInputClientMessageFilter::~TextInputClientMessageFilter() {} void TextInputClientMessageFilter::OnGotStringAtPoint(
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index ab89709..f22e0211 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -15,6 +15,7 @@ #include "content/common/content_switches_internal.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "media/base/media_switches.h" #include "services/device/public/cpp/device_features.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" #include "ui/gl/gl_switches.h" @@ -49,10 +50,6 @@ WebRuntimeFeatures::EnableMediaControlsOverlayPlayButton(true); #else // defined(OS_ANDROID) WebRuntimeFeatures::EnableNavigatorContentUtils(true); - if (base::FeatureList::IsEnabled( - features::kCrossOriginMediaPlaybackRequiresUserGesture)) { - WebRuntimeFeatures::EnableAutoplayMutedVideos(true); - } #endif // defined(OS_ANDROID) #if defined(OS_ANDROID) || defined(USE_AURA) @@ -383,6 +380,13 @@ if (base::FeatureList::IsEnabled(features::kIdleTimeSpellChecking)) WebRuntimeFeatures::EnableFeatureFromString("IdleTimeSpellChecking", true); +#if !defined(OS_ANDROID) + if (command_line.GetSwitchValueASCII(switches::kAutoplayPolicy) == + switches::autoplay::kCrossOriginUserGestureRequiredPolicy) { + WebRuntimeFeatures::EnableAutoplayMutedVideos(true); + } +#endif + // Enable explicitly enabled features, and then disable explicitly disabled // ones. if (command_line.HasSwitch(switches::kEnableBlinkFeatures)) {
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 1d04f8c..d7b13a1 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -110,12 +110,11 @@ "java/src/org/chromium/content/browser/ActivityContentVideoViewEmbedder.java", "java/src/org/chromium/content/browser/AudioFocusDelegate.java", "java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java", + "java/src/org/chromium/content/browser/BaseChildProcessConnection.java", "java/src/org/chromium/content/browser/BindingManager.java", "java/src/org/chromium/content/browser/BindingManagerImpl.java", "java/src/org/chromium/content/browser/BrowserStartupController.java", "java/src/org/chromium/content/browser/ChildConnectionAllocator.java", - "java/src/org/chromium/content/browser/ChildProcessConnection.java", - "java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java", "java/src/org/chromium/content/browser/ChildProcessConstants.java", "java/src/org/chromium/content/browser/ChildProcessLauncher.java", "java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java", @@ -133,10 +132,12 @@ "java/src/org/chromium/content/browser/DeviceUtils.java", "java/src/org/chromium/content/browser/FloatingActionModeCallback.java", "java/src/org/chromium/content/browser/GpuProcessCallback.java", + "java/src/org/chromium/content/browser/ImportantChildProcessConnection.java", "java/src/org/chromium/content/browser/InterfaceRegistrarImpl.java", "java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java", "java/src/org/chromium/content/browser/JavascriptInterface.java", "java/src/org/chromium/content/browser/LauncherThread.java", + "java/src/org/chromium/content/browser/ManagedChildProcessConnection.java", "java/src/org/chromium/content/browser/MediaResourceGetter.java", "java/src/org/chromium/content/browser/MediaSessionImpl.java", "java/src/org/chromium/content/browser/MemoryMonitorAndroid.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java b/content/public/android/java/src/org/chromium/content/browser/BaseChildProcessConnection.java similarity index 61% rename from content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java rename to content/public/android/java/src/org/chromium/content/browser/BaseChildProcessConnection.java index 710741b..52bfe5e5 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/BaseChildProcessConnection.java
@@ -26,67 +26,155 @@ import java.io.IOException; import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; /** * Manages a connection between the browser activity and a child service. */ -public class ChildProcessConnectionImpl implements ChildProcessConnection { +public abstract class BaseChildProcessConnection { + private static final String TAG = "BaseChildProcessConn"; + + /** + * Used to notify the consumer about disconnection of the service. This callback is provided + * earlier than ConnectionCallbacks below, as a child process might die before the connection is + * fully set up. + */ + interface DeathCallback { + // Called on Launcher thread. + void onChildProcessDied(BaseChildProcessConnection connection); + } + + /** + * Used to notify the consumer about the process start. These callbacks will be invoked before + * the ConnectionCallbacks. + */ + interface StartCallback { + /** + * Called when the child process has successfully started and is ready for connection + * setup. + */ + void onChildStarted(); + + /** + * Called when the child process failed to start. This can happen if the process is already + * in use by another client. + */ + void onChildStartFailed(); + } + + /** + * Used to notify the consumer about the connection being established. + */ + interface ConnectionCallback { + /** + * Called when the connection to the service is established. + * @param connecion the connection object to the child process + */ + void onConnected(BaseChildProcessConnection connection); + } + + /** Used to create specialization connection instances. */ + interface Factory { + BaseChildProcessConnection create(Context context, int number, boolean sandboxed, + DeathCallback deathCallback, String serviceClassName, + Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams); + } + + /** Interface representing a connection to the Android service. Can be mocked in unit-tests. */ + protected interface ChildServiceConnection { + boolean bind(); + void unbind(); + boolean isBound(); + } + + /** Implementation of ChildServiceConnection that does connect to a service. */ + protected class ChildServiceConnectionImpl + implements ChildServiceConnection, ServiceConnection { + private final int mBindFlags; + private boolean mBound; + + private Intent createServiceBindIntent() { + Intent intent = new Intent(); + if (mCreationParams != null) { + mCreationParams.addIntentExtras(intent); + } + intent.setComponent(mServiceName); + return intent; + } + + private ChildServiceConnectionImpl(int bindFlags) { + mBindFlags = bindFlags; + } + + @Override + public boolean bind() { + if (!mBound) { + try { + TraceEvent.begin("BaseChildProcessConnection.ChildServiceConnection.bind"); + Intent intent = createServiceBindIntent(); + if (mChildProcessCommonParameters != null) { + intent.putExtras(mChildProcessCommonParameters); + } + mBound = mContext.bindService(intent, this, mBindFlags); + } finally { + TraceEvent.end("BaseChildProcessConnection.ChildServiceConnection.bind"); + } + } + return mBound; + } + + @Override + public void unbind() { + if (mBound) { + mContext.unbindService(this); + mBound = false; + } + } + + @Override + public boolean isBound() { + return mBound; + } + + @Override + public void onServiceConnected(ComponentName className, final IBinder service) { + LauncherThread.post(new Runnable() { + @Override + public void run() { + BaseChildProcessConnection.this.onServiceConnectedOnLauncherThread(service); + } + }); + } + + // Called on the main thread to notify that the child service did not disconnect gracefully. + @Override + public void onServiceDisconnected(ComponentName className) { + LauncherThread.post(new Runnable() { + @Override + public void run() { + BaseChildProcessConnection.this.onServiceDisconnectedOnLauncherThread(); + } + }); + } + } + + // Caches whether non-sandboxed and sandboxed services require an extra + // binding flag provided via ChildProcessCreationParams. + // TODO(mnaganov): Get rid of it after the release of the next Android SDK. + private static Boolean sNeedsExtrabindFlags[] = new Boolean[2]; private final Context mContext; private final int mServiceNumber; - private final boolean mInSandbox; - private final ChildProcessConnection.DeathCallback mDeathCallback; + private final boolean mSandboxed; + private final BaseChildProcessConnection.DeathCallback mDeathCallback; private final ComponentName mServiceName; - // Synchronization: While most internal flow occurs on the UI thread, the public API - // (specifically start and stop) may be called from any thread, hence all entry point methods - // into the class are synchronized on the lock to protect access to these members. - private final Object mLock = new Object(); - private IChildProcessService mService; - // Set to true when the service connection callback runs. This differs from - // mServiceConnectComplete, which tracks that the connection completed successfully. - private boolean mDidOnServiceConnected; - // Set to true when the service connected successfully. - private boolean mServiceConnectComplete; - // Set to true when the service disconnects, as opposed to being properly closed. This happens - // when the process crashes or gets killed by the system out-of-memory killer. - private boolean mServiceDisconnected; - // When the service disconnects (i.e. mServiceDisconnected is set to true), the status of the - // oom bindings is stashed here for future inspection. - private boolean mWasOomProtected; - private int mPid; // Process ID of the corresponding child process. - // Initial binding protects the newly spawned process from being killed before it is put to use, - // it is maintained between calls to start() and removeInitialBinding(). - private ChildServiceConnection mInitialBinding; - // Strong binding will make the service priority equal to the priority of the activity. We want - // the OS to be able to kill background renderers as it kills other background apps, so strong - // bindings are maintained only for services that are active at the moment (between - // addStrongBinding() and removeStrongBinding()). - private ChildServiceConnection mStrongBinding; - // Low priority binding maintained in the entire lifetime of the connection, i.e. between calls - // to start() and stop(). - private ChildServiceConnection mWaivedBinding; - // Incremented on addStrongBinding(), decremented on removeStrongBinding(). - private int mStrongBindingCount; - // Moderate binding will make the service priority equal to the priority of a visible process - // while the app is in the foreground. It will stay bound only while the app is in the - // foreground to protect a background process from the system out-of-memory killer. - private ChildServiceConnection mModerateBinding; - // Parameters passed to the child process through the service binding intent. // If the service gets recreated by the framework the intent will be reused, so these parameters // should be common to all processes of that type. private final Bundle mChildProcessCommonParameters; - private final boolean mAlwaysInForeground; private final ChildProcessCreationParams mCreationParams; - // Caches whether non-sandboxed and sandboxed services require an extra - // binding flag provided via ChildProcessCreationParams. - // TODO(mnaganov): Get rid of it after the release of the next Android SDK. - private static Boolean sNeedsExtrabindFlags[] = new Boolean[2]; - - private static final String TAG = "ChildProcessConnect"; - private static class ConnectionParams { final String[] mCommandLine; final FileDescriptorInfo[] mFilesToBeMapped; @@ -100,197 +188,142 @@ } } + // Synchronization: While most internal flow occurs on the UI thread, the public API + // (specifically start and stop) may be called from any thread, hence all entry point methods + // into the class are synchronized on the lock to protect access to these members. + // TODO(jcivelli): crbug.com/714657 remove this lock. + private final Object mLock = new Object(); + // This is set in start() and is used in onServiceConnected(). - private ChildProcessConnection.StartCallback mStartCallback; + @GuardedBy("mLock") + private StartCallback mStartCallback; // This is set in setupConnection() and is later used in doConnectionSetupLocked(), after which // the variable is cleared. Therefore this is only valid while the connection is being set up. + @GuardedBy("mLock") private ConnectionParams mConnectionParams; // Callback provided in setupConnection() that will communicate the result to the caller. This // has to be called exactly once after setupConnection(), even if setup fails, so that the // caller can free up resources associated with the setup attempt. This is set to null after the // call. - private ChildProcessConnection.ConnectionCallback mConnectionCallback; + @GuardedBy("mLock") + private ConnectionCallback mConnectionCallback; - private class ChildServiceConnection implements ServiceConnection { - private boolean mBound; + @GuardedBy("mLock") + private IChildProcessService mService; - private final int mBindFlags; + // Set to true when the service connection callback runs. This differs from + // mServiceConnectComplete, which tracks that the connection completed successfully. + @GuardedBy("mLock") + private boolean mDidOnServiceConnected; - private Intent createServiceBindIntent() { - Intent intent = new Intent(); - if (mCreationParams != null) { - mCreationParams.addIntentExtras(intent); - } - intent.setComponent(mServiceName); - return intent; - } + // Set to true when the service connected successfully. + @GuardedBy("mLock") + private boolean mServiceConnectComplete; - public ChildServiceConnection(int bindFlags) { - mBindFlags = bindFlags; - } + // Set to true when the service disconnects, as opposed to being properly closed. This happens + // when the process crashes or gets killed by the system out-of-memory killer. + @GuardedBy("mLock") + private boolean mServiceDisconnected; - boolean bind() { - if (!mBound) { - try { - TraceEvent.begin("ChildProcessConnectionImpl.ChildServiceConnection.bind"); - Intent intent = createServiceBindIntent(); - if (mChildProcessCommonParameters != null) { - intent.putExtras(mChildProcessCommonParameters); - } - mBound = mContext.bindService(intent, this, mBindFlags); - } finally { - TraceEvent.end("ChildProcessConnectionImpl.ChildServiceConnection.bind"); - } - } - return mBound; - } + // Process ID of the corresponding child process. + @GuardedBy("mLock") + private int mPid; - void unbind() { - if (mBound) { - mContext.unbindService(this); - mBound = false; - } - } - - boolean isBound() { - return mBound; - } - - @Override - public void onServiceConnected(ComponentName className, final IBinder service) { - LauncherThread.post(new Runnable() { - @Override - public void run() { - ChildProcessConnectionImpl.this.onServiceConnectedOnLauncherThread(service); - } - }); - } - - // Called on the main thread to notify that the child service did not disconnect gracefully. - @Override - public void onServiceDisconnected(ComponentName className) { - LauncherThread.post(new Runnable() { - @Override - public void run() { - ChildProcessConnectionImpl.this.onServiceDisconnectedOnLauncherThread(); - } - }); - } - } - - ChildProcessConnectionImpl(Context context, int number, boolean inSandbox, - ChildProcessConnection.DeathCallback deathCallback, String serviceClassName, - Bundle childProcessCommonParameters, boolean alwaysInForeground, - ChildProcessCreationParams creationParams) { + protected BaseChildProcessConnection(Context context, int number, boolean sandboxed, + DeathCallback deathCallback, String serviceClassName, + Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams) { mContext = context; mServiceNumber = number; - mInSandbox = inSandbox; + mSandboxed = sandboxed; mDeathCallback = deathCallback; String packageName = creationParams != null ? creationParams.getPackageName() : context.getPackageName(); mServiceName = new ComponentName(packageName, serviceClassName + mServiceNumber); mChildProcessCommonParameters = childProcessCommonParameters; - mAlwaysInForeground = alwaysInForeground; mCreationParams = creationParams; - int initialFlags = Context.BIND_AUTO_CREATE; - if (mAlwaysInForeground) initialFlags |= Context.BIND_IMPORTANT; - int extraBindFlags = 0; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && mCreationParams != null - && mCreationParams.getIsExternalService() - && isExportedService(inSandbox, mContext, mServiceName)) { - extraBindFlags = Context.BIND_EXTERNAL_SERVICE; - } - mInitialBinding = new ChildServiceConnection(initialFlags | extraBindFlags); - mStrongBinding = new ChildServiceConnection( - Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT | extraBindFlags); - mWaivedBinding = new ChildServiceConnection( - Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY | extraBindFlags); - mModerateBinding = new ChildServiceConnection(Context.BIND_AUTO_CREATE | extraBindFlags); } - private static boolean isExportedService(boolean inSandbox, Context context, - ComponentName serviceName) { - // Check for the cached value first. It is assumed that all pooled child services - // have identical attributes in the manifest. - final int arrayIndex = inSandbox ? 1 : 0; - if (sNeedsExtrabindFlags[arrayIndex] != null) { - return sNeedsExtrabindFlags[arrayIndex].booleanValue(); - } - boolean result = false; - try { - PackageManager packageManager = context.getPackageManager(); - ServiceInfo serviceInfo = packageManager.getServiceInfo(serviceName, 0); - result = serviceInfo.exported; - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Could not retrieve info about service %s", serviceName, e); - } - sNeedsExtrabindFlags[arrayIndex] = Boolean.valueOf(result); - return result; + public final Context getContext() { + return mContext; } - @Override - public int getServiceNumber() { + public final int getServiceNumber() { return mServiceNumber; } - @Override - public boolean isInSandbox() { - return mInSandbox; + public final boolean isSandboxed() { + return mSandboxed; } - @Override - public String getPackageName() { + public final String getPackageName() { return mCreationParams != null ? mCreationParams.getPackageName() - : mContext.getPackageName(); + : mContext.getPackageName(); } - @Override - public ChildProcessCreationParams getCreationParams() { + public final ChildProcessCreationParams getCreationParams() { return mCreationParams; } - @Override - public IChildProcessService getService() { + public final IChildProcessService getService() { synchronized (mLock) { return mService; } } - @Override + public final ComponentName getServiceName() { + return mServiceName; + } + + /** + * @return the connection pid, or 0 if not yet connected + */ public int getPid() { synchronized (mLock) { return mPid; } } - @Override - public void start(ChildProcessConnection.StartCallback startCallback) { + /** + * Starts a connection to an IChildProcessService. This must be followed by a call to + * setupConnection() to setup the connection parameters. start() and setupConnection() are + * separate to allow to pass whatever parameters are available in start(), and complete the + * remainder later while reducing the connection setup latency. + * @param startCallback (optional) callback when the child process starts or fails to start. + */ + public void start(StartCallback startCallback) { try { - TraceEvent.begin("ChildProcessConnectionImpl.start"); + TraceEvent.begin("BaseChildProcessConnection.start"); assert LauncherThread.runningOnLauncherThread(); synchronized (mLock) { - assert mConnectionParams == null : - "setupConnection() called before start() in ChildProcessConnectionImpl."; + assert mConnectionParams + == null + : "setupConnection() called before start() in BaseChildProcessConnection."; mStartCallback = startCallback; - if (!mInitialBinding.bind()) { + if (!bind()) { Log.e(TAG, "Failed to establish the service connection."); // We have to notify the caller so that they can free-up associated resources. // TODO(ppi): Can we hard-fail here? - mDeathCallback.onChildProcessDied(ChildProcessConnectionImpl.this); - } else { - mWaivedBinding.bind(); + mDeathCallback.onChildProcessDied(BaseChildProcessConnection.this); } } } finally { - TraceEvent.end("ChildProcessConnectionImpl.start"); + TraceEvent.end("BaseChildProcessConnection.start"); } } - @Override + /** + * Setups the connection after it was started with start(). + * @param commandLine (optional) will be ignored if the command line was already sent in start() + * @param filesToBeMapped a list of file descriptors that should be registered + * @param callback optional client specified callbacks that the child can use to communicate + * with the parent process + * @param connectionCallback will be called exactly once after the connection is set up or the + * setup fails + */ public void setupConnection(String[] commandLine, FileDescriptorInfo[] filesToBeMapped, @Nullable IBinder callback, ConnectionCallback connectionCallback) { assert LauncherThread.runningOnLauncherThread(); @@ -298,11 +331,11 @@ assert mConnectionParams == null; if (mServiceDisconnected) { Log.w(TAG, "Tried to setup a connection that already disconnected."); - connectionCallback.onConnected(0); + connectionCallback.onConnected(null); return; } try { - TraceEvent.begin("ChildProcessConnectionImpl.setupConnection"); + TraceEvent.begin("BaseChildProcessConnection.setupConnection"); mConnectionCallback = connectionCallback; mConnectionParams = new ConnectionParams(commandLine, filesToBeMapped, callback); // Run the setup if the service is already connected. If not, @@ -311,22 +344,19 @@ doConnectionSetupLocked(); } } finally { - TraceEvent.end("ChildProcessConnectionImpl.setupConnection"); + TraceEvent.end("BaseChildProcessConnection.setupConnection"); } } } - @Override + /** + * Terminates the connection to IChildProcessService, closing all bindings. It is safe to call + * this multiple times. + */ public void stop() { synchronized (mLock) { - mInitialBinding.unbind(); - mStrongBinding.unbind(); - mWaivedBinding.unbind(); - mModerateBinding.unbind(); - mStrongBindingCount = 0; - if (mService != null) { - mService = null; - } + unbind(); + mService = null; mConnectionParams = null; } } @@ -341,7 +371,7 @@ } try { TraceEvent.begin( - "ChildProcessConnectionImpl.ChildServiceConnection.onServiceConnected"); + "BaseChildProcessConnection.ChildServiceConnection.onServiceConnected"); mDidOnServiceConnected = true; mService = IChildProcessService.Stub.asInterface(service); @@ -381,7 +411,7 @@ } } finally { TraceEvent.end( - "ChildProcessConnectionImpl.ChildServiceConnection.onServiceConnected"); + "BaseChildProcessConnection.ChildServiceConnection.onServiceConnected"); } } } @@ -394,16 +424,14 @@ if (mServiceDisconnected) { return; } - // Stash the status of the oom bindings, since stop() will release all bindings. - mWasOomProtected = isCurrentlyOomProtected(); mServiceDisconnected = true; Log.w(TAG, "onServiceDisconnected (crash or killed by oom): pid=%d", mPid); stop(); // We don't want to auto-restart on crash. Let the browser do that. - mDeathCallback.onChildProcessDied(ChildProcessConnectionImpl.this); + mDeathCallback.onChildProcessDied(BaseChildProcessConnection.this); // If we have a pending connection callback, we need to communicate the failure to // the caller. if (mConnectionCallback != null) { - mConnectionCallback.onConnected(0); + mConnectionCallback.onConnected(null); } mConnectionCallback = null; } @@ -415,7 +443,7 @@ assert mPid != 0 : "Child service claims to be run by a process of pid=0."; if (mConnectionCallback != null) { - mConnectionCallback.onConnected(mPid); + mConnectionCallback.onConnected(this); } mConnectionCallback = null; } @@ -426,9 +454,10 @@ * connection has been established (as signaled by onServiceConnected()). These two events can * happen in any order. Has to be called with mLock. */ + @GuardedBy("mLock") private void doConnectionSetupLocked() { try { - TraceEvent.begin("ChildProcessConnectionImpl.doConnectionSetupLocked"); + TraceEvent.begin("BaseChildProcessConnection.doConnectionSetupLocked"); assert mServiceConnectComplete && mService != null; assert mConnectionParams != null; @@ -460,129 +489,55 @@ } mConnectionParams = null; } finally { - TraceEvent.end("ChildProcessConnectionImpl.doConnectionSetupLocked"); + TraceEvent.end("BaseChildProcessConnection.doConnectionSetupLocked"); } } - @Override - public boolean isInitialBindingBound() { - synchronized (mLock) { - return mInitialBinding.isBound(); - } + /** Subclasses should implement this method to bind/unbind to the actual service. */ + protected abstract boolean bind(); + protected abstract void unbind(); + + protected ChildServiceConnection createServiceConnection(int bindFlags) { + return new ChildServiceConnectionImpl(bindFlags); } - @Override - public boolean isStrongBindingBound() { - synchronized (mLock) { - return mStrongBinding.isBound(); - } + protected boolean shouldBindAsExportedService() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && getCreationParams() != null + && getCreationParams().getIsExternalService() + && isExportedService(isSandboxed(), getContext(), getServiceName()); } - @Override - public void removeInitialBinding() { - synchronized (mLock) { - assert !mAlwaysInForeground; - mInitialBinding.unbind(); + private static boolean isExportedService( + boolean inSandbox, Context context, ComponentName serviceName) { + // Check for the cached value first. It is assumed that all pooled child services + // have identical attributes in the manifest. + final int arrayIndex = inSandbox ? 1 : 0; + if (sNeedsExtrabindFlags[arrayIndex] != null) { + return sNeedsExtrabindFlags[arrayIndex].booleanValue(); } - } - - @Override - public boolean isOomProtectedOrWasWhenDied() { - synchronized (mLock) { - if (mServiceDisconnected) { - return mWasOomProtected; - } else { - return isCurrentlyOomProtected(); - } + boolean result = false; + try { + PackageManager packageManager = context.getPackageManager(); + ServiceInfo serviceInfo = packageManager.getServiceInfo(serviceName, 0); + result = serviceInfo.exported; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Could not retrieve info about service %s", serviceName, e); } - } - - private boolean isCurrentlyOomProtected() { - synchronized (mLock) { - assert !mServiceDisconnected; - if (mAlwaysInForeground) return ChildProcessLauncher.isApplicationInForeground(); - return mInitialBinding.isBound() || mStrongBinding.isBound(); - } - } - - @Override - public void dropOomBindings() { - synchronized (mLock) { - assert !mAlwaysInForeground; - mInitialBinding.unbind(); - - mStrongBindingCount = 0; - mStrongBinding.unbind(); - - mModerateBinding.unbind(); - } - } - - @Override - public void addStrongBinding() { - synchronized (mLock) { - if (mService == null) { - Log.w(TAG, "The connection is not bound for %d", mPid); - return; - } - if (mStrongBindingCount == 0) { - mStrongBinding.bind(); - } - mStrongBindingCount++; - } - } - - @Override - public void removeStrongBinding() { - synchronized (mLock) { - if (mService == null) { - Log.w(TAG, "The connection is not bound for %d", mPid); - return; - } - assert mStrongBindingCount > 0; - mStrongBindingCount--; - if (mStrongBindingCount == 0) { - mStrongBinding.unbind(); - } - } - } - - @Override - public boolean isModerateBindingBound() { - synchronized (mLock) { - return mModerateBinding.isBound(); - } - } - - @Override - public void addModerateBinding() { - synchronized (mLock) { - if (mService == null) { - Log.w(TAG, "The connection is not bound for %d", mPid); - return; - } - mModerateBinding.bind(); - } - } - - @Override - public void removeModerateBinding() { - synchronized (mLock) { - if (mService == null) { - Log.w(TAG, "The connection is not bound for %d", mPid); - return; - } - mModerateBinding.unbind(); - } + sNeedsExtrabindFlags[arrayIndex] = Boolean.valueOf(result); + return result; } @VisibleForTesting public void crashServiceForTesting() throws RemoteException { - mService.crashIntentionallyForTesting(); + synchronized (mLock) { + mService.crashIntentionallyForTesting(); + } } @VisibleForTesting public boolean isConnected() { - return mService != null; + synchronized (mLock) { + return mService != null; + } } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/BindingManager.java b/content/public/android/java/src/org/chromium/content/browser/BindingManager.java index 75fda5a8..dfa3581 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BindingManager.java +++ b/content/public/android/java/src/org/chromium/content/browser/BindingManager.java
@@ -32,7 +32,7 @@ * Registers a freshly started child process. This can be called on any thread. * @param pid handle of the service process */ - void addNewConnection(int pid, ChildProcessConnection connection); + void addNewConnection(int pid, ManagedChildProcessConnection connection); /** * Called when the service visibility changes or is determined for the first time. On low-memory @@ -70,18 +70,11 @@ void onBroughtToForeground(); /** - * @return True iff the given service process is protected from the out-of-memory killing, or it - * was protected when it died unexpectedly. This can be used to decide if a disconnection of a - * renderer was a crash or a probable out-of-memory kill. This can be called on any thread. - */ - boolean isOomProtected(int pid); - - /** * Should be called when the connection to the child process goes away (either after a clean * exit or an unexpected crash). At this point we let go of the reference to the * ChildProcessConnection. This can be called on any thread. */ - void clearConnection(int pid); + void removeConnection(int pid); /** * Starts moderate binding management.
diff --git a/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java index beb3074..81ee555 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java
@@ -22,6 +22,8 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +import javax.annotation.concurrent.GuardedBy; + /** * Manages oom bindings used to bound child services. */ @@ -47,7 +49,10 @@ private static class ModerateBindingPool extends LruCache<Integer, ManagedConnection> implements ComponentCallbacks2 { private final Object mDelayedClearerLock = new Object(); + + @GuardedBy("mDelayedClearerLock") private Runnable mDelayedClearer; + private final Handler mHandler = new Handler(ThreadUtils.getUiThreadLooper()); public ModerateBindingPool(int maxSize) { @@ -102,8 +107,8 @@ } void addConnection(ManagedConnection managedConnection) { - ChildProcessConnection connection = managedConnection.mConnection; - if (connection != null && connection.isInSandbox()) { + ManagedChildProcessConnection connection = managedConnection.mConnection; + if (connection != null && connection.isSandboxed()) { managedConnection.addModerateBinding(); if (connection.isModerateBindingBound()) { put(connection.getServiceNumber(), managedConnection); @@ -114,8 +119,8 @@ } void removeConnection(ManagedConnection managedConnection) { - ChildProcessConnection connection = managedConnection.mConnection; - if (connection != null && connection.isInSandbox()) { + ManagedChildProcessConnection connection = managedConnection.mConnection; + if (connection != null && connection.isSandboxed()) { remove(connection.getServiceNumber()); } } @@ -163,15 +168,15 @@ new AtomicReference<>(); /** - * Wraps ChildProcessConnection keeping track of additional information needed to manage the - * bindings of the connection. The reference to ChildProcessConnection is cleared when the - * connection goes away, but ManagedConnection itself is kept (until overwritten by a new entry - * for the same pid). + * Wraps ManagedChildProcessConnection keeping track of additional information needed to manage + * the bindings of the connection. The reference to ManagedChildProcessConnection is cleared + * when the connection goes away, but ManagedConnection itself is kept (until overwritten by a + * new entry for the same pid). */ private class ManagedConnection { // Set in constructor, cleared in clearConnection() (on a separate thread). // Need to keep a local reference to avoid it being cleared while using it. - private ChildProcessConnection mConnection; + private ManagedChildProcessConnection mConnection; // True iff there is a strong binding kept on the service because it is working in // foreground. @@ -181,15 +186,12 @@ // application background period. private boolean mBoundForBackgroundPeriod; - // When mConnection is cleared, oom binding status is stashed here. - private boolean mWasOomProtected; - /** * Removes the initial service binding. * @return true if the binding was removed. */ private boolean removeInitialBinding() { - ChildProcessConnection connection = mConnection; + ManagedChildProcessConnection connection = mConnection; if (connection == null || !connection.isInitialBindingBound()) return false; connection.removeInitialBinding(); @@ -198,7 +200,7 @@ /** Adds a strong service binding. */ private void addStrongBinding() { - ChildProcessConnection connection = mConnection; + ManagedChildProcessConnection connection = mConnection; if (connection == null) return; connection.addStrongBinding(); @@ -208,7 +210,7 @@ /** Removes a strong service binding. */ private void removeStrongBinding(final boolean keepAsModerate) { - final ChildProcessConnection connection = mConnection; + final ManagedChildProcessConnection connection = mConnection; // We have to fail gracefully if the strong binding is not present, as on low-end the // binding could have been removed by dropOomBindings() when a new service was started. if (connection == null || !connection.isStrongBindingBound()) return; @@ -239,7 +241,7 @@ * binding. * @param connection The ChildProcessConnection to add to the moderate binding pool. */ - private void addConnectionToModerateBindingPool(ChildProcessConnection connection) { + private void addConnectionToModerateBindingPool(ManagedChildProcessConnection connection) { ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); if (moderateBindingPool != null && !connection.isStrongBindingBound()) { moderateBindingPool.addConnection(ManagedConnection.this); @@ -248,15 +250,14 @@ /** Removes the moderate service binding. */ private void removeModerateBinding() { - ChildProcessConnection connection = mConnection; + ManagedChildProcessConnection connection = mConnection; if (connection == null || !connection.isModerateBindingBound()) return; - connection.removeModerateBinding(); } /** Adds the moderate service binding. */ private void addModerateBinding() { - ChildProcessConnection connection = mConnection; + ManagedChildProcessConnection connection = mConnection; if (connection == null) return; connection.addModerateBinding(); @@ -268,13 +269,13 @@ */ private void dropBindings() { assert mIsLowMemoryDevice; - ChildProcessConnection connection = mConnection; + ManagedChildProcessConnection connection = mConnection; if (connection == null) return; connection.dropOomBindings(); } - ManagedConnection(ChildProcessConnection connection) { + ManagedConnection(ManagedChildProcessConnection connection) { mConnection = connection; } @@ -315,27 +316,11 @@ mBoundForBackgroundPeriod = nextBound; } - boolean isOomProtected() { - // When a process crashes, we can be queried about its oom status before or after the - // connection is cleared. For the latter case, the oom status is stashed in - // mWasOomProtected. - ChildProcessConnection connection = mConnection; - return connection != null - ? connection.isOomProtectedOrWasWhenDied() : mWasOomProtected; - } - void clearConnection() { - mWasOomProtected = mConnection.isOomProtectedOrWasWhenDied(); ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); if (moderateBindingPool != null) moderateBindingPool.removeConnection(this); mConnection = null; } - - /** @return true iff the reference to the connection is no longer held */ - @VisibleForTesting - boolean isConnectionCleared() { - return mConnection == null; - } } // This can be manipulated on different threads, synchronize access on mManagedConnections. @@ -381,7 +366,7 @@ } @Override - public void addNewConnection(int pid, ChildProcessConnection connection) { + public void addNewConnection(int pid, ManagedChildProcessConnection connection) { // This will reset the previous entry for the pid in the unlikely event of the OS // reusing renderer pids. synchronized (mManagedConnections) { @@ -454,31 +439,24 @@ } @Override - public boolean isOomProtected(int pid) { - // In the unlikely event of the OS reusing renderer pid, the call will refer to the most - // recent renderer of the given pid. The binding state for a pid is being reset in - // addNewConnection(). + public void removeConnection(int pid) { ManagedConnection managedConnection; synchronized (mManagedConnections) { managedConnection = mManagedConnections.get(pid); + if (managedConnection != null) { + mManagedConnections.remove(pid); + } } - return managedConnection != null ? managedConnection.isOomProtected() : false; - } - - @Override - public void clearConnection(int pid) { - ManagedConnection managedConnection; - synchronized (mManagedConnections) { - managedConnection = mManagedConnections.get(pid); + if (managedConnection != null) { + managedConnection.clearConnection(); } - if (managedConnection != null) managedConnection.clearConnection(); } /** @return true iff the connection reference is no longer held */ @VisibleForTesting public boolean isConnectionCleared(int pid) { synchronized (mManagedConnections) { - return mManagedConnections.get(pid).isConnectionCleared(); + return mManagedConnections.get(pid) == null; } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java b/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java index 43c0367..7e3e9db 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java
@@ -48,8 +48,11 @@ private static int sSandboxedServicesCountForTesting = -1; private static String sSandboxedServicesNameForTesting; + // The factory used to create BaseChildProcessConnection instances. + private final BaseChildProcessConnection.Factory mConnectionFactory; + // Connections to services. Indices of the array correspond to the service numbers. - private final ChildProcessConnection[] mChildProcessConnections; + private final BaseChildProcessConnection[] mChildProcessConnections; private final String mChildClassName; private final boolean mInSandbox; @@ -63,11 +66,12 @@ @SuppressFBWarnings("LI_LAZY_INIT_STATIC") // Method is single thread. public static ChildConnectionAllocator getAllocator( - Context context, String packageName, boolean inSandbox) { + Context context, String packageName, boolean sandboxed) { assert LauncherThread.runningOnLauncherThread(); - if (!inSandbox) { + if (!sandboxed) { if (sPrivilegedChildConnectionAllocator == null) { - sPrivilegedChildConnectionAllocator = new ChildConnectionAllocator(false, + sPrivilegedChildConnectionAllocator = new ChildConnectionAllocator( + ImportantChildProcessConnection.FACTORY, false /* sandboxed */, getNumberOfServices(context, false, packageName), getClassNameOfService(context, false, packageName)); } @@ -83,8 +87,8 @@ + " inSandbox = true", packageName); sSandboxedChildConnectionAllocatorMap.put(packageName, - new ChildConnectionAllocator(true, - getNumberOfServices(context, true, packageName), + new ChildConnectionAllocator(ManagedChildProcessConnection.FACTORY, + true /* sandboxed */, getNumberOfServices(context, true, packageName), getClassNameOfService(context, true, packageName))); } return sSandboxedChildConnectionAllocatorMap.get(packageName); @@ -160,9 +164,10 @@ sSandboxedServicesNameForTesting = serviceName; } - private ChildConnectionAllocator( + private ChildConnectionAllocator(BaseChildProcessConnection.Factory connectionFactory, boolean inSandbox, int numChildServices, String serviceClassName) { - mChildProcessConnections = new ChildProcessConnectionImpl[numChildServices]; + mConnectionFactory = connectionFactory; + mChildProcessConnections = new BaseChildProcessConnection[numChildServices]; mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); for (int i = 0; i < numChildServices; i++) { mFreeConnectionIndices.add(i); @@ -172,9 +177,9 @@ } // Allocates or enqueues. If there are no free slots, returns null and enqueues the spawn data. - public ChildProcessConnection allocate(ChildSpawnData spawnData, - ChildProcessConnection.DeathCallback deathCallback, Bundle childProcessCommonParameters, - boolean queueIfNoSlotAvailable) { + public BaseChildProcessConnection allocate(ChildSpawnData spawnData, + BaseChildProcessConnection.DeathCallback deathCallback, + Bundle childProcessCommonParameters, boolean queueIfNoSlotAvailable) { assert LauncherThread.runningOnLauncherThread(); assert spawnData.isInSandbox() == mInSandbox; if (mFreeConnectionIndices.isEmpty()) { @@ -186,15 +191,15 @@ } int slot = mFreeConnectionIndices.remove(0); assert mChildProcessConnections[slot] == null; - mChildProcessConnections[slot] = new ChildProcessConnectionImpl(spawnData.getContext(), - slot, mInSandbox, deathCallback, mChildClassName, childProcessCommonParameters, - spawnData.isAlwaysInForeground(), spawnData.getCreationParams()); + mChildProcessConnections[slot] = mConnectionFactory.create(spawnData.getContext(), slot, + mInSandbox, deathCallback, mChildClassName, childProcessCommonParameters, + spawnData.getCreationParams()); Log.d(TAG, "Allocator allocated a connection, sandbox: %b, slot: %d", mInSandbox, slot); return mChildProcessConnections[slot]; } // Also return the first ChildSpawnData in the pending queue, if any. - public ChildSpawnData free(ChildProcessConnection connection) { + public ChildSpawnData free(BaseChildProcessConnection connection) { assert LauncherThread.runningOnLauncherThread(); int slot = connection.getServiceNumber(); if (mChildProcessConnections[slot] != connection) { @@ -228,7 +233,7 @@ } @VisibleForTesting - ChildProcessConnection[] connectionArrayForTesting() { + BaseChildProcessConnection[] connectionArrayForTesting() { return mChildProcessConnections; }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnection.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnection.java deleted file mode 100644 index 79bb922..0000000 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnection.java +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright 2012 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.content.browser; - -import android.os.IBinder; - -import org.chromium.base.process_launcher.ChildProcessCreationParams; -import org.chromium.base.process_launcher.FileDescriptorInfo; -import org.chromium.base.process_launcher.IChildProcessService; - -import javax.annotation.Nullable; - -/** - * Manages a connection between the browser activity and a child service. ChildProcessConnection is - * responsible for estabilishing the connection (start()), closing it (stop()) and manipulating the - * bindings held onto the service (addStrongBinding(), removeStrongBinding(), - * removeInitialBinding()). - */ -public interface ChildProcessConnection { - /** - * Used to notify the consumer about disconnection of the service. This callback is provided - * earlier than ConnectionCallbacks below, as a child process might die before the connection is - * fully set up. - */ - interface DeathCallback { - // Called on Launcher thread. - void onChildProcessDied(ChildProcessConnection connection); - } - - /** - * Used to notify the consumer about the process start. These callbacks will be invoked before - * the ConnectionCallbacks. - */ - interface StartCallback { - /** - * Called when the child process has successfully started and is ready for connection - * setup. - */ - void onChildStarted(); - - /** - * Called when the child process failed to start. This can happen if the process is already - * in use by another client. - */ - void onChildStartFailed(); - } - - /** - * Used to notify the consumer about the connection being established. - */ - interface ConnectionCallback { - /** - * Called when the connection to the service is established. - * @param pid the pid of the child process - */ - void onConnected(int pid); - } - - int getServiceNumber(); - - boolean isInSandbox(); - - String getPackageName(); - - ChildProcessCreationParams getCreationParams(); - - IChildProcessService getService(); - - /** - * @return the connection pid, or 0 if not yet connected - */ - int getPid(); - - /** - * Starts a connection to an IChildProcessService. This must be followed by a call to - * setupConnection() to setup the connection parameters. start() and setupConnection() are - * separate to allow to pass whatever parameters are available in start(), and complete the - * remainder later while reducing the connection setup latency. - * @param startCallback (optional) callback when the child process starts or fails to start. - */ - void start(StartCallback startCallback); - - /** - * Setups the connection after it was started with start(). - * @param commandLine (optional) will be ignored if the command line was already sent in start() - * @param filesToBeMapped a list of file descriptors that should be registered - * @param callback optional client specified callbacks that the child can use to communicate - * with the parent process - * @param connectionCallback will be called exactly once after the connection is set up or the - * setup fails - */ - void setupConnection(String[] commandLine, FileDescriptorInfo[] filesToBeMapped, - @Nullable IBinder callback, ConnectionCallback connectionCallback); - - /** - * Terminates the connection to IChildProcessService, closing all bindings. It is safe to call - * this multiple times. - */ - void stop(); - - /** @return true iff the initial oom binding is currently bound. */ - boolean isInitialBindingBound(); - - /** @return true iff the strong oom binding is currently bound. */ - boolean isStrongBindingBound(); - - /** - * Called to remove the strong binding established when the connection was started. It is safe - * to call this multiple times. - */ - void removeInitialBinding(); - - /** - * For live connections, this returns true iff either the initial or the strong binding is - * bound, i.e. the connection has at least one oom binding. For connections that disconnected - * (did not exit properly), this returns true iff the connection had at least one oom binding - * when it disconnected. - */ - boolean isOomProtectedOrWasWhenDied(); - - /** - * Unbinds the bindings that protect the process from oom killing. It is safe to call this - * multiple times, before as well as after stop(). - */ - void dropOomBindings(); - - /** - * Attaches a strong binding that will make the service as important as the main process. Each - * call should be succeeded by removeStrongBinding(), but multiple strong bindings can be - * requested and released independently. - */ - void addStrongBinding(); - - /** - * Called when the service is no longer in active use of the consumer. - */ - void removeStrongBinding(); - - /** - * Attaches a moderate binding that will give the service the priority of a visible process, but - * keep the priority below a strongly bound process. - */ - void addModerateBinding(); - - /** - * Called when the service is no longer in moderate use of the consumer. - */ - void removeModerateBinding(); - - /** @return true iff the moderate oom binding is currently bound. */ - boolean isModerateBindingBound(); -}
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java index c6e5262..611e2a1b 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -36,18 +36,20 @@ /** * Implemented by ChildProcessLauncherHelper. */ - public interface LaunchCallback { void onChildProcessStarted(int pid); } + public interface LaunchCallback { + void onChildProcessStarted(BaseChildProcessConnection connection); + } private static final boolean SPARE_CONNECTION_ALWAYS_IN_FOREGROUND = false; @VisibleForTesting - static ChildProcessConnection allocateConnection( + static BaseChildProcessConnection allocateConnection( ChildSpawnData spawnData, Bundle childProcessCommonParams, boolean forWarmUp) { assert LauncherThread.runningOnLauncherThread(); - ChildProcessConnection.DeathCallback deathCallback = - new ChildProcessConnection.DeathCallback() { + BaseChildProcessConnection.DeathCallback deathCallback = + new BaseChildProcessConnection.DeathCallback() { @Override - public void onChildProcessDied(ChildProcessConnection connection) { + public void onChildProcessDied(BaseChildProcessConnection connection) { assert LauncherThread.runningOnLauncherThread(); if (connection.getPid() != 0) { stop(connection.getPid()); @@ -106,14 +108,14 @@ } @VisibleForTesting - static ChildProcessConnection allocateBoundConnection(ChildSpawnData spawnData, - ChildProcessConnection.StartCallback startCallback, boolean forWarmUp) { + static BaseChildProcessConnection allocateBoundConnection(ChildSpawnData spawnData, + BaseChildProcessConnection.StartCallback startCallback, boolean forWarmUp) { assert LauncherThread.runningOnLauncherThread(); final Context context = spawnData.getContext(); final boolean inSandbox = spawnData.isInSandbox(); final ChildProcessCreationParams creationParams = spawnData.getCreationParams(); - ChildProcessConnection connection = allocateConnection( + BaseChildProcessConnection connection = allocateConnection( spawnData, createCommonParamsBundle(spawnData.getCreationParams()), forWarmUp); if (connection != null) { connection.start(startCallback); @@ -121,7 +123,8 @@ String packageName = creationParams != null ? creationParams.getPackageName() : context.getPackageName(); if (inSandbox - && !ChildConnectionAllocator.getAllocator(context, packageName, inSandbox) + && !ChildConnectionAllocator + .getAllocator(context, packageName, true /* sandboxed */) .isFreeConnectionAvailable()) { // Proactively releases all the moderate bindings once all the sandboxed services // are allocated, which will be very likely to have some of them killed by OOM @@ -134,7 +137,7 @@ private static final long FREE_CONNECTION_DELAY_MILLIS = 1; - private static void freeConnection(ChildProcessConnection connection) { + private static void freeConnection(BaseChildProcessConnection connection) { assert LauncherThread.runningOnLauncherThread(); if (connection == sSpareSandboxedConnection) clearSpareConnection(); @@ -143,7 +146,7 @@ // alive when it's been unbound for a short time. If a new connection to the same service // is bound at that point, the process is reused and bad things happen (mostly static // variables are set when we don't expect them to). - final ChildProcessConnection conn = connection; + final BaseChildProcessConnection conn = connection; LauncherThread.postDelayed(new Runnable() { @Override public void run() { @@ -154,7 +157,7 @@ // ChildProcessLauncherHelper, we'll have a context around that we can pass in // there. ChildConnectionAllocator allocator = ChildConnectionAllocator.getAllocator( - null /* context */, conn.getPackageName(), conn.isInSandbox()); + null /* context */, conn.getPackageName(), conn.isSandboxed()); assert allocator != null; final ChildSpawnData pendingSpawn = allocator.free(conn); if (pendingSpawn != null) { @@ -175,12 +178,9 @@ }, FREE_CONNECTION_DELAY_MILLIS); } - // Represents an invalid process handle; same as base/process/process.h kNullProcessHandle. - private static final int NULL_PROCESS_HANDLE = 0; - // Map from pid to ChildService connection. - private static Map<Integer, ChildProcessConnection> sServiceMap = - new ConcurrentHashMap<Integer, ChildProcessConnection>(); + private static Map<Integer, BaseChildProcessConnection> sServiceMap = + new ConcurrentHashMap<Integer, BaseChildProcessConnection>(); // Lock for getBindingManager() private static final Object sBindingManagerLock = new Object(); @@ -192,9 +192,9 @@ // This is used for a child process allocation to determine if StartCallback should be chained. // |sSpareConnectionStartCallback| is the chained StartCallback. This is also used to determine // if there is already a child process launch that's used this this connection. - private static ChildProcessConnection sSpareSandboxedConnection; + private static BaseChildProcessConnection sSpareSandboxedConnection; private static boolean sSpareConnectionStarting; - private static ChildProcessConnection.StartCallback sSpareConnectionStartCallback; + private static BaseChildProcessConnection.StartCallback sSpareConnectionStartCallback; // Manages oom bindings used to bind chind services. Lazily initialized by getBindingManager() private static BindingManager sBindingManager; @@ -278,8 +278,8 @@ if (sSpareSandboxedConnection != null) return; ChildProcessCreationParams params = ChildProcessCreationParams.getDefault(); - ChildProcessConnection.StartCallback startCallback = - new ChildProcessConnection.StartCallback() { + BaseChildProcessConnection.StartCallback startCallback = + new BaseChildProcessConnection.StartCallback() { @Override public void onChildStarted() { assert LauncherThread.runningOnLauncherThread(); @@ -347,7 +347,7 @@ if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { if (params != null && !params.getPackageName().equals(context.getPackageName())) { // WebViews and WebAPKs have renderer processes running in their applications. - // When launching these renderer processes, {@link ChildProcessConnectionImpl} + // When launching these renderer processes, {@link ManagedChildProcessConnection} // requires the package name of the application which holds the renderer process. // Therefore, the package name in ChildProcessCreationParams could be the package // name of WebViews, WebAPKs, or Chrome, depending on the host application. @@ -375,7 +375,7 @@ } @VisibleForTesting - public static ChildProcessConnection startInternal(final Context context, + public static BaseChildProcessConnection startInternal(final Context context, final String[] commandLine, final int childProcessId, final FileDescriptorInfo[] filesToBeMapped, final LaunchCallback launchCallback, final IBinder childProcessCallback, final boolean inSandbox, @@ -384,18 +384,18 @@ try { TraceEvent.begin("ChildProcessLauncher.startInternal"); - ChildProcessConnection allocatedConnection = null; + BaseChildProcessConnection allocatedConnection = null; String packageName = creationParams != null ? creationParams.getPackageName() : context.getPackageName(); - ChildProcessConnection.StartCallback startCallback = - new ChildProcessConnection.StartCallback() { + BaseChildProcessConnection.StartCallback startCallback = + new BaseChildProcessConnection.StartCallback() { @Override public void onChildStarted() {} @Override public void onChildStartFailed() { assert LauncherThread.runningOnLauncherThread(); - Log.e(TAG, "ChildProcessConnection.start failed, trying again"); + Log.e(TAG, "BaseChildProcessConnection.start failed, trying again"); LauncherThread.post(new Runnable() { @Override public void run() { @@ -464,25 +464,29 @@ } @VisibleForTesting - static void triggerConnectionSetup(final ChildProcessConnection connection, + static void triggerConnectionSetup(final BaseChildProcessConnection connection, String[] commandLine, int childProcessId, FileDescriptorInfo[] filesToBeMapped, final IBinder childProcessCallback, final LaunchCallback launchCallback) { assert LauncherThread.runningOnLauncherThread(); Log.d(TAG, "Setting up connection to process: slot=%d", connection.getServiceNumber()); - ChildProcessConnection.ConnectionCallback connectionCallback = - new ChildProcessConnection.ConnectionCallback() { + BaseChildProcessConnection.ConnectionCallback connectionCallback = + new BaseChildProcessConnection.ConnectionCallback() { @Override - public void onConnected(int pid) { - Log.d(TAG, "on connect callback, pid=%d", pid); - if (pid != NULL_PROCESS_HANDLE) { - getBindingManager().addNewConnection(pid, connection); + public void onConnected(BaseChildProcessConnection connection) { + if (connection != null) { + int pid = connection.getPid(); + Log.d(TAG, "on connect callback, pid=%d", pid); + if (connection instanceof ManagedChildProcessConnection) { + getBindingManager().addNewConnection( + pid, (ManagedChildProcessConnection) connection); + } sServiceMap.put(pid, connection); } // If the connection fails and pid == 0, the Java-side cleanup was already // handled by DeathCallback. We still have to call back to native for // cleanup there. if (launchCallback != null) { // Will be null in Java instrumentation tests. - launchCallback.onChildProcessStarted(pid); + launchCallback.onChildProcessStarted(connection); } } }; @@ -499,12 +503,12 @@ static void stop(int pid) { assert LauncherThread.runningOnLauncherThread(); Log.d(TAG, "stopping child connection: pid=%d", pid); - ChildProcessConnection connection = sServiceMap.remove(pid); + BaseChildProcessConnection connection = sServiceMap.remove(pid); if (connection == null) { // Can happen for single process. return; } - getBindingManager().clearConnection(pid); + getBindingManager().removeConnection(pid); connection.stop(); freeConnection(connection); } @@ -524,7 +528,7 @@ if (sServiceMap.get(pid) == null) return false; try { - ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForTesting(); + ((ManagedChildProcessConnection) sServiceMap.get(pid)).crashServiceForTesting(); } catch (RemoteException ex) { return false; }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java index cd0f0703..ffe74a8 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
@@ -25,9 +25,12 @@ class ChildProcessLauncherHelper { private static final String TAG = "ChildProcLH"; + // Represents an invalid process handle; same as base/process/process.h kNullProcessHandle. + private static final int NULL_PROCESS_HANDLE = 0; + // Note native pointer is only guaranteed live until nativeOnChildProcessStarted. private long mNativeChildProcessLauncherHelper; - private int mPid; + private BaseChildProcessConnection mChildProcessConnection; @CalledByNative private static FileDescriptorInfo makeFdInfo( @@ -64,27 +67,47 @@ ChildProcessLauncher.start(ContextUtils.getApplicationContext(), paramId, commandLine, childProcessId, filesToBeMapped, new ChildProcessLauncher.LaunchCallback() { @Override - public void onChildProcessStarted(int pid) { - mPid = pid; + public void onChildProcessStarted(BaseChildProcessConnection connection) { + mChildProcessConnection = connection; if (mNativeChildProcessLauncherHelper != 0) { - nativeOnChildProcessStarted(mNativeChildProcessLauncherHelper, pid); + nativeOnChildProcessStarted( + mNativeChildProcessLauncherHelper, getPid()); } mNativeChildProcessLauncherHelper = 0; } }); } + private int getPid() { + return mChildProcessConnection == null ? NULL_PROCESS_HANDLE + : mChildProcessConnection.getPid(); + } + // Called on client (UI or IO) thread. @CalledByNative private boolean isOomProtected() { - return ChildProcessLauncher.getBindingManager().isOomProtected(mPid); + // mChildProcessConnection is set on a different thread but does not change once it's been + // set. So it is safe to test whether it's null from a different thread. + if (mChildProcessConnection == null) { + return false; + } + + if (mChildProcessConnection instanceof ImportantChildProcessConnection) { + // The connection was bound as BIND_IMPORTANT. This should prevent it from being killed + // when the app is on the foreground (that's our best guess, but there is no absolute + // guarantee). + return ChildProcessLauncher.isApplicationInForeground(); + } + + return ((ManagedChildProcessConnection) mChildProcessConnection) + .isOomProtectedOrWasWhenDied(); } @CalledByNative private void setInForeground(int pid, boolean inForeground) { assert LauncherThread.runningOnLauncherThread(); - assert mPid == pid; - ChildProcessLauncher.getBindingManager().setInForeground(mPid, inForeground); + assert getPid() == pid; + ChildProcessLauncher.getBindingManager().setInForeground(pid, inForeground); } @CalledByNative
diff --git a/content/public/android/java/src/org/chromium/content/browser/ImportantChildProcessConnection.java b/content/public/android/java/src/org/chromium/content/browser/ImportantChildProcessConnection.java new file mode 100644 index 0000000..ec5b738e --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/browser/ImportantChildProcessConnection.java
@@ -0,0 +1,50 @@ +// 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. + +package org.chromium.content.browser; + +import android.content.Context; +import android.os.Bundle; + +import org.chromium.base.process_launcher.ChildProcessCreationParams; + +/** + * A connection that is bound as important, meaning the framework brings it to the foreground + * process level when the app is. + */ +public class ImportantChildProcessConnection extends BaseChildProcessConnection { + public static final Factory FACTORY = new BaseChildProcessConnection.Factory() { + @Override + public BaseChildProcessConnection create(Context context, int number, boolean sandboxed, + DeathCallback deathCallback, String serviceClassName, + Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams) { + return new ImportantChildProcessConnection(context, number, sandboxed, deathCallback, + serviceClassName, childProcessCommonParameters, creationParams); + } + }; + + private final ChildServiceConnection mBinding; + + private ImportantChildProcessConnection(Context context, int number, boolean sandboxed, + DeathCallback deathCallback, String serviceClassName, + Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams) { + super(context, number, sandboxed, deathCallback, serviceClassName, + childProcessCommonParameters, creationParams); + int flags = Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT; + if (shouldBindAsExportedService()) { + flags |= Context.BIND_EXTERNAL_SERVICE; + } + mBinding = createServiceConnection(flags); + } + + @Override + public boolean bind() { + return mBinding.bind(); + } + + @Override + public void unbind() { + mBinding.unbind(); + } +}
diff --git a/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java b/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java index 622b92b..f9732a60 100644 --- a/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java +++ b/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java
@@ -8,6 +8,7 @@ import android.os.Looper; import org.chromium.base.JavaHandlerThread; +import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -16,10 +17,13 @@ public final class LauncherThread { private static final JavaHandlerThread sThread = new JavaHandlerThread("Chrome_ProcessLauncherThread"); - private static final Handler sHandler; + private static final Handler sThreadHandler; + // Can be overritten in tests. + private static Handler sHandler; static { sThread.maybeStart(); - sHandler = new Handler(sThread.getLooper()); + sThreadHandler = new Handler(sThread.getLooper()); + sHandler = sThreadHandler; } public static void post(Runnable r) { @@ -34,6 +38,16 @@ return sHandler.getLooper() == Looper.myLooper(); } + @VisibleForTesting + public static void setCurrentThreadAsLauncherThread() { + sHandler = new Handler(); + } + + @VisibleForTesting + public static void setLauncherThreadAsLauncherThread() { + sHandler = sThreadHandler; + } + @CalledByNative private static JavaHandlerThread getHandlerThread() { return sThread;
diff --git a/content/public/android/java/src/org/chromium/content/browser/ManagedChildProcessConnection.java b/content/public/android/java/src/org/chromium/content/browser/ManagedChildProcessConnection.java new file mode 100644 index 0000000..99f4122 --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/browser/ManagedChildProcessConnection.java
@@ -0,0 +1,225 @@ +// 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. + +package org.chromium.content.browser; + +import android.content.Context; +import android.os.Bundle; + +import org.chromium.base.Log; +import org.chromium.base.VisibleForTesting; +import org.chromium.base.process_launcher.ChildProcessCreationParams; + +import javax.annotation.concurrent.GuardedBy; + +/** + * ManagedChildProcessConnection is a connection to a child service that can hold several bindings + * to the service so it can be more or less agressively protected against OOM. + */ +public class ManagedChildProcessConnection extends BaseChildProcessConnection { + private static final String TAG = "ManChildProcessConn"; + + public static final Factory FACTORY = new BaseChildProcessConnection.Factory() { + @Override + public BaseChildProcessConnection create(Context context, int number, boolean sandboxed, + DeathCallback deathCallback, String serviceClassName, + Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams) { + return new ManagedChildProcessConnection(context, number, sandboxed, deathCallback, + serviceClassName, childProcessCommonParameters, creationParams); + } + }; + + // Synchronization: While most internal flow occurs on the UI thread, the public API + // (specifically start and stop) may be called from any thread, hence all entry point methods + // into the class are synchronized on the lock to protect access to these members. + private final Object mBindingLock = new Object(); + + // Initial binding protects the newly spawned process from being killed before it is put to use, + // it is maintained between calls to start() and removeInitialBinding(). + @GuardedBy("mBindingLock") + private final ChildServiceConnection mInitialBinding; + + // Strong binding will make the service priority equal to the priority of the activity. We want + // the OS to be able to kill background renderers as it kills other background apps, so strong + // bindings are maintained only for services that are active at the moment (between + // addStrongBinding() and removeStrongBinding()). + @GuardedBy("mBindingLock") + private final ChildServiceConnection mStrongBinding; + + // Low priority binding maintained in the entire lifetime of the connection, i.e. between calls + // to start() and stop(). + @GuardedBy("mBindingLock") + private final ChildServiceConnection mWaivedBinding; + + // Incremented on addStrongBinding(), decremented on removeStrongBinding(). + @GuardedBy("mBindingLock") + private int mStrongBindingCount; + + // Moderate binding will make the service priority equal to the priority of a visible process + // while the app is in the foreground. It will stay bound only while the app is in the + // foreground to protect a background process from the system out-of-memory killer. + @GuardedBy("mBindingLock") + private final ChildServiceConnection mModerateBinding; + + @GuardedBy("mBindingLock") + private boolean mWasOomProtectedOnUnbind; + + @VisibleForTesting + ManagedChildProcessConnection(Context context, int number, boolean sandboxed, + DeathCallback deathCallback, String serviceClassName, + Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams) { + super(context, number, sandboxed, deathCallback, serviceClassName, + childProcessCommonParameters, creationParams); + + int initialFlags = Context.BIND_AUTO_CREATE; + int extraBindFlags = shouldBindAsExportedService() ? Context.BIND_EXTERNAL_SERVICE : 0; + + synchronized (mBindingLock) { + mInitialBinding = createServiceConnection(initialFlags | extraBindFlags); + mStrongBinding = createServiceConnection( + Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT | extraBindFlags); + mWaivedBinding = createServiceConnection( + Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY | extraBindFlags); + mModerateBinding = createServiceConnection(Context.BIND_AUTO_CREATE | extraBindFlags); + } + } + + @Override + protected boolean bind() { + synchronized (mBindingLock) { + if (!mInitialBinding.bind()) { + return false; + } + mWaivedBinding.bind(); + } + return true; + } + + @Override + public void unbind() { + synchronized (mBindingLock) { + if (!isBound()) { + return; + } + mWasOomProtectedOnUnbind = isCurrentlyOomProtected(); + mInitialBinding.unbind(); + mStrongBinding.unbind(); + mWaivedBinding.unbind(); + mModerateBinding.unbind(); + mStrongBindingCount = 0; + } + } + + @GuardedBy("mBindingLock") + private boolean isBound() { + return mInitialBinding.isBound() || mStrongBinding.isBound() || mWaivedBinding.isBound() + || mModerateBinding.isBound(); + } + + public boolean isInitialBindingBound() { + synchronized (mBindingLock) { + return mInitialBinding.isBound(); + } + } + + public boolean isStrongBindingBound() { + synchronized (mBindingLock) { + return mStrongBinding.isBound(); + } + } + + public void removeInitialBinding() { + synchronized (mBindingLock) { + mInitialBinding.unbind(); + } + } + + public boolean isOomProtectedOrWasWhenDied() { + // Call isConnected() outside of the synchronized block or we could deadlock. + final boolean isConnected = isConnected(); + synchronized (mBindingLock) { + if (isConnected) { + return isCurrentlyOomProtected(); + } + return mWasOomProtectedOnUnbind; + } + } + + @GuardedBy("mBindingLock") + private boolean isCurrentlyOomProtected() { + return mInitialBinding.isBound() || mStrongBinding.isBound(); + } + + public void dropOomBindings() { + synchronized (mBindingLock) { + mInitialBinding.unbind(); + + mStrongBindingCount = 0; + mStrongBinding.unbind(); + + mModerateBinding.unbind(); + } + } + + public void addStrongBinding() { + // Call isConnected() outside of the synchronized block or we could deadlock. + final boolean isConnected = isConnected(); + synchronized (mBindingLock) { + if (!isConnected) { + Log.w(TAG, "The connection is not bound for %d", getPid()); + return; + } + if (mStrongBindingCount == 0) { + mStrongBinding.bind(); + } + mStrongBindingCount++; + } + } + + public void removeStrongBinding() { + // Call isConnected() outside of the synchronized block or we could deadlock. + final boolean isConnected = isConnected(); + synchronized (mBindingLock) { + if (!isConnected) { + Log.w(TAG, "The connection is not bound for %d", getPid()); + return; + } + assert mStrongBindingCount > 0; + mStrongBindingCount--; + if (mStrongBindingCount == 0) { + mStrongBinding.unbind(); + } + } + } + + public boolean isModerateBindingBound() { + synchronized (mBindingLock) { + return mModerateBinding.isBound(); + } + } + + public void addModerateBinding() { + // Call isConnected() outside of the synchronized block or we could deadlock. + final boolean isConnected = isConnected(); + synchronized (mBindingLock) { + if (!isConnected) { + Log.w(TAG, "The connection is not bound for %d", getPid()); + return; + } + mModerateBinding.bind(); + } + } + + public void removeModerateBinding() { + // Call isConnected() outside of the synchronized block or we could deadlock. + final boolean isConnected = isConnected(); + synchronized (mBindingLock) { + if (!isConnected) { + Log.w(TAG, "The connection is not bound for %d", getPid()); + return; + } + mModerateBinding.unbind(); + } + } +}
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java index c4f1d473..7ed9f11 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
@@ -102,7 +102,7 @@ Assert.assertEquals(0, ChildProcessLauncher.connectedServicesCountForTesting()); // Start and connect to a new service. - final ChildProcessConnectionImpl connection = startConnection(); + final BaseChildProcessConnection connection = startConnection(); Assert.assertEquals(1, allocatedChromeSandboxedConnectionsCount()); // Verify that the service is not yet set up. @@ -138,7 +138,7 @@ Assert.assertEquals(0, allocatedChromeSandboxedConnectionsCount()); // Start and connect to a new service. - final ChildProcessConnectionImpl connection = startConnection(); + final BaseChildProcessConnection connection = startConnection(); Assert.assertEquals(1, allocatedChromeSandboxedConnectionsCount()); // Initiate the connection setup. @@ -193,7 +193,7 @@ Assert.assertEquals(0, allocatedChromeSandboxedConnectionsCount()); // Start and connect to a new service. - final ChildProcessConnectionImpl connection = startConnection(); + final BaseChildProcessConnection connection = startConnection(); Assert.assertEquals(1, allocatedChromeSandboxedConnectionsCount()); // Queue up a new spawn request. There is no way to kill the pending connection, leak it @@ -269,10 +269,10 @@ Assert.assertEquals(0, allocatedChromeSandboxedConnectionsCount()); // Start and connect to a new service of an external APK. - ChildProcessConnectionImpl externalApkConnection = + BaseChildProcessConnection externalApkConnection = allocateConnection(EXTERNAL_APK_PACKAGE_NAME); // Start and connect to a new service for a regular tab. - ChildProcessConnectionImpl tabConnection = allocateConnection(appContext.getPackageName()); + BaseChildProcessConnection tabConnection = allocateConnection(appContext.getPackageName()); // Verify that one connection is allocated for an external APK and a regular tab // respectively. @@ -305,17 +305,17 @@ appContext, EXTERNAL_APK_PACKAGE_NAME)); // Setup a connection for an external APK to reach the maximum allowed connection number. - ChildProcessConnectionImpl externalApkConnection = + BaseChildProcessConnection externalApkConnection = allocateConnection(EXTERNAL_APK_PACKAGE_NAME); Assert.assertNotNull(externalApkConnection); // Verify that there isn't any connection available for the external APK. - ChildProcessConnectionImpl exceedNumberExternalApkConnection = + BaseChildProcessConnection exceedNumberExternalApkConnection = allocateConnection(EXTERNAL_APK_PACKAGE_NAME); Assert.assertNull(exceedNumberExternalApkConnection); // Verify that we can still allocate connection for a regular tab. - ChildProcessConnectionImpl tabConnection = allocateConnection(appContext.getPackageName()); + BaseChildProcessConnection tabConnection = allocateConnection(appContext.getPackageName()); Assert.assertNotNull(tabConnection); } @@ -405,7 +405,7 @@ final ChildProcessCreationParams creationParams = new ChildProcessCreationParams( context.getPackageName(), false /* isExternalService */, LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */); - final ChildProcessConnection conn = + final BaseChildProcessConnection conn = ChildProcessLauncherTestHelperService.startInternalForTesting( context, sProcessWaitArguments, new FileDescriptorInfo[0], creationParams); @@ -419,7 +419,7 @@ Assert.assertEquals(0, conn.getServiceNumber()); - final ChildProcessConnection[] sandboxedConnections = + final BaseChildProcessConnection[] sandboxedConnections = getSandboxedConnectionArrayForTesting(context, context.getPackageName()); // Wait for the retry to succeed. @@ -429,7 +429,7 @@ public boolean isSatisfied() { boolean allChildrenConnected = true; for (int i = 0; i <= 1; ++i) { - ChildProcessConnection conn = sandboxedConnections[i]; + BaseChildProcessConnection conn = sandboxedConnections[i]; allChildrenConnected &= conn != null && conn.getService() != null; } return allChildrenConnected; @@ -438,7 +438,7 @@ // Check that only two connections are created. for (int i = 0; i < sandboxedConnections.length; ++i) { - ChildProcessConnection sandboxedConn = sandboxedConnections[i]; + BaseChildProcessConnection sandboxedConn = sandboxedConnections[i]; if (i <= 1) { Assert.assertNotNull(sandboxedConn); Assert.assertNotNull(sandboxedConn.getService()); @@ -448,7 +448,7 @@ } Assert.assertTrue(conn == sandboxedConnections[0]); - final ChildProcessConnection retryConn = sandboxedConnections[1]; + final BaseChildProcessConnection retryConn = sandboxedConnections[1]; Assert.assertFalse(conn == retryConn); @@ -488,7 +488,7 @@ public void run() { Assert.assertEquals(1, allocatedChromeSandboxedConnectionsCount()); - final ChildProcessConnection conn = + final BaseChildProcessConnection conn = ChildProcessLauncherTestHelperService.startInternalForTesting( context, new String[0], new FileDescriptorInfo[0], null); Assert.assertEquals( @@ -530,12 +530,11 @@ }); } - private ChildProcessConnectionImpl startConnection() { + private BaseChildProcessConnection startConnection() { // Allocate a new connection. Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - final ChildProcessConnectionImpl connection = - (ChildProcessConnectionImpl) allocateBoundConnectionForTesting( - context, getDefaultChildProcessCreationParams(context.getPackageName())); + final BaseChildProcessConnection connection = allocateBoundConnectionForTesting( + context, getDefaultChildProcessCreationParams(context.getPackageName())); // Wait for the service to connect. CriteriaHelper.pollInstrumentationThread( @@ -557,12 +556,12 @@ 0 /* childProcessId */, filesToMap, null /* launchCallback */); } - private static ChildProcessConnection allocateBoundConnectionForTesting( + private static BaseChildProcessConnection allocateBoundConnectionForTesting( final Context context, final ChildProcessCreationParams creationParams) { return ChildProcessLauncherTestHelperService.runOnLauncherAndGetResult( - new Callable<ChildProcessConnection>() { + new Callable<BaseChildProcessConnection>() { @Override - public ChildProcessConnection call() { + public BaseChildProcessConnection call() { return ChildProcessLauncher.allocateBoundConnection( new ChildSpawnData(context, null /* commandLine */, 0 /* childProcessId */, null /* filesToBeMapped */, @@ -579,16 +578,16 @@ * but doesn't really start the connection to bind a service. It is for testing whether the * connection is allocated properly for different application packages. */ - private ChildProcessConnectionImpl allocateConnection(final String packageName) { + private BaseChildProcessConnection allocateConnection(final String packageName) { return ChildProcessLauncherTestHelperService.runOnLauncherAndGetResult( - new Callable<ChildProcessConnectionImpl>() { + new Callable<BaseChildProcessConnection>() { @Override - public ChildProcessConnectionImpl call() { + public BaseChildProcessConnection call() { // Allocate a new connection. Context context = InstrumentationRegistry.getTargetContext(); ChildProcessCreationParams creationParams = getDefaultChildProcessCreationParams(packageName); - return (ChildProcessConnectionImpl) ChildProcessLauncher.allocateConnection( + return ChildProcessLauncher.allocateConnection( new ChildSpawnData(context, null /* commandLine */, 0 /* childProcessId */, null /* filesToBeMapped */, null /* launchCallback */, null /* childProcessCallback */, @@ -631,12 +630,12 @@ }); } - private static ChildProcessConnection[] getSandboxedConnectionArrayForTesting( + private static BaseChildProcessConnection[] getSandboxedConnectionArrayForTesting( final Context context, final String packageName) { return ChildProcessLauncherTestHelperService.runOnLauncherAndGetResult( - new Callable<ChildProcessConnection[]>() { + new Callable<BaseChildProcessConnection[]>() { @Override - public ChildProcessConnection[] call() { + public BaseChildProcessConnection[] call() { return ChildConnectionAllocator .getAllocator(context, packageName, true /*isSandboxed */) .connectionArrayForTesting(); @@ -670,7 +669,7 @@ LibraryProcessType.PROCESS_CHILD, false /* bindToCallerCheck */); } - private void triggerConnectionSetup(final ChildProcessConnectionImpl connection) { + private void triggerConnectionSetup(final BaseChildProcessConnection connection) { ChildProcessLauncherTestHelperService.runOnLauncherThreadBlocking(new Runnable() { @Override public void run() {
diff --git a/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java b/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java index 09268ad..f10218b 100644 --- a/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java +++ b/content/public/android/junit/src/org/chromium/content/browser/BindingManagerImplTest.java
@@ -10,21 +10,18 @@ import android.app.Activity; import android.app.Application; -import android.os.IBinder; import android.util.Pair; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.robolectric.Robolectric; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowLooper; import org.chromium.base.process_launcher.ChildProcessCreationParams; -import org.chromium.base.process_launcher.FileDescriptorInfo; -import org.chromium.base.process_launcher.IChildProcessService; import org.chromium.base.test.util.Feature; import org.chromium.testing.local.LocalRobolectricTestRunner; @@ -40,19 +37,42 @@ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class BindingManagerImplTest { - private static class MockChildProcessConnection implements ChildProcessConnection { - boolean mInitialBindingBound; - boolean mModerateBindingBound; - int mStrongBindingCount; - final int mPid; + private static class MockChildServiceConnection + implements BaseChildProcessConnection.ChildServiceConnection { + private boolean mBound; + + @Override + public boolean bind() { + mBound = true; + return true; + } + + @Override + public void unbind() { + mBound = false; + } + + @Override + public boolean isBound() { + return mBound; + } + } + + private static class TestChildProcessConnection extends ManagedChildProcessConnection { + private final int mPid; + private boolean mConnected; /** - * Creates a mock binding corresponding to real ChildProcessConnectionImpl after the + * Creates a mock binding corresponding to real ManagedChildProcessConnection after the * connection is established: with initial binding bound and no strong binding. */ - MockChildProcessConnection(int pid) { - mInitialBindingBound = true; - mStrongBindingCount = 0; + private TestChildProcessConnection(int pid) { + super(null /* context */, pid /* number */, true /* sandboxed */, + null /* deathCallback */, null /* serviceClassName */, + null /* childProcessCommonParameters */, + new ChildProcessCreationParams("org.chromium.test", + false /* isExternalService */, 0 /* libraryProcessType */, + false /* bindToCallerCheck */)); mPid = pid; } @@ -62,97 +82,26 @@ } @Override - public boolean isInitialBindingBound() { - return mInitialBindingBound; + protected ChildServiceConnection createServiceConnection(int bindFlags) { + return new MockChildServiceConnection(); } + // We don't have a real service so we have to mock the connection status. @Override - public boolean isStrongBindingBound() { - return mStrongBindingCount > 0; - } - - @Override - public void removeInitialBinding() { - mInitialBindingBound = false; - } - - @Override - public boolean isOomProtectedOrWasWhenDied() { - return mInitialBindingBound || mStrongBindingCount > 0; - } - - @Override - public void dropOomBindings() { - mInitialBindingBound = false; - mStrongBindingCount = 0; - } - - @Override - public void addStrongBinding() { - mStrongBindingCount++; - } - - @Override - public void removeStrongBinding() { - assert mStrongBindingCount > 0; - mStrongBindingCount--; + public void start(StartCallback startCallback) { + super.start(startCallback); + mConnected = true; } @Override public void stop() { - mInitialBindingBound = false; - mStrongBindingCount = 0; + super.stop(); + mConnected = false; } @Override - public int getServiceNumber() { - return mPid; - } - - @Override - public boolean isInSandbox() { - return true; - } - - @Override - public IChildProcessService getService() { - throw new UnsupportedOperationException(); - } - - @Override - public void start(StartCallback startCallback) { - throw new UnsupportedOperationException(); - } - - @Override - public void setupConnection(String[] commandLine, FileDescriptorInfo[] filesToBeMapped, - IBinder callback, ConnectionCallback connectionCallbacks) { - throw new UnsupportedOperationException(); - } - - @Override - public void addModerateBinding() { - mModerateBindingBound = true; - } - - @Override - public void removeModerateBinding() { - mModerateBindingBound = false; - } - - @Override - public boolean isModerateBindingBound() { - return mModerateBindingBound; - } - - @Override - public String getPackageName() { - return null; - } - - @Override - public ChildProcessCreationParams getCreationParams() { - return null; + public boolean isConnected() { + return mConnected; } } @@ -185,18 +134,30 @@ @Before public void setUp() { + // The tests run on only one thread. Pretend that is the launcher thread so LauncherThread + // asserts are not triggered. + LauncherThread.setCurrentThreadAsLauncherThread(); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); - mLowEndManager = BindingManagerImpl.createBindingManagerForTesting(true); - mHighEndManager = BindingManagerImpl.createBindingManagerForTesting(false); - mModerateBindingManager = BindingManagerImpl.createBindingManagerForTesting(false); - mModerateBindingManager.startModerateBindingManagement(mActivity, 4); + mLowEndManager = + BindingManagerImpl.createBindingManagerForTesting(true /* isLowEndDevice */); + mHighEndManager = + BindingManagerImpl.createBindingManagerForTesting(false /* isLowEndDevice */); + mModerateBindingManager = + BindingManagerImpl.createBindingManagerForTesting(false /* isLowEndDevice */); + mModerateBindingManager.startModerateBindingManagement(mActivity, 4 /* maxSize */); mAllManagers = new ManagerEntry[] { new ManagerEntry(mLowEndManager, "low-end"), new ManagerEntry(mHighEndManager, "high-end"), new ManagerEntry(mModerateBindingManager, "moderate-binding")}; } + @After + public void tearDown() { + LauncherThread.setLauncherThreadAsLauncherThread(); + } + /** * Verifies that when running on low-end, the binding manager drops the oom bindings for the * previously bound connection when a new connection is used in foreground. @@ -208,7 +169,8 @@ BindingManagerImpl manager = mLowEndManager; // Add a connection to the manager. - MockChildProcessConnection firstConnection = new MockChildProcessConnection(1); + TestChildProcessConnection firstConnection = new TestChildProcessConnection(1); + firstConnection.start(null /* startCallback */); manager.addNewConnection(firstConnection.getPid(), firstConnection); // Bind a strong binding on the connection. @@ -216,7 +178,8 @@ Assert.assertTrue(firstConnection.isStrongBindingBound()); // Add a new connection. - MockChildProcessConnection secondConnection = new MockChildProcessConnection(2); + TestChildProcessConnection secondConnection = new TestChildProcessConnection(2); + secondConnection.start(null /* startCallback */); manager.addNewConnection(secondConnection.getPid(), secondConnection); // Verify that the strong binding for the first connection wasn't dropped. @@ -240,7 +203,8 @@ final BindingManagerImpl manager = mLowEndManager; // Add a connection to the manager. - final MockChildProcessConnection connection = new MockChildProcessConnection(1); + final TestChildProcessConnection connection = new TestChildProcessConnection(1); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); Assert.assertTrue(connection.isInitialBindingBound()); Assert.assertFalse(connection.isStrongBindingBound()); @@ -268,7 +232,8 @@ final BindingManagerImpl manager = mHighEndManager; // Add a connection to the manager. - final MockChildProcessConnection connection = new MockChildProcessConnection(1); + final TestChildProcessConnection connection = new TestChildProcessConnection(1); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); Assert.assertTrue(connection.isInitialBindingBound()); Assert.assertFalse(connection.isStrongBindingBound()); @@ -301,9 +266,11 @@ // This test applies only to the moderate-binding manager. final BindingManagerImpl manager = mModerateBindingManager; - // Add a connection to the manager. - final MockChildProcessConnection connection = new MockChildProcessConnection(1); + // Add a connection to the manager and start it. + final TestChildProcessConnection connection = new TestChildProcessConnection(1); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); + Assert.assertTrue(connection.isInitialBindingBound()); Assert.assertFalse(connection.isStrongBindingBound()); Assert.assertFalse(connection.isModerateBindingBound()); @@ -341,7 +308,8 @@ String message = managerEntry.getErrorMessage(); // Add a connection to the manager. - MockChildProcessConnection connection = new MockChildProcessConnection(1); + TestChildProcessConnection connection = new TestChildProcessConnection(1); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); // Verify that the initial binding is held. @@ -354,13 +322,9 @@ } /** - * Verifies that BindingManagerImpl correctly stashes the status of the connection oom bindings - * when the connection is cleared. BindingManagerImpl should reply to isOomProtected() queries - * with live status of the connection while it's still around and reply with stashed status - * after clearConnection() is called. - * * This test corresponds to a process crash scenario: after a process dies and its connection is - * cleared, isOomProtected() may be called to decide if it was a crash or out-of-memory kill. + * cleared, isOomProtectedOrWasWhenDied() may be called on the connection to decide if it was a + * crash or out-of-memory kill. */ @Test @Feature({"ProcessManagement"}) @@ -371,26 +335,27 @@ String message = managerEntry.getErrorMessage(); // Add a connection to the manager. - MockChildProcessConnection connection = new MockChildProcessConnection(1); + TestChildProcessConnection connection = new TestChildProcessConnection(1); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); // Initial binding is an oom binding. - Assert.assertTrue(message, manager.isOomProtected(connection.getPid())); + Assert.assertTrue(message, connection.isOomProtectedOrWasWhenDied()); // After initial binding is removed, the connection is no longer oom protected. manager.setInForeground(connection.getPid(), false); manager.determinedVisibility(connection.getPid()); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); - Assert.assertFalse(message, manager.isOomProtected(connection.getPid())); + Assert.assertFalse(message, connection.isOomProtectedOrWasWhenDied()); // Add a strong binding, restoring the oom protection. manager.setInForeground(connection.getPid(), true); - Assert.assertTrue(message, manager.isOomProtected(connection.getPid())); + Assert.assertTrue(message, connection.isOomProtectedOrWasWhenDied()); // Simulate a process crash - clear a connection in binding manager and remove the // bindings. Assert.assertFalse(manager.isConnectionCleared(connection.getPid())); - manager.clearConnection(connection.getPid()); + manager.removeConnection(connection.getPid()); Assert.assertTrue(manager.isConnectionCleared(connection.getPid())); connection.stop(); @@ -398,7 +363,7 @@ // oom status as protected. Assert.assertFalse(message, connection.isInitialBindingBound()); Assert.assertFalse(message, connection.isStrongBindingBound()); - Assert.assertTrue(message, manager.isOomProtected(connection.getPid())); + Assert.assertTrue(message, connection.isOomProtectedOrWasWhenDied()); } } @@ -421,18 +386,21 @@ String message = managerEntry.getErrorMessage(); // Add two connections, bind and release each. - MockChildProcessConnection firstConnection = new MockChildProcessConnection(1); + TestChildProcessConnection firstConnection = new TestChildProcessConnection(1); + firstConnection.start(null /* startCallback */); manager.addNewConnection(firstConnection.getPid(), firstConnection); manager.setInForeground(firstConnection.getPid(), true); manager.setInForeground(firstConnection.getPid(), false); - MockChildProcessConnection secondConnection = new MockChildProcessConnection(2); + TestChildProcessConnection secondConnection = new TestChildProcessConnection(2); + secondConnection.start(null /* startCallback */); manager.addNewConnection(secondConnection.getPid(), secondConnection); manager.setInForeground(secondConnection.getPid(), true); manager.setInForeground(secondConnection.getPid(), false); // Add third connection, do not bind it. - MockChildProcessConnection thirdConnection = new MockChildProcessConnection(3); + TestChildProcessConnection thirdConnection = new TestChildProcessConnection(3); + thirdConnection.start(null /* startCallback */); manager.addNewConnection(thirdConnection.getPid(), thirdConnection); manager.setInForeground(thirdConnection.getPid(), false); @@ -470,15 +438,16 @@ // This test applies only to the moderate-binding manager. final BindingManagerImpl manager = mModerateBindingManager; - MockChildProcessConnection[] connections = new MockChildProcessConnection[3]; + TestChildProcessConnection[] connections = new TestChildProcessConnection[3]; for (int i = 0; i < connections.length; i++) { - connections[i] = new MockChildProcessConnection(i + 1); + connections[i] = new TestChildProcessConnection(i + 1); + connections[i].start(null /* startCallback */); manager.addNewConnection(connections[i].getPid(), connections[i]); } // Verify that each connection has a moderate binding after binding and releasing a strong // binding. - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { manager.setInForeground(connection.getPid(), true); manager.setInForeground(connection.getPid(), false); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); @@ -487,42 +456,44 @@ // Exclude lastInForeground because it will be kept in foreground when onSentToBackground() // is called as |mLastInForeground|. - MockChildProcessConnection lastInForeground = new MockChildProcessConnection(0); + TestChildProcessConnection lastInForeground = new TestChildProcessConnection(0); manager.addNewConnection(lastInForeground.getPid(), lastInForeground); + lastInForeground.start(null /* startCallback */); manager.setInForeground(lastInForeground.getPid(), true); manager.setInForeground(lastInForeground.getPid(), false); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); // Verify that leaving the application for a short time doesn't clear the moderate bindings. manager.onSentToBackground(); - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { Assert.assertTrue(connection.isModerateBindingBound()); } Assert.assertTrue(lastInForeground.isStrongBindingBound()); Assert.assertFalse(lastInForeground.isModerateBindingBound()); manager.onBroughtToForeground(); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { Assert.assertTrue(connection.isModerateBindingBound()); } // Call onSentToBackground() and verify that all the moderate bindings drop after some // delay. manager.onSentToBackground(); - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { Assert.assertTrue(connection.isModerateBindingBound()); } Assert.assertTrue(lastInForeground.isStrongBindingBound()); Assert.assertFalse(lastInForeground.isModerateBindingBound()); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { Assert.assertFalse(connection.isModerateBindingBound()); } // Call onBroughtToForeground() and verify that the previous moderate bindings aren't // recovered. manager.onBroughtToForeground(); - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { Assert.assertFalse(connection.isModerateBindingBound()); } } @@ -536,15 +507,16 @@ final Application app = mActivity.getApplication(); final BindingManagerImpl manager = mModerateBindingManager; - MockChildProcessConnection[] connections = new MockChildProcessConnection[4]; + TestChildProcessConnection[] connections = new TestChildProcessConnection[4]; for (int i = 0; i < connections.length; i++) { - connections[i] = new MockChildProcessConnection(i + 1); + connections[i] = new TestChildProcessConnection(i + 1); + connections[i].start(null /* startCallback */); manager.addNewConnection(connections[i].getPid(), connections[i]); } // Verify that each connection has a moderate binding after binding and releasing a strong // binding. - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { manager.setInForeground(connection.getPid(), true); manager.setInForeground(connection.getPid(), false); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); @@ -553,7 +525,7 @@ // Call onLowMemory() and verify that all the moderate bindings drop. app.onLowMemory(); - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { Assert.assertFalse(connection.isModerateBindingBound()); } } @@ -568,17 +540,17 @@ // This test applies only to the moderate-binding manager. final BindingManagerImpl manager = mModerateBindingManager; - ArrayList<Pair<Integer, Integer>> levelAndExpectedVictimCountList = - new ArrayList<Pair<Integer, Integer>>(); + ArrayList<Pair<Integer, Integer>> levelAndExpectedVictimCountList = new ArrayList<>(); levelAndExpectedVictimCountList.add( new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_MODERATE, 1)); levelAndExpectedVictimCountList.add(new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_LOW, 2)); levelAndExpectedVictimCountList.add( new Pair<Integer, Integer>(TRIM_MEMORY_RUNNING_CRITICAL, 4)); - MockChildProcessConnection[] connections = new MockChildProcessConnection[4]; + TestChildProcessConnection[] connections = new TestChildProcessConnection[4]; for (int i = 0; i < connections.length; i++) { - connections[i] = new MockChildProcessConnection(i + 1); + connections[i] = new TestChildProcessConnection(i + 1); + connections[i].start(null /* startCallback */); manager.addNewConnection(connections[i].getPid(), connections[i]); } @@ -586,7 +558,7 @@ String message = "Failed for the level=" + pair.first; // Verify that each connection has a moderate binding after binding and releasing a // strong binding. - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { manager.setInForeground(connection.getPid(), true); manager.setInForeground(connection.getPid(), false); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); @@ -611,15 +583,16 @@ // This test applies only to the moderate-binding manager. final BindingManagerImpl manager = mModerateBindingManager; - MockChildProcessConnection[] connections = new MockChildProcessConnection[4]; + TestChildProcessConnection[] connections = new TestChildProcessConnection[4]; for (int i = 0; i < connections.length; i++) { - connections[i] = new MockChildProcessConnection(i + 1); + connections[i] = new TestChildProcessConnection(i + 1); + connections[i].start(null /* startCallback */); manager.addNewConnection(connections[i].getPid(), connections[i]); } // Verify that each connection has a moderate binding after binding and releasing a strong // binding. - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { manager.setInForeground(connection.getPid(), true); manager.setInForeground(connection.getPid(), false); ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); @@ -629,7 +602,7 @@ // Call BindingManager.releaseAllModerateBindings() and verify that all the moderate // bindings drop. manager.releaseAllModerateBindings(); - for (MockChildProcessConnection connection : connections) { + for (TestChildProcessConnection connection : connections) { Assert.assertFalse(connection.isModerateBindingBound()); } } @@ -644,7 +617,8 @@ BindingManagerImpl manager = BindingManagerImpl.createBindingManagerForTesting(false); manager.startModerateBindingManagement(mActivity, 4); - MockChildProcessConnection connection = new MockChildProcessConnection(0); + TestChildProcessConnection connection = new TestChildProcessConnection(0); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); Assert.assertTrue(connection.isInitialBindingBound()); Assert.assertFalse(connection.isModerateBindingBound()); @@ -665,7 +639,8 @@ BindingManagerImpl manager = BindingManagerImpl.createBindingManagerForTesting(false); manager.startModerateBindingManagement(mActivity, 4); - MockChildProcessConnection connection = new MockChildProcessConnection(0); + TestChildProcessConnection connection = new TestChildProcessConnection(0); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); Assert.assertTrue(connection.isInitialBindingBound()); Assert.assertFalse(connection.isStrongBindingBound()); @@ -688,7 +663,8 @@ BindingManagerImpl manager = BindingManagerImpl.createBindingManagerForTesting(false); manager.startModerateBindingManagement(mActivity, 4); - MockChildProcessConnection connection = new MockChildProcessConnection(0); + TestChildProcessConnection connection = new TestChildProcessConnection(0); + connection.start(null /* startCallback */); manager.addNewConnection(connection.getPid(), connection); manager.setInForeground(connection.getPid(), false); manager.determinedVisibility(connection.getPid());
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h index 4ece52b3..ffe2eaed 100644 --- a/content/public/browser/navigation_controller.h +++ b/content/public/browser/navigation_controller.h
@@ -268,7 +268,9 @@ // committed entries. virtual NavigationEntry* GetLastCommittedEntry() const = 0; - // Returns the index of the last committed entry. + // Returns the index of the last committed entry. It will be -1 if there are + // no entries, or if there is a transient entry before the first entry + // commits. virtual int GetLastCommittedEntryIndex() const = 0; // Returns true if the source for the current entry can be viewed.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 850838a..a35805d 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -339,14 +339,6 @@ base::FEATURE_DISABLED_BY_DEFAULT}; #endif -#if !defined(OS_ANDROID) -// Controls whether media playback in cross-origin iframes is enabled. The -// feature overrides |kDisableGestureRequirementForMediaPlayback|. -const base::Feature kCrossOriginMediaPlaybackRequiresUserGesture{ - "CrossOriginMediaPlaybackRequiresUserGesture", - base::FEATURE_DISABLED_BY_DEFAULT}; -#endif // !defined(OS_ANDROID) - #if defined(OS_WIN) // Emergency "off switch" for new Windows sandbox security mitigation, // sandbox::MITIGATION_EXTENSION_POINT_DISABLE.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index a14b144..df86cb3 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -88,11 +88,6 @@ CONTENT_EXPORT extern const base::Feature kWebNfc; #endif // defined(OS_ANDROID) -#if !defined(OS_ANDROID) -CONTENT_EXPORT extern const base::Feature - kCrossOriginMediaPlaybackRequiresUserGesture; -#endif // !defined(OS_ANDROID) - #if defined(OS_WIN) CONTENT_EXPORT extern const base::Feature kWinSboxDisableExtensionPoints; #endif // defined(OS_WIN)
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java index 51c4d26e..2907d16a 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java
@@ -21,7 +21,7 @@ import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.process_launcher.ChildProcessCreationParams; import org.chromium.base.process_launcher.FileDescriptorInfo; -import org.chromium.content.browser.ChildProcessConnection; +import org.chromium.content.browser.BaseChildProcessConnection; import org.chromium.content.browser.ChildProcessLauncher; import org.chromium.content.browser.LauncherThread; @@ -86,12 +86,12 @@ } } - public static ChildProcessConnection startInternalForTesting(final Context context, + public static BaseChildProcessConnection startInternalForTesting(final Context context, final String[] commandLine, final FileDescriptorInfo[] filesToMap, final ChildProcessCreationParams params) { - return runOnLauncherAndGetResult(new Callable<ChildProcessConnection>() { + return runOnLauncherAndGetResult(new Callable<BaseChildProcessConnection>() { @Override - public ChildProcessConnection call() { + public BaseChildProcessConnection call() { return ChildProcessLauncher.startInternal(context, commandLine, 0 /* childProcessId */, filesToMap, null /* launchCallback */, null /* childProcessCallback */, true /* inSandbox */, @@ -124,7 +124,7 @@ final boolean bindToCaller = true; ChildProcessCreationParams params = new ChildProcessCreationParams( getPackageName(), false, LibraryProcessType.PROCESS_CHILD, bindToCaller); - final ChildProcessConnection conn = + final BaseChildProcessConnection conn = startInternalForTesting(this, commandLine, new FileDescriptorInfo[0], params); // Poll the connection until it is set up. The main test in ChildProcessLauncherTest, which
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc index 4f61f46..681bffd0 100644 --- a/content/utility/utility_thread_impl.cc +++ b/content/utility/utility_thread_impl.cc
@@ -90,8 +90,12 @@ base::Bind(&UtilityThreadImpl::BindServiceFactoryRequest, base::Unretained(this)), base::ThreadTaskRunnerHandle::Get()); - ChildThread::Get()->GetServiceManagerConnection()->AddConnectionFilter( - base::MakeUnique<SimpleConnectionFilter>(std::move(registry))); + + content::ServiceManagerConnection* connection = GetServiceManagerConnection(); + if (connection) { + connection->AddConnectionFilter( + base::MakeUnique<SimpleConnectionFilter>(std::move(registry))); + } GetContentClient()->utility()->UtilityThreadStarted();
diff --git a/courgette/BUILD.gn b/courgette/BUILD.gn index 8e3d30f..8c96e43 100644 --- a/courgette/BUILD.gn +++ b/courgette/BUILD.gn
@@ -13,6 +13,8 @@ "assembly_program.h", "consecutive_range_visitor.h", "courgette.h", + "courgette_flow.cc", + "courgette_flow.h", "crc.cc", "crc.h", "difference_estimator.cc",
diff --git a/courgette/courgette_flow.cc b/courgette/courgette_flow.cc new file mode 100644 index 0000000..2fa9810 --- /dev/null +++ b/courgette/courgette_flow.cc
@@ -0,0 +1,189 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "courgette/courgette_flow.h" + +#include <stdarg.h> + +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/strings/stringprintf.h" +#include "courgette/assembly_program.h" +#include "courgette/encoded_program.h" +#include "courgette/program_detector.h" + +namespace courgette { + +/******** CourgetteFlow::Data ********/ + +CourgetteFlow::Data::Data() = default; + +CourgetteFlow::Data::~Data() = default; + +/******** CourgetteFlow ********/ + +CourgetteFlow::CourgetteFlow() = default; + +CourgetteFlow::~CourgetteFlow() = default; + +// static +const char* CourgetteFlow::name(Group group) { + switch (group) { + case ONLY: + return "input"; + case OLD: + return "'old' input"; + case NEW: + return "'new' input"; + default: + NOTREACHED(); + break; + } + return nullptr; +} + +CourgetteFlow::Data* CourgetteFlow::data(Group group) { + switch (group) { + case ONLY: + return &data_only_; + case OLD: + return &data_old_; + case NEW: + return &data_new_; + default: + NOTREACHED(); + break; + } + return nullptr; +} + +bool CourgetteFlow::ok() { + return status_ == C_OK; +} + +bool CourgetteFlow::failed() { + return status_ != C_OK; +} + +Status CourgetteFlow::status() { + return status_; +} + +const std::string& CourgetteFlow::message() { + return message_; +} + +void CourgetteFlow::ReadSourceStreamSetFromBuffer(Group group, + const BasicBuffer& buffer) { + if (failed()) + return; + Data* d = data(group); + if (!check(d->sources.Init(buffer.data(), buffer.length()), + C_GENERAL_ERROR)) { + setMessage("Cannot read %s as SourceStreamSet.", name(group)); + } +} + +void CourgetteFlow::ReadAssemblyProgramFromBuffer(Group group, + const BasicBuffer& buffer, + bool annotate) { + if (failed()) + return; + Data* d = data(group); + auto parser = annotate ? ParseDetectedExecutableWithAnnotation + : ParseDetectedExecutable; + if (!check(parser(buffer.data(), buffer.length(), &d->program))) + setMessage("Cannot parse %s (code = %d).", name(group), status_); +} + +void CourgetteFlow::ReadEncodedProgramFromSourceStreamSet( + Group group, + SourceStreamSet* opt_sources /* nullptr */) { + if (failed()) + return; + Data* d = data(group); + SourceStreamSet* sources = opt_sources ? opt_sources : &d->sources; + if (!check(ReadEncodedProgram(sources, &d->encoded))) + setMessage("Cannot read %s as encoded program.", name(group)); +} + +void CourgetteFlow::CreateEncodedProgramFromAssemblyProgram(Group group) { + if (failed()) + return; + Data* d = data(group); + if (!check(Encode(*d->program, &d->encoded))) + setMessage("Cannot encode %s (code = %d).", name(group), status_); +} + +void CourgetteFlow::WriteSinkStreamFromSinkStreamSet(Group group, + SinkStream* sink) { + DCHECK(sink); + if (failed()) + return; + if (!check(data(group)->sinks.CopyTo(sink), C_GENERAL_ERROR)) + setMessage("Cannnot combine serialized streams for %s.", name(group)); +} + +void CourgetteFlow::WriteSinkStreamSetFromEncodedProgram( + Group group, + SinkStreamSet* opt_sinks /* nullptr */) { + if (failed()) + return; + Data* d = data(group); + SinkStreamSet* sinks = opt_sinks ? opt_sinks : &d->sinks; + if (!check(WriteEncodedProgram(d->encoded.get(), sinks))) + setMessage("Cannot serialize encoded %s.", name(group)); +} + +void CourgetteFlow::WriteExecutableFromEncodedProgram(Group group, + SinkStream* sink) { + DCHECK(sink); + if (failed()) + return; + if (!check(Assemble(data(group)->encoded.get(), sink))) + setMessage("Cannot assemble %s.", name(group)); +} + +void CourgetteFlow::AdjustNewAssemblyProgramToMatchOld() { + if (failed()) + return; + if (!check(Adjust(*data_old_.program, data_new_.program.get()))) + setMessage("Cannot adjust %s to match %s.", name(OLD), name(NEW)); +} + +void CourgetteFlow::DestroyAssemblyProgram(Group group) { + if (failed()) + return; + data(group)->program.reset(); +} + +void CourgetteFlow::DestroyEncodedProgram(Group group) { + if (failed()) + return; + data(group)->encoded.reset(); +} + +bool CourgetteFlow::check(Status new_status) { + if (new_status == C_OK) + return true; + status_ = new_status; + return false; +} + +bool CourgetteFlow::check(bool success, Status failure_mode) { + if (success) + return true; + status_ = failure_mode; + return false; +} + +void CourgetteFlow::setMessage(const char* format, ...) { + va_list args; + va_start(args, format); + message_ = base::StringPrintV(format, args); + va_end(args); +} + +} // namespace courgette
diff --git a/courgette/courgette_flow.h b/courgette/courgette_flow.h new file mode 100644 index 0000000..9b8cb889 --- /dev/null +++ b/courgette/courgette_flow.h
@@ -0,0 +1,144 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COURGETTE_COURGETTE_FLOW_H_ +#define COURGETTE_COURGETTE_FLOW_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "courgette/courgette.h" +#include "courgette/region.h" +#include "courgette/streams.h" + +namespace courgette { + +class AssemblyProgram; +class EncodedProgram; + +// An adaptor for Region as BasicBuffer. +class RegionBuffer : public BasicBuffer { + public: + explicit RegionBuffer(const Region& region) : region_(region) {} + ~RegionBuffer() override {} + + // BasicBuffer: + const uint8_t* data() const override { return region_.start(); } + size_t length() const override { return region_.length(); } + + private: + Region region_; + + DISALLOW_COPY_AND_ASSIGN(RegionBuffer); +}; + +// CourgetteFlow stores Courgette data arranged into groups, and exposes +// "commands" that operate on them. On the first occurrence of an error, the +// Courgette error code is recorded, error messages are generated and stored, +// and all subsequent commands become no-op. This allows callers to concisely +// specify high-level logic with minimal code for error handling. +class CourgetteFlow { + public: + // A group of Courgette data, for a single executable. Takes negligible space + // when unused. + struct Data { + Data(); + ~Data(); + + std::unique_ptr<AssemblyProgram> program; + std::unique_ptr<EncodedProgram> encoded; + SinkStreamSet sinks; + SourceStreamSet sources; + }; + + // Group enumeration into |data_*_| fields. + enum Group { + ONLY, // The only file processed. + OLD, // The "old" file during patching. + NEW, // The "new" file during patching. + }; + + CourgetteFlow(); + ~CourgetteFlow(); + + static const char* name(Group group); + Data* data(Group group); // Allows caller to modify. + bool ok(); + bool failed(); + Status status(); + const std::string& message(); + + // Commands that perform no-op on error. This allows caller to concisely + // specify high-level logic, and perform a single error check at the end. Care + // must be taken w.r.t. error handling if |data()| is harvested between + // commands. + + // Reads |buffer| to initialize |data(group)->sources|. + void ReadSourceStreamSetFromBuffer(Group group, const BasicBuffer& buffer); + + // Reads |buffer| to initialize |data(group)->program|, passing |annotate| as + // initialization parameter (true if AdjustNewAssemblyProgramToMatchOld() gets + // called later). + void ReadAssemblyProgramFromBuffer(Group group, + const BasicBuffer& buffer, + bool annotate); + + // Reads |opt_sources| if given, or else |data(group)->sources| to initialize + // |data(group).encoded|. + void ReadEncodedProgramFromSourceStreamSet( + Group group, + SourceStreamSet* opt_sources = nullptr); + + // Uses |data(group)->program| to initialize |data(group)->encoded|. + void CreateEncodedProgramFromAssemblyProgram(Group group); + + // Serializese |data(group)->sinks| to |sink|. + void WriteSinkStreamFromSinkStreamSet(Group group, SinkStream* sink); + + // Serializes |data(group)->encoded| to |opt_sinks| if given, or else to + // |data(group)->sinks|. + void WriteSinkStreamSetFromEncodedProgram(Group group, + SinkStreamSet* opt_sinks = nullptr); + + // Converts |data(group)->encoded| to an exectuable and writes the result to + // |sink|. + void WriteExecutableFromEncodedProgram(Group group, SinkStream* sink); + + // Adjusts |data(NEW)->program| Labels to match |data(OLD)->program| Labels. + void AdjustNewAssemblyProgramToMatchOld(); + + // Destructor commands to reduce memory usage. + + void DestroyAssemblyProgram(Group group); + + void DestroyEncodedProgram(Group group); + + private: + // Utilities to process return values from Courgette functions, and assign + // |status_| and |message_|. Usage: + // if (!check(some_courgette_function(param1, ...))) + // setMessage("format string %s...", value1, ...); + + // Reassigns |status_|, and returns true if |C_OK|. + bool check(Status new_status); + + // check() alternative for functions that return true on succes. On failure + // assigns |status_| to |failure_mode|. + bool check(bool success, Status failure_mode); + + void setMessage(const char* format, ...); + + Status status_ = C_OK; + std::string message_; + Data data_only_; + Data data_old_; + Data data_new_; + + DISALLOW_COPY_AND_ASSIGN(CourgetteFlow); +}; + +} // namespace courgette + +#endif // COURGETTE_COURGETTE_FLOW_H_
diff --git a/courgette/courgette_tool.cc b/courgette/courgette_tool.cc index 5ca91d1aa..46bd578 100644 --- a/courgette/courgette_tool.cc +++ b/courgette/courgette_tool.cc
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <stdarg.h> #include <stddef.h> #include <stdint.h> +#include <initializer_list> #include <memory> #include <string> #include <vector> @@ -15,26 +17,45 @@ #include "base/files/file_util.h" #include "base/files/memory_mapped_file.h" #include "base/logging.h" +#include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "courgette/assembly_program.h" #include "courgette/courgette.h" +#include "courgette/courgette_flow.h" #include "courgette/encoded_program.h" #include "courgette/program_detector.h" #include "courgette/streams.h" #include "courgette/third_party/bsdiff/bsdiff.h" +namespace { + +using courgette::CourgetteFlow; + +const char kUsageGen[] = "-gen <old_in> <new_in> <patch_out>"; +const char kUsageApply[] = "-apply <old_in> <patch_in> <new_out>"; +const char kUsageGenbsdiff[] = "-genbsdiff <old_in> <new_in> <patch_out>"; +const char kUsageApplybsdiff[] = "-applybsdiff <old_in> <patch_in> <new_out>"; +const char kUsageSupported[] = "-supported <exec_file_in>"; +const char kUsageDis[] = "-dis <exec_file_in> <assembly_file_out>"; +const char kUsageAsm[] = "-asm <assembly_file_in> <exec_file_out>"; +const char kUsageDisadj[] = "-disadj <old_in> <new_in> <new_assembly_file_out>"; +const char kUsageGen1[] = "-gen1[au] <old_in> <new_in> <patch_base_out>"; + +/******** Utilities to print help and exit ********/ + void PrintHelp() { - fprintf(stderr, - "Usage:\n" - " courgette -supported <executable_file>\n" - " courgette -dis <executable_file> <binary_assembly_file>\n" - " courgette -asm <binary_assembly_file> <executable_file>\n" - " courgette -disadj <executable_file> <reference> <binary_assembly_file>\n" - " courgette -gen <v1> <v2> <patch>\n" - " courgette -apply <v1> <patch> <v2>\n" - "\n"); + fprintf(stderr, "Main Usage:\n"); + for (auto usage : + {kUsageGen, kUsageApply, kUsageGenbsdiff, kUsageApplybsdiff}) { + fprintf(stderr, " courgette %s\n", usage); + } + fprintf(stderr, "Diagnosis Usage:\n"); + for (auto usage : + {kUsageSupported, kUsageDis, kUsageAsm, kUsageDisadj, kUsageGen1}) { + fprintf(stderr, " courgette %s\n", usage); + } } void UsageProblem(const char* message) { @@ -53,20 +74,29 @@ exit(1); } +/******** BufferedFileReader ********/ + // A file reader that calls Problem() on failure. -class BufferedFileReader { +class BufferedFileReader : public courgette::BasicBuffer { public: BufferedFileReader(const base::FilePath& file_name, const char* kind) { if (!buffer_.Initialize(file_name)) Problem("Can't read %s file.", kind); } - const uint8_t* data() const { return buffer_.data(); } - size_t length() const { return buffer_.length(); } + ~BufferedFileReader() override {} + + // courgette::BasicBuffer: + const uint8_t* data() const override { return buffer_.data(); } + size_t length() const override { return buffer_.length(); } private: base::MemoryMappedFile buffer_; + + DISALLOW_COPY_AND_ASSIGN(BufferedFileReader); }; +/******** Various helpers ********/ + void WriteSinkToFile(const courgette::SinkStream *sink, const base::FilePath& output_file) { int count = @@ -79,38 +109,6 @@ Problem("Incomplete write."); } -void Disassemble(const base::FilePath& input_file, - const base::FilePath& output_file) { - BufferedFileReader buffer(input_file, "input"); - - std::unique_ptr<courgette::AssemblyProgram> program; - const courgette::Status parse_status = courgette::ParseDetectedExecutable( - buffer.data(), buffer.length(), &program); - if (parse_status != courgette::C_OK) - Problem("Can't parse input (code = %d).", parse_status); - - std::unique_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); - if (encode_status != courgette::C_OK) - Problem("Can't encode program."); - - program.reset(); - - courgette::SinkStreamSet sinks; - const courgette::Status write_status = - courgette::WriteEncodedProgram(encoded.get(), &sinks); - if (write_status != courgette::C_OK) - Problem("Can't serialize encoded program."); - - encoded.reset(); - - courgette::SinkStream sink; - if (!sinks.CopyTo(&sink)) - Problem("Can't combine serialized encoded program streams."); - - WriteSinkToFile(&sink, output_file); -} - bool Supported(const base::FilePath& input_file) { bool result = false; @@ -153,50 +151,41 @@ return result; } -void DisassembleAndAdjust(const base::FilePath& program_file, - const base::FilePath& model_file, - const base::FilePath& output_file) { - BufferedFileReader program_buffer(program_file, "program"); - BufferedFileReader model_buffer(model_file, "model"); - - std::unique_ptr<courgette::AssemblyProgram> program; - const courgette::Status parse_program_status = - courgette::ParseDetectedExecutable(program_buffer.data(), - program_buffer.length(), &program); - if (parse_program_status != courgette::C_OK) - Problem("Can't parse program input (code = %d).", parse_program_status); - - std::unique_ptr<courgette::AssemblyProgram> model; - const courgette::Status parse_model_status = - courgette::ParseDetectedExecutable(model_buffer.data(), - model_buffer.length(), &model); - if (parse_model_status != courgette::C_OK) - Problem("Can't parse model input (code = %d).", parse_model_status); - - const courgette::Status adjust_status = Adjust(*model, program.get()); - if (adjust_status != courgette::C_OK) - Problem("Can't adjust program."); - - model.reset(); - - std::unique_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); - if (encode_status != courgette::C_OK) - Problem("Can't encode program."); - - program.reset(); - - courgette::SinkStreamSet sinks; - const courgette::Status write_status = - courgette::WriteEncodedProgram(encoded.get(), &sinks); - if (write_status != courgette::C_OK) - Problem("Can't serialize encoded program."); - - encoded.reset(); - +void Disassemble(const base::FilePath& input_file, + const base::FilePath& output_file) { + CourgetteFlow flow; + BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); + flow.ReadAssemblyProgramFromBuffer(flow.ONLY, input_buffer, false); + flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY); + flow.DestroyAssemblyProgram(flow.ONLY); + flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY); + flow.DestroyEncodedProgram(flow.ONLY); courgette::SinkStream sink; - if (!sinks.CopyTo(&sink)) - Problem("Can't combine serialized encoded program streams."); + flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink); + if (flow.failed()) + Problem(flow.message().c_str()); + + WriteSinkToFile(&sink, output_file); +} + +void DisassembleAndAdjust(const base::FilePath& old_file, + const base::FilePath& new_file, + const base::FilePath& output_file) { + CourgetteFlow flow; + BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); + BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); + flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, true); + flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, true); + flow.AdjustNewAssemblyProgramToMatchOld(); + flow.DestroyAssemblyProgram(flow.OLD); + flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); + flow.DestroyAssemblyProgram(flow.NEW); + flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); + flow.DestroyEncodedProgram(flow.NEW); + courgette::SinkStream sink; + flow.WriteSinkStreamFromSinkStreamSet(flow.NEW, &sink); + if (flow.failed()) + Problem(flow.message().c_str()); WriteSinkToFile(&sink, output_file); } @@ -206,69 +195,32 @@ // original file's stream and the new file's stream. This is completely // uninteresting to users, but it is handy for seeing how much each which // streams are contributing to the final file size. Adjustment is optional. -void DisassembleAdjustDiff(const base::FilePath& model_file, - const base::FilePath& program_file, +void DisassembleAdjustDiff(const base::FilePath& old_file, + const base::FilePath& new_file, const base::FilePath& output_file_root, bool adjust) { - BufferedFileReader model_buffer(model_file, "old"); - BufferedFileReader program_buffer(program_file, "new"); - - auto parser = adjust ? courgette::ParseDetectedExecutableWithAnnotation - : courgette::ParseDetectedExecutable; - - std::unique_ptr<courgette::AssemblyProgram> model; - const courgette::Status parse_model_status = - parser(model_buffer.data(), model_buffer.length(), &model); - if (parse_model_status != courgette::C_OK) - Problem("Can't parse model input (code = %d).", parse_model_status); - - std::unique_ptr<courgette::AssemblyProgram> program; - const courgette::Status parse_program_status = - parser(program_buffer.data(), program_buffer.length(), &program); - if (parse_program_status != courgette::C_OK) - Problem("Can't parse program input (code = %d).", parse_program_status); - - if (adjust) { - const courgette::Status adjust_status = Adjust(*model, program.get()); - if (adjust_status != courgette::C_OK) - Problem("Can't adjust program."); - } - - std::unique_ptr<courgette::EncodedProgram> encoded_program; - const courgette::Status encode_program_status = - Encode(*program, &encoded_program); - if (encode_program_status != courgette::C_OK) - Problem("Can't encode program."); - - program.reset(); - - std::unique_ptr<courgette::EncodedProgram> encoded_model; - const courgette::Status encode_model_status = Encode(*model, &encoded_model); - if (encode_model_status != courgette::C_OK) - Problem("Can't encode model."); - - model.reset(); - - courgette::SinkStreamSet program_sinks; - const courgette::Status write_program_status = - courgette::WriteEncodedProgram(encoded_program.get(), &program_sinks); - if (write_program_status != courgette::C_OK) - Problem("Can't serialize encoded program."); - - encoded_program.reset(); - - courgette::SinkStreamSet model_sinks; - const courgette::Status write_model_status = - courgette::WriteEncodedProgram(encoded_model.get(), &model_sinks); - if (write_model_status != courgette::C_OK) - Problem("Can't serialize encoded model."); - - encoded_model.reset(); + CourgetteFlow flow; + BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); + BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); + flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, adjust); + flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, adjust); + if (adjust) + flow.AdjustNewAssemblyProgramToMatchOld(); + flow.CreateEncodedProgramFromAssemblyProgram(flow.OLD); + flow.DestroyAssemblyProgram(flow.OLD); + flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); + flow.DestroyAssemblyProgram(flow.NEW); + flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD); + flow.DestroyEncodedProgram(flow.OLD); + flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); + flow.DestroyEncodedProgram(flow.NEW); + if (flow.failed()) + Problem(flow.message().c_str()); courgette::SinkStream empty_sink; for (int i = 0; ; ++i) { - courgette::SinkStream* old_stream = model_sinks.stream(i); - courgette::SinkStream* new_stream = program_sinks.stream(i); + courgette::SinkStream* old_stream = flow.data(flow.OLD)->sinks.stream(i); + courgette::SinkStream* new_stream = flow.data(flow.NEW)->sinks.stream(i); if (old_stream == NULL && new_stream == NULL) break; @@ -291,24 +243,14 @@ void Assemble(const base::FilePath& input_file, const base::FilePath& output_file) { - BufferedFileReader buffer(input_file, "input"); - - courgette::SourceStreamSet sources; - if (!sources.Init(buffer.data(), buffer.length())) - Problem("Bad input file."); - - std::unique_ptr<courgette::EncodedProgram> encoded; - const courgette::Status read_status = - courgette::ReadEncodedProgram(&sources, &encoded); - if (read_status != courgette::C_OK) - Problem("Bad encoded program."); - + CourgetteFlow flow; + BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); + flow.ReadSourceStreamSetFromBuffer(flow.ONLY, input_buffer); + flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY); courgette::SinkStream sink; - - const courgette::Status assemble_status = - courgette::Assemble(encoded.get(), &sink); - if (assemble_status != courgette::C_OK) - Problem("Can't assemble."); + flow.WriteExecutableFromEncodedProgram(flow.ONLY, &sink); + if (flow.failed()) + Problem(flow.message().c_str()); WriteSinkToFile(&sink, output_file); } @@ -430,6 +372,8 @@ WriteSinkToFile(&new_stream, new_file); } +} // namespace + int main(int argc, const char* argv[]) { base::AtExitManager at_exit_manager; base::CommandLine::Init(argc, argv); @@ -468,50 +412,51 @@ repeat_count = 1; if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + - cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + - cmd_spread_1_adjusted + cmd_spread_1_unadjusted - != 1) + cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + + cmd_spread_1_adjusted + cmd_spread_1_unadjusted != + 1) { UsageProblem( - "Must have exactly one of:\n" - " -supported -asm, -dis, -disadj, -gen or -apply, -genbsdiff" - " or -applybsdiff."); + "First argument must be one of:\n" + " -supported, -asm, -dis, -disadj, -gen, -apply, -genbsdiff," + " -applybsdiff, or -gen1[au]."); + } while (repeat_count-- > 0) { if (cmd_sup) { if (values.size() != 1) - UsageProblem("-supported <executable_file>"); + UsageProblem(kUsageSupported); return !Supported(values[0]); } else if (cmd_dis) { - if (values.size() != 2) - UsageProblem("-dis <executable_file> <courgette_file>"); - Disassemble(values[0], values[1]); + if (values.size() != 2) + UsageProblem(kUsageDis); + Disassemble(values[0], values[1]); } else if (cmd_asm) { if (values.size() != 2) - UsageProblem("-asm <courgette_file_input> <executable_file_output>"); + UsageProblem(kUsageAsm); Assemble(values[0], values[1]); } else if (cmd_disadj) { if (values.size() != 3) - UsageProblem("-disadj <executable_file> <model> <courgette_file>"); + UsageProblem(kUsageDisadj); DisassembleAndAdjust(values[0], values[1], values[2]); } else if (cmd_make_patch) { if (values.size() != 3) - UsageProblem("-gen <old_file> <new_file> <patch_file>"); + UsageProblem(kUsageGen); GenerateEnsemblePatch(values[0], values[1], values[2]); } else if (cmd_apply_patch) { if (values.size() != 3) - UsageProblem("-apply <old_file> <patch_file> <new_file>"); + UsageProblem(kUsageApply); ApplyEnsemblePatch(values[0], values[1], values[2]); } else if (cmd_make_bsdiff_patch) { if (values.size() != 3) - UsageProblem("-genbsdiff <old_file> <new_file> <patch_file>"); + UsageProblem(kUsageGenbsdiff); GenerateBSDiffPatch(values[0], values[1], values[2]); } else if (cmd_apply_bsdiff_patch) { if (values.size() != 3) - UsageProblem("-applybsdiff <old_file> <patch_file> <new_file>"); + UsageProblem(kUsageApplybsdiff); ApplyBSDiffPatch(values[0], values[1], values[2]); } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { if (values.size() != 3) - UsageProblem("-gen1[au] <old_file> <new_file> <patch_files_root>"); + UsageProblem(kUsageGen1); DisassembleAdjustDiff(values[0], values[1], values[2], cmd_spread_1_adjusted); } else {
diff --git a/courgette/encode_decode_unittest.cc b/courgette/encode_decode_unittest.cc index 6e88ee3..7b705f12 100644 --- a/courgette/encode_decode_unittest.cc +++ b/courgette/encode_decode_unittest.cc
@@ -9,10 +9,13 @@ #include "courgette/assembly_program.h" #include "courgette/base_test_unittest.h" #include "courgette/courgette.h" +#include "courgette/courgette_flow.h" #include "courgette/encoded_program.h" #include "courgette/program_detector.h" #include "courgette/streams.h" +namespace courgette { + class EncodeDecodeTest : public BaseTest { public: void TestAssembleToStreamDisassemble(const std::string& file, @@ -22,57 +25,63 @@ void EncodeDecodeTest::TestAssembleToStreamDisassemble( const std::string& file, size_t expected_encoded_length) const { - const uint8_t* original_buffer = - reinterpret_cast<const uint8_t*>(file.data()); + const uint8_t* original_data = reinterpret_cast<const uint8_t*>(file.data()); size_t original_length = file.length(); + CourgetteFlow flow; - std::unique_ptr<courgette::AssemblyProgram> program; - const courgette::Status parse_status = courgette::ParseDetectedExecutable( - original_buffer, original_length, &program); - EXPECT_EQ(courgette::C_OK, parse_status); + // Convert executable to encoded assembly. + RegionBuffer original_buffer(Region(original_data, original_length)); + flow.ReadAssemblyProgramFromBuffer(flow.ONLY, original_buffer, false); + EXPECT_EQ(C_OK, flow.status()); + EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->program.get()); - std::unique_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); - EXPECT_EQ(courgette::C_OK, encode_status); + flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY); + EXPECT_EQ(C_OK, flow.status()); + EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->encoded.get()); - program.reset(); + flow.DestroyAssemblyProgram(flow.ONLY); + EXPECT_EQ(C_OK, flow.status()); + EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->program.get()); - courgette::SinkStreamSet sinks; - const courgette::Status write_status = - WriteEncodedProgram(encoded.get(), &sinks); - EXPECT_EQ(courgette::C_OK, write_status); + flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY); + EXPECT_EQ(C_OK, flow.status()); - encoded.reset(); + flow.DestroyEncodedProgram(flow.ONLY); + EXPECT_EQ(C_OK, flow.status()); + EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->encoded.get()); - courgette::SinkStream sink; - bool can_collect = sinks.CopyTo(&sink); - EXPECT_TRUE(can_collect); + SinkStream sink; + flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink); + EXPECT_EQ(C_OK, flow.status()); - const void* buffer = sink.Buffer(); - size_t length = sink.Length(); + const void* encoded_data = sink.Buffer(); + size_t encoded_length = sink.Length(); + EXPECT_EQ(expected_encoded_length, encoded_length); - EXPECT_EQ(expected_encoded_length, length); + // Convert encoded assembly back to executable. + RegionBuffer encoded_buffer(Region(encoded_data, encoded_length)); + flow.ReadSourceStreamSetFromBuffer(flow.ONLY, encoded_buffer); + EXPECT_EQ(C_OK, flow.status()); - courgette::SourceStreamSet sources; - bool can_get_source_streams = sources.Init(buffer, length); - EXPECT_TRUE(can_get_source_streams); + flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY); + EXPECT_EQ(C_OK, flow.status()); + EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->encoded.get()); - std::unique_ptr<courgette::EncodedProgram> encoded2; - const courgette::Status read_status = ReadEncodedProgram(&sources, &encoded2); - EXPECT_EQ(courgette::C_OK, read_status); + SinkStream executable; + flow.WriteExecutableFromEncodedProgram(flow.ONLY, &executable); + EXPECT_EQ(C_OK, flow.status()); - courgette::SinkStream assembled; - const courgette::Status assemble_status = - Assemble(encoded2.get(), &assembled); - EXPECT_EQ(courgette::C_OK, assemble_status); + flow.DestroyEncodedProgram(flow.ONLY); + EXPECT_EQ(C_OK, flow.status()); + EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->encoded.get()); + EXPECT_TRUE(flow.ok()); + EXPECT_FALSE(flow.failed()); - encoded2.reset(); + const void* executable_data = executable.Buffer(); + size_t executable_length = executable.Length(); + EXPECT_EQ(original_length, executable_length); - const void* assembled_buffer = assembled.Buffer(); - size_t assembled_length = assembled.Length(); - - EXPECT_EQ(original_length, assembled_length); - EXPECT_EQ(0, memcmp(original_buffer, assembled_buffer, original_length)); + EXPECT_EQ(0, memcmp(original_data, executable_data, original_length)); } TEST_F(EncodeDecodeTest, PE) { @@ -99,3 +108,5 @@ std::string file = FileContents("elf-armv7"); TestAssembleToStreamDisassemble(file, 8531); } + +} // namespace courgette
diff --git a/courgette/encoded_program_fuzz_unittest.cc b/courgette/encoded_program_fuzz_unittest.cc index be32adf..108283516 100644 --- a/courgette/encoded_program_fuzz_unittest.cc +++ b/courgette/encoded_program_fuzz_unittest.cc
@@ -17,10 +17,9 @@ #include <memory> #include "base/test/test_suite.h" -#include "courgette/assembly_program.h" #include "courgette/base_test_unittest.h" #include "courgette/courgette.h" -#include "courgette/program_detector.h" +#include "courgette/courgette_flow.h" #include "courgette/streams.h" class DecodeFuzzTest : public BaseTest { @@ -41,32 +40,36 @@ void DecodeFuzzTest::FuzzExe(const char* file_name) const { std::string file1 = FileContents(file_name); - const uint8_t* original_buffer = - reinterpret_cast<const uint8_t*>(file1.data()); + const uint8_t* original_data = reinterpret_cast<const uint8_t*>(file1.data()); size_t original_length = file1.length(); + courgette::CourgetteFlow flow; - std::unique_ptr<courgette::AssemblyProgram> program; - const courgette::Status parse_status = - courgette::ParseDetectedExecutable(original_buffer, original_length, - &program); - EXPECT_EQ(courgette::C_OK, parse_status); + courgette::RegionBuffer original_buffer( + courgette::Region(original_data, original_length)); + flow.ReadAssemblyProgramFromBuffer(flow.ONLY, original_buffer, false); + EXPECT_EQ(courgette::C_OK, flow.status()); + EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->program.get()); - std::unique_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); - EXPECT_EQ(courgette::C_OK, encode_status); + flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY); + EXPECT_EQ(courgette::C_OK, flow.status()); + EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->encoded.get()); - program.reset(); + flow.DestroyAssemblyProgram(flow.ONLY); + EXPECT_EQ(courgette::C_OK, flow.status()); + EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->program.get()); - courgette::SinkStreamSet sinks; - const courgette::Status write_status = - WriteEncodedProgram(encoded.get(), &sinks); - EXPECT_EQ(courgette::C_OK, write_status); + flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY); + EXPECT_EQ(courgette::C_OK, flow.status()); - encoded.reset(); + flow.DestroyEncodedProgram(flow.ONLY); + EXPECT_EQ(courgette::C_OK, flow.status()); + EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->encoded.get()); courgette::SinkStream sink; - bool can_collect = sinks.CopyTo(&sink); - EXPECT_TRUE(can_collect); + flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink); + EXPECT_EQ(courgette::C_OK, flow.status()); + EXPECT_TRUE(flow.ok()); + EXPECT_FALSE(flow.failed()); size_t length = sink.Length(); @@ -173,34 +176,27 @@ } } -bool DecodeFuzzTest::TryAssemble(const std::string& buffer, +bool DecodeFuzzTest::TryAssemble(const std::string& file, std::string* output) const { - std::unique_ptr<courgette::EncodedProgram> encoded; - bool result = false; + courgette::CourgetteFlow flow; + courgette::RegionBuffer file_buffer(courgette::Region( + reinterpret_cast<const uint8_t*>(file.data()), file.length())); + flow.ReadSourceStreamSetFromBuffer(flow.ONLY, file_buffer); + if (flow.failed()) + return false; - courgette::SourceStreamSet sources; - bool can_get_source_streams = sources.Init(buffer.c_str(), buffer.length()); - if (can_get_source_streams) { - const courgette::Status read_status = - ReadEncodedProgram(&sources, &encoded); - if (read_status == courgette::C_OK) { - courgette::SinkStream assembled; - const courgette::Status assemble_status = - Assemble(encoded.get(), &assembled); + flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY); + if (flow.failed()) + return false; - if (assemble_status == courgette::C_OK) { - const void* assembled_buffer = assembled.Buffer(); - size_t assembled_length = assembled.Length(); + courgette::SinkStream sink; + flow.WriteExecutableFromEncodedProgram(flow.ONLY, &sink); + if (flow.failed()) + return false; - output->clear(); - output->assign(reinterpret_cast<const char*>(assembled_buffer), - assembled_length); - result = true; - } - } - } - - return result; + output->clear(); + output->assign(reinterpret_cast<const char*>(sink.Buffer()), sink.Length()); + return true; } TEST_F(DecodeFuzzTest, All) {
diff --git a/courgette/patch_generator_x86_32.h b/courgette/patch_generator_x86_32.h index 0c2f9f0..b03d7c1 100644 --- a/courgette/patch_generator_x86_32.h +++ b/courgette/patch_generator_x86_32.h
@@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This is the transformation and adjustment for all executables. -// The executable type is determined by ParseDetectedExecutable function. - #ifndef COURGETTE_PATCH_GENERATOR_X86_32_H_ #define COURGETTE_PATCH_GENERATOR_X86_32_H_ @@ -13,12 +10,16 @@ #include "base/logging.h" #include "base/macros.h" #include "courgette/assembly_program.h" +#include "courgette/courgette_flow.h" #include "courgette/ensemble.h" #include "courgette/patcher_x86_32.h" #include "courgette/program_detector.h" namespace courgette { +// PatchGeneratorX86_32 is the universal patch generator for all executables, +// performing transformation and adjustment. The executable type is determined +// by the program detector. class PatchGeneratorX86_32 : public TransformationPatchGenerator { public: PatchGeneratorX86_32(Element* old_element, @@ -62,56 +63,26 @@ if (!corrected_parameters->Empty()) return C_GENERAL_ERROR; - // Generate old version of program using |corrected_parameters|. - // TODO(sra): refactor to use same code from patcher_. - std::unique_ptr<AssemblyProgram> old_program; - Status old_parse_status = ParseDetectedExecutableWithAnnotation( - old_element_->region().start(), old_element_->region().length(), - &old_program); - if (old_parse_status != C_OK) { - LOG(ERROR) << "Cannot parse an executable " << old_element_->Name(); - return old_parse_status; + CourgetteFlow flow; + RegionBuffer old_buffer(old_element_->region()); + RegionBuffer new_buffer(new_element_->region()); + flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, true); + flow.CreateEncodedProgramFromAssemblyProgram(flow.OLD); + flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD, + old_transformed_element); + flow.DestroyEncodedProgram(flow.OLD); + flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, true); + flow.AdjustNewAssemblyProgramToMatchOld(); + flow.DestroyAssemblyProgram(flow.OLD); + flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); + flow.DestroyAssemblyProgram(flow.NEW); + flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW, + new_transformed_element); + if (flow.failed()) { + LOG(ERROR) << flow.message() << " (" << old_element_->Name() << " => " + << new_element_->Name() << ")"; } - - // TODO(huangs): Move the block below to right before |new_program| gets - // used, so we can reduce Courgette-gen peak memory. - std::unique_ptr<AssemblyProgram> new_program; - Status new_parse_status = ParseDetectedExecutableWithAnnotation( - new_element_->region().start(), new_element_->region().length(), - &new_program); - if (new_parse_status != C_OK) { - LOG(ERROR) << "Cannot parse an executable " << new_element_->Name(); - return new_parse_status; - } - - std::unique_ptr<EncodedProgram> old_encoded; - Status old_encode_status = Encode(*old_program, &old_encoded); - if (old_encode_status != C_OK) - return old_encode_status; - - Status old_write_status = - WriteEncodedProgram(old_encoded.get(), old_transformed_element); - - old_encoded.reset(); - - if (old_write_status != C_OK) - return old_write_status; - - Status adjust_status = Adjust(*old_program, new_program.get()); - old_program.reset(); - if (adjust_status != C_OK) - return adjust_status; - - std::unique_ptr<EncodedProgram> new_encoded; - Status new_encode_status = Encode(*new_program, &new_encoded); - if (new_encode_status != C_OK) - return new_encode_status; - - new_program.reset(); - - Status new_write_status = - WriteEncodedProgram(new_encoded.get(), new_transformed_element); - return new_write_status; + return flow.status(); } Status Reform(SourceStreamSet* transformed_element,
diff --git a/courgette/patcher_x86_32.h b/courgette/patcher_x86_32.h index c5f4e3c0..fa822dc 100644 --- a/courgette/patcher_x86_32.h +++ b/courgette/patcher_x86_32.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 COURGETTE_WIN32_X86_PATCHER_H_ -#define COURGETTE_WIN32_X86_PATCHER_H_ +#ifndef COURGETTE_PATCHER_X86_32_H_ +#define COURGETTE_PATCHER_X86_32_H_ #include <stdint.h> @@ -11,15 +11,15 @@ #include "base/macros.h" #include "courgette/assembly_program.h" +#include "courgette/courgette_flow.h" #include "courgette/encoded_program.h" #include "courgette/ensemble.h" #include "courgette/program_detector.h" namespace courgette { -// PatcherX86_32 is the universal patcher for all executables. The executable -// type is determined by ParseDetectedExecutable function. -// +// PatcherX86_32 is the universal patcher for all executables. The executable +// type is determined by the program detector. class PatcherX86_32 : public TransformationPatcher { public: explicit PatcherX86_32(const Region& region) @@ -49,36 +49,26 @@ Status Transform(SourceStreamSet* corrected_parameters, SinkStreamSet* transformed_element) { - Status status; - if (!corrected_parameters->Empty()) - return C_GENERAL_ERROR; // Don't expect any corrected parameters. - - std::unique_ptr<AssemblyProgram> program; - status = ParseDetectedExecutable(ensemble_region_.start() + base_offset_, - base_length_, - &program); - if (status != C_OK) - return status; - - std::unique_ptr<EncodedProgram> encoded; - status = Encode(*program, &encoded); - if (status != C_OK) - return status; - - program.reset(); - - return WriteEncodedProgram(encoded.get(), transformed_element); + CourgetteFlow flow; + RegionBuffer only_buffer( + Region(ensemble_region_.start() + base_offset_, base_length_)); + flow.ReadAssemblyProgramFromBuffer(flow.ONLY, only_buffer, false); + flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY); + flow.DestroyAssemblyProgram(flow.ONLY); + flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY, transformed_element); + if (flow.failed()) + LOG(ERROR) << flow.message(); + return flow.status(); } Status Reform(SourceStreamSet* transformed_element, SinkStream* reformed_element) { - Status status; - std::unique_ptr<EncodedProgram> encoded_program; - status = ReadEncodedProgram(transformed_element, &encoded_program); - if (status != C_OK) - return status; - - return Assemble(encoded_program.get(), reformed_element); + CourgetteFlow flow; + flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY, transformed_element); + flow.WriteExecutableFromEncodedProgram(flow.ONLY, reformed_element); + if (flow.failed()) + LOG(ERROR) << flow.message(); + return flow.status(); } private: @@ -90,6 +80,6 @@ DISALLOW_COPY_AND_ASSIGN(PatcherX86_32); }; -} // namespace +} // namespace courgette -#endif // COURGETTE_WIN32_X86_PATCHER_H_ +#endif // COURGETTE_PATCHER_X86_32_H_
diff --git a/courgette/streams.h b/courgette/streams.h index c23d710..fb7204e 100644 --- a/courgette/streams.h +++ b/courgette/streams.h
@@ -33,6 +33,15 @@ // Maximum number of streams in a stream set. static const unsigned int kMaxStreams = 10; +// A simple interface for reading binary data. +class BasicBuffer { + public: + BasicBuffer() {} + virtual ~BasicBuffer() {} + virtual const uint8_t* data() const = 0; + virtual size_t length() const = 0; +}; + // A SourceStream allows a region of memory to be scanned by a sequence of Read // operations. The stream does not own the memory. class SourceStream { @@ -234,5 +243,6 @@ DISALLOW_COPY_AND_ASSIGN(SinkStreamSet); }; -} // namespace +} // namespace courgette + #endif // COURGETTE_STREAMS_H_
diff --git a/device/BUILD.gn b/device/BUILD.gn index b9d73b20..3b481aa6 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -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("vr/features.gni") +import("vr/features/features.gni") import("//build/config/features.gni") import("//testing/test.gni")
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn index 66f5c096..a1ed8c4 100644 --- a/device/vr/BUILD.gn +++ b/device/vr/BUILD.gn
@@ -2,23 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("features.gni") -import("//build/buildflag_header.gni") +import("features/features.gni") import("//mojo/public/tools/bindings/mojom.gni") if (is_android) { import("//build/config/android/rules.gni") # For generate_jni(). } -# Generate a buildflag header for compile-time checking of WebVR support. -buildflag_header("features") { - header = "features.h" - flags = [ - "ENABLE_VR=$enable_vr", - "ENABLE_OPENVR=$enable_openvr", - ] -} - component("vr") { output_name = "device_vr" @@ -27,11 +17,9 @@ ] defines = [ "DEVICE_VR_IMPLEMENTATION" ] deps = [ - ":features", + ":mojo_bindings", + "features", ] - if (!is_ios) { - deps += [ ":mojo_bindings" ] - } if (!enable_vr) { sources += [ @@ -128,19 +116,17 @@ } } -if (!is_ios) { - mojom("mojo_bindings") { - sources = [ - "vr_service.mojom", - ] +mojom("mojo_bindings") { + sources = [ + "vr_service.mojom", + ] - public_deps = [ - "//gpu/ipc/common:interfaces", - "//mojo/common:common_custom_types", - ] + public_deps = [ + "//gpu/ipc/common:interfaces", + "//mojo/common:common_custom_types", + ] - export_class_attribute = "DEVICE_VR_EXPORT" - export_define = "DEVICE_VR_IMPLEMENTATION=1" - export_header = "device/vr/vr_export.h" - } + export_class_attribute = "DEVICE_VR_EXPORT" + export_define = "DEVICE_VR_IMPLEMENTATION=1" + export_header = "device/vr/vr_export.h" }
diff --git a/device/vr/features/BUILD.gn b/device/vr/features/BUILD.gn new file mode 100644 index 0000000..e8afb4a --- /dev/null +++ b/device/vr/features/BUILD.gn
@@ -0,0 +1,15 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("features.gni") +import("//build/buildflag_header.gni") + +# Generate a buildflag header for compile-time checking of WebVR support. +buildflag_header("features") { + header = "features.h" + flags = [ + "ENABLE_VR=$enable_vr", + "ENABLE_OPENVR=$enable_openvr", + ] +}
diff --git a/device/vr/features.gni b/device/vr/features/features.gni similarity index 100% rename from device/vr/features.gni rename to device/vr/features/features.gni
diff --git a/device/vr/vr_device_manager.cc b/device/vr/vr_device_manager.cc index bd314f4c..af97c0a 100644 --- a/device/vr/vr_device_manager.cc +++ b/device/vr/vr_device_manager.cc
@@ -10,7 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" #include "build/build_config.h" -#include "device/vr/features.h" +#include "device/vr/features/features.h" #if defined(OS_ANDROID) #include "device/vr/android/gvr/gvr_device_provider.h"
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc index 93d4103e..c030fda 100644 --- a/extensions/browser/api/networking_private/networking_private_chromeos.cc +++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -860,10 +860,14 @@ case UIProxyConfig::MODE_PROXY_PER_SCHEME: { base::DictionaryValue* manual = EnsureDictionaryValue(::onc::proxy::kManual, proxy_settings); - SetManualProxy(manual, state, ::onc::proxy::kHttp, config.http_proxy); - SetManualProxy(manual, state, ::onc::proxy::kHttps, config.https_proxy); - SetManualProxy(manual, state, ::onc::proxy::kFtp, config.ftp_proxy); - SetManualProxy(manual, state, ::onc::proxy::kSocks, config.socks_proxy); + if (config.http_proxy.server.is_valid()) + SetManualProxy(manual, state, ::onc::proxy::kHttp, config.http_proxy); + if (config.https_proxy.server.is_valid()) + SetManualProxy(manual, state, ::onc::proxy::kHttps, config.https_proxy); + if (config.ftp_proxy.server.is_valid()) + SetManualProxy(manual, state, ::onc::proxy::kFtp, config.ftp_proxy); + if (config.socks_proxy.server.is_valid()) + SetManualProxy(manual, state, ::onc::proxy::kSocks, config.socks_proxy); break; } case UIProxyConfig::MODE_PAC_SCRIPT: {
diff --git a/extensions/common/api/networking_onc.idl b/extensions/common/api/networking_onc.idl index 6e37363..960c7a9 100644 --- a/extensions/common/api/networking_onc.idl +++ b/extensions/common/api/networking_onc.idl
@@ -263,9 +263,12 @@ ClientCertificateType ClientCertType; DOMString? Identity; DOMString? Inner; - DOMString Outer; + // The outer EAP type. Required by ONC, but may not be provided when + // translating from Shill. + DOMString? Outer; DOMString? Password; boolean? SaveCredentials; + DOMString[]? ServerCAPEMs; DOMString[]? ServerCARefs; boolean? UseProactiveKeyCaching; boolean? UseSystemCAs;
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl index 5b9d9bd..4e3be9b 100644 --- a/extensions/common/api/networking_private.idl +++ b/extensions/common/api/networking_private.idl
@@ -233,9 +233,12 @@ DOMString? ClientCertType; DOMString? Identity; DOMString? Inner; - DOMString Outer; + // The outer EAP type. Required by ONC, but may not be provided when + // translating from Shill. + DOMString? Outer; DOMString? Password; boolean? SaveCredentials; + DOMString[]? ServerCAPEMs; DOMString[]? ServerCARefs; boolean? UseProactiveKeyCaching; boolean? UseSystemCAs; @@ -248,9 +251,12 @@ ManagedDOMString? ClientCertType; ManagedDOMString? Identity; ManagedDOMString? Inner; - ManagedDOMString Outer; + // The outer EAP type. Required by ONC, but may not be provided when + // translating from Shill. + ManagedDOMString? Outer; ManagedDOMString? Password; ManagedBoolean? SaveCredentials; + ManagedDOMStringList? ServerCAPEMs; ManagedDOMStringList? ServerCARefs; ManagedBoolean? UseProactiveKeyCaching; ManagedBoolean? UseSystemCAs;
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 03b4c76..571974c 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -11,6 +11,9 @@ // Allow users to specify a custom buffer size for debugging purpose. const char kAudioBufferSize[] = "audio-buffer-size"; +// Command line flag name to set the autoplay policy. +const char kAutoplayPolicy[] = "autoplay-policy"; + // Set number of threads to use for video decoding. const char kVideoThreads[] = "video-threads"; @@ -135,21 +138,25 @@ const char kMSEAudioBufferSizeLimit[] = "mse-audio-buffer-size-limit"; const char kMSEVideoBufferSizeLimit[] = "mse-video-buffer-size-limit"; +namespace autoplay { + +// Autoplay policy to require a user gesture in ordor to play for cross origin +// iframes. +const char kCrossOriginUserGestureRequiredPolicy[] = + "cross-origin-user-gesture-required"; + +// Autoplay policy that does not require any user gesture. +const char kNoUserGestureRequiredPolicy[] = "no-user-gesture-required"; + +// Autoplay policy to require a user gesture in order to play. +const char kUserGestureRequiredPolicy[] = "user-gesture-required"; + +} // namespace autoplay + } // namespace switches namespace media { -#if defined(OS_WIN) -// Enables video decode acceleration using the D3D11 video decoder api. -// This is completely insecure - DO NOT USE except for testing. -const base::Feature kD3D11VideoDecoding{"D3D11VideoDecoding", - base::FEATURE_DISABLED_BY_DEFAULT}; - -// Enables H264 HW encode acceleration using Media Foundation for Windows. -const base::Feature kMediaFoundationH264Encoding{ - "MediaFoundationH264Encoding", base::FEATURE_ENABLED_BY_DEFAULT}; -#endif // defined(OS_WIN) - // Use new audio rendering mixer. const base::Feature kNewAudioRenderingMixingStrategy{ "NewAudioRenderingMixingStrategy", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -214,4 +221,15 @@ #endif +#if defined(OS_WIN) +// Enables video decode acceleration using the D3D11 video decoder api. +// This is completely insecure - DO NOT USE except for testing. +const base::Feature kD3D11VideoDecoding{"D3D11VideoDecoding", + base::FEATURE_DISABLED_BY_DEFAULT}; + +// Enables H264 HW encode acceleration using Media Foundation for Windows. +const base::Feature kMediaFoundationH264Encoding{ + "MediaFoundationH264Encoding", base::FEATURE_ENABLED_BY_DEFAULT}; +#endif // defined(OS_WIN) + } // namespace media
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index b2234d1a..f40ea604 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -17,6 +17,8 @@ MEDIA_EXPORT extern const char kAudioBufferSize[]; +MEDIA_EXPORT extern const char kAutoplayPolicy[]; + MEDIA_EXPORT extern const char kVideoThreads[]; MEDIA_EXPORT extern const char kEnableMediaSuspend[]; @@ -75,6 +77,14 @@ MEDIA_EXPORT extern const char kMSEAudioBufferSizeLimit[]; MEDIA_EXPORT extern const char kMSEVideoBufferSizeLimit[]; +namespace autoplay { + +MEDIA_EXPORT extern const char kCrossOriginUserGestureRequiredPolicy[]; +MEDIA_EXPORT extern const char kNoUserGestureRequiredPolicy[]; +MEDIA_EXPORT extern const char kUserGestureRequiredPolicy[]; + +} // namespace autoplay + } // namespace switches namespace media { @@ -82,11 +92,7 @@ // All features in alphabetical order. The features should be documented // alongside the definition of their values in the .cc file. -#if defined(OS_WIN) -MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoding; -MEDIA_EXPORT extern const base::Feature kMediaFoundationH264Encoding; -#endif // defined(OS_WIN) - +MEDIA_EXPORT extern const base::Feature kAutoplayPolicy; MEDIA_EXPORT extern const base::Feature kNewAudioRenderingMixingStrategy; MEDIA_EXPORT extern const base::Feature kOverlayFullscreenVideo; MEDIA_EXPORT extern const base::Feature kResumeBackgroundVideo; @@ -103,6 +109,12 @@ MEDIA_EXPORT extern const base::Feature kVideoFullscreenOrientationLock; MEDIA_EXPORT extern const base::Feature kMediaDrmPersistentLicense; #endif // defined(OS_ANDROID) + +#if defined(OS_WIN) +MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoding; +MEDIA_EXPORT extern const base::Feature kMediaFoundationH264Encoding; +#endif // defined(OS_WIN) + } // namespace media #endif // MEDIA_BASE_MEDIA_SWITCHES_H_
diff --git a/mojo/README.md b/mojo/README.md index 64d129f..3c4428d 100644 --- a/mojo/README.md +++ b/mojo/README.md
@@ -1,4 +1,4 @@ -#  Mojo +# Mojo This document is a subset of the [Mojo documentation](/mojo). [TOC]
diff --git a/mojo/edk/embedder/README.md b/mojo/edk/embedder/README.md index 6fc2cce..f6f8f356 100644 --- a/mojo/edk/embedder/README.md +++ b/mojo/edk/embedder/README.md
@@ -1,4 +1,4 @@ -#  Mojo Embedder Development Kit (EDK) +# Mojo Embedder Development Kit (EDK) This document is a subset of the [Mojo documentation](/mojo). [TOC]
diff --git a/mojo/edk/system/node_channel.cc b/mojo/edk/system/node_channel.cc index bed3848..0c438ebe 100644 --- a/mojo/edk/system/node_channel.cc +++ b/mojo/edk/system/node_channel.cc
@@ -692,7 +692,7 @@ MACH_PORT_NULL) { pending_relay_messages_.push( std::make_pair(data->destination, std::move(message))); - break; + return; } } #endif
diff --git a/mojo/public/c/system/README.md b/mojo/public/c/system/README.md index 6e4ad3d9..a668fc1 100644 --- a/mojo/public/c/system/README.md +++ b/mojo/public/c/system/README.md
@@ -1,4 +1,4 @@ -#  Mojo C System API +# Mojo C System API This document is a subset of the [Mojo documentation](/mojo). [TOC]
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index ef11c693..f94e314 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -39,6 +39,7 @@ "connection_error_callback.h", "connector.h", "disconnect_reason.h", + "equals_traits.h", "filter_chain.h", "interface_data_view.h", "interface_endpoint_client.h", @@ -65,7 +66,6 @@ "lib/control_message_handler.h", "lib/control_message_proxy.cc", "lib/control_message_proxy.h", - "lib/equals_traits.h", "lib/filter_chain.cc", "lib/fixed_buffer.cc", "lib/fixed_buffer.h",
diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md index 9a8e2b04..7426f043 100644 --- a/mojo/public/cpp/bindings/README.md +++ b/mojo/public/cpp/bindings/README.md
@@ -1,4 +1,4 @@ -#  Mojo C++ Bindings API +# Mojo C++ Bindings API This document is a subset of the [Mojo documentation](/mojo). [TOC] @@ -457,13 +457,222 @@ message. Thus the `impl` above will first log our message and *then* see a connection error and break out of the run loop. +### Enums + +[Mojom enums](/mojo/public/tools/bindings#Enumeration-Types) translate directly +to equivalent strongly-typed C++11 enum classes with `int32_t` as the underlying +type. The typename and value names are identical between Mojom and C++. + +For example, consider the following Mojom definition: + +```cpp +module business.mojom; + +enum Department { + kEngineering, + kMarketng, + kSales, +}; +``` + +This translates to the following C++ definition: + +```cpp +namespace business { +namespace mojom { + +enum class Department : int32_t { + kEngineering, + kMarketing, + kSales, +}; + +} // namespace mojom +} // namespace business +``` + +### Structs + +[Mojom structs](mojo/public/tools/bindings#Structs) can be used to define +logical groupings of fields into a new composite type. Every Mojom struct +elicits the generation of an identically named, representative C++ class, with +identically named public fields of corresponding C++ types, and several helpful +public methods. + +For example, consider the following Mojom struct: + +```cpp +module business.mojom; + +struct Employee { + int64 id; + string username; + Department department; +}; +``` + +This would generate a C++ class like so: + +```cpp +namespace business { +namespace mojom { + +class Employee; + +using EmployeePtr = mojo::StructPtr<Employee>; + +class Employee { + public: + // Default constructor - applies default values, potentially ones specified + // explicitly within the Mojom. + Employee(); + + // Value constructor - an explicit argument for every field in the struct, in + // lexical Mojom definition order. + Employee(int64_t id, const std::string& username, Department department); + + // Creates a new copy of this struct value + EmployeePtr Clone(); + + // Tests for equality with another struct value of the same type. + bool Equals(const Employee& other); + + // Equivalent public fields with names identical to the Mojom. + int64_t id; + std::string username; + Department department; +}; + +} // namespace mojom +} // namespace business +``` + +Note when used as a message parameter or as a field within another Mojom struct, +a `struct` type is wrapped by the move-only `mojo::StructPtr` helper, which is +roughly equivalent to a `std::unique_ptr` with some additional utility methods. +This allows struct values to be nullable and struct types to be potentially +self-referential. + +Every genereated struct class has a static `New()` method which returns a new +`mojo::StructPtr<T>` wrapping a new instance of the class constructed by +forwarding the arguments from `New`. For example: + +```cpp +mojom::EmployeePtr e1 = mojom::Employee::New(); +e1->id = 42; +e1->username = "mojo"; +e1->department = mojom::Department::kEngineering; +``` + +is equivalent to + +```cpp +auto e1 = mojom::Employee::New(42, "mojo", mojom::Department::kEngineering); +``` + +Now if we define an interface like: + +```cpp +interface EmployeeManager { + AddEmployee(Employee e); +}; +``` + +We'll get this C++ interface to implement: + +```cpp +class EmployeeManager { + public: + virtual ~EmployeManager() {} + + virtual void AddEmployee(EmployeePtr e) = 0; +}; +``` + +And we can send this message from C++ code as follows: + +```cpp +mojom::EmployeManagerPtr manager = ...; +manager->AddEmployee( + Employee::New(42, "mojo", mojom::Department::kEngineering)); + +// or +auto e = Employee::New(42, "mojo", mojom::Department::kEngineering); +manager->AddEmployee(std::move(e)); +``` + +### Unions + +Similarly to [structs](#Structs), tagged unions generate an identically named, +representative C++ class which is typically wrapped in a `mojo::StructPtr<T>`. + +Unlike structs, all generated union fields are private and must be retrieved and +manipulated using accessors. A field `foo` is accessible by `foo()` and +settable by `set_foo()`. There is also a boolean `is_foo()` for each field which +indicates whether the union is currently taking on the value of field `foo` in +exclusion to all other union fields. + +Finally, every generated union class also has a nested `Tag` enum class which +enumerates all of the named union fields. A Mojom union value's current type can +be determined by calling the `which()` method which returns a `Tag`. + +For example, consider the following Mojom definitions: + +```cpp +union Value { + int64 int_value; + float32 float_vlaue; + string string_value; +}; + +interface Dictionary { + AddValue(string key, Value value); +}; +``` + +This generates a the following C++ interface: + +```cpp +class Value { + public: + virtual ~Value() {} + + virtual void AddValue(const std::string& key, ValuePtr value) = 0; +}; +``` + +And we can use it like so: + +```cpp +ValuePtr value = Value::New(); +value->set_int_value(42); +CHECK(value->is_int_value()); +CHECK_EQ(value->which(), Value::Tag::INT_VALUE); + +value->set_float_value(42); +CHECK(value->is_float_value()); +CHECK_EQ(value->which(), Value::Tag::FLOAT_VALUE); + +value->set_string_value("bananas"); +CHECK(value->is_string_value()); +CHECK_EQ(value->which(), Value::Tag::STRING_VALUE); +``` + +Finally, note that if a union value is not currently occupied by a given field, +attempts to access that field will DCHECK: + +```cpp +ValuePtr value = Value::New(); +value->set_int_value(42); +LOG(INFO) << "Value is " << value->string_value(); // DCHECK! +``` + ### Sending Interfaces Over Interfaces -Now we know how to create interface pipes and use their Ptr and Request -endpoints in some interesting ways. This still doesn't add up to interesting -IPC! The bread and butter of Mojo IPC is the ability to transfer interface -endpoints across other interfaces, so let's take a look at how to accomplish -that. +We know how to create interface pipes and use their Ptr and Request endpoints +in some interesting ways. This still doesn't add up to interesting IPC! The +bread and butter of Mojo IPC is the ability to transfer interface endpoints +across other interfaces, so let's take a look at how to accomplish that. #### Sending Interface Requests
diff --git a/mojo/public/cpp/bindings/lib/equals_traits.h b/mojo/public/cpp/bindings/equals_traits.h similarity index 74% rename from mojo/public/cpp/bindings/lib/equals_traits.h rename to mojo/public/cpp/bindings/equals_traits.h index 53c7dce..5d5dfa2 100644 --- a/mojo/public/cpp/bindings/lib/equals_traits.h +++ b/mojo/public/cpp/bindings/equals_traits.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 MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ -#define MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ +#ifndef MOJO_PUBLIC_CPP_BINDINGS_EQUALS_TRAITS_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_EQUALS_TRAITS_H_ #include <type_traits> #include <unordered_map> @@ -13,7 +13,10 @@ #include "mojo/public/cpp/bindings/lib/template_util.h" namespace mojo { -namespace internal { + +// EqualsTraits<> allows you to specify comparison functions for mapped mojo +// objects. By default objects can be compared if they implement operator==() +// or have a method named Equals(). template <typename T> struct HasEqualsMethod { @@ -24,7 +27,7 @@ static const bool value = sizeof(Test<T>(0)) == sizeof(char); private: - EnsureTypeIsComplete<T> check_t_; + internal::EnsureTypeIsComplete<T> check_t_; }; template <typename T, bool has_equals_method = HasEqualsMethod<T>::value> @@ -51,7 +54,9 @@ if (!a || !b) return false; - return internal::Equals(*a, *b); + // NOTE: Not just Equals() because that's EqualsTraits<>::Equals() and we + // want mojo::Equals() for things like base::Optional<std::vector<T>>. + return mojo::Equals(*a, *b); } }; @@ -61,7 +66,7 @@ if (a.size() != b.size()) return false; for (size_t i = 0; i < a.size(); ++i) { - if (!internal::Equals(a[i], b[i])) + if (!mojo::Equals(a[i], b[i])) return false; } return true; @@ -76,7 +81,7 @@ return false; for (const auto& element : a) { auto iter = b.find(element.first); - if (iter == b.end() || !internal::Equals(element.second, iter->second)) + if (iter == b.end() || !mojo::Equals(element.second, iter->second)) return false; } return true; @@ -88,7 +93,6 @@ return EqualsTraits<T>::Equals(a, b); } -} // namespace internal } // namespace mojo -#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_EQUALS_TRAITS_H_ +#endif // MOJO_PUBLIC_CPP_BINDINGS_EQUALS_TRAITS_H_
diff --git a/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h b/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h index 07f969dd..f18274f 100644 --- a/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h +++ b/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h
@@ -8,7 +8,7 @@ #include <type_traits> #include "mojo/public/cpp/bindings/clone_traits.h" -#include "mojo/public/cpp/bindings/lib/equals_traits.h" +#include "mojo/public/cpp/bindings/equals_traits.h" #include "third_party/WebKit/Source/platform/wtf/HashMap.h" #include "third_party/WebKit/Source/platform/wtf/Optional.h" #include "third_party/WebKit/Source/platform/wtf/Vector.h" @@ -39,15 +39,13 @@ } }; -namespace internal { - template <typename T> struct EqualsTraits<WTF::Vector<T>, false> { static bool Equals(const WTF::Vector<T>& a, const WTF::Vector<T>& b) { if (a.size() != b.size()) return false; for (size_t i = 0; i < a.size(); ++i) { - if (!internal::Equals(a[i], b[i])) + if (!Equals(a[i], b[i])) return false; } return true; @@ -65,14 +63,13 @@ for (auto iter = a.begin(); iter != a_end; ++iter) { auto b_iter = b.find(iter->key); - if (b_iter == b_end || !internal::Equals(iter->value, b_iter->value)) + if (b_iter == b_end || !Equals(iter->value, b_iter->value)) return false; } return true; } }; -} // namespace internal } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_
diff --git a/mojo/public/cpp/system/README.md b/mojo/public/cpp/system/README.md index f169411..3b60c39 100644 --- a/mojo/public/cpp/system/README.md +++ b/mojo/public/cpp/system/README.md
@@ -1,4 +1,4 @@ -#  Mojo C++ System API +# Mojo C++ System API This document is a subset of the [Mojo documentation](/mojo). [TOC]
diff --git a/mojo/public/java/bindings/README.md b/mojo/public/java/bindings/README.md index 2831344f..5f9b492 100644 --- a/mojo/public/java/bindings/README.md +++ b/mojo/public/java/bindings/README.md
@@ -1,4 +1,4 @@ -#  Mojo Java Bindings API +# Mojo Java Bindings API This document is a subset of the [Mojo documentation](/mojo). [TOC]
diff --git a/mojo/public/java/system/README.md b/mojo/public/java/system/README.md index c62f30b..373009c5 100644 --- a/mojo/public/java/system/README.md +++ b/mojo/public/java/system/README.md
@@ -1,4 +1,4 @@ -#  Mojo Java System API +# Mojo Java System API This document is a subset of the [Mojo documentation](/mojo). [TOC]
diff --git a/mojo/public/js/README.md b/mojo/public/js/README.md index f510b03..2193450 100644 --- a/mojo/public/js/README.md +++ b/mojo/public/js/README.md
@@ -1,4 +1,4 @@ -#  Mojo JavaScript System and Bindings APIs +# Mojo JavaScript System and Bindings APIs This document is a subset of the [Mojo documentation](/mojo). **NOTE:** The JavaScript APIs are currently in flux and will stabilize soon.
diff --git a/mojo/public/tools/bindings/README.md b/mojo/public/tools/bindings/README.md index 7a62d7e..b224991 100644 --- a/mojo/public/tools/bindings/README.md +++ b/mojo/public/tools/bindings/README.md
@@ -1,4 +1,4 @@ -#  Mojom IDL and Bindings Generator +# Mojom IDL and Bindings Generator This document is a subset of the [Mojo documentation](/mojo). [TOC] @@ -256,6 +256,29 @@ code, see [documentation for individual target languages](#Generated-Code-For-Target-Languages). +### Unions + +Mojom supports tagged unions using the **union** keyword. A union is a +collection of fields which may taken the value of any single one of those fields +at a time. Thus they provide a way to represent a variant value type while +minimizing storage requirements. + +Union fields may be of any type supported by [struct](#Structs) fields. For +example: + +```cpp +enum ExampleUnion { + string str; + StringPair pair; + int64 id; + array<uint64, 2> guid; + SampleInterface iface; +}; +``` + +For details on how unions like this translate to generated bindings code, see +[documentation for individual target languages](#Generated-Code-For-Target-Languages). + ### Enumeration Types Enumeration types may be defined using the **enum** keyword either directly
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index 9cb28d4e..19d806d2 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -46,9 +46,9 @@ #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" #include "mojo/public/cpp/bindings/associated_interface_request.h" #include "mojo/public/cpp/bindings/clone_traits.h" +#include "mojo/public/cpp/bindings/equals_traits.h" #include "mojo/public/cpp/bindings/interface_ptr.h" #include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/lib/equals_traits.h" #include "mojo/public/cpp/bindings/lib/control_message_handler.h" #include "mojo/public/cpp/bindings/lib/control_message_proxy.h" #include "mojo/public/cpp/bindings/lib/serialization.h"
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_template_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_template_definition.tmpl index feb86156..0ab7f27e 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_template_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_template_definition.tmpl
@@ -13,7 +13,7 @@ T, {{struct.name}}>::value>::type*> bool {{struct.name}}::Equals(const T& other) const { {%- for field in struct.fields %} - if (!mojo::internal::Equals(this->{{field.name}}, other.{{field.name}})) + if (!mojo::Equals(this->{{field.name}}, other.{{field.name}})) return false; {%- endfor %} return true;
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_template_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_template_definition.tmpl index 4c4851f..a29a1b7f 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_template_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_template_definition.tmpl
@@ -30,9 +30,9 @@ case Tag::{{field.name|upper}}: {%- if field.kind|is_object_kind or field.kind|is_any_handle_or_interface_kind %} - return mojo::internal::Equals(*(data_.{{field.name}}), *(other.data_.{{field.name}})); + return mojo::Equals(*(data_.{{field.name}}), *(other.data_.{{field.name}})); {%- else %} - return mojo::internal::Equals(data_.{{field.name}}, other.data_.{{field.name}}); + return mojo::Equals(data_.{{field.name}}, other.data_.{{field.name}}); {%- endif %} {%- endfor %} };
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 6bda6d0e..a060b35 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc
@@ -40,7 +40,6 @@ #include "net/log/net_log_event_type.h" #include "net/log/net_log_source.h" #include "net/log/net_log_source_type.h" -#include "net/quic/chromium/quic_http_stream.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool.h" #include "net/socket/client_socket_pool_manager.h"
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc index 691d6fa45..30a09c3 100644 --- a/net/quic/chromium/quic_stream_factory.cc +++ b/net/quic/chromium/quic_stream_factory.cc
@@ -623,7 +623,7 @@ return factory_->GetTimeDelayForWaitingJob(server_id_); } -std::unique_ptr<QuicHttpStream> QuicStreamRequest::CreateStream() { +std::unique_ptr<HttpStream> QuicStreamRequest::CreateStream() { if (!session_) return nullptr; return base::MakeUnique<QuicHttpStream>(session_, http_server_properties_);
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h index 28f66da..916c2f97 100644 --- a/net/quic/chromium/quic_stream_factory.h +++ b/net/quic/chromium/quic_stream_factory.h
@@ -130,7 +130,7 @@ // returns the amount of time waiting job should be delayed. base::TimeDelta GetTimeDelayForWaitingJob() const; - std::unique_ptr<QuicHttpStream> CreateStream(); + std::unique_ptr<HttpStream> CreateStream(); std::unique_ptr<BidirectionalStreamImpl> CreateBidirectionalStreamImpl();
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc index 7246829..8ba2ff6 100644 --- a/net/quic/chromium/quic_stream_factory_test.cc +++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -157,8 +157,8 @@ class QuicHttpStreamPeer { public: - static QuicChromiumClientSession* GetSession(QuicHttpStream* stream) { - return stream->session_.get(); + static QuicChromiumClientSession* GetSession(HttpStream* stream) { + return static_cast<QuicHttpStream*>(stream)->session_.get(); } }; @@ -289,7 +289,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); stream.reset(); @@ -437,7 +437,7 @@ // posted by QuicChromiumClientSession::MigrateToSocket(). base::RunLoop().RunUntilIdle(); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -766,7 +766,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); QuicStreamRequest request2(factory_.get(), &http_server_properties_); @@ -811,7 +811,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -837,7 +837,7 @@ /*cert_verify_flags=*/0, url_, "POST", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -860,7 +860,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); @@ -891,7 +891,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); @@ -922,7 +922,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); @@ -953,7 +953,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); @@ -979,7 +979,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); @@ -1009,7 +1009,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); @@ -1051,7 +1051,7 @@ EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); TestCompletionCallback callback; @@ -1059,7 +1059,7 @@ EXPECT_EQ(OK, request2.Request(server2, privacy_mode_, /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_EQ(GetActiveSession(host_port_pair_), GetActiveSession(server2)); @@ -1110,7 +1110,7 @@ /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback.callback())); EXPECT_EQ(OK, callback.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -1143,7 +1143,7 @@ EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); TestCompletionCallback callback; @@ -1151,7 +1151,7 @@ EXPECT_EQ(OK, request2.Request(server2, privacy_mode_, /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); factory_->OnSessionGoingAway(GetActiveSession(host_port_pair_)); @@ -1163,7 +1163,7 @@ EXPECT_EQ(OK, request3.Request(server2, privacy_mode_, /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback3.callback())); - std::unique_ptr<QuicHttpStream> stream3 = request3.CreateStream(); + std::unique_ptr<HttpStream> stream3 = request3.CreateStream(); EXPECT_TRUE(stream3.get()); EXPECT_TRUE(HasActiveSession(server2)); @@ -1196,7 +1196,7 @@ EXPECT_EQ(OK, request.Request(server1, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); TestCompletionCallback callback; @@ -1204,7 +1204,7 @@ EXPECT_EQ(OK, request2.Request(server2, privacy_mode_, /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_EQ(GetActiveSession(server1), GetActiveSession(server2)); @@ -1240,7 +1240,7 @@ EXPECT_EQ(OK, request.Request(server1, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); TestCompletionCallback callback; @@ -1248,7 +1248,7 @@ EXPECT_EQ(OK, request2.Request(server2, privacy_mode_, /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_EQ(GetActiveSession(server1), GetActiveSession(server2)); @@ -1295,7 +1295,7 @@ EXPECT_EQ(OK, request.Request(server1, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); TestCompletionCallback callback; @@ -1303,7 +1303,7 @@ EXPECT_EQ(OK, request2.Request(server2, privacy_mode_, /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_NE(GetActiveSession(server1), GetActiveSession(server2)); @@ -1336,7 +1336,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Mark the session as going away. Ensure that while it is still alive @@ -1355,7 +1355,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -1388,7 +1388,7 @@ socket_data.AddSocketDataToFactory(&socket_factory_); HttpRequestInfo request_info; - std::vector<std::unique_ptr<QuicHttpStream>> streams; + std::vector<std::unique_ptr<HttpStream>> streams; // The MockCryptoClientStream sets max_open_streams to be // kDefaultMaxStreamsPerConnection / 2. for (size_t i = 0; i < kDefaultMaxStreamsPerConnection / 2; i++) { @@ -1402,7 +1402,7 @@ } else { EXPECT_THAT(rv, IsOk()); } - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream); EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_, CompletionCallback())); @@ -1413,7 +1413,7 @@ EXPECT_EQ(OK, request.Request(host_port_pair_, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, CompletionCallback())); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream); EXPECT_EQ(ERR_IO_PENDING, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_, @@ -1494,7 +1494,7 @@ EXPECT_EQ(OK, request2.Request(host_port_pair_, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream = request2.CreateStream(); + std::unique_ptr<HttpStream> stream = request2.CreateStream(); EXPECT_TRUE(stream.get()); stream.reset(); @@ -1527,7 +1527,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); HttpRequestInfo request_info; EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_, CompletionCallback())); @@ -1611,7 +1611,7 @@ EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_)); // Create QuicHttpStream. - std::unique_ptr<QuicHttpStream> stream = request2.CreateStream(); + std::unique_ptr<HttpStream> stream = request2.CreateStream(); EXPECT_TRUE(stream.get()); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -1671,7 +1671,7 @@ EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_)); // Create QuicHttpStream. - std::unique_ptr<QuicHttpStream> stream = request2.CreateStream(); + std::unique_ptr<HttpStream> stream = request2.CreateStream(); EXPECT_TRUE(stream.get()); stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); @@ -1705,7 +1705,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); HttpRequestInfo request_info; EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_, CompletionCallback())); @@ -1772,7 +1772,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -1839,7 +1839,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -1902,7 +1902,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -1964,7 +1964,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -2012,7 +2012,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2070,7 +2070,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -2119,7 +2119,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2171,7 +2171,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -2219,7 +2219,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2267,7 +2267,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Ensure that session is alive and active. @@ -2305,7 +2305,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Ensure that session is alive and active. @@ -2347,7 +2347,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2422,7 +2422,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -2469,7 +2469,7 @@ EXPECT_EQ(OK, request1.Request(server1, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream1 = request1.CreateStream(); + std::unique_ptr<HttpStream> stream1 = request1.CreateStream(); EXPECT_TRUE(stream1.get()); // Create request and QuicHttpStream to create session2. @@ -2477,7 +2477,7 @@ EXPECT_EQ(OK, request2.Request(server2, privacy_mode_, /*cert_verify_flags=*/0, url2_, "GET", net_log_, callback_.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); QuicChromiumClientSession* session1 = GetActiveSession(server1); @@ -2563,7 +2563,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2626,7 +2626,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -2687,7 +2687,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2752,7 +2752,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -2805,7 +2805,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2857,7 +2857,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -2909,7 +2909,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -2967,7 +2967,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3055,7 +3055,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3144,7 +3144,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created, but marked as non-migratable. @@ -3208,7 +3208,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3287,7 +3287,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3367,7 +3367,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3464,7 +3464,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3562,7 +3562,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3642,7 +3642,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -3694,7 +3694,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3782,7 +3782,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -3847,7 +3847,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -3910,7 +3910,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -4051,7 +4051,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Cause QUIC stream to be created. @@ -4106,7 +4106,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); HttpRequestInfo request_info; EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_, CompletionCallback())); @@ -4159,7 +4159,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); HttpRequestInfo request_info; EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_, CompletionCallback())); @@ -4287,7 +4287,7 @@ // the CancelWaitForDataReady task hasn't been posted. ASSERT_EQ(0u, runner_->GetPostedTasks().size()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -4334,7 +4334,7 @@ EXPECT_EQ(QuicTime::Delta::FromSeconds(kPingTimeoutSecs), session->connection()->ping_timeout()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); HttpRequestInfo request_info; EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, @@ -4365,7 +4365,7 @@ EXPECT_EQ(QuicTime::Delta::FromSeconds(10), session2->connection()->ping_timeout()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_EQ(OK, stream2->InitializeStream(&request_info, DEFAULT_PRIORITY, net_log_, CompletionCallback())); @@ -4437,7 +4437,7 @@ EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); // Restore |race_cert_verification|. @@ -4490,7 +4490,7 @@ // yielded the read. EXPECT_EQ(1u, observer.executed_count()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_FALSE(stream.get()); // Session is already closed. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -4535,7 +4535,7 @@ // yielded the read. EXPECT_EQ(1u, observer.executed_count()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_FALSE(stream.get()); // Session is already closed. EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); @@ -4558,7 +4558,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get())); @@ -4604,7 +4604,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + std::unique_ptr<HttpStream> stream = request.CreateStream(); EXPECT_TRUE(stream.get()); EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get())); @@ -4632,7 +4632,7 @@ EXPECT_EQ(index->GetPromised(kDefaultUrl), nullptr); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); EXPECT_TRUE(socket_data1.AllReadDataConsumed()); @@ -4663,7 +4663,7 @@ /*cert_verify_flags=*/0, url_, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream1 = request1.CreateStream(); + std::unique_ptr<HttpStream> stream1 = request1.CreateStream(); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(host_port_pair_)); @@ -4673,7 +4673,7 @@ EXPECT_EQ(OK, request2.Request(destination2, privacy_mode_, /*cert_verify_flags=*/0, url_, "GET", net_log_, callback2.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); QuicChromiumClientSession* session1 = @@ -4846,7 +4846,7 @@ callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream1 = request1.CreateStream(); + std::unique_ptr<HttpStream> stream1 = request1.CreateStream(); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); @@ -4856,7 +4856,7 @@ EXPECT_EQ(OK, request2.Request(destination, privacy_mode_, /*cert_verify_flags=*/0, url2, "GET", net_log_, callback2.callback())); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); QuicChromiumClientSession* session1 = @@ -4917,7 +4917,7 @@ /*cert_verify_flags=*/0, url1, "GET", net_log_, callback_.callback())); EXPECT_EQ(OK, callback_.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream1 = request1.CreateStream(); + std::unique_ptr<HttpStream> stream1 = request1.CreateStream(); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); @@ -4928,7 +4928,7 @@ /*cert_verify_flags=*/0, url2, "GET", net_log_, callback2.callback())); EXPECT_EQ(OK, callback2.WaitForResult()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); // |request2| does not pool to the first session, because PrivacyMode does not @@ -5000,7 +5000,7 @@ /*cert_verify_flags=*/0, url1, "GET", net_log_, callback_.callback())); EXPECT_THAT(callback_.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream1 = request1.CreateStream(); + std::unique_ptr<HttpStream> stream1 = request1.CreateStream(); EXPECT_TRUE(stream1.get()); EXPECT_TRUE(HasActiveSession(origin1_)); @@ -5011,7 +5011,7 @@ /*cert_verify_flags=*/0, url2, "GET", net_log_, callback2.callback())); EXPECT_THAT(callback2.WaitForResult(), IsOk()); - std::unique_ptr<QuicHttpStream> stream2 = request2.CreateStream(); + std::unique_ptr<HttpStream> stream2 = request2.CreateStream(); EXPECT_TRUE(stream2.get()); // |request2| does not pool to the first session, because the certificate does
diff --git a/ppapi/proxy/tcp_socket_resource.h b/ppapi/proxy/tcp_socket_resource.h index 57da040..3266805d 100644 --- a/ppapi/proxy/tcp_socket_resource.h +++ b/ppapi/proxy/tcp_socket_resource.h
@@ -14,8 +14,6 @@ namespace ppapi { -enum TCPSocketVersion; - namespace proxy { class PPAPI_PROXY_EXPORT TCPSocketResource : public thunk::PPB_TCPSocket_API,
diff --git a/services/service_manager/public/cpp/standalone_service/mach_broker.cc b/services/service_manager/public/cpp/standalone_service/mach_broker.cc index 8f8c670..a9cc00f 100644 --- a/services/service_manager/public/cpp/standalone_service/mach_broker.cc +++ b/services/service_manager/public/cpp/standalone_service/mach_broker.cc
@@ -5,7 +5,6 @@ #include "services/service_manager/public/cpp/standalone_service/mach_broker.h" #include "base/logging.h" -#include "base/memory/singleton.h" namespace service_manager { @@ -22,7 +21,8 @@ // static MachBroker* MachBroker::GetInstance() { - return base::Singleton<MachBroker>::get(); + static MachBroker* broker = new MachBroker; + return broker; } MachBroker::MachBroker() : broker_(kBootstrapPortName) {
diff --git a/services/service_manager/public/cpp/standalone_service/mach_broker.h b/services/service_manager/public/cpp/standalone_service/mach_broker.h index bb96e9f..a85b0fc 100644 --- a/services/service_manager/public/cpp/standalone_service/mach_broker.h +++ b/services/service_manager/public/cpp/standalone_service/mach_broker.h
@@ -7,10 +7,6 @@ #include "base/mac/mach_port_broker.h" -namespace base { -template <typename T> struct DefaultSingletonTraits; -} - namespace service_manager { // A global singleton |MachBroker| is used by the service manager to provide @@ -43,7 +39,6 @@ private: MachBroker(); ~MachBroker(); - friend struct base::DefaultSingletonTraits<MachBroker>; base::MachPortBroker broker_; };
diff --git a/services/service_manager/public/cpp/test/BUILD.gn b/services/service_manager/public/cpp/test/BUILD.gn index c1697a3..90f3aea 100644 --- a/services/service_manager/public/cpp/test/BUILD.gn +++ b/services/service_manager/public/cpp/test/BUILD.gn
@@ -20,6 +20,7 @@ "//mojo/edk/system", "//services/catalog:lib", "//services/service_manager/background:lib", + "//services/service_manager/public/cpp/standalone_service", ] if (is_android) {
diff --git a/services/service_manager/public/cpp/test/run_all_service_tests.cc b/services/service_manager/public/cpp/test/run_all_service_tests.cc index 7b13364..41e53eb 100644 --- a/services/service_manager/public/cpp/test/run_all_service_tests.cc +++ b/services/service_manager/public/cpp/test/run_all_service_tests.cc
@@ -18,13 +18,7 @@ #endif #if defined(OS_MACOSX) && !defined(OS_IOS) -#include "base/mac/mach_port_broker.h" -#endif - -#if defined(OS_MACOSX) && !defined(OS_IOS) -namespace { -base::MachPortBroker* g_mach_broker = nullptr; -} +#include "services/service_manager/public/cpp/standalone_service/mach_broker.h" #endif int main(int argc, char** argv) { @@ -36,11 +30,8 @@ mojo::edk::Init(); #if defined(OS_MACOSX) && !defined(OS_IOS) - if (!g_mach_broker) { - g_mach_broker = new base::MachPortBroker("Service Tests"); - CHECK(g_mach_broker->Init()); - mojo::edk::SetMachPortProvider(g_mach_broker); - } + mojo::edk::SetMachPortProvider( + service_manager::MachBroker::GetInstance()->port_provider()); #endif #if defined(OS_ANDROID)
diff --git a/services/ui/gpu/gpu_main.cc b/services/ui/gpu/gpu_main.cc index 580e5b4fc..fed0107d 100644 --- a/services/ui/gpu/gpu_main.cc +++ b/services/ui/gpu/gpu_main.cc
@@ -213,7 +213,8 @@ image_factory); frame_sink_manager_ = base::MakeUnique<viz::MojoFrameSinkManager>( - true, display_provider_.get(), std::move(request), std::move(client)); + true, display_provider_.get()); + frame_sink_manager_->Connect(std::move(request), std::move(client)); } void GpuMain::TearDownOnCompositorThread() {
diff --git a/testing/buildbot/filters/ash_mus_unittests.filter b/testing/buildbot/filters/ash_mus_unittests.filter index 02224f2..ed9440f4c 100644 --- a/testing/buildbot/filters/ash_mus_unittests.filter +++ b/testing/buildbot/filters/ash_mus_unittests.filter
@@ -1,17 +1,6 @@ -AcceleratorControllerTest.DisallowedAtModalWindow -AcceleratorControllerTest.GlobalAccelerators -AcceleratorControllerTest.RotateScreen --AppListPresenterDelegateTest.TinyDisplay --AppListPresenterDelegateTest.HideOnFocusOut/0 --AppListPresenterDelegateTest.HideOnFocusOut/1 --AppListPresenterDelegateTest.RemainVisibleWhenFocusingToApplistContainer/0 --AppListPresenterDelegateTest.RemainVisibleWhenFocusingToApplistContainer/1 --AppListPresenterDelegateTest.ClickOutsideBubbleClosesBubble/0 --AppListPresenterDelegateTest.ClickOutsideBubbleClosesBubble/1 --AppListPresenterDelegateTest.TapOutsideBubbleClosesBubble/0 --AppListPresenterDelegateTest.TapOutsideBubbleClosesBubble/1 --AppListPresenterDelegateTest.NonPrimaryDisplay/0 --AppListPresenterDelegateTest.NonPrimaryDisplay/1 -AshNativeCursorManagerTest.FractionalScale -AshNativeCursorManagerTest.LockCursor -AshNativeCursorManagerTest.SetCursor
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index a156f5ca..5527629 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1451,14 +1451,13 @@ ], "experiments": [ { - "name": "EnabledSoftFetches", + "name": "EnabledSoftFetchesChromeReader_Rest", "params": { - "fetching_interval_hours-wifi-active_ntp_user": "8", - "scheduler_trigger_types": "persistent_scheduler_wake_up,ntp_opened", - "send_top_languages": "true", - "soft_fetching_interval_hours-active-active_ntp_user": "2", - "soft_fetching_interval_hours-active-active_suggestions_consumer": "1", - "soft_fetching_interval_hours-active-rare_ntp_user": "4" + "soft_fetching_interval_hours-fallback-active_ntp_user": "10", + "soft_fetching_interval_hours-fallback-active_suggestions_consumer": "1", + "soft_fetching_interval_hours-fallback-rare_ntp_user": "4", + "user_classifier_active_consumer_clicks_at_least_once_per_hours": "96", + "user_classifier_rare_user_opens_ntp_at_most_once_per_hours": "66" }, "enable_features": [ "NTPArticleSuggestions"
diff --git a/third_party/WebKit/LayoutTests/transforms/perspective-fixed-pos-descendant-expected.html b/third_party/WebKit/LayoutTests/transforms/perspective-fixed-pos-descendant-expected.html new file mode 100644 index 0000000..9417b44 --- /dev/null +++ b/third_party/WebKit/LayoutTests/transforms/perspective-fixed-pos-descendant-expected.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<div style="width:100px; height:100px; perspective:100px; background:green;"></div> +This test verifies CSS perspective correctly applies to fixed-position descendants. The test passes if a 100x100 green box completely occludes the red box behind. \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/transforms/perspective-fixed-pos-descendant.html b/third_party/WebKit/LayoutTests/transforms/perspective-fixed-pos-descendant.html new file mode 100644 index 0000000..3a087c0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/transforms/perspective-fixed-pos-descendant.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<div style="width:100px; height:100px; perspective:100px; background:red;"> + <div style="position:fixed; left:25px; top:25px; width:50px; height:50px; transform:translateZ(50px); background:green;"></div> +</div> +This test verifies CSS perspective correctly applies to fixed-position descendants. The test passes if a 100x100 green box completely occludes the red box behind. \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/webaudio/constructor/convolver.html b/third_party/WebKit/LayoutTests/webaudio/constructor/convolver.html index 410869d2a..d4c7377 100644 --- a/third_party/WebKit/LayoutTests/webaudio/constructor/convolver.html +++ b/third_party/WebKit/LayoutTests/webaudio/constructor/convolver.html
@@ -5,8 +5,8 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../resources/audit-util.js"></script> - <script src="../resources/audio-testing.js"></script> - <script src="audionodeoptions.js"></script> + <script src="../resources/audit.js"></script> + <script src="new-audionodeoptions.js"></script> </head> <body> @@ -15,151 +15,110 @@ var audit = Audit.createTaskRunner(); - audit.defineTask("initialize", function (taskDone) { - Should("context = new OfflineAudioContext(...)", function () { - context = new OfflineAudioContext(1, 1, 48000); - }).notThrow(); - taskDone(); + audit.define('initialize', (task, should) => { + context = initializeContext(should); + task.done(); }); - audit.defineTask("invalid constructor", function (taskDone) { - var node; - var success = true; - - succes = Should("new ConvolverNode()", function () { - node = new ConvolverNode(); - }).throw("TypeError"); - success = Should("new ConvolverNode(1)", function () { - node = new ConvolverNode(1); - }).throw("TypeError") && success; - success = Should("new ConvolverNode(context, 42)", function () { - node = new ConvolverNode(context, 42); - }).throw("TypeError") && success; - - Should("Invalid constructors", success) - .summarize( - "correctly threw errors", - "did not throw errors in all cases"); - taskDone(); + audit.define('invalid constructor', (task, should) => { + testInvalidConstructor(should, 'ConvolverNode', context); + task.done(); }); - audit.defineTask("default constructor", function (taskDone) { - var node; - var success = true; + audit.define('default constructor', (task, should) => { + let prefix = 'node0'; + let node = testDefaultConstructor(should, 'ConvolverNode', context, { + prefix: prefix, + numberOfInputs: 1, + numberOfOutputs: 1, + channelCount: 2, + channelCountMode: 'clamped-max', + channelInterpretation: 'speakers' + }); - success = Should("node0 = new ConvolverNode(context)", function () { - node = new ConvolverNode(context); - }).notThrow(); - success = Should("node0 instanceOf ConvolverNode", node instanceof ConvolverNode) - .beEqualTo(true) && success; - success = Should("node0.normalize", node.normalize) - .beEqualTo(true) && success; + testDefaultAttributes( + should, node, prefix, + [{name: 'normalize', value: true}, {name: 'buffer', value: null}]); - success = Should("node0.channelCount", node.channelCount) - .beEqualTo(2) && success; - success = Should("node0.channelCountMode", node.channelCountMode) - .beEqualTo("clamped-max") && success; - success = Should("node0.channelInterpretation", node.channelInterpretation) - .beEqualTo("speakers") && success; - - success = Should("new ConvolverNode(context)", success) - .summarize( - "constructed node with correct attributes", - "did not construct correct node correctly") - - taskDone(); + task.done(); }); - audit.defineTask("test AudioNodeOptions", function (taskDone) { - testAudioNodeOptions(context, "ConvolverNode", { - expectedChannelCount: { - value: 2, + audit.define('test AudioNodeOptions', (task, should) => { + testAudioNodeOptions(should, context, 'ConvolverNode', { + channelCount: + {value: 2, isFixed: true, errorType: 'NotSupportedError'}, + channelCountMode: { + value: 'clamped-max', isFixed: true, - errorType: "NotSupportedError" - }, - expectedChannelCountMode: { - value: "clamped-max", - isFixed: true, - errorType: "NotSupportedError" + errorType: 'NotSupportedError' }, }); - taskDone(); + task.done(); }); - audit.defineTask("nullable buffer", function (taskDone) { + audit.define('nullable buffer', (task, should) => { var node; - var success = true; + var options = {buffer: null}; - var options = { buffer: null }; - - success = Should("node1 = new ConvolverNode(c, " + JSON.stringify(options), function () { - node = new ConvolverNode(context, options); - }).notThrow(); + should( + () => { + node = new ConvolverNode(context, options); + }, + 'node1 = new ConvolverNode(c, ' + JSON.stringify(options)) + .notThrow(); - success = Should("node1.buffer", node.buffer) - .beEqualTo(null); + should(node.buffer, 'node1.buffer').beEqualTo(null); - Should("Null buffer in constructor handled", success) - .summarize( - "correctly", - "incorrectly"); - - taskDone(); + task.done(); }); - audit.defineTask("construct with options", function (taskDone) { + audit.define('construct with options', (task, should) => { var buf = context.createBuffer(1, 1, context.sampleRate); - var options = { - buffer: buf, - disableNormalization: false - }; + var options = {buffer: buf, disableNormalization: false}; - var message = "node = new ConvolverNode(c, " + JSON.stringify(options) + ")"; + var message = + 'node = new ConvolverNode(c, ' + JSON.stringify(options) + ')'; var node; - success = Should(message, function () { + should(() => { node = new ConvolverNode(context, options); - }).notThrow(); + }, message).notThrow(); - success = Should("node1 instanceOf ConvolverNode", node instanceof ConvolverNode) - .beEqualTo(true) && success; - success = Should("node1.buffer === <buf>", node.buffer === - options.buffer) - .beEqualTo(true) && success; - success = Should("node1.normalize", node.normalize) - .beEqualTo(!options.disableNormalization) && success; + should(node instanceof ConvolverNode, 'node1 instanceOf ConvolverNode') + .beEqualTo(true); + should(node.buffer === options.buffer, 'node1.buffer === <buf>') + .beEqualTo(true); + should(node.normalize, 'node1.normalize') + .beEqualTo(!options.disableNormalization); options.buffer = null; options.disableNormalization = true; - message = "node2 = new ConvolverNode(, " + JSON.stringify(options) + ")"; + message = + 'node2 = new ConvolverNode(, ' + JSON.stringify(options) + ')'; - success = Should(message, function () { + should(() => { node = new ConvolverNode(context, options); - }).notThrow() && success; - success = Should("node2.buffer", node.buffer).beEqualTo(null) && success; - success = Should("node2.normalize", node.normalize) - .beEqualTo(!options.disableNormalization) && success; + }, message).notThrow(); + should(node.buffer, 'node2.buffer').beEqualTo(null); + should(node.normalize, 'node2.normalize') + .beEqualTo(!options.disableNormalization); options.disableNormalization = false; - message = "node3 = new ConvolverNode(context, " + JSON.stringify(options) + ")"; + message = 'node3 = new ConvolverNode(context, ' + + JSON.stringify(options) + ')'; - success = Should(message, function () { + should(() => { node = new ConvolverNode(context, options); - }).notThrow() && success; - success = Should("node3.buffer", node.buffer).beEqualTo(null) && success; - success = Should("node3.normalize", node.normalize) - .beEqualTo(!options.disableNormalization) && success; + }, message).notThrow(); + should(node.buffer, 'node3.buffer').beEqualTo(null); + should(node.normalize, 'node3.normalize') + .beEqualTo(!options.disableNormalization); - Should("new ConvolverNode() with options", success) - .summarize( - "constructed with correct attributes", - "was not constructed correctly"); - - taskDone(); + task.done(); }); - audit.runTasks(); + audit.run(); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/constructor/gain.html b/third_party/WebKit/LayoutTests/webaudio/constructor/gain.html index 022476c..3be0bc78 100644 --- a/third_party/WebKit/LayoutTests/webaudio/constructor/gain.html +++ b/third_party/WebKit/LayoutTests/webaudio/constructor/gain.html
@@ -5,8 +5,8 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../resources/audit-util.js"></script> - <script src="../resources/audio-testing.js"></script> - <script src="audionodeoptions.js"></script> + <script src="../resources/audit.js"></script> + <script src="new-audionodeoptions.js"></script> </head> <body> @@ -15,102 +15,64 @@ var audit = Audit.createTaskRunner(); - audit.defineTask("initialize", function (taskDone) { - Should("context = new OfflineAudioContext(...)", function () { - context = new OfflineAudioContext(1, 1, 48000); - }).notThrow(); - taskDone(); + audit.define('initialize', (task, should) => { + context = initializeContext(should); + task.done(); }); - audit.defineTask("invalid constructor", function (taskDone) { + audit.define('invalid constructor', (task, should) => { + testInvalidConstructor(should, 'GainNode', context); + task.done(); + }); + + audit.define('default constructor', (task, should) => { + let prefix = 'node0'; + let node = testDefaultConstructor(should, 'GainNode', context, { + prefix: prefix, + numberOfInputs: 1, + numberOfOutputs: 1, + channelCount: 2, + channelCountMode: 'max', + channelInterpretation: 'speakers' + }); + + testDefaultAttributes(should, node, prefix, [{name: 'gain', value: 1}]); + + task.done(); + }); + + audit.define('test AudioNodeOptions', (task, should) => { + testAudioNodeOptions(should, context, 'GainNode'); + task.done(); + }); + + audit.define('constructor with options', (task, should) => { var node; - var success = true; - - success = Should("new GainNode()", function () { - node = new GainNode(); - }).throw("TypeError"); - success = Should("new GainNode(1)", function () { - node = new GainNode(1); - }).throw("TypeError") && success; - success = Should("new GainNode(context, 42)", function () { - node = new GainNode(context, 42); - }).throw("TypeError") && success; - - Should("Invalid constructors", success) - .summarize( - "correctly threw errors", - "did not throw errors in all cases"); - - taskDone(); - }); - - audit.defineTask("default constructor", function (taskDone) { - var node; - var success = true; - - success = Should("node0 = new GainNode(context)", function () { - node = new GainNode(context); - }).notThrow(); - success = Should("node0 instanceof GainNode", - node instanceof GainNode) - .beEqualTo(true) && success; - - success = Should("node0.gain.value", node.gain.value) - .beEqualTo(1) && success; - - success = Should("node0.channelCount", node.channelCount) - .beEqualTo(2) && success; - success = Should("node0.channelCountMode", node.channelCountMode) - .beEqualTo("max") && success; - success = Should("node0.channelInterpretation", node.channelInterpretation) - .beEqualTo("speakers") && success; - - Should("new GainNode(context)", success) - .summarize( - "constructed node with correct attributes", - "did not construct correct node correctly") - - taskDone(); - }); - - audit.defineTask("test AudioNodeOptions", function (taskDone) { - testAudioNodeOptions(context, "GainNode"); - taskDone(); - }); - - audit.defineTask("constructor with options", function (taskDone) { - var node; - var success = true; var options = { gain: -2, }; - success = Should("node1 = new GainNode(c, " + JSON.stringify(options) + ")", function () { - node = new GainNode(context, options); - }).notThrow(); - success = Should("node1 instanceof GainNode", - node instanceof GainNode) - .beEqualTo(true) && success; + should( + () => { + node = new GainNode(context, options); + }, + 'node1 = new GainNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node instanceof GainNode, 'node1 instanceof GainNode') + .beEqualTo(true); - success = Should("node1.gain.value", node.gain.value) - .beEqualTo(options.gain) && success; + should(node.gain.value, 'node1.gain.value').beEqualTo(options.gain); - success = Should("node1.channelCount", node.channelCount) - .beEqualTo(2) && success; - success = Should("node1.channelCountMode", node.channelCountMode) - .beEqualTo("max") && success; - success = Should("node1.channelInterpretation", node.channelInterpretation) - .beEqualTo("speakers") && success; + should(node.channelCount, 'node1.channelCount').beEqualTo(2); + should(node.channelCountMode, 'node1.channelCountMode') + .beEqualTo('max'); + should(node.channelInterpretation, 'node1.channelInterpretation') + .beEqualTo('speakers'); - Should("new GainNode() with options", success) - .summarize( - "constructed with correct attributes", - "was not constructed correctly"); - - taskDone(); + task.done(); }); - audit.runTasks(); + audit.run(); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/constructor/panner.html b/third_party/WebKit/LayoutTests/webaudio/constructor/panner.html index ec9cee33..3b082a7 100644 --- a/third_party/WebKit/LayoutTests/webaudio/constructor/panner.html +++ b/third_party/WebKit/LayoutTests/webaudio/constructor/panner.html
@@ -5,7 +5,8 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../resources/audit-util.js"></script> - <script src="../resources/audio-testing.js"></script> + <script src="../resources/audit.js"></script> + <script src="new-audionodeoptions.js"></script> </head> <body> @@ -14,242 +15,190 @@ var audit = Audit.createTaskRunner(); - audit.defineTask("initialize", function (taskDone) { - Should("context = new OfflineAudioContext(...)", function () { - context = new OfflineAudioContext(1, 1, 48000); - }).notThrow(); - - taskDone(); + audit.define('initialize', (task, should) => { + context = initializeContext(should); + task.done(); }); - audit.defineTask("invalid constructor", function (taskDone) { - var node; - var success = true; - - success = Should("new PannerNode()", function () { - node = new PannerNode(); - }).throw("TypeError"); - success = Should("new PannerNode(1)", function () { - node = new PannerNode(1) && success; - }).throw("TypeError"); - success = Should("new PannerNode(context, 42)", function () { - node = new PannerNode(context, 42) && success; - }).throw("TypeError"); - - Should("Invalid constructors", success) - .summarize( - "correctly threw errors", - "did not throw errors in all cases"); - - taskDone(); + audit.define('invalid constructor', (task, should) => { + testInvalidConstructor(should, 'PannerNode', context); + task.done(); }); - audit.defineTask("default constructor", function (taskDone) { - var node; - var success = true; + audit.define('default constructor', (task, should) => { + let prefix = 'node0'; + let node = testDefaultConstructor(should, 'PannerNode', context, { + prefix: prefix, + numberOfInputs: 1, + numberOfOutputs: 1, + channelCount: 2, + channelCountMode: 'clamped-max', + channelInterpretation: 'speakers' + }); - success = Should("node0 = new PannerNode(context)", function () { - node = new PannerNode(context); - }).notThrow(); - success = Should("node0 instanceof PannerNode", node instanceof PannerNode) - .beEqualTo(true) && success; - - success = Should("node0.panningModel", node.panningModel) - .beEqualTo("equalpower") && success; - success = Should("node0.positionX.value", node.positionX.value) - .beEqualTo(0) && success; - success = Should("node0.positionY.value", node.positionY.value) - .beEqualTo(0) && success; - success = Should("node0.positionZ.value", node.positionZ.value) - .beEqualTo(0) && success; - success = Should("node0.orientationX.value", node.orientationX.value) - .beEqualTo(1) && success; - success = Should("node0.orientationY.value", node.orientationY.value) - .beEqualTo(0) && success; - success = Should("node0.orientationZ.value", node.orientationZ.value) - .beEqualTo(0) && success; - success = Should("node0.distanceModel", node.distanceModel) - .beEqualTo("inverse") && success; - success = Should("node0.refDistance", node.refDistance) - .beEqualTo(1) && success; - success = Should("node0.maxDistance", node.maxDistance) - .beEqualTo(10000) && success; - success = Should("node0.rolloffFactor", node.rolloffFactor) - .beEqualTo(1) && success; - success = Should("node0.coneInnerAngle", node.coneInnerAngle) - .beEqualTo(360) && success; - success = Should("node0.coneOuterAngle", node.coneOuterAngle) - .beEqualTo(360) && success; - success = Should("node0.coneOuterGain", node.coneOuterGain) - .beEqualTo(0) && success; + testDefaultAttributes(should, node, prefix, [ + {name: 'panningModel', value: 'equalpower'}, + {name: 'positionX', value: 0}, {name: 'positionY', value: 0}, + {name: 'positionZ', value: 0}, {name: 'orientationX', value: 1}, + {name: 'orientationY', value: 0}, {name: 'orientationZ', value: 0}, + {name: 'distanceModel', value: 'inverse'}, + {name: 'refDistance', value: 1}, {name: 'maxDistance', value: 10000}, + {name: 'rolloffFactor', value: 1}, + {name: 'coneInnerAngle', value: 360}, + {name: 'coneOuterAngle', value: 360}, + {name: 'coneOuterGain', value: 0} + ]); // Test the listener too, while we're at it. - success = Should("context.listener.positionX.value", context.listener.positionX.value) - .beEqualTo(0) && success; - success = Should("context.listener.positionY.value", context.listener.positionY.value) - .beEqualTo(0) && success; - success = Should("context.listener.positionZ.value", context.listener.positionZ.value) - .beEqualTo(0) && success; - success = Should("context.listener.forwardX.value", context.listener.forwardX.value) - .beEqualTo(0) && success; - success = Should("context.listener.forwardY.value", context.listener.forwardY.value) - .beEqualTo(0) && success; - success = Should("context.listener.forwardZ.value", context.listener.forwardZ.value) - .beEqualTo(-1) && success; - success = Should("context.listener.upX.value", context.listener.upX.value) - .beEqualTo(0) && success; - success = Should("context.listener.upY.value", context.listener.upY.value) - .beEqualTo(1) && success; - success = Should("context.listener.upZ.value", context.listener.upZ.value) - .beEqualTo(0) && success; + let listenerAttributes = [ + {name: 'positionX', value: 0}, + {name: 'positionY', value: 0}, + {name: 'positionZ', value: 0}, + {name: 'forwardX', value: 0}, + {name: 'forwardY', value: 0}, + {name: 'forwardZ', value: -1}, + {name: 'upX', value: 0}, + {name: 'upY', value: 1}, + {name: 'upZ', value: 0}, + ]; - success = Should("node0.channelCount", node.channelCount) - .beEqualTo(2) && success; - success = Should("node0.channelCountMode", node.channelCountMode) - .beEqualTo("clamped-max") && success; - success = Should("node0.channelInterpretation", node.channelInterpretation) - .beEqualTo("speakers") && success; + listenerAttributes.forEach((item) => { + should( + context.listener[item.name].value, + 'context.listener.' + item.name + '.value') + .beEqualTo(item.value); + }); - Should("new PannerNode(context)", success) - .summarize( - "constructed node with correct attributes", - "did not construct correct node correctly") - - taskDone(); + task.done(); }); - audit.defineTask("test AudioNodeOptions", function (taskDone) { + audit.define('test AudioNodeOptions', (task, should) => { // Can't use testAudioNodeOptions because the constraints for this node // are not supported there. var node; var success = true; // Test that we can set the channel count to 1 or 2. - var options = { - channelCount: 1 - }; - success = Should("node1 = new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).notThrow() && success; - success = Should("node1.channelCount", node.channelCount) - .beEqualTo(options.channelCount) && success; + var options = {channelCount: 1}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node1 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.channelCount, 'node1.channelCount') + .beEqualTo(options.channelCount); - options = { - channelCount: 2 - }; - success = Should("node2 = new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).notThrow() && success; - success = Should("node2.channelCount", node.channelCount) - .beEqualTo(options.channelCount) && success; + options = {channelCount: 2}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node2 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.channelCount, 'node2.channelCount') + .beEqualTo(options.channelCount); // Test that other channel counts throw an error - options = { - channelCount: 0 - }; - success = Should("new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).throw("NotSupportedError") && success; + options = {channelCount: 0}; + should( + () => { + node = new PannerNode(context, options); + }, + 'new PannerNode(c, ' + JSON.stringify(options) + ')') + .throw('NotSupportedError'); - options = { - channelCount: 3 - }; - success = Should("new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).throw("NotSupportedError") && success; + options = {channelCount: 3}; + should( + () => { + node = new PannerNode(context, options); + }, + 'new PannerNode(c, ' + JSON.stringify(options) + ')') + .throw('NotSupportedError'); - options = { - channelCount: 99 - }; - success = Should("new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).throw("NotSupportedError") && success; + options = {channelCount: 99}; + should( + () => { + node = new PannerNode(context, options); + }, + 'new PannerNode(c, ' + JSON.stringify(options) + ')') + .throw('NotSupportedError'); // Test channelCountMode. A mode of "max" is illegal, but others are // ok. - options = { - channelCountMode: "clamped-max" - }; - success = Should("node3 = new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).notThrow() && success; - success = Should("node3.channelCountMode", node.channelCountMode) - .beEqualTo(options.channelCountMode) && success; + options = {channelCountMode: 'clamped-max'}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node3 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.channelCountMode, 'node3.channelCountMode') + .beEqualTo(options.channelCountMode); - options = { - channelCountMode: "explicit" - }; - success = Should("node4 = new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).notThrow() && success; - success = Should("node4.channelCountMode", node.channelCountMode) - .beEqualTo(options.channelCountMode); + options = {channelCountMode: 'explicit'}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node4 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.channelCountMode, 'node4.channelCountMode') + .beEqualTo(options.channelCountMode); - options = { - channelCountMode: "max" - }; - success = Should("new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).throw("NotSupportedError") && success; + options = {channelCountMode: 'max'}; + should( + () => { + node = new PannerNode(context, options); + }, + 'new PannerNode(c, ' + JSON.stringify(options) + ')') + .throw('NotSupportedError'); - options = { - channelCountMode: "foobar" - }; - success = Should('new PannerNode(c, " + JSON.stringify(options) + ")', - function () { - node = new PannerNode(context, options); - }).throw("TypeError") && success; + options = {channelCountMode: 'foobar'}; + should( + () => { + node = new PannerNode(context, options); + }, + 'new PannerNode(c, " + JSON.stringify(options) + ")') + .throw('TypeError'); // Test channelInterpretation. - options = { - channelInterpretation: "speakers" - }; - success = Should("node5 = new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).notThrow() && success; - success = Should("node5.channelInterpretation", node.channelInterpretation) - .beEqualTo(options.channelInterpretation) && success; + options = {channelInterpretation: 'speakers'}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node5 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.channelInterpretation, 'node5.channelInterpretation') + .beEqualTo(options.channelInterpretation); - options = { - channelInterpretation: "discrete" - }; - success = Should("node6 = new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).notThrow() && success; - success = Should("node6.channelInterpretation", node.channelInterpretation) - .beEqualTo(options.channelInterpretation) && success; + options = {channelInterpretation: 'discrete'}; + should( + () => { + node = new PannerNode(context, options); + }, + 'node6 = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node.channelInterpretation, 'node6.channelInterpretation') + .beEqualTo(options.channelInterpretation); - options = { - channelInterpretation: "foobar" - }; - success = Should("new PannerNode(c, " + JSON.stringify(options) + ")", - function () { - node = new PannerNode(context, options); - }).throw("TypeError") && success; + options = {channelInterpretation: 'foobar'}; + should( + () => { + node = new PannerNode(context, options); + }, + 'new PannerNode(c, ' + JSON.stringify(options) + ')') + .throw('TypeError'); - Should("AudioNodeOptions for PannerNode", success) - .summarize( - "were correctly handled", - "were not correctly handled"); - - taskDone(); + task.done(); }); - audit.defineTask("constructor with options", function (taskDone) { + audit.define('constructor with options', (task, should) => { var node; var success = true; var options = { - panningModel: "HRTF", + panningModel: 'HRTF', // We use full double float values here to verify also that the actual // AudioParam value is properly rounded to a float. The actual value // is immaterial as long as x != Math.fround(x). @@ -259,7 +208,7 @@ orientationX: -Math.SQRT2, orientationY: -2 * Math.SQRT2, orientationZ: -3 * Math.SQRT2, - distanceModel: "linear", + distanceModel: 'linear', // We use full double float values here to verify also that the actual // attribute is a double float. The actual value is immaterial as // long as x != Math.fround(x). @@ -271,57 +220,54 @@ coneOuterGain: 6 * Math.PI }; - success = Should("node = new PannerNode(c, " + JSON.stringify(options) + ")", function () { - node = new PannerNode(context, options); - }).notThrow(); - success = Should("node instanceof PannerNode", node instanceof PannerNode) - .beEqualTo(true) && success; + should( + () => { + node = new PannerNode(context, options); + }, + 'node = new PannerNode(c, ' + JSON.stringify(options) + ')') + .notThrow(); + should(node instanceof PannerNode, 'node instanceof PannerNode') + .beEqualTo(true); - success = Should("node.panningModel", node.panningModel) - .beEqualTo(options.panningModel) && success; - success = Should("node.positionX.value", node.positionX.value) - .beEqualTo(Math.fround(options.positionX)) && success; - success = Should("node.positionY.value", node.positionY.value) - .beEqualTo(Math.fround(options.positionY)) && success; - success = Should("node.positionZ.value", node.positionZ.value) - .beEqualTo(Math.fround(options.positionZ)) && success; - success = Should("node.orientationX.value", node.orientationX.value) - .beEqualTo(Math.fround(options.orientationX)) && success; - success = Should("node.orientationY.value", node.orientationY.value) - .beEqualTo(Math.fround(options.orientationY)) && success; - success = Should("node.orientationZ.value", node.orientationZ.value) - .beEqualTo(Math.fround(options.orientationZ)) && success; - success = Should("node.distanceModel", node.distanceModel) - .beEqualTo(options.distanceModel) && success; - success = Should("node.refDistance", node.refDistance) - .beEqualTo(options.refDistance) && success; - success = Should("node.maxDistance", node.maxDistance) - .beEqualTo(options.maxDistance) && success; - success = Should("node.rolloffFactor", node.rolloffFactor) - .beEqualTo(options.rolloffFactor) && success; - success = Should("node.coneInnerAngle", node.coneInnerAngle) - .beEqualTo(options.coneInnerAngle) && success; - success = Should("node.coneOuterAngle", node.coneOuterAngle) - .beEqualTo(options.coneOuterAngle) && success; - success = Should("node.coneOuterGain", node.coneOuterGain) - .beEqualTo(options.coneOuterGain) && success; + should(node.panningModel, 'node.panningModel') + .beEqualTo(options.panningModel); + should(node.positionX.value, 'node.positionX.value') + .beEqualTo(Math.fround(options.positionX)); + should(node.positionY.value, 'node.positionY.value') + .beEqualTo(Math.fround(options.positionY)); + should(node.positionZ.value, 'node.positionZ.value') + .beEqualTo(Math.fround(options.positionZ)); + should(node.orientationX.value, 'node.orientationX.value') + .beEqualTo(Math.fround(options.orientationX)); + should(node.orientationY.value, 'node.orientationY.value') + .beEqualTo(Math.fround(options.orientationY)); + should(node.orientationZ.value, 'node.orientationZ.value') + .beEqualTo(Math.fround(options.orientationZ)); + should(node.distanceModel, 'node.distanceModel') + .beEqualTo(options.distanceModel); + should(node.refDistance, 'node.refDistance') + .beEqualTo(options.refDistance); + should(node.maxDistance, 'node.maxDistance') + .beEqualTo(options.maxDistance); + should(node.rolloffFactor, 'node.rolloffFactor') + .beEqualTo(options.rolloffFactor); + should(node.coneInnerAngle, 'node.coneInnerAngle') + .beEqualTo(options.coneInnerAngle); + should(node.coneOuterAngle, 'node.coneOuterAngle') + .beEqualTo(options.coneOuterAngle); + should(node.coneOuterGain, 'node.coneOuterGain') + .beEqualTo(options.coneOuterGain); - success = Should("node.channelCount", node.channelCount) - .beEqualTo(2) && success; - success = Should("node.channelCountMode", node.channelCountMode) - .beEqualTo("clamped-max") && success; - success = Should("node.channelInterpretation", node.channelInterpretation) - .beEqualTo("speakers") && success; + should(node.channelCount, 'node.channelCount').beEqualTo(2); + should(node.channelCountMode, 'node.channelCountMode') + .beEqualTo('clamped-max'); + should(node.channelInterpretation, 'node.channelInterpretation') + .beEqualTo('speakers'); - Should("new PannerNode() with options", success) - .summarize( - "constructed with correct attributes", - "was not constructed correctly"); - - taskDone(); + task.done(); }); - audit.runTasks(); + audit.run(); </script> </body> </html>
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp index 445b2ad..3a595e1c 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -1596,26 +1596,6 @@ graphics_layer_->OffsetFromLayoutObject()); } -void CompositedLayerMapping::RegisterScrollingLayers() { - // Register fixed position layers and their containers with the scrolling - // coordinator. - ScrollingCoordinator* scrolling_coordinator = - owning_layer_.GetScrollingCoordinator(); - if (!scrolling_coordinator) - return; - - scrolling_coordinator->UpdateLayerPositionConstraint(&owning_layer_); - - // Page scale is applied as a transform on the root layout view layer. Because - // the scroll layer is further up in the hierarchy, we need to avoid marking - // the root layout view layer as a container. - bool is_container = - owning_layer_.GetLayoutObject().CanContainFixedPositionObjects() && - !owning_layer_.IsRootLayer(); - scrolling_coordinator->SetLayerIsContainerForFixedPositionLayers( - graphics_layer_.get(), is_container); -} - void CompositedLayerMapping::UpdateInternalHierarchy() { // m_foregroundLayer has to be inserted in the correct order with child // layers, so it's not inserted here. @@ -2490,6 +2470,37 @@ } } +void CompositedLayerMapping::RegisterScrollingLayers() { + // Register fixed position layers and their containers with the scrolling + // coordinator. + ScrollingCoordinator* scrolling_coordinator = + owning_layer_.GetScrollingCoordinator(); + if (!scrolling_coordinator) + return; + + scrolling_coordinator->UpdateLayerPositionConstraint(&owning_layer_); + + // Page scale is applied as a transform on the root layout view layer. Because + // the scroll layer is further up in the hierarchy, we need to avoid marking + // the root layout view layer as a container. + bool is_container = + owning_layer_.GetLayoutObject().CanContainFixedPositionObjects() && + !owning_layer_.IsRootLayer(); + scrolling_coordinator->SetLayerIsContainerForFixedPositionLayers( + graphics_layer_.get(), is_container); + // Fixed-pos descendants inherits the space that has all CSS property applied, + // including perspective, overflow scroll/clip. Thus we also mark every layers + // below the main graphics layer so transforms implemented by them don't get + // skipped. + ApplyToGraphicsLayers( + this, + [scrolling_coordinator, is_container](GraphicsLayer* layer) { + scrolling_coordinator->SetLayerIsContainerForFixedPositionLayers( + layer, is_container); + }, + kApplyToChildContainingLayers); +} + bool CompositedLayerMapping::UpdateSquashingLayers( bool needs_squashing_layers) { bool layers_changed = false;
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js index 37e7ff121..dc07c7f3 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -631,6 +631,7 @@ super(); this._groupBySetting = Common.settings.createSetting('timelineTreeGroupBy', Timeline.AggregatedTimelineTreeView.GroupBy.None); + this._groupByCombobox = new UI.ToolbarComboBox(this._onGroupByChanged.bind(this)); this.init(filters); this._stackView = new Timeline.TimelineStackView(this); this._stackView.addEventListener( @@ -639,6 +640,16 @@ /** * @override + */ + wasShown() { + var groupById = this._groupBySetting.get(); + var option = this._groupByCombobox.options().find(option => option.value === groupById); + if (option) + this._groupByCombobox.select(option); + } + + /** + * @override * @param {!Timeline.TimelineSelection} selection */ updateContents(selection) { @@ -712,7 +723,6 @@ */ populateToolbar(toolbar) { super.populateToolbar(toolbar); - this._groupByCombobox = new UI.ToolbarComboBox(this._onGroupByChanged.bind(this)); /** * @param {string} name * @param {string} id
diff --git a/third_party/WebKit/Source/modules/media_controls/OWNERS b/third_party/WebKit/Source/modules/media_controls/OWNERS new file mode 100644 index 0000000..9c2b5a9 --- /dev/null +++ b/third_party/WebKit/Source/modules/media_controls/OWNERS
@@ -0,0 +1,5 @@ +avayvod@chromium.org +mlamouri@chromium.org + +# TEAM: media-dev@chromium.org +# COMPONENT: Blink>Media>Controls
diff --git a/third_party/WebKit/Source/platform/LengthBox.cpp b/third_party/WebKit/Source/platform/LengthBox.cpp index a78defd..975087c 100644 --- a/third_party/WebKit/Source/platform/LengthBox.cpp +++ b/third_party/WebKit/Source/platform/LengthBox.cpp
@@ -110,39 +110,4 @@ return IsHorizontalWritingMode(writing_mode) ? bottom : left; } -const Length& LengthBox::LogicalLeft(WritingMode writing_mode) const { - return LengthBox::LogicalLeft(writing_mode, left_, top_); -} - -const Length& LengthBox::LogicalRight(WritingMode writing_mode) const { - return LengthBox::LogicalRight(writing_mode, right_, bottom_); -} - -const Length& LengthBox::Before(WritingMode writing_mode) const { - return LengthBox::Before(writing_mode, top_, left_, right_); -} - -const Length& LengthBox::After(WritingMode writing_mode) const { - return LengthBox::After(writing_mode, bottom_, left_, right_); -} - -const Length& LengthBox::Start(WritingMode writing_mode, - TextDirection direction) const { - return LengthBox::Start(writing_mode, direction, top_, left_, right_, - bottom_); -} - -const Length& LengthBox::end(WritingMode writing_mode, - TextDirection direction) const { - return LengthBox::End(writing_mode, direction, top_, left_, right_, bottom_); -} - -const Length& LengthBox::Over(WritingMode writing_mode) const { - return LengthBox::Over(writing_mode, top_, right_); -} - -const Length& LengthBox::Under(WritingMode writing_mode) const { - return LengthBox::Under(writing_mode, bottom_, left_); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/platform/LengthBox.h b/third_party/WebKit/Source/platform/LengthBox.h index f9927a70..4fb231c 100644 --- a/third_party/WebKit/Source/platform/LengthBox.h +++ b/third_party/WebKit/Source/platform/LengthBox.h
@@ -92,16 +92,6 @@ const Length& Top() const { return top_; } const Length& Bottom() const { return bottom_; } - const Length& LogicalLeft(WritingMode) const; - const Length& LogicalRight(WritingMode) const; - - const Length& Before(WritingMode) const; - const Length& After(WritingMode) const; - const Length& Start(WritingMode, TextDirection) const; - const Length& end(WritingMode, TextDirection) const; - const Length& Over(WritingMode) const; - const Length& Under(WritingMode) const; - bool operator==(const LengthBox& o) const { return left_ == o.left_ && right_ == o.right_ && top_ == o.top_ && bottom_ == o.bottom_;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp index 1b07e96..ce23989e 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp
@@ -92,7 +92,12 @@ bool clip_ancestor_of_effect = IsAncestorOf<ClipPaintPropertyNode>(clip_.Get(), effect_->OutputClip()); - if (!effect_->IsRoot() && clip_ancestor_of_effect) { + if (!effect_->IsRoot() && + (clip_ancestor_of_effect || + // Effects that don't move pixels commute with all clips, so always apply + // them first when inside compatible transforms. + (!effect_->HasFilterThatMovesPixels() && + !effect_transform_strict_ancestor_of_transform))) { return kEffect; } if (!clip_->IsRoot())
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp index e1218a9..6b1e01d 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeStateTest.cpp
@@ -10,6 +10,47 @@ class PropertyTreeStateTest : public ::testing::Test {}; +TEST_F(PropertyTreeStateTest, ClipBelowOutputClipOfEffect) { + RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create( + ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), + FloatRoundedRect()); + + RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::Create( + EffectPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), + ClipPaintPropertyNode::Root(), kColorFilterNone, + CompositorFilterOperations(), 1.0, SkBlendMode::kSrcOver); + + PropertyTreeState state(TransformPaintPropertyNode::Root(), clip.Get(), + effect.Get()); + EXPECT_EQ(PropertyTreeState::kEffect, state.GetInnermostNode()); + + PropertyTreeStateIterator iterator(state); + EXPECT_EQ(PropertyTreeState::kClip, iterator.Next()->GetInnermostNode()); + EXPECT_EQ(PropertyTreeState::kNone, iterator.Next()->GetInnermostNode()); +} + +TEST_F(PropertyTreeStateTest, ClipBelowOutputClipOfEffectMovingPixels) { + RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create( + ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), + FloatRoundedRect()); + + CompositorFilterOperations operations; + operations.AppendBlurFilter(2); + RefPtr<EffectPaintPropertyNode> effect = EffectPaintPropertyNode::Create( + EffectPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), + ClipPaintPropertyNode::Root(), kColorFilterNone, operations, 1.0, + SkBlendMode::kSrcOver); + + PropertyTreeState state(TransformPaintPropertyNode::Root(), clip.Get(), + effect.Get()); + // If the effect moves pixels, the clip must happen first. + EXPECT_EQ(PropertyTreeState::kClip, state.GetInnermostNode()); + + PropertyTreeStateIterator iterator(state); + EXPECT_EQ(PropertyTreeState::kEffect, iterator.Next()->GetInnermostNode()); + EXPECT_EQ(PropertyTreeState::kNone, iterator.Next()->GetInnermostNode()); +} + TEST_F(PropertyTreeStateTest, TransformOnEffectOnClip) { RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::Create(TransformPaintPropertyNode::Root(), @@ -79,24 +120,27 @@ CompositorFilterOperations(), 1.0, SkBlendMode::kSrcOver); PropertyTreeState state(transform.Get(), clip.Get(), effect.Get()); - EXPECT_EQ(PropertyTreeState::kClip, state.GetInnermostNode()); + EXPECT_EQ(PropertyTreeState::kEffect, state.GetInnermostNode()); PropertyTreeStateIterator iterator(state); - EXPECT_EQ(PropertyTreeState::kEffect, iterator.Next()->GetInnermostNode()); + EXPECT_EQ(PropertyTreeState::kClip, iterator.Next()->GetInnermostNode()); EXPECT_EQ(PropertyTreeState::kTransform, iterator.Next()->GetInnermostNode()); EXPECT_EQ(PropertyTreeState::kNone, iterator.Next()->GetInnermostNode()); } TEST_F(PropertyTreeStateTest, ClipDescendantOfTransform) { + // CSS transform RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::Create(TransformPaintPropertyNode::Root(), TransformationMatrix(), FloatPoint3D()); + // Scroll transform RefPtr<TransformPaintPropertyNode> transform2 = TransformPaintPropertyNode::Create( transform.Get(), TransformationMatrix(), FloatPoint3D()); + // CSS clip RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create( ClipPaintPropertyNode::Root(), transform2.Get(), FloatRoundedRect()); @@ -105,10 +149,11 @@ ClipPaintPropertyNode::Root(), kColorFilterNone, CompositorFilterOperations(), 1.0, SkBlendMode::kSrcOver); - // Here the clip is inside of its own transform, but the transform is an - // ancestor of the clip's transform. This models situations such as - // a clip inside a scroller that applies to an absolute-positioned element - // which escapes the scroll transform but not the clip. + // Here the clip is inside of its own transform, but the + // PropertyTreeState of the content is an ancestor of the clip's transform./ + // This models situations such as a CSS clip inside a scroller that applies to + // an absolute-positioned element which escapes the scroll transforms but not + // the clip. PropertyTreeState state(transform.Get(), clip.Get(), effect.Get()); EXPECT_EQ(PropertyTreeState::kClip, state.GetInnermostNode()); @@ -119,11 +164,6 @@ } TEST_F(PropertyTreeStateTest, EffectDescendantOfTransform) { - RefPtr<TransformPaintPropertyNode> transform = - TransformPaintPropertyNode::Create(TransformPaintPropertyNode::Root(), - TransformationMatrix(), - FloatPoint3D()); - RefPtr<ClipPaintPropertyNode> clip = ClipPaintPropertyNode::Create( ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(), FloatRoundedRect()); @@ -138,11 +178,7 @@ kColorFilterNone, CompositorFilterOperations(), 1.0, SkBlendMode::kSrcOver); - // Here the clip is inside of its own transform, but the transform is an - // ancestor of the clip's transform. This models situations such as - // a clip inside a scroller that applies to an absolute-positioned element - // which escapes the scroll transform but not the clip. - PropertyTreeState state(transform.Get(), clip.Get(), effect.Get()); + PropertyTreeState state(transform2.Get(), clip.Get(), effect.Get()); EXPECT_EQ(PropertyTreeState::kEffect, state.GetInnermostNode()); PropertyTreeStateIterator iterator(state);
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index 90915e7..09be675f 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -1074,6 +1074,14 @@ if (layer_tree_view_) { GetPage()->LayerTreeViewInitialized(*layer_tree_view_, local_root_->GetFrame()->View()); + + // TODO(kenrb): Currently GPU rasterization is always enabled for OOPIFs. + // This is okay because it is only necessarily to set the trigger to false + // for certain cases that affect the top-level frame, but it would be better + // to be consistent with the top-level frame. Ideally the logic should + // be moved from WebViewImpl into WebFrameWidget and used for all local + // frame roots. https://crbug.com/712794 + layer_tree_view_->HeuristicsForGpuRasterizationUpdated(true); } // FIXME: only unittests, click to play, Android priting, and printing (for
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp index 31a751f..3fce7fb 100644 --- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -2009,12 +2009,12 @@ } IntSize WebViewTest::PrintICBSizeFromPageSize(const FloatSize& page_size) { - // This needs to match printingMinimumShrinkFactor in PrintContext.cpp. The + // This needs to match |kPrintingMinimumShrinkFactor| in PrintContext.cpp. The // layout is scaled by this factor for printing. constexpr float kMinimumShrinkFactor = 1.333f; // The expected layout size comes from the calculation done in - // resizePageRectsKeepingRatio which is used from PrintContext::begin to + // ResizePageRectsKeepingRatio() which is used from PrintContext::begin() to // scale the page size. const float ratio = page_size.Height() / (float)page_size.Width(); const int icb_width = floor(page_size.Width() * kMinimumShrinkFactor);
diff --git a/third_party/ced/README.chromium b/third_party/ced/README.chromium index 291a265..0a84776e 100644 --- a/third_party/ced/README.chromium +++ b/third_party/ced/README.chromium
@@ -4,7 +4,7 @@ Version: 2f40a850bcc5d6f7c1bfa02dbf42ad19d8220dc0 License: Apache 2.0 License File: LICENSE -Security Critical: no +Security Critical: yes Description: Compact Encoding Detection(CED for short) is a library written in C++ that
diff --git a/third_party/closure_compiler/externs/networking_private.js b/third_party/closure_compiler/externs/networking_private.js index ecdd915..e911ff8 100644 --- a/third_party/closure_compiler/externs/networking_private.js +++ b/third_party/closure_compiler/externs/networking_private.js
@@ -299,9 +299,10 @@ * ClientCertType: (string|undefined), * Identity: (string|undefined), * Inner: (string|undefined), - * Outer: string, + * Outer: (string|undefined), * Password: (string|undefined), * SaveCredentials: (boolean|undefined), + * ServerCAPEMs: (!Array<string>|undefined), * ServerCARefs: (!Array<string>|undefined), * UseProactiveKeyCaching: (boolean|undefined), * UseSystemCAs: (boolean|undefined) @@ -318,9 +319,10 @@ * ClientCertType: (!chrome.networkingPrivate.ManagedDOMString|undefined), * Identity: (!chrome.networkingPrivate.ManagedDOMString|undefined), * Inner: (!chrome.networkingPrivate.ManagedDOMString|undefined), - * Outer: !chrome.networkingPrivate.ManagedDOMString, + * Outer: (!chrome.networkingPrivate.ManagedDOMString|undefined), * Password: (!chrome.networkingPrivate.ManagedDOMString|undefined), * SaveCredentials: (!chrome.networkingPrivate.ManagedBoolean|undefined), + * ServerCAPEMs: (!chrome.networkingPrivate.ManagedDOMStringList|undefined), * ServerCARefs: (!chrome.networkingPrivate.ManagedDOMStringList|undefined), * UseProactiveKeyCaching: (!chrome.networkingPrivate.ManagedBoolean|undefined), * UseSystemCAs: (!chrome.networkingPrivate.ManagedBoolean|undefined) @@ -1224,6 +1226,7 @@ * trusted device. * @param {function(boolean):void} callback A callback function that indicates * whether or not the device is a trusted device. + * @deprecated Use networking.castPrivate API. * @see https://developer.chrome.com/extensions/networkingPrivate#method-verifyDestination */ chrome.networkingPrivate.verifyDestination = function(properties, callback) {}; @@ -1237,6 +1240,7 @@ * @param {string} networkGuid The GUID of the Cellular network to activate. * @param {function(string):void} callback A callback function that receives * base64-encoded encrypted credential data to send to a trusted device. + * @deprecated Use networking.castPrivate API. * @see https://developer.chrome.com/extensions/networkingPrivate#method-verifyAndEncryptCredentials */ chrome.networkingPrivate.verifyAndEncryptCredentials = function(properties, networkGuid, callback) {}; @@ -1250,6 +1254,7 @@ * @param {string} data A string containing the base64-encoded data to encrypt. * @param {function(string):void} callback A callback function that receives * base64-encoded encrypted data to send to a trusted device. + * @deprecated Use networking.castPrivate API. * @see https://developer.chrome.com/extensions/networkingPrivate#method-verifyAndEncryptData */ chrome.networkingPrivate.verifyAndEncryptData = function(properties, data, callback) {}; @@ -1265,6 +1270,7 @@ * that the request failed (e.g. MAC address lookup failed). 'Timeout' * indicates that the lookup timed out. Otherwise a valid status is * returned (see $(ref:getWifiTDLSStatus)). + * @deprecated Use networking.castPrivate API. * @see https://developer.chrome.com/extensions/networkingPrivate#method-setWifiTDLSEnabledState */ chrome.networkingPrivate.setWifiTDLSEnabledState = function(ip_or_mac_address, enabled, callback) {}; @@ -1275,6 +1281,7 @@ * @param {function(string):void} callback A callback function that receives a * string with the current TDLS status which can be 'Connected', * 'Disabled', 'Disconnected', 'Nonexistent', or 'Unknown'. + * @deprecated Use networking.castPrivate API. * @see https://developer.chrome.com/extensions/networkingPrivate#method-getWifiTDLSStatus */ chrome.networkingPrivate.getWifiTDLSStatus = function(ip_or_mac_address, callback) {};
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 9284e4d..411a1a3 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -157,13 +157,13 @@ 'ClangToTLinuxLLD': 'clang_tot_lld_release_shared', 'ClangToTLinuxUBSanVptr': 'clang_tot_edge_ubsan_no_recover_hack_static_release', 'ClangToTMac': 'clang_tot_minimal_symbols_shared_release', - 'ClangToTMac (dbg)': 'clang_tot_minimal_symbols_shared_debug', + 'ClangToTMac (dbg)': 'clang_tot_shared_debug', 'ClangToTMacASan': 'asan_disable_nacl_clang_tot_full_symbols_static_release', 'ClangToTWin': 'clang_tot_official_minimal_symbols_static_release_x86', - 'ClangToTWin(dbg)': 'clang_tot_minimal_symbols_shared_debug_x86', + 'ClangToTWin(dbg)': 'clang_tot_shared_debug_x86', 'ClangToTWin(dll)': 'clang_tot_minimal_symbols_shared_release_x86', 'ClangToTWin64': 'clang_tot_official_minimal_symbols_static_release', - 'ClangToTWin64(dbg)': 'clang_tot_minimal_symbols_shared_debug', + 'ClangToTWin64(dbg)': 'clang_tot_shared_debug', 'ClangToTWin64(dll)': 'clang_tot_shared_release', 'ClangToTiOS': 'ios', 'Closure Compilation Linux': 'closure_compilation', @@ -1107,8 +1107,8 @@ 'clang_tot', 'full_symbols', 'shared', 'release', ], - 'clang_tot_minimal_symbols_shared_debug': [ - 'clang_tot', 'minimal_symbols', 'shared', 'debug', + 'clang_tot_shared_debug': [ + 'clang_tot', 'shared', 'debug', ], 'clang_tot_full_symbols_shared_debug_use_lld': [ @@ -1119,8 +1119,8 @@ 'clang_tot', 'full_symbols', 'shared', 'debug', 'use_lld', 'x86', ], - 'clang_tot_minimal_symbols_shared_debug_x86': [ - 'clang_tot', 'minimal_symbols', 'shared', 'debug', 'x86', + 'clang_tot_shared_debug_x86': [ + 'clang_tot', 'shared', 'debug', 'x86', ], 'clang_tot_shared_release_use_lld': [
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index f8590d48..d19d7b15 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -103823,6 +103823,7 @@ <int value="879992337" label="disable-pull-to-refresh-effect"/> <int value="880510010" label="enable-permissions-bubbles"/> <int value="884106779" label="supervised-user-safesites"/> + <int value="886907524" label="autoplay-policy"/> <int value="887011602" label="enable-spelling-auto-correct"/> <int value="892899792" label="MaterialDesignIncognitoNTP:disabled"/> <int value="902608487" label="AutofillUpstreamRequestCvcIfMissing:enabled"/>
diff --git a/ui/app_list/app_list_switches.cc b/ui/app_list/app_list_switches.cc index 0f6d670..c583832 100644 --- a/ui/app_list/app_list_switches.cc +++ b/ui/app_list/app_list_switches.cc
@@ -26,9 +26,6 @@ // If set, the app list will be enabled as if enabled from CWS. const char kEnableAppList[] = "enable-app-list"; -// Enables the fullscreen app list. -extern const char kEnableFullscreenAppList[] = "enable-fullscreen-app-list"; - // Enable/disable syncing of the app list independent of extensions. const char kEnableSyncAppList[] = "enable-sync-app-list"; const char kDisableSyncAppList[] = "disable-sync-app-list"; @@ -90,10 +87,5 @@ return !AnswerServerUrl().empty(); } -bool IsFullscreenAppListEnabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - kEnableFullscreenAppList); -} - } // namespace switches } // namespace app_list
diff --git a/ui/app_list/app_list_switches.h b/ui/app_list/app_list_switches.h index b3cc9a9..d4fc5fb 100644 --- a/ui/app_list/app_list_switches.h +++ b/ui/app_list/app_list_switches.h
@@ -18,7 +18,6 @@ APP_LIST_EXPORT extern const char kCustomLauncherPage[]; APP_LIST_EXPORT extern const char kDisableAppListDismissOnBlur[]; APP_LIST_EXPORT extern const char kEnableAppList[]; -APP_LIST_EXPORT extern const char kEnableFullscreenAppList[]; APP_LIST_EXPORT extern const char kEnableSyncAppList[]; APP_LIST_EXPORT extern const char kDisableSyncAppList[]; APP_LIST_EXPORT extern const char kEnableDriveSearchInChromeLauncher[]; @@ -42,8 +41,6 @@ bool APP_LIST_EXPORT IsAnswerCardEnabled(); -bool APP_LIST_EXPORT IsFullscreenAppListEnabled(); - } // namespace switches } // namespace app_list
diff --git a/ui/app_list/demo/app_list_demo_views.cc b/ui/app_list/demo/app_list_demo_views.cc index 8f0a806b..d21cdaf 100644 --- a/ui/app_list/demo/app_list_demo_views.cc +++ b/ui/app_list/demo/app_list_demo_views.cc
@@ -60,8 +60,8 @@ gfx::NativeView container = window_context; view_ = new app_list::AppListView(this); - view_->Initialize(container, 0); - view_->MaybeSetAnchorPoint(gfx::Point(300, 300)); + view_->InitAsBubble(container, 0); + view_->SetAnchorPoint(gfx::Point(300, 300)); // Populate some apps. GetTestModel()->PopulateApps(kInitialItems);
diff --git a/ui/app_list/presenter/app_list_presenter_impl_unittest.cc b/ui/app_list/presenter/app_list_presenter_impl_unittest.cc index 6edb9875..372b8d16 100644 --- a/ui/app_list/presenter/app_list_presenter_impl_unittest.cc +++ b/ui/app_list/presenter/app_list_presenter_impl_unittest.cc
@@ -44,7 +44,7 @@ int current_apps_page) override { init_called_ = true; view_ = view; - view->Initialize(container_, current_apps_page); + view->InitAsBubble(container_, current_apps_page); } void OnShown(int64_t display_id) override { on_shown_called_ = true; } void OnDismissed() override { on_dismissed_called_ = true; }
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc index 1278828..2a1be91f 100644 --- a/ui/app_list/views/app_list_view.cc +++ b/ui/app_list/views/app_list_view.cc
@@ -31,8 +31,6 @@ #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/image/image_skia.h" @@ -131,7 +129,10 @@ // An animation observer to hide the view at the end of the animation. class HideViewAnimationObserver : public ui::ImplicitAnimationObserver { public: - HideViewAnimationObserver() : frame_(NULL), target_(NULL) {} + HideViewAnimationObserver() + : frame_(NULL), + target_(NULL) { + } ~HideViewAnimationObserver() override { if (target_) @@ -189,22 +190,37 @@ RemoveAllChildViews(true); } -void AppListView::Initialize(gfx::NativeView parent, int initial_apps_page) { +void AppListView::InitAsBubble(gfx::NativeView parent, int initial_apps_page) { base::Time start_time = base::Time::Now(); + InitContents(parent, initial_apps_page); + AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); - set_color(kContentsBackgroundColor); + set_margins(gfx::Insets()); set_parent_window(parent); + set_close_on_deactivate(false); + set_shadow(views::BubbleBorder::NO_ASSETS); + set_color(kContentsBackgroundColor); + // This creates the app list widget. (Before this, child widgets cannot be + // created.) + views::BubbleDialogDelegateView::CreateBubble(this); - if (switches::IsFullscreenAppListEnabled()) - InitializeFullscreen(parent, initial_apps_page); - else - InitializeBubble(parent, initial_apps_page); - + SetBubbleArrow(views::BubbleBorder::FLOAT); + // We can now create the internal widgets. InitChildWidgets(); + + aura::Window* window = GetWidget()->GetNativeWindow(); + window->SetEventTargeter(base::MakeUnique<views::BubbleWindowTargeter>(this)); + + const int kOverlayCornerRadius = + GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(); + overlay_view_ = new AppListOverlayView(kOverlayCornerRadius); + overlay_view_->SetBoundsRect(GetContentsBounds()); AddChildView(overlay_view_); + if (delegate_) delegate_->ViewInitialized(); + UMA_HISTOGRAM_TIMES("Apps.AppListCreationTime", base::Time::Now() - start_time); } @@ -215,10 +231,8 @@ GetBubbleFrameView()->SchedulePaint(); } -void AppListView::MaybeSetAnchorPoint(const gfx::Point& anchor_point) { - // if the AppListView is a bubble - if (!switches::IsFullscreenAppListEnabled()) - SetAnchorRect(gfx::Rect(anchor_point, gfx::Size())); +void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) { + SetAnchorRect(gfx::Rect(anchor_point, gfx::Size())); } void AppListView::SetDragAndDropHostOfCurrentAppList( @@ -236,9 +250,7 @@ } void AppListView::UpdateBounds() { - // if the AppListView is a bubble - if (!switches::IsFullscreenAppListEnabled()) - SizeToContents(); + SizeToContents(); } void AppListView::SetAppListOverlayVisible(bool visible) { @@ -292,10 +304,6 @@ } } -const char* AppListView::GetClassName() const { - return "AppListView"; -} - bool AppListView::ShouldHandleSystemCommands() const { return true; } @@ -335,6 +343,7 @@ app_list_main_view_->SetPaintToLayer(); app_list_main_view_->layer()->SetFillsBoundsOpaquely(false); app_list_main_view_->layer()->SetMasksToBounds(true); + // This will be added to the |search_box_widget_| after the app list widget is // initialized. search_box_view_ = new SearchBoxView(app_list_main_view_, delegate_); @@ -401,49 +410,9 @@ app_list_main_view_->contents_view()->Layout(); } -void AppListView::InitializeFullscreen(gfx::NativeView parent, - int initial_apps_page) { - const gfx::Rect& display_work_area_bounds = - display::Screen::GetScreen()->GetDisplayNearestView(parent).work_area(); - views::Widget* widget = new views::Widget; - views::Widget::InitParams app_list_overlay_view_params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - - app_list_overlay_view_params.parent = parent; - app_list_overlay_view_params.delegate = this; - app_list_overlay_view_params.opacity = - views::Widget::InitParams::TRANSLUCENT_WINDOW; - app_list_overlay_view_params.bounds = display_work_area_bounds; - widget->Init(app_list_overlay_view_params); - widget->GetLayer()->SetBackgroundBlur(10); - - overlay_view_ = new AppListOverlayView(0 /* no corners */); -} - -void AppListView::InitializeBubble(gfx::NativeView parent, - int initial_apps_page) { - set_margins(gfx::Insets()); - set_close_on_deactivate(false); - set_shadow(views::BubbleBorder::NO_ASSETS); - - // This creates the app list widget. (Before this, child widgets cannot be - // created.) - views::BubbleDialogDelegateView::CreateBubble(this); - - SetBubbleArrow(views::BubbleBorder::FLOAT); - // We can now create the internal widgets. - - aura::Window* window = GetWidget()->GetNativeWindow(); - window->SetEventTargeter(base::MakeUnique<views::BubbleWindowTargeter>(this)); - - const int kOverlayCornerRadius = - GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(); - overlay_view_ = new AppListOverlayView(kOverlayCornerRadius); - overlay_view_->SetBoundsRect(GetContentsBounds()); -} - -void AppListView::OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, - views::Widget* widget) const { +void AppListView::OnBeforeBubbleWidgetInit( + views::Widget::InitParams* params, + views::Widget* widget) const { if (!params->native_widget) { views::ViewsDelegate* views_delegate = views::ViewsDelegate::GetInstance(); if (views_delegate && !views_delegate->native_widget_factory().is_null()) { @@ -472,7 +441,8 @@ DCHECK(mask); DCHECK(GetBubbleFrameView()); - mask->addRect(gfx::RectToSkRect(GetBubbleFrameView()->GetContentsBounds())); + mask->addRect(gfx::RectToSkRect( + GetBubbleFrameView()->GetContentsBounds())); } bool AppListView::AcceleratorPressed(const ui::Accelerator& accelerator) { @@ -505,8 +475,8 @@ gfx::Rect speech_bounds = centered_bounds; int preferred_height = speech_view_->GetPreferredSize().height(); speech_bounds.Inset(kSpeechUIMargin, kSpeechUIMargin); - speech_bounds.set_height( - std::min(speech_bounds.height(), preferred_height)); + speech_bounds.set_height(std::min(speech_bounds.height(), + preferred_height)); speech_bounds.Inset(-speech_view_->GetInsets()); speech_view_->SetBoundsRect(speech_bounds); } @@ -552,7 +522,8 @@ animation_observer_->set_frame(GetBubbleFrameView()); gfx::Transform speech_transform; - speech_transform.Translate(0, SkFloatToMScalar(kSpeechUIAppearingPosition)); + speech_transform.Translate( + 0, SkFloatToMScalar(kSpeechUIAppearingPosition)); if (will_appear) speech_view_->layer()->SetTransform(speech_transform);
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h index cbdb1d89..fb3b061e 100644 --- a/ui/app_list/views/app_list_view.h +++ b/ui/app_list/views/app_list_view.h
@@ -38,18 +38,16 @@ explicit AppListView(AppListViewDelegate* delegate); ~AppListView() override; - // Initializes the widget as a bubble or fullscreen view depending on the - // presence of a cmd line switch. parent and initial_apps_page are used for - // both the bubble and fullscreen initialization. - void Initialize(gfx::NativeView parent, int initial_apps_page); + // Initializes the widget. + void InitAsBubble(gfx::NativeView parent, int initial_apps_page); void SetBubbleArrow(views::BubbleBorder::Arrow arrow); - void MaybeSetAnchorPoint(const gfx::Point& anchor_point); + void SetAnchorPoint(const gfx::Point& anchor_point); // If |drag_and_drop_host| is not NULL it will be called upon drag and drop // operations outside the application list. This has to be called after - // Initialize was called since the app list object needs to exist so that + // InitAsBubble was called since the app list object needs to exist so that // it can set the host. void SetDragAndDropHostOfCurrentAppList( ApplicationDragAndDropHost* drag_and_drop_host); @@ -71,7 +69,6 @@ // Overridden from views::View: gfx::Size GetPreferredSize() const override; void OnPaint(gfx::Canvas* canvas) override; - const char* GetClassName() const override; // WidgetDelegate overrides: bool ShouldHandleSystemCommands() const override; @@ -96,12 +93,6 @@ void InitChildWidgets(); - // Initializes the widget for fullscreen mode. - void InitializeFullscreen(gfx::NativeView parent, int initial_apps_page); - - // Initializes the widget as a bubble. - void InitializeBubble(gfx::NativeView parent, int initial_apps_page); - // Overridden from views::BubbleDialogDelegateView: void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const override; @@ -126,8 +117,8 @@ SpeechView* speech_view_; views::View* search_box_focus_host_; // Owned by the views hierarchy. - views::Widget* search_box_widget_; // Owned by the app list's widget. - SearchBoxView* search_box_view_; // Owned by |search_box_widget_|. + views::Widget* search_box_widget_; // Owned by the app list's widget. + SearchBoxView* search_box_view_; // Owned by |search_box_widget_|. // A semi-transparent white overlay that covers the app list while dialogs are // open.
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc index 56e2bdd..a93a966 100644 --- a/ui/app_list/views/app_list_view_unittest.cc +++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -172,8 +172,8 @@ view_ = new app_list::AppListView(delegate_.get()); // Initialize centered around a point that ensures the window is wholly shown. - view_->Initialize(parent, 0); - view_->MaybeSetAnchorPoint(gfx::Point(300, 300)); + view_->InitAsBubble(parent, 0); + view_->SetAnchorPoint(gfx::Point(300, 300)); } AppListViewTestContext::~AppListViewTestContext() {
diff --git a/ui/aura/window.h b/ui/aura/window.h index c50ccd0d..2996584 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h
@@ -175,7 +175,7 @@ // LayoutManager may adjust the bounds. void SetBounds(const gfx::Rect& new_bounds); - // Changes the bounds of the window in the screen coordinates. + // Changes the bounds of the window in the screen coordintates. // If present, the window's parent's LayoutManager may adjust the bounds. void SetBoundsInScreen(const gfx::Rect& new_bounds_in_screen_coords, const display::Display& dst_display);
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 744fd65..43da095 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -3,7 +3,7 @@ # found in the LICENSE file. import("//build/config/ui.gni") -import("//device/vr/features.gni") +import("//device/vr/features/features.gni") import("//testing/test.gni") import("//testing/libfuzzer/fuzzer_test.gni") @@ -255,7 +255,7 @@ "//base:base_static", "//base:i18n", "//base/third_party/dynamic_annotations", - "//device/vr:features", + "//device/vr/features", "//skia", "//third_party/zlib", ]
diff --git a/ui/gfx/DEPS b/ui/gfx/DEPS index bef0c572..a6891ad4 100644 --- a/ui/gfx/DEPS +++ b/ui/gfx/DEPS
@@ -1,7 +1,7 @@ include_rules = [ "+base", "+cc/paint", - "+device/vr/features.h", + "+device/vr/features/features.h", "+skia/ext", "+third_party/harfbuzz-ng", "+third_party/skia",
diff --git a/ui/gfx/font_render_params.h b/ui/gfx/font_render_params.h index af89e34..ade3672 100644 --- a/ui/gfx/font_render_params.h +++ b/ui/gfx/font_render_params.h
@@ -9,7 +9,7 @@ #include <vector> #include "build/build_config.h" -#include "device/vr/features.h" +#include "device/vr/features/features.h" #include "third_party/skia/include/core/SkFontLCDConfig.h" #include "ui/gfx/font.h" #include "ui/gfx/gfx_export.h"
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index de3ac38..fbce29e 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -581,26 +581,26 @@ return; } - bool can_close = true; - if (non_client_view_) - can_close = non_client_view_->CanClose(); - if (can_close) { - SaveWindowPlacement(); + if (non_client_view_ && !non_client_view_->CanClose()) + return; - // During tear-down the top-level focus manager becomes unavailable to - // GTK tabbed panes and their children, so normal deregistration via - // |FormManager::ViewRemoved()| calls are fouled. We clear focus here - // to avoid these redundant steps and to avoid accessing deleted views - // that may have been in focus. - if (is_top_level() && focus_manager_.get()) - focus_manager_->SetFocusedView(NULL); + // The actions below can cause this function to be called again, so mark + // |this| as closed early. See crbug.com/714334 + widget_closed_ = true; + SaveWindowPlacement(); - for (WidgetObserver& observer : observers_) - observer.OnWidgetClosing(this); + // During tear-down the top-level focus manager becomes unavailable to + // GTK tabbed panes and their children, so normal deregistration via + // |FocusManager::ViewRemoved()| calls are fouled. We clear focus here + // to avoid these redundant steps and to avoid accessing deleted views + // that may have been in focus. + if (is_top_level() && focus_manager_.get()) + focus_manager_->SetFocusedView(nullptr); - native_widget_->Close(); - widget_closed_ = true; - } + for (WidgetObserver& observer : observers_) + observer.OnWidgetClosing(this); + + native_widget_->Close(); } void Widget::CloseNow() {
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc index 52845e5ed..fe51c6f 100644 --- a/ui/views/widget/widget_unittest.cc +++ b/ui/views/widget/widget_unittest.cc
@@ -738,6 +738,8 @@ void OnWidgetDestroying(Widget* widget) override { if (active_ == widget) active_ = nullptr; + if (widget_activated_ == widget) + widget_activated_ = nullptr; widget_closed_ = widget; } @@ -808,11 +810,10 @@ Widget* widget_to_close_on_hide_; }; -TEST_F(WidgetObserverTest, DISABLED_ActivationChange) { +TEST_F(WidgetObserverTest, ActivationChange) { WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget()); - - Widget* toplevel1 = NewWidget(); - Widget* toplevel2 = NewWidget(); + WidgetAutoclosePtr toplevel1(NewWidget()); + WidgetAutoclosePtr toplevel2(NewWidget()); toplevel1->Show(); toplevel2->Show(); @@ -822,20 +823,82 @@ toplevel1->Activate(); RunPendingMessages(); - EXPECT_EQ(toplevel1, widget_activated()); + EXPECT_EQ(toplevel1.get(), widget_activated()); toplevel2->Activate(); RunPendingMessages(); - EXPECT_EQ(toplevel1, widget_deactivated()); - EXPECT_EQ(toplevel2, widget_activated()); - EXPECT_EQ(toplevel2, active()); + EXPECT_EQ(toplevel1.get(), widget_deactivated()); + EXPECT_EQ(toplevel2.get(), widget_activated()); + EXPECT_EQ(toplevel2.get(), active()); } -TEST_F(WidgetObserverTest, DISABLED_VisibilityChange) { - WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget()); +namespace { - Widget* child1 = NewWidget(); - Widget* child2 = NewWidget(); +// This class simulates a focus manager that moves focus to a second widget when +// the first one is closed. It simulates a situation where a sequence of widget +// observers might try to call Widget::Close in response to a OnWidgetClosing(). +class WidgetActivationForwarder : public TestWidgetObserver { + public: + WidgetActivationForwarder(Widget* current_active_widget, + Widget* widget_to_activate) + : TestWidgetObserver(current_active_widget), + widget_to_activate_(widget_to_activate) {} + + ~WidgetActivationForwarder() override {} + + private: + // WidgetObserver overrides: + void OnWidgetClosing(Widget* widget) override { + widget->OnNativeWidgetActivationChanged(false); + widget_to_activate_->Activate(); + } + void OnWidgetActivationChanged(Widget* widget, bool active) override { + if (!active) + widget->Close(); + } + + Widget* widget_to_activate_; + + DISALLOW_COPY_AND_ASSIGN(WidgetActivationForwarder); +}; + +// This class observes a widget and counts the number of times OnWidgetClosing +// is called. +class WidgetCloseCounter : public TestWidgetObserver { + public: + explicit WidgetCloseCounter(Widget* widget) : TestWidgetObserver(widget) {} + + ~WidgetCloseCounter() override {} + + int close_count() const { return close_count_; } + + private: + // WidgetObserver overrides: + void OnWidgetClosing(Widget* widget) override { close_count_++; } + + int close_count_ = 0; + + DISALLOW_COPY_AND_ASSIGN(WidgetCloseCounter); +}; + +} // namespace + +// Makes sure close notifications aren't sent more than once when a Widget is +// shutting down. Test for crbug.com/714334 +TEST_F(WidgetObserverTest, CloseReentrancy) { + Widget* widget1 = CreateTopLevelPlatformWidget(); + Widget* widget2 = CreateTopLevelPlatformWidget(); + WidgetCloseCounter counter(widget1); + WidgetActivationForwarder focus_manager(widget1, widget2); + widget1->Close(); + EXPECT_EQ(1, counter.close_count()); + widget2->Close(); +} + +TEST_F(WidgetObserverTest, VisibilityChange) { + WidgetAutoclosePtr toplevel(CreateTopLevelPlatformWidget()); + WidgetAutoclosePtr child1(NewWidget()); + WidgetAutoclosePtr child2(NewWidget()); toplevel->Show(); child1->Show(); @@ -844,16 +907,16 @@ reset(); child1->Hide(); - EXPECT_EQ(child1, widget_hidden()); + EXPECT_EQ(child1.get(), widget_hidden()); child2->Hide(); - EXPECT_EQ(child2, widget_hidden()); + EXPECT_EQ(child2.get(), widget_hidden()); child1->Show(); - EXPECT_EQ(child1, widget_shown()); + EXPECT_EQ(child1.get(), widget_shown()); child2->Show(); - EXPECT_EQ(child2, widget_shown()); + EXPECT_EQ(child2.get(), widget_shown()); } TEST_F(WidgetObserverTest, DestroyBubble) {
diff --git a/ui/webui/resources/cr_elements/hidden_style_css.html b/ui/webui/resources/cr_elements/hidden_style_css.html new file mode 100644 index 0000000..4c22288 --- /dev/null +++ b/ui/webui/resources/cr_elements/hidden_style_css.html
@@ -0,0 +1,15 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<!-- Common style for Material Design WebUI, such that the |hidden| attributes + works within Shadow DOM. --> +<dom-module id="cr-hidden-style"> + <template> + <style> + /* Included here so we don't have to include "iron-positioning" in every + * stylesheet. See crbug.com/498405. */ + [hidden] { + display: none !important; + } + </style> + </template> +</dom-module>
diff --git a/ui/webui/resources/cr_elements/shared_style_css.html b/ui/webui/resources/cr_elements/shared_style_css.html index e00e4945..f4157f6 100644 --- a/ui/webui/resources/cr_elements/shared_style_css.html +++ b/ui/webui/resources/cr_elements/shared_style_css.html
@@ -1,11 +1,12 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> +<link rel="import" href="hidden_style_css.html"> <!-- Common styles for Material Design WebUI. Included directly in settings_shared_css.html. --> <dom-module id="cr-shared-style"> <template> - <style> + <style include="cr-hidden-style"> /* Chrome spinners should be blue. */ paper-spinner { --paper-spinner-layer-1-color: var(--google-blue-500);
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp index 8d96278..1f3a45ff 100644 --- a/ui/webui/resources/cr_elements_resources.grdp +++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -146,6 +146,9 @@ file="../../webui/resources/cr_elements/shared_style_css.html" type="chrome_html" flattenhtml="true" /> + <structure name="IDR_CR_ELEMENTS_CR_HIDDEN_STYLE_CSS_HTML" + file="../../webui/resources/cr_elements/hidden_style_css.html" + type="chrome_html" /> <structure name="IDR_CR_ELEMENTS_CR_SHARED_VARS_CSS_HTML" file="../../webui/resources/cr_elements/shared_vars_css.html" type="chrome_html" />