diff --git a/AUTHORS b/AUTHORS index 44353195..fb71d426 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -467,6 +467,7 @@ Jongdeok Kim <jongdeok.kim@navercorp.com> Jongheon Kim <sapzape@gmail.com> JongKwon Lee <jongkwon.lee@navercorp.com> +Jongmok Kim <jongmok.kim@navercorp.com> Jongsoo Lee <leejongsoo@gmail.com> Joone Hur <joone.hur@intel.com> Joonghun Park <pjh0718@gmail.com>
diff --git a/DEPS b/DEPS index 0f5e24ab..1fbc921 100644 --- a/DEPS +++ b/DEPS
@@ -181,11 +181,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': '4ca0dacbce515bcc1b96ac574b80a9d2386b9a15', + 'skia_revision': 'fca88b6504045731b3e8605abf544b15cc7e2a81', # 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': '1bcbb571d7410173970be186312c601abe776c34', + 'v8_revision': '0537aa80179c8c1ff187149b026b1e5e723c4d90', # 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. @@ -193,7 +193,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '7d45184d4baaccb6719b5f2f8c30311c0a54582e', + 'angle_revision': '135f8fcba837098a5ee0ed699d59445716908825', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -201,7 +201,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': 'a216865467ddf9430fe1207adcd71c2d5318e3bc', + 'pdfium_revision': 'c040c8f850515cd82b3dbcefed870ccc843fdb54', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -244,7 +244,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': 'bc9b29411747ee0e529db2d9745702ad20c461c7', + 'catapult_revision': '6b345995a82794d776ed6b20202b5dbcc6845619', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -252,7 +252,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '04ccecc2d7b27a688bec903bb0120a60135b6799', + 'devtools_frontend_revision': '3df70e9c609d0af3984133ac8bf2a053548490f6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -312,7 +312,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '8ffd3f23331dc56d3cd45d416e850cee88119330', + 'dawn_revision': 'c2e16963a9cc1eb749b541e7960b3539bd623bae', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -894,7 +894,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '938e6c4638472c79ed28356d95b65dfc9ec82df5', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '9d7cd6e7198b2e6b4430697e8de2dc8eead60148', 'condition': 'checkout_linux', }, @@ -1297,7 +1297,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '56d4671ce7831c937ddb2bc577cb176df0d82eeb', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'aa94421bfd1f15e3338caf194cc175c899efbb5f', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1571,7 +1571,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c518c7f9fe9a1ddea91f962ae4dc7b923b33510f', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1d7da3cc922f0a1f9e9fcacae685c67a1a99daa5', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/ErrorCodeConversionHelper.java b/android_webview/java/src/org/chromium/android_webview/ErrorCodeConversionHelper.java index fcd17c8..677b445 100644 --- a/android_webview/java/src/org/chromium/android_webview/ErrorCodeConversionHelper.java +++ b/android_webview/java/src/org/chromium/android_webview/ErrorCodeConversionHelper.java
@@ -117,7 +117,6 @@ case NetError.ERR_SSL_NO_RENEGOTIATION: case NetError.ERR_SSL_DECOMPRESSION_FAILURE_ALERT: case NetError.ERR_SSL_BAD_RECORD_MAC_ALERT: - case NetError.ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: case NetError.ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED: case NetError.ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY: return ERROR_FAILED_SSL_HANDSHAKE;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedHolderTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedHolderTest.java index ab15e54..fe23c3c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedHolderTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/VariationsSeedHolderTest.java
@@ -44,17 +44,27 @@ mUpdateFinished = new CallbackHelper(); } + public TestHolder(CallbackHelper writeFinished) { + mWriteFinished = writeFinished; + mUpdateFinished = new CallbackHelper(); + } + // Don't schedule the seed download job. @Override public void scheduleFetchIfNeeded() {} + @Override + public void onWriteFinished() { + mWriteFinished.notifyCalled(); + } + public void writeSeedIfNewerBlocking(File destination, long date) throws IOException, TimeoutException { ParcelFileDescriptor fd = null; try { fd = ParcelFileDescriptor.open(destination, ParcelFileDescriptor.MODE_WRITE_ONLY); int calls = mWriteFinished.getCallCount(); - writeSeedIfNewer(fd, date, /*onFinished=*/mWriteFinished::notifyCalled); + writeSeedIfNewer(fd, date); mWriteFinished.waitForCallback(calls); } finally { if (fd != null) fd.close(); @@ -63,7 +73,7 @@ public void updateSeedBlocking(SeedInfo newSeed) throws TimeoutException { int calls = mUpdateFinished.getCallCount(); - updateSeed(newSeed, /*onFinished=*/mUpdateFinished::notifyCalled); + updateSeed(newSeed, /*onFinished=*/() -> mUpdateFinished.notifyCalled()); mUpdateFinished.waitForCallback(calls); } } @@ -182,12 +192,14 @@ Arrays.fill(mockSeeds[i].seedData, (byte) i); } - TestHolder holder = new TestHolder(); - // Used to track the completion of every updateSeed and writeSeedIfNewer call. CallbackHelper callbackHelper = new CallbackHelper(); int callbacksExpected = 0; + // TestHolder will notify callbackHelper whenever a writeSeedIfNewer request + // completes. + TestHolder holder = new TestHolder(callbackHelper); + // "Download" each mock seed to the holder. for (int i = 0; i < mockSeeds.length; i++) { callbacksExpected++; @@ -205,8 +217,7 @@ fds.add(fd); callbacksExpected++; - holder.writeSeedIfNewer( - fd, Long.MIN_VALUE, /*onFinished=*/callbackHelper::notifyCalled); + holder.writeSeedIfNewer(fd, Long.MIN_VALUE); } }
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedHolder.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedHolder.java index a00f533..88b5d14 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedHolder.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedHolder.java
@@ -55,12 +55,9 @@ // newer than mDestinationDate. private long mDestinationDate; - private Runnable mOnFinished; - - public SeedWriter(ParcelFileDescriptor destination, long date, Runnable onFinished) { + public SeedWriter(ParcelFileDescriptor destination, long date) { mDestination = destination; mDestinationDate = date; - mOnFinished = onFinished; } @Override @@ -86,7 +83,7 @@ } } finally { VariationsUtils.closeSafely(mDestination); - mOnFinished.run(); + onWriteFinished(); } } } @@ -140,8 +137,8 @@ } @VisibleForTesting - public void writeSeedIfNewer(ParcelFileDescriptor destination, long date, Runnable onFinished) { - mSeedHandler.post(new SeedWriter(destination, date, onFinished)); + public void writeSeedIfNewer(ParcelFileDescriptor destination, long date) { + mSeedHandler.post(new SeedWriter(destination, date)); } @VisibleForTesting @@ -153,4 +150,7 @@ public void scheduleFetchIfNeeded() { AwVariationsSeedFetcher.scheduleIfNeeded(); } + + // overridden by tests + public void onWriteFinished() {} }
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedServer.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedServer.java index 7e9cfea..dae5645 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedServer.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/VariationsSeedServer.java
@@ -11,41 +11,16 @@ import org.chromium.android_webview.common.services.IVariationsSeedServer; -import javax.annotation.concurrent.GuardedBy; - /** * VariationsSeedServer is a bound service that shares the Variations seed with all the WebViews * on the system. A WebView will bind and call getSeed, passing a file descriptor to which the - * service should write the seed. The service will convert itself into a started service while - * processing seed requests, and stop itself when the last outstanding request has completed. + * service should write the seed. */ public class VariationsSeedServer extends Service { private final IVariationsSeedServer.Stub mBinder = new IVariationsSeedServer.Stub() { - // Stores the number of pending getSeed calls. When all calls have completed, we can stop - // the service. - // Usage of this variable must be synchronized as getSeed calls can be dispatched to - // multiple threads simultaneously. - @GuardedBy("mLock") - private int mPendingGetSeedCalls = 0; - private final Object mLock = new Object(); - @Override public void getSeed(ParcelFileDescriptor newSeedFile, long oldSeedDate) { - synchronized (mLock) { - if (mPendingGetSeedCalls++ == 0) { - startService(new Intent(VariationsSeedServer.this, VariationsSeedServer.class)); - } - } - VariationsSeedHolder.getInstance().writeSeedIfNewer( - newSeedFile, oldSeedDate, /*onFinished=*/this::onGetSeedComplete); - } - - private void onGetSeedComplete() { - synchronized (mLock) { - if (--mPendingGetSeedCalls == 0) { - stopSelf(); - } - } + VariationsSeedHolder.getInstance().writeSeedIfNewer(newSeedFile, oldSeedDate); } };
diff --git a/ash/assistant/ui/logo_view/logo_view_impl.cc b/ash/assistant/ui/logo_view/logo_view_impl.cc index 406e1d84..07d101f 100644 --- a/ash/assistant/ui/logo_view/logo_view_impl.cc +++ b/ash/assistant/ui/logo_view/logo_view_impl.cc
@@ -217,7 +217,7 @@ void LogoViewImpl::VisibilityChanged(views::View* starting_from, bool is_visible) { - if (is_visible) + if (IsDrawn()) state_animator_.StartAnimator(); else state_animator_.StopAnimator();
diff --git a/ash/shelf/hotseat_widget.cc b/ash/shelf/hotseat_widget.cc index c368fc2..9e86d52 100644 --- a/ash/shelf/hotseat_widget.cc +++ b/ash/shelf/hotseat_widget.cc
@@ -126,9 +126,6 @@ // The WallpaperController, responsible for providing proper colors. WallpaperControllerImpl* wallpaper_controller_; - // The most recent color that the |opaque_background_| has been animated to. - SkColor target_color_; - DISALLOW_COPY_AND_ASSIGN(DelegateView); }; @@ -170,20 +167,7 @@ DCHECK(HotseatWidget::ShouldShowHotseatBackground()); opaque_background_.SetVisible(true); - - if (ShelfConfig::Get()->GetDefaultShelfColor() != target_color_) { - target_color_ = ShelfConfig::Get()->GetDefaultShelfColor(); - - ui::ScopedLayerAnimationSettings animation_setter( - opaque_background_.GetAnimator()); - animation_setter.SetTransitionDuration( - ShelfConfig::Get()->shelf_animation_duration()); - animation_setter.SetTweenType(gfx::Tween::EASE_OUT); - animation_setter.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - - opaque_background_.SetColor(target_color_); - } + opaque_background_.SetColor(ShelfConfig::Get()->GetDefaultShelfColor()); const int radius = ShelfConfig::Get()->hotseat_size() / 2; gfx::RoundedCornersF rounded_corners = {radius, radius, radius, radius};
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc index 518a14d..5e2bbf2 100644 --- a/ash/shelf/scrollable_shelf_view.cc +++ b/ash/shelf/scrollable_shelf_view.cc
@@ -605,6 +605,8 @@ gfx::Rect icon_bounds = shelf_view_->view_model()->ideal_bounds( shelf_view_->model()->ItemIndexByID(id)); + icon_bounds.Offset(edge_padding.left() - padding_insets_.left(), 0); + // Transforms |icon_bounds| from shelf view's coordinates to scrollable shelf // view's coordinates manually. icon_bounds.Offset( @@ -1262,7 +1264,7 @@ bool use_target_bounds) const { // Display centering alignment if (ShouldApplyDisplayCentering(use_target_bounds)) - return CalculatePaddingForDisplayCentering(); + return CalculatePaddingForDisplayCentering(use_target_bounds); const int icons_size = shelf_view_->GetSizeOfAppIcons( shelf_view_->number_of_visible_apps(), false) + @@ -1319,7 +1321,8 @@ : GetLocalBounds(); } -gfx::Insets ScrollableShelfView::CalculatePaddingForDisplayCentering() const { +gfx::Insets ScrollableShelfView::CalculatePaddingForDisplayCentering( + bool use_target_bounds) const { const int icons_size = shelf_view_->GetSizeOfAppIcons( shelf_view_->number_of_visible_apps(), false) + 2 * ShelfConfig::Get()->GetAppIconEndPadding(); @@ -1330,7 +1333,9 @@ const int gap = (display_size_primary - icons_size) / 2; // Calculates paddings in view coordinates. - const gfx::Rect screen_bounds = GetBoundsInScreen(); + const gfx::Rect screen_bounds = + use_target_bounds ? GetShelf()->shelf_layout_manager()->GetHotseatBounds() + : GetBoundsInScreen(); const int before_padding = gap - GetShelf()->PrimaryAxisValue( screen_bounds.x() - display_bounds.x(), screen_bounds.y() - display_bounds.y());
diff --git a/ash/shelf/scrollable_shelf_view.h b/ash/shelf/scrollable_shelf_view.h index 746eb25f..3b46fe2 100644 --- a/ash/shelf/scrollable_shelf_view.h +++ b/ash/shelf/scrollable_shelf_view.h
@@ -257,8 +257,9 @@ // view bounds or target view bounds. gfx::Rect GetAvailableLocalBounds(bool use_target_bounds) const; - // Calculates padding for display centering alignment. - gfx::Insets CalculatePaddingForDisplayCentering() const; + // Calculates padding for display centering alignment depending on which view + // bounds are used: actual view bounds or target view bounds. + gfx::Insets CalculatePaddingForDisplayCentering(bool use_target_bounds) const; // Returns whether the received gesture event should be handled here. bool ShouldHandleGestures(const ui::GestureEvent& event);
diff --git a/ash/shelf/shelf_config.cc b/ash/shelf/shelf_config.cc index d5350f9..9c6b9ed 100644 --- a/ash/shelf/shelf_config.cc +++ b/ash/shelf/shelf_config.cc
@@ -304,20 +304,10 @@ AshColorProvider::AshColorMode::kDark); } - AshColorProvider::BaseLayerType layer_type; - if (!chromeos::switches::ShouldShowShelfHotseat()) { - layer_type = IsTabletMode() - ? AshColorProvider::BaseLayerType::kTransparent60 - : AshColorProvider::BaseLayerType::kTransparent74; - } else if (IsTabletMode()) { - layer_type = is_in_app() ? AshColorProvider::BaseLayerType::kTransparent90 - : AshColorProvider::BaseLayerType::kTransparent60; - } else { - layer_type = AshColorProvider::BaseLayerType::kTransparent74; - } - SkColor final_color = AshColorProvider::Get()->GetBaseLayerColor( - layer_type, AshColorProvider::AshColorMode::kDark); + IsTabletMode() ? AshColorProvider::BaseLayerType::kTransparent60 + : AshColorProvider::BaseLayerType::kTransparent74, + AshColorProvider::AshColorMode::kDark); return GetThemedColorFromWallpaper(final_color); }
diff --git a/ash/strings/ash_strings_af.xtb b/ash/strings/ash_strings_af.xtb index 52d95d9..8d7405f 100644 --- a/ash/strings/ash_strings_af.xtb +++ b/ash/strings/ash_strings_af.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Druk <ph name="KEYBOARD_SHORTCUT" /> om sleutelborduitleg te wissel.</translation> <translation id="2501920221385095727">Taaisleutels</translation> <translation id="2509468283778169019">HOOFLETTERSLOT is aan</translation> -<translation id="2517825809102302935">Skakel af vir vanaand</translation> <translation id="2519465031217098801">Aan</translation> <translation id="2542089167727451762">Tik op jou profielprent</translation> <translation id="255671100581129685">Die Google Assistent is nie in 'n publieke sessie beskikbaar nie.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Herbegin en stel terug</translation> <translation id="495046168593986294">Rollees op</translation> <translation id="4961318399572185831">Saai skerm uit</translation> -<translation id="5018302031617932556">Aandbeligting maak dit makliker om in dowwe lig na jou skerm te kyk en te lees. Tik om dit te verander.</translation> <translation id="5030687792513154421">Die tyd is om</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> het aan 'n nuwe foon gekoppel</translation> <translation id="5083553833479578423">Ontsluit meer Assistent-kenmerke.</translation>
diff --git a/ash/strings/ash_strings_am.xtb b/ash/strings/ash_strings_am.xtb index ec7775d..635d656 100644 --- a/ash/strings/ash_strings_am.xtb +++ b/ash/strings/ash_strings_am.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">የቁልፍ ሰሌዳ አቀማመጥን ለመቀየር <ph name="KEYBOARD_SHORTCUT" />ን ይጫኑ</translation> <translation id="2501920221385095727">ተጣባቂ ቁልፎች</translation> <translation id="2509468283778169019">CAPS LOCK በርቷል</translation> -<translation id="2517825809102302935">ለዛሬ ማታ አጥፋ</translation> <translation id="2519465031217098801">አብራ</translation> <translation id="2542089167727451762">የመገለጫ ምስልዎን መታ ያድርጉ</translation> <translation id="255671100581129685">የGoogle ረዳቱ በይፋዊ ክፍለ-ጊዜ ውስጥ አይገኝም።</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ዳግም ይጀምሩ እና ዳግም ያቀናብሩ</translation> <translation id="495046168593986294">ወደ ላይ ይሸብልሉ</translation> <translation id="4961318399572185831">የCast ማያ ገጽ</translation> -<translation id="5018302031617932556">የሌሊት ብርሃን በእርስዎ ማያ ገጽ ላይ መመልከትን ወይም በደብዛዛ ብርሃን ማንበብን ይበልጥ ቀላል ያደርገዋል። ይህን ለመለወጥ መታ ያድርጉ።</translation> <translation id="5030687792513154421">ሰዓት አልቋል</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ከአዲስ ስልክ ጋር ተገናኝቷል</translation> <translation id="5083553833479578423">ተጨማሪ የረዳት ባህሪያትን ያስከፍቱ።</translation>
diff --git a/ash/strings/ash_strings_ar.xtb b/ash/strings/ash_strings_ar.xtb index a91cf91..8491b15e 100644 --- a/ash/strings/ash_strings_ar.xtb +++ b/ash/strings/ash_strings_ar.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">انقر على <ph name="KEYBOARD_SHORTCUT" /> لتبديل تنسيق لوحة المفاتيح.</translation> <translation id="2501920221385095727">مفاتيح الثبات</translation> <translation id="2509468283778169019">مفتاح CAPS LOCK قيد التشغيل</translation> -<translation id="2517825809102302935">إيقاف الميزة لهذه الليلة</translation> <translation id="2519465031217098801">مفعّل</translation> <translation id="2542089167727451762">انقر على صورة الملف الشخصي.</translation> <translation id="255671100581129685">لا يتوفَّر "مساعد Google" في جلسة عامة.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">إعادة التشغيل وإعادة الضبط</translation> <translation id="495046168593986294">التمرير لأعلى</translation> <translation id="4961318399572185831">إرسال الشاشة</translation> -<translation id="5018302031617932556">تسهّل ميزة "الإضاءة الليلية" النظر إلى الشاشة أو القراءة في الإضاءة الخافتة. انقر لتغيير هذا الإعداد.</translation> <translation id="5030687792513154421">انتهى الوقت</translation> <translation id="5035236842988137213">الجهاز <ph name="DEVICE_NAME" /> متصل بهاتف جديد</translation> <translation id="5083553833479578423">الاستفادة من المزيد من ميزات "مساعد Google"</translation>
diff --git a/ash/strings/ash_strings_as.xtb b/ash/strings/ash_strings_as.xtb index 2cd666e6..f35841bee 100644 --- a/ash/strings/ash_strings_as.xtb +++ b/ash/strings/ash_strings_as.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">কীব'র্ডৰ লেইআউট সলনি কৰিবলৈ <ph name="KEYBOARD_SHORTCUT" /> টিপক।</translation> <translation id="2501920221385095727">ষ্টিকি কী</translation> <translation id="2509468283778169019">CAPS LOCK হৈ আছে</translation> -<translation id="2517825809102302935">আজি ৰাতিৰ বাবে অফ কৰক</translation> <translation id="2519465031217098801">অন আছে</translation> <translation id="2542089167727451762">আপোনাৰ প্ৰ’ফাইলৰ প্ৰতিচ্ছবিত টিপক</translation> <translation id="255671100581129685">ৰাজহুৱা ছেশ্বনত Google Assistant নাই।</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ৰিষ্টাৰ্ট কৰি ৰিছেট কৰক</translation> <translation id="495046168593986294">ওপৰলৈ স্ক্ৰল কৰক</translation> <translation id="4961318399572185831">স্ক্রীণ কাষ্ট কৰক</translation> -<translation id="5018302031617932556">ৰাতিৰ পোহৰে আপোনাৰ স্ক্ৰীনখনলৈ চোৱা অথবা কম পোহৰত পঢ়া সহজ কৰি তোলে। এইটো সলনি কৰিবলৈ টিপক।</translation> <translation id="5030687792513154421">সময় সীমা উকলিল</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" />ক এটা নতুন ডিভাইচত সংযোগ কৰা হ'ল</translation> <translation id="5083553833479578423">Assistantৰ অন্যান্য সুবিধাসমূহ ব্যৱহাৰ কৰক।</translation>
diff --git a/ash/strings/ash_strings_az.xtb b/ash/strings/ash_strings_az.xtb index 32211b3..2dbe066e 100644 --- a/ash/strings/ash_strings_az.xtb +++ b/ash/strings/ash_strings_az.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Klaviatura düzülüşünü dəyişmək üçün <ph name="KEYBOARD_SHORTCUT" /> süyməsinə klikləyin.</translation> <translation id="2501920221385095727">Əvəzedici açarlar</translation> <translation id="2509468283778169019">CAPS LOCK aktivdir</translation> -<translation id="2517825809102302935">Bu gecəlik söndürün</translation> <translation id="2519465031217098801">Aktiv</translation> <translation id="2542089167727451762">Profil şəklinizə toxunun</translation> <translation id="255671100581129685">Google Assistent ictimai sessiyada əlçatan deyil.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Yenidən başlayın və sıfırlayın</translation> <translation id="495046168593986294">Yuxarı sürüşdürün</translation> <translation id="4961318399572185831">Cast ekran</translation> -<translation id="5018302031617932556">Gecə İşığı zəif işıqda ekrana baxmağı və ya oxumağı asanlaşdırır. Bunu dəyişmək üçün toxunun.</translation> <translation id="5030687792513154421">Vaxt bitdi</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> yeni telefona qoşuldu</translation> <translation id="5083553833479578423">Daha çox Assistent funksiyalarını kiliddən çıxarın.</translation>
diff --git a/ash/strings/ash_strings_be.xtb b/ash/strings/ash_strings_be.xtb index 0ae6305..915ac5a 100644 --- a/ash/strings/ash_strings_be.xtb +++ b/ash/strings/ash_strings_be.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Каб пераключыць раскладку клавіятуры, націсніце <ph name="KEYBOARD_SHORTCUT" />.</translation> <translation id="2501920221385095727">Заліпанне клавіш</translation> <translation id="2509468283778169019">CAPS LOCK уключаны</translation> -<translation id="2517825809102302935">Выключыць на сённяшні вечар</translation> <translation id="2519465031217098801">Уключана</translation> <translation id="2542089167727451762">Націсніце відарыс профілю</translation> <translation id="255671100581129685">Памочнік Google недаступны ў агульнадаступным сеансе.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Перазапусціць і скінуць</translation> <translation id="495046168593986294">Прагартаць уверх</translation> <translation id="4961318399572185831">Трансляцыя экрана</translation> -<translation id="5018302031617932556">У начным рэжыме зручней глядзець на экран пры цьмяным асвятленні. Націсніце, каб змяніць рэжым.</translation> <translation id="5030687792513154421">Час выйшаў</translation> <translation id="5035236842988137213">Прылада <ph name="DEVICE_NAME" /> падключана да новага тэлефона</translation> <translation id="5083553833479578423">Адкрыйце больш функцый Памочніка.</translation>
diff --git a/ash/strings/ash_strings_bg.xtb b/ash/strings/ash_strings_bg.xtb index 42df3bde..664e2315 100644 --- a/ash/strings/ash_strings_bg.xtb +++ b/ash/strings/ash_strings_bg.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Натиснете <ph name="KEYBOARD_SHORTCUT" /> за превключване на клавиатурната подредба.</translation> <translation id="2501920221385095727">Оставащи клавиши</translation> <translation id="2509468283778169019">„CAPS LOCK“ е включен</translation> -<translation id="2517825809102302935">Изключване за тази вечер</translation> <translation id="2519465031217098801">Вкл.</translation> <translation id="2542089167727451762">Докоснете изображението на потребителския си профил</translation> <translation id="255671100581129685">Google Асистент не е налице по време на публична сесия.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Рестартиране и нулиране</translation> <translation id="495046168593986294">Превъртане нагоре</translation> <translation id="4961318399572185831">Предаване на екрана</translation> -<translation id="5018302031617932556">Функцията „Нощно осветление“ облекчава гледането на екрана и улеснява четенето при слаба светлина. Докоснете, за да промените настройките ѝ.</translation> <translation id="5030687792513154421">Времето свърши</translation> <translation id="5035236842988137213">Устройството <ph name="DEVICE_NAME" /> е свързано с нов телефон</translation> <translation id="5083553833479578423">Отключете още функции на Асистент.</translation>
diff --git a/ash/strings/ash_strings_bn.xtb b/ash/strings/ash_strings_bn.xtb index fd86651..5358c6f 100644 --- a/ash/strings/ash_strings_bn.xtb +++ b/ash/strings/ash_strings_bn.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">কীবোর্ড লে-আউট পরিবর্তন করতে <ph name="KEYBOARD_SHORTCUT" /> টিপুন।</translation> <translation id="2501920221385095727">স্টিকি কীজ</translation> <translation id="2509468283778169019">CAPS LOCK চালু</translation> -<translation id="2517825809102302935">আজ রাতের জন্য বন্ধ করুন</translation> <translation id="2519465031217098801">চালু করা আছে</translation> <translation id="2542089167727451762">আপনার প্রোফাইল ছবিতে ট্যাপ করুন</translation> <translation id="255671100581129685">সর্বজনীন সেশনে Google অ্যাসিস্ট্যান্ট উপলভ্য নয়।</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">রিস্টার্ট করুন এবং রিসেট করুন</translation> <translation id="495046168593986294">উপরের দিকে স্ক্রল করুন</translation> <translation id="4961318399572185831">স্ক্রিন কাস্ট করুন</translation> -<translation id="5018302031617932556">নাইট লাইটের জন্য স্ক্রিনের দিকে স্বচ্ছন্দে তাকানো যায় বা কম আলোতে পড়া যায়। এটি পরিবর্তন করতে ট্যাপ করুন।</translation> <translation id="5030687792513154421">সময় শেষ</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" />টি নতুন ফোনে কানেক্ট করা হয়েছে</translation> <translation id="5083553833479578423">অ্যাসিস্ট্যান্ট-এর আরও বৈশিষ্ট্য আনলক করুন।</translation>
diff --git a/ash/strings/ash_strings_bs.xtb b/ash/strings/ash_strings_bs.xtb index 9e04858..9cdfe90 100644 --- a/ash/strings/ash_strings_bs.xtb +++ b/ash/strings/ash_strings_bs.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Pritisnite <ph name="KEYBOARD_SHORTCUT" /> da promijenite raspored tastature.</translation> <translation id="2501920221385095727">Ljepljive tipke</translation> <translation id="2509468283778169019">Uključena su velika slova</translation> -<translation id="2517825809102302935">Isključi za večeras</translation> <translation id="2519465031217098801">Uključeno</translation> <translation id="2542089167727451762">Dodirnite sliku profila</translation> <translation id="255671100581129685">Google Asistent nije dostupan u javnoj sesiji.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Ponovo pokreni i vrati na zadano</translation> <translation id="495046168593986294">Klizni prema gore</translation> <translation id="4961318399572185831">Emitiraj ekran</translation> -<translation id="5018302031617932556">Noćno svjetlo omogućava lakše gledanje u ekran ili čitanje pod prigušenim svjetlom. Dodirnite da promijenite.</translation> <translation id="5030687792513154421">Vrijeme je isteklo</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> je povezan na novi telefon</translation> <translation id="5083553833479578423">Otključajte više funkcija Asistenta.</translation>
diff --git a/ash/strings/ash_strings_ca.xtb b/ash/strings/ash_strings_ca.xtb index 6afa1fe..99a8ecc 100644 --- a/ash/strings/ash_strings_ca.xtb +++ b/ash/strings/ash_strings_ca.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Prem <ph name="KEYBOARD_SHORTCUT" /> per canviar el disseny del teclat.</translation> <translation id="2501920221385095727">Tecles permanents</translation> <translation id="2509468283778169019">BLOQ MAJ està activat.</translation> -<translation id="2517825809102302935">Desactiva aquesta nit</translation> <translation id="2519465031217098801">Activat</translation> <translation id="2542089167727451762">Toca la teva imatge de perfil</translation> <translation id="255671100581129685">L'Assistent de Google no està disponible a les sessions públiques.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Reinicia i restableix</translation> <translation id="495046168593986294">Desplaça't cap amunt</translation> <translation id="4961318399572185831">Emet la pantalla</translation> -<translation id="5018302031617932556">Amb la funció Llum nocturna, és més fàcil mirar la pantalla i llegir-hi amb poca llum. Toca per canviar-ho.</translation> <translation id="5030687792513154421">S'ha acabat el temps</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> s'ha connectat a un altre telèfon</translation> <translation id="5083553833479578423">Desbloqueja més funcions de l'Assistent.</translation>
diff --git a/ash/strings/ash_strings_cs.xtb b/ash/strings/ash_strings_cs.xtb index 456cff81..42d885a 100644 --- a/ash/strings/ash_strings_cs.xtb +++ b/ash/strings/ash_strings_cs.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Rozložení klávesnice změníte stisknutím kláves <ph name="KEYBOARD_SHORTCUT" /></translation> <translation id="2501920221385095727">Jedním prstem</translation> <translation id="2509468283778169019">CAPS LOCK je zapnutý</translation> -<translation id="2517825809102302935">Pro dnešní noc vypnout</translation> <translation id="2519465031217098801">Zapnuto</translation> <translation id="2542089167727451762">Klepněte na profilovou fotku</translation> <translation id="255671100581129685">Asistent Google není ve veřejné relaci k dispozici.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Restartovat a resetovat</translation> <translation id="495046168593986294">Posunout nahoru</translation> <translation id="4961318399572185831">Odesílání obrazovky</translation> -<translation id="5018302031617932556">Noční režim usnadňuje sledování obrazovky nebo čtení při tlumeném osvětlení. Toto nastavení změníte klepnutím.</translation> <translation id="5030687792513154421">Čas vypršel</translation> <translation id="5035236842988137213">Zařízení <ph name="DEVICE_NAME" /> je připojeno k novému telefonu</translation> <translation id="5083553833479578423">Odemkněte další funkce Asistenta.</translation>
diff --git a/ash/strings/ash_strings_da.xtb b/ash/strings/ash_strings_da.xtb index 3d21e5e..86a1a81 100644 --- a/ash/strings/ash_strings_da.xtb +++ b/ash/strings/ash_strings_da.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Tryk på <ph name="KEYBOARD_SHORTCUT" /> for at skifte tastaturlayout.</translation> <translation id="2501920221385095727">Træge taster</translation> <translation id="2509468283778169019">CAPS LOCK er slået til</translation> -<translation id="2517825809102302935">Deaktiver i aften</translation> <translation id="2519465031217098801">Til</translation> <translation id="2542089167727451762">Tryk på dit profilbillede</translation> <translation id="255671100581129685">Google Assistent er ikke tilgængelig i en offentlig session.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Genstart og nulstil</translation> <translation id="495046168593986294">Rul op</translation> <translation id="4961318399572185831">Cast skærm</translation> -<translation id="5018302031617932556">Nattelys gør det mere behageligt at kigge på din skærm eller læse på den i svag belysning. Tryk for at ændre dette.</translation> <translation id="5030687792513154421">Tiden er gået</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> har oprettet forbindelse til en ny telefon</translation> <translation id="5083553833479578423">Få adgang til endnu flere Assistent-funktioner.</translation>
diff --git a/ash/strings/ash_strings_de.xtb b/ash/strings/ash_strings_de.xtb index 4b242287..547e490 100644 --- a/ash/strings/ash_strings_de.xtb +++ b/ash/strings/ash_strings_de.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Drücken Sie <ph name="KEYBOARD_SHORTCUT" />, um das Tastaturlayout zu ändern.</translation> <translation id="2501920221385095727">Sticky Keys</translation> <translation id="2509468283778169019">Feststelltaste An</translation> -<translation id="2517825809102302935">Für heute Abend deaktiveren</translation> <translation id="2519465031217098801">An</translation> <translation id="2542089167727451762">Tippen Sie auf Ihr Profilbild</translation> <translation id="255671100581129685">In öffentlichen Sitzungen ist Google Assistant nicht verfügbar.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Neu starten und zurücksetzen</translation> <translation id="495046168593986294">Nach oben scrollen</translation> <translation id="4961318399572185831">Bildschirmübertragung</translation> -<translation id="5018302031617932556">Mit der Funktion "Nachtlicht" ist der Bildschirm bei schwachem Licht nicht störend hell und das Lesen fällt leichter. Zum Ändern hier tippen.</translation> <translation id="5030687792513154421">Die Zeit ist abgelaufen</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ist mit einem neuen Smartphone verbunden</translation> <translation id="5083553833479578423">Möchten Sie weitere Assistant-Funktionen freischalten?</translation>
diff --git a/ash/strings/ash_strings_el.xtb b/ash/strings/ash_strings_el.xtb index e3563df..aca0d65 100644 --- a/ash/strings/ash_strings_el.xtb +++ b/ash/strings/ash_strings_el.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Πατήστε <ph name="KEYBOARD_SHORTCUT" />, για να αλλάξετε διάταξη πληκτρολογίου.</translation> <translation id="2501920221385095727">Σταθερά πλήκτρα</translation> <translation id="2509468283778169019">Το CAPS LOCK είναι ενεργοποιημένο</translation> -<translation id="2517825809102302935">Απενεργοποίηση για απόψε</translation> <translation id="2519465031217098801">Ενεργό</translation> <translation id="2542089167727451762">Πατήστε την εικόνα προφίλ σας</translation> <translation id="255671100581129685">Ο Βοηθός Google δεν διατίθεται σε δημόσιες περιόδους λειτουργίας.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Επανεκκίνηση και επαναφορά</translation> <translation id="495046168593986294">Κύλιση προς τα επάνω</translation> <translation id="4961318399572185831">Μετάδοση οθόνης</translation> -<translation id="5018302031617932556">Ο Νυχτερινός φωτισμός διευκολύνει το θέαση της οθόνης ή την ανάγνωση σε συνθήκες χαμηλού φωτισμού. Πατήστε, για να αλλάξετε τη ρύθμιση.</translation> <translation id="5030687792513154421">Τέλος χρόνου</translation> <translation id="5035236842988137213">Η συσκευή <ph name="DEVICE_NAME" /> συνδέθηκε σε ένα νέο τηλέφωνο</translation> <translation id="5083553833479578423">Ξεκλειδώστε περισσότερες λειτουργίες του Βοηθού.</translation>
diff --git a/ash/strings/ash_strings_en-GB.xtb b/ash/strings/ash_strings_en-GB.xtb index 81b29594..e759a110 100644 --- a/ash/strings/ash_strings_en-GB.xtb +++ b/ash/strings/ash_strings_en-GB.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Hit <ph name="KEYBOARD_SHORTCUT" /> to switch keyboard layout.</translation> <translation id="2501920221385095727">Sticky keys</translation> <translation id="2509468283778169019">CAPS LOCK is on</translation> -<translation id="2517825809102302935">Turn off for tonight</translation> <translation id="2519465031217098801">On</translation> <translation id="2542089167727451762">Tap your profile image</translation> <translation id="255671100581129685">The Google Assistant is not available in a public session.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Restart and reset</translation> <translation id="495046168593986294">Scroll up</translation> <translation id="4961318399572185831">Cast screen</translation> -<translation id="5018302031617932556">Night Light makes it easier to look at your screen or read in dim light. Tap to change this.</translation> <translation id="5030687792513154421">Time is up</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> connected to a new phone</translation> <translation id="5083553833479578423">Unlock more Assistant features.</translation>
diff --git a/ash/strings/ash_strings_es-419.xtb b/ash/strings/ash_strings_es-419.xtb index f5c3b7f..c1cf4a5 100644 --- a/ash/strings/ash_strings_es-419.xtb +++ b/ash/strings/ash_strings_es-419.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Presiona <ph name="KEYBOARD_SHORTCUT" /> para cambiar de diseño de teclado.</translation> <translation id="2501920221385095727">Teclas especiales</translation> <translation id="2509468283778169019">BLOQ MAYÚS está activado.</translation> -<translation id="2517825809102302935">Desactivar esta noche</translation> <translation id="2519465031217098801">Sí</translation> <translation id="2542089167727451762">Presiona tu imagen de perfil</translation> <translation id="255671100581129685">El Asistente de Google no está disponible en una sesión pública.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Reiniciar y restablecer</translation> <translation id="495046168593986294">Desplazar hacia arriba</translation> <translation id="4961318399572185831">Transmitir pantalla</translation> -<translation id="5018302031617932556">La Luz nocturna te permite ver la pantalla o leer mejor con luz tenue. Presiona para cambiarla.</translation> <translation id="5030687792513154421">Se acabó el tiempo</translation> <translation id="5035236842988137213">Se conectó el dispositivo <ph name="DEVICE_NAME" /> a un teléfono nuevo</translation> <translation id="5083553833479578423">Desbloquea más funciones del Asistente.</translation>
diff --git a/ash/strings/ash_strings_es.xtb b/ash/strings/ash_strings_es.xtb index 6ebddd8..532bcfb1 100644 --- a/ash/strings/ash_strings_es.xtb +++ b/ash/strings/ash_strings_es.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Pulsa <ph name="KEYBOARD_SHORTCUT" /> para cambiar el diseño del teclado.</translation> <translation id="2501920221385095727">Teclas persistentes</translation> <translation id="2509468283778169019">Bloqueo de mayúsculas activado</translation> -<translation id="2517825809102302935">Desactivar esta noche</translation> <translation id="2519465031217098801">Activado</translation> <translation id="2542089167727451762">Toca tu imagen de perfil</translation> <translation id="255671100581129685">El Asistente de Google no está disponible en las sesiones públicas.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Reiniciar y restablecer</translation> <translation id="495046168593986294">Desplazarse hacia arriba</translation> <translation id="4961318399572185831">Enviar pantalla</translation> -<translation id="5018302031617932556">Con la luz nocturna, resulta más fácil mirar la pantalla o leer con poca luz. Toca aquí para cambiar este ajuste.</translation> <translation id="5030687792513154421">Se ha agotado el tiempo</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> está conectado a un nuevo teléfono</translation> <translation id="5083553833479578423">Descubre más funciones del Asistente.</translation>
diff --git a/ash/strings/ash_strings_et.xtb b/ash/strings/ash_strings_et.xtb index d17a28d..f485953 100644 --- a/ash/strings/ash_strings_et.xtb +++ b/ash/strings/ash_strings_et.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Klaviatuuripaigutuse muutmiseks vajutage klahvikombinatsiooni <ph name="KEYBOARD_SHORTCUT" />.</translation> <translation id="2501920221385095727">Nakkeklahvid</translation> <translation id="2509468283778169019">SUURTÄHELUKK on sisse lülitatud</translation> -<translation id="2517825809102302935">Lülita tänaseks õhtuks välja</translation> <translation id="2519465031217098801">Sees</translation> <translation id="2542089167727451762">Puudutage oma profiilipilti</translation> <translation id="255671100581129685">Google'i assistent ei ole avalikus seansis saadaval.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Taaskäivita ja lähtesta</translation> <translation id="495046168593986294">Keri üles</translation> <translation id="4961318399572185831">Ekraani ülekandmine</translation> -<translation id="5018302031617932556">Öövalgus muudab hämaras valguses ekraani vaatamise ja lugemise lihtsamaks. Puudutage selle muutmiseks.</translation> <translation id="5030687792513154421">Aeg on läbi</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ühendati uue telefoniga</translation> <translation id="5083553833479578423">Avage rohkem assistendi funktsioone.</translation>
diff --git a/ash/strings/ash_strings_eu.xtb b/ash/strings/ash_strings_eu.xtb index d0b856a..a5b01f45 100644 --- a/ash/strings/ash_strings_eu.xtb +++ b/ash/strings/ash_strings_eu.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Teklatuaren diseinua aldatzeko, sakatu <ph name="KEYBOARD_SHORTCUT" />.</translation> <translation id="2501920221385095727">Tekla itsaskorrak</translation> <translation id="2509468283778169019">BLOK MAIUS aktibatuta dago</translation> -<translation id="2517825809102302935">Desaktibatu gaur gauerako</translation> <translation id="2519465031217098801">Aktibatuta</translation> <translation id="2542089167727451762">Sakatu profileko irudia</translation> <translation id="255671100581129685">Google-ren Laguntzailea ez dago erabilgarri saio publikoetan.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Berrabiarazi eta berrezarri</translation> <translation id="495046168593986294">Egin gora</translation> <translation id="4961318399572185831">Igorri pantaila</translation> -<translation id="5018302031617932556">Gaueko argia eginbideari esker, ez zaizu egingo horren nekagarria argi gutxiko inguruetan pantailari begira egotea. Sakatu hau aldatzeko.</translation> <translation id="5030687792513154421">Amaitu da denbora</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> beste telefono batekin konektatu da</translation> <translation id="5083553833479578423">Lortu Laguntzailea eginbidearen aukera gehiago.</translation>
diff --git a/ash/strings/ash_strings_fa.xtb b/ash/strings/ash_strings_fa.xtb index dcc48da..a71b468 100644 --- a/ash/strings/ash_strings_fa.xtb +++ b/ash/strings/ash_strings_fa.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">برای تغییر طرحبندی صفحهکلید، <ph name="KEYBOARD_SHORTCUT" /> را فشار دهید.</translation> <translation id="2501920221385095727">کلیدهای چسبان</translation> <translation id="2509468283778169019">CAPS LOCK روشن است</translation> -<translation id="2517825809102302935">امشب خاموش شود</translation> <translation id="2519465031217098801">روشن</translation> <translation id="2542089167727451762">روی تصویر نمایه ضربه بزنید</translation> <translation id="255671100581129685">«دستیار Google» در جلسه عمومی در دسترس نیست.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">بازراهاندازی و بازنشانی</translation> <translation id="495046168593986294">پیمایش به بالا</translation> <translation id="4961318399572185831">فرستادن صفحه</translation> -<translation id="5018302031617932556">بااستفاده از «نور شب»، نگاه کردن به صفحهنمایش یا خواندن در نور کم آسانتر میشود. برای تغییر ضربه بزنید.</translation> <translation id="5030687792513154421">وقت تمام شد</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> به تلفن جدیدی متصل است</translation> <translation id="5083553833479578423">باز کردن قفل ویژگیهای بیشتری از «دستیار».</translation>
diff --git a/ash/strings/ash_strings_fi.xtb b/ash/strings/ash_strings_fi.xtb index 560f490..dd64d82 100644 --- a/ash/strings/ash_strings_fi.xtb +++ b/ash/strings/ash_strings_fi.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Paina <ph name="KEYBOARD_SHORTCUT" /> vaihtaaksesi näppäimistöasettelua.</translation> <translation id="2501920221385095727">Päälle jäävät näppäimet</translation> <translation id="2509468283778169019">CAPS LOCK on päällä</translation> -<translation id="2517825809102302935">Poista päältä täksi yöksi</translation> <translation id="2519465031217098801">Päällä</translation> <translation id="2542089167727451762">Napauta profiilikuvaasi</translation> <translation id="255671100581129685">Google Assistantia ei voi käyttää julkisella käyttökerralla.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Käynnistä uudelleen ja palauta</translation> <translation id="495046168593986294">Vieritä ylös</translation> <translation id="4961318399572185831">Suoratoista näyttö</translation> -<translation id="5018302031617932556">Yövalo helpottaa näytön katsomista ja lukemista hämärässä. Muuta tätä napauttamalla.</translation> <translation id="5030687792513154421">Aika on lopussa</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> yhdistetty uuteen puhelimeen</translation> <translation id="5083553833479578423">Käytä lisää Assistantin ominaisuuksia.</translation>
diff --git a/ash/strings/ash_strings_fil.xtb b/ash/strings/ash_strings_fil.xtb index 37b22ec..50896700 100644 --- a/ash/strings/ash_strings_fil.xtb +++ b/ash/strings/ash_strings_fil.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Pindutin ang <ph name="KEYBOARD_SHORTCUT" /> upang palitan ang layout ng keyboard.</translation> <translation id="2501920221385095727">Mga sticky key</translation> <translation id="2509468283778169019">Naka-on ang CAPS LOCK</translation> -<translation id="2517825809102302935">I-off para ngayong gabi</translation> <translation id="2519465031217098801">Naka-on</translation> <translation id="2542089167727451762">I-tap ang iyong larawan sa profile</translation> <translation id="255671100581129685">Hindi available ang Google Assistant sa isang pampublikong session.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">I-restart at i-reset</translation> <translation id="495046168593986294">Mag-scroll pataas</translation> <translation id="4961318399572185831">I-cast ang screen</translation> -<translation id="5018302031617932556">Mas pinapadali ng Night Light na tumingin sa iyong screen o magbasa sa dilim. I-tap para baguhin ito.</translation> <translation id="5030687792513154421">Tapos na ang oras</translation> <translation id="5035236842988137213">Kumonekta ang <ph name="DEVICE_NAME" /> sa isang bagong telepono</translation> <translation id="5083553833479578423">Mag-unlock ng higit pang feature ng Assistant.</translation>
diff --git a/ash/strings/ash_strings_fr-CA.xtb b/ash/strings/ash_strings_fr-CA.xtb index e44a513f..97db5f38 100644 --- a/ash/strings/ash_strings_fr-CA.xtb +++ b/ash/strings/ash_strings_fr-CA.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Appuyez sur <ph name="KEYBOARD_SHORTCUT" /> pour changer la disposition du clavier.</translation> <translation id="2501920221385095727">Touches rémanentes</translation> <translation id="2509468283778169019">Touche VERR MAJ activée</translation> -<translation id="2517825809102302935">Désactiver pour ce soir</translation> <translation id="2519465031217098801">Activé</translation> <translation id="2542089167727451762">Touchez l'image de votre profil</translation> <translation id="255671100581129685">L'Assistant Google n'est pas disponible dans une session publique.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Redémarrer et réinitialiser</translation> <translation id="495046168593986294">Faire défiler vers le haut</translation> <translation id="4961318399572185831">Diffuser un écran</translation> -<translation id="5018302031617932556">Le mode Éclairage nocturne permet de regarder l'écran plus facilement lorsque l'éclairage est faible. Touchez pour changer ce réglage.</translation> <translation id="5030687792513154421">Le temps est écoulé</translation> <translation id="5035236842988137213">L'appareil <ph name="DEVICE_NAME" /> est connecté à un nouveau téléphone</translation> <translation id="5083553833479578423">Déverrouillez davantage de fonctionnalités de l'Assistant Google.</translation>
diff --git a/ash/strings/ash_strings_fr.xtb b/ash/strings/ash_strings_fr.xtb index aae07ec2..ad14ac9 100644 --- a/ash/strings/ash_strings_fr.xtb +++ b/ash/strings/ash_strings_fr.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Appuyez sur <ph name="KEYBOARD_SHORTCUT" /> pour changer la disposition du clavier.</translation> <translation id="2501920221385095727">Touches persistantes</translation> <translation id="2509468283778169019">Touche VERR MAJ activée</translation> -<translation id="2517825809102302935">Désactiver pour cette nuit</translation> <translation id="2519465031217098801">Activé</translation> <translation id="2542089167727451762">Appuyez sur votre image de profil</translation> <translation id="255671100581129685">L'Assistant Google n'est pas disponible dans une session publique.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Redémarrer et réinitialiser</translation> <translation id="495046168593986294">Faire défiler vers le haut</translation> <translation id="4961318399572185831">Caster l'écran</translation> -<translation id="5018302031617932556">Cette fonctionnalité facilite la lecture à l'écran lorsque l'éclairage est faible. Appuyez pour modifier ce paramètre.</translation> <translation id="5030687792513154421">Temps écoulé</translation> <translation id="5035236842988137213">L'appareil <ph name="DEVICE_NAME" /> est associé à un nouveau téléphone</translation> <translation id="5083553833479578423">Déverrouiller plus de fonctionnalités de l'Assistant.</translation>
diff --git a/ash/strings/ash_strings_gl.xtb b/ash/strings/ash_strings_gl.xtb index 3bb8841e..ed74822 100644 --- a/ash/strings/ash_strings_gl.xtb +++ b/ash/strings/ash_strings_gl.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Para cambiar o deseño de teclado, preme <ph name="KEYBOARD_SHORTCUT" />.</translation> <translation id="2501920221385095727">Teclas presas</translation> <translation id="2509468283778169019">Bloqueo de maiúsculas activado</translation> -<translation id="2517825809102302935">Desactivar esta noite</translation> <translation id="2519465031217098801">Si</translation> <translation id="2542089167727451762">Toca a imaxe do teu perfil</translation> <translation id="255671100581129685">O Asistente de Google non está dispoñible cando se utiliza unha sesión pública.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Reiniciar e restablecer</translation> <translation id="495046168593986294">Desprazarse cara arriba</translation> <translation id="4961318399572185831">Enviar pantalla</translation> -<translation id="5018302031617932556">Luz nocturna fai que sexa máis fácil mirar a pantalla ou ler con pouca luz. Toca para cambiar esta opción.</translation> <translation id="5030687792513154421">Rematou o tempo</translation> <translation id="5035236842988137213">O <ph name="DEVICE_NAME" /> está conectado a un novo teléfono</translation> <translation id="5083553833479578423">Desbloquea máis funcións do Asistente.</translation>
diff --git a/ash/strings/ash_strings_gu.xtb b/ash/strings/ash_strings_gu.xtb index 4740e4b..12f0a5e 100644 --- a/ash/strings/ash_strings_gu.xtb +++ b/ash/strings/ash_strings_gu.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">કીબોર્ડ લેઆઉટ સ્વિચ કરવા માટે <ph name="KEYBOARD_SHORTCUT" />ને દબાવો.</translation> <translation id="2501920221385095727">સ્ટિકી કી</translation> <translation id="2509468283778169019">CAPS LOCK ચાલુ છે</translation> -<translation id="2517825809102302935">આજ રાત્રિ પૂરતું બંધ કરો</translation> <translation id="2519465031217098801">ચાલુ</translation> <translation id="2542089167727451762">તમારા પ્રોફાઇલ ફોટા પર ટૅપ કરો</translation> <translation id="255671100581129685">જાહેર સત્રમાં Google આસિસ્ટંટ ઉપલબ્ધ હોતું નથી.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ફરી શરૂ કરો અને રીસેટ કરો</translation> <translation id="495046168593986294">ઉપર સ્ક્રોલ કરો</translation> <translation id="4961318399572185831">સ્ક્રીનને કાસ્ટ કરો</translation> -<translation id="5018302031617932556">રાત્રિ પ્રકાશથી તમે તમારી સ્ક્રીનને સરળતાથી જોઈ શકો છો અથવા ઓછા પ્રકાશમાં વાંચી શકો છો. આને બદલવા માટે ટૅપ કરો.</translation> <translation id="5030687792513154421">સમય પૂરો થયો</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" />, નવા ફોન સાથે કનેક્ટ થયું</translation> <translation id="5083553833479578423">આસિસ્ટંટની વધુ સુવિધાઓને અનલૉક કરો.</translation>
diff --git a/ash/strings/ash_strings_hi.xtb b/ash/strings/ash_strings_hi.xtb index 0b19d2b..6dfb9af 100644 --- a/ash/strings/ash_strings_hi.xtb +++ b/ash/strings/ash_strings_hi.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">कीबोर्ड लेआउट स्विच करने के लिए <ph name="KEYBOARD_SHORTCUT" /> दबाएं.</translation> <translation id="2501920221385095727">स्टिकी बटन</translation> <translation id="2509468283778169019">CAPS LOCK चालू है</translation> -<translation id="2517825809102302935">आज रात के लिए बंद करें</translation> <translation id="2519465031217098801">चालू है</translation> <translation id="2542089167727451762">अपनी प्रोफ़ाइल फ़ोटो पर टैप करें</translation> <translation id="255671100581129685">सार्वजनिक सत्र में Google Assistant उपलब्ध नहीं है.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">रीस्टार्ट करें और रीसेट करें</translation> <translation id="495046168593986294">ऊपर स्क्रोल करें</translation> <translation id="4961318399572185831">स्क्रीन कास्ट करें</translation> -<translation id="5018302031617932556">'नाइट लाइट' की मदद से कम रोशनी में स्क्रीन को देखना और पढ़ना आसान हो जाता है. इसे बदलने के लिए टैप करें.</translation> <translation id="5030687792513154421">समय पूरा हो गया</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> एक नए फ़ोन से कनेक्ट हो गया है</translation> <translation id="5083553833479578423">Assistant की और भी सुविधाओं के बारे में जानें.</translation>
diff --git a/ash/strings/ash_strings_hr.xtb b/ash/strings/ash_strings_hr.xtb index ff96bf3..72bac824 100644 --- a/ash/strings/ash_strings_hr.xtb +++ b/ash/strings/ash_strings_hr.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Pritisnite <ph name="KEYBOARD_SHORTCUT" /> da biste promijenili raspored tipkovnice.</translation> <translation id="2501920221385095727">Ljepljive tipke</translation> <translation id="2509468283778169019">Opcija CAPS LOCK uključena</translation> -<translation id="2517825809102302935">Isključi za noćas</translation> <translation id="2519465031217098801">Uključeno</translation> <translation id="2542089167727451762">Dodirnite svoju profilnu sliku</translation> <translation id="255671100581129685">Google asistent nije dostupan u javnoj sesiji.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Ponovo pokreni i vrati na prethodno</translation> <translation id="495046168593986294">Pomakni prema gore</translation> <translation id="4961318399572185831">Emitiranje zaslona</translation> -<translation id="5018302031617932556">Noćno svjetlo olakšava gledanje zaslona ili čitanje pri slabom svjetlu. Dodirnite da biste to promijenili.</translation> <translation id="5030687792513154421">Vrijeme je isteklo</translation> <translation id="5035236842988137213">Uređaj <ph name="DEVICE_NAME" /> povezan je s novim telefonom</translation> <translation id="5083553833479578423">Otključajte više značajki Asistenta.</translation>
diff --git a/ash/strings/ash_strings_hu.xtb b/ash/strings/ash_strings_hu.xtb index d6f884b..314808deed 100644 --- a/ash/strings/ash_strings_hu.xtb +++ b/ash/strings/ash_strings_hu.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">A billentyűzetkiosztás átváltásához nyomja meg a(z) <ph name="KEYBOARD_SHORTCUT" /> billentyűparancsot.</translation> <translation id="2501920221385095727">Beragadó billentyűk</translation> <translation id="2509468283778169019">A CAPS LOCK be van kapcsolva</translation> -<translation id="2517825809102302935">Kikapcsolás ma estére</translation> <translation id="2519465031217098801">Be</translation> <translation id="2542089167727451762">Koppintson a profilképre</translation> <translation id="255671100581129685">A Google Segéd nem áll rendelkezésre nyilvános munkamenetben.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Újraindítás és visszaállítás</translation> <translation id="495046168593986294">Görgetés felfelé</translation> <translation id="4961318399572185831">Képernyő átküldése</translation> -<translation id="5018302031617932556">Az Éjszakai fény funkció kellemesebbé teszi a képernyő nézését és az olvasást gyenge fény mellett Koppintson a módosításához.</translation> <translation id="5030687792513154421">Lejárt az idő</translation> <translation id="5035236842988137213">A(z) <ph name="DEVICE_NAME" /> új telefonhoz csatlakozott</translation> <translation id="5083553833479578423">Hozzáférés a Segéd további funkcióihoz</translation>
diff --git a/ash/strings/ash_strings_hy.xtb b/ash/strings/ash_strings_hy.xtb index 461e146..63e90dd2 100644 --- a/ash/strings/ash_strings_hy.xtb +++ b/ash/strings/ash_strings_hy.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Ստեղնաշարի դասավորությունը փոխելու համար սեղմեք <ph name="KEYBOARD_SHORTCUT" />։</translation> <translation id="2501920221385095727">Կպչուն ստեղներ</translation> <translation id="2509468283778169019">CAPS LOCK-ը միացված է</translation> -<translation id="2517825809102302935">Անջատել այսօր</translation> <translation id="2519465031217098801">Միացված է</translation> <translation id="2542089167727451762">Հպեք ձեր պրոֆիլի նկարին</translation> <translation id="255671100581129685">Google Օգնականը հասանելի չէ հանրային աշխատաշրջանում։</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Վերագործարկել և վերակայել</translation> <translation id="495046168593986294">Ոլորել վեր</translation> <translation id="4961318399572185831">Էկրանի հեռարձակում</translation> -<translation id="5018302031617932556">Գիշերային ռեժիմը թույլ է տալիս ավելի հանգիստ նայել էկրանին և կարդալ թույլ լուսավորության պայմաններում։ Հպեք՝ այս կարգավորումը փոխելու համար։</translation> <translation id="5030687792513154421">Ժամանակը սպառվեց</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> սարքը կապվեց նոր հեռախոսի հետ</translation> <translation id="5083553833479578423">Օգտվեք Օգնականի այլ գործառույթներից</translation>
diff --git a/ash/strings/ash_strings_id.xtb b/ash/strings/ash_strings_id.xtb index ae5f65c..784b9554e 100644 --- a/ash/strings/ash_strings_id.xtb +++ b/ash/strings/ash_strings_id.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Tekan <ph name="KEYBOARD_SHORTCUT" /> untuk mengganti tata letak keyboard.</translation> <translation id="2501920221385095727">Tombol sticky</translation> <translation id="2509468283778169019">CAPS LOCK aktif</translation> -<translation id="2517825809102302935">Nonaktifkan untuk malam ini</translation> <translation id="2519465031217098801">Aktif</translation> <translation id="2542089167727451762">Ketuk gambar profil Anda</translation> <translation id="255671100581129685">Asisten Google tidak tersedia dalam sesi publik.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Mulai ulang dan setel ulang</translation> <translation id="495046168593986294">Scroll ke atas</translation> <translation id="4961318399572185831">Transmisikan layar</translation> -<translation id="5018302031617932556">Cahaya Malam memudahkan Anda melihat layar atau membaca saat cahaya redup. Ketuk untuk mengubahnya.</translation> <translation id="5030687792513154421">Waktu habis</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> terhubung ke ponsel baru</translation> <translation id="5083553833479578423">Dapatkan lebih banyak fitur Asisten.</translation>
diff --git a/ash/strings/ash_strings_is.xtb b/ash/strings/ash_strings_is.xtb index 23bfe10..dd9bad9b 100644 --- a/ash/strings/ash_strings_is.xtb +++ b/ash/strings/ash_strings_is.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Ýttu á <ph name="KEYBOARD_SHORTCUT" /> til að skipta um lyklaskipan.</translation> <translation id="2501920221385095727">Festilyklar</translation> <translation id="2509468283778169019">Hástafalás er á</translation> -<translation id="2517825809102302935">Slökkva á þessu í kvöld</translation> <translation id="2519465031217098801">Kveikt</translation> <translation id="2542089167727451762">Ýttu á prófílmyndina þína</translation> <translation id="255671100581129685">Google hjálparinn er ekki í boði í opinberri lotu.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Endurræsa og endurstilla</translation> <translation id="495046168593986294">Fletta upp</translation> <translation id="4961318399572185831">Senda út skjá</translation> -<translation id="5018302031617932556">Næturljós auðveldar þér að horfa á skjáinn og lesa af honum í lítilli birtu. Ýttu til að breyta þessu.</translation> <translation id="5030687792513154421">Nú er tíminn á þrotum</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> tengdist nýjum síma</translation> <translation id="5083553833479578423">Opnaðu fyrir fleiri eiginleika hjálparans.</translation>
diff --git a/ash/strings/ash_strings_it.xtb b/ash/strings/ash_strings_it.xtb index 2d4013f7..0b7b745 100644 --- a/ash/strings/ash_strings_it.xtb +++ b/ash/strings/ash_strings_it.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Premi <ph name="KEYBOARD_SHORTCUT" /> per cambiare il layout della tastiera.</translation> <translation id="2501920221385095727">Tasti permanenti</translation> <translation id="2509468283778169019">BLOC MAIUSC è attivo</translation> -<translation id="2517825809102302935">Disattiva per stanotte</translation> <translation id="2519465031217098801">On</translation> <translation id="2542089167727451762">Tocca la tua immagine del profilo</translation> <translation id="255671100581129685">L'Assistente Google non è disponibile in una sessione pubblica.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Riavvia e reimposta</translation> <translation id="495046168593986294">Scorri verso l'alto</translation> <translation id="4961318399572185831">Trasmetti schermo</translation> -<translation id="5018302031617932556">Con la funzione Luminosità notturna, potrai guardare lo schermo senza sforzare la vista o leggere in condizioni di luce attenuata. Tocca per modificare.</translation> <translation id="5030687792513154421">Tempo scaduto</translation> <translation id="5035236842988137213">Il dispositivo <ph name="DEVICE_NAME" /> si è connesso a un nuovo telefono</translation> <translation id="5083553833479578423">Sblocca altre funzioni dell'assistente.</translation>
diff --git a/ash/strings/ash_strings_iw.xtb b/ash/strings/ash_strings_iw.xtb index aac66db..9fb62e1 100644 --- a/ash/strings/ash_strings_iw.xtb +++ b/ash/strings/ash_strings_iw.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">צריך להקיש על <ph name="KEYBOARD_SHORTCUT" /> כדי להחליף פריסת מקלדת.</translation> <translation id="2501920221385095727">מקשים דביקים</translation> <translation id="2509468283778169019">CAPS LOCK מופעל</translation> -<translation id="2517825809102302935">כיבוי תאורת הלילה ללילה זה</translation> <translation id="2519465031217098801">מופעל</translation> <translation id="2542089167727451762">יש להקיש על תמונת הפרופיל</translation> <translation id="255671100581129685">Google Assistant אינו זמין בסשן ציבורי.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">הפעלה מחדש ואתחול</translation> <translation id="495046168593986294">גלילה למעלה</translation> <translation id="4961318399572185831">העברת מסך</translation> -<translation id="5018302031617932556">עם תאורת לילה, קל יותר להסתכל על המסך או לקרוא כשהתאורה מסביב עמומה. אפשר להקיש כדי לשנות את ההגדרה.</translation> <translation id="5030687792513154421">נגמר הזמן</translation> <translation id="5035236842988137213">מכשיר <ph name="DEVICE_NAME" /> התחבר לטלפון חדש</translation> <translation id="5083553833479578423">אפשר להפעיל תכונות Assistant נוספות.</translation>
diff --git a/ash/strings/ash_strings_ja.xtb b/ash/strings/ash_strings_ja.xtb index 9c83083..504eafd 100644 --- a/ash/strings/ash_strings_ja.xtb +++ b/ash/strings/ash_strings_ja.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">キーボード レイアウトを切り替えるには <ph name="KEYBOARD_SHORTCUT" /> キーを押します。</translation> <translation id="2501920221385095727">固定キー</translation> <translation id="2509468283778169019">Caps Lock がオンになっています</translation> -<translation id="2517825809102302935">今夜は無効にする</translation> <translation id="2519465031217098801">オン</translation> <translation id="2542089167727451762">プロフィール画像をタップしてください</translation> <translation id="255671100581129685">Google アシスタントは、公開セッションではご利用いただけません。</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">再起動してリセット</translation> <translation id="495046168593986294">上にスクロール</translation> <translation id="4961318399572185831">画面をキャスト</translation> -<translation id="5018302031617932556">夜間モードを利用すると、薄明かりの下でも画面が見やすくなります。タップしてこの設定を変更できます。</translation> <translation id="5030687792513154421">時間切れです</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> が新しいスマートフォンに接続されました</translation> <translation id="5083553833479578423">さらに多くのアシスタント機能をぜひご活用ください。</translation>
diff --git a/ash/strings/ash_strings_ka.xtb b/ash/strings/ash_strings_ka.xtb index d45259e9..e93f967 100644 --- a/ash/strings/ash_strings_ka.xtb +++ b/ash/strings/ash_strings_ka.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">კლავიატურის განლაგების გადასართველად გამოიყენეთ კლავიშთა კომბინაცია: <ph name="KEYBOARD_SHORTCUT" />.</translation> <translation id="2501920221385095727">კლავიშების ფიქსაცია</translation> <translation id="2509468283778169019">CAPS LOCK ჩართულია</translation> -<translation id="2517825809102302935">ამაღამ გამორთვა</translation> <translation id="2519465031217098801">ჩართული</translation> <translation id="2542089167727451762">შეეხეთ თქვენს პროფილის სურათს</translation> <translation id="255671100581129685">Google ასისტენტი მიუწვდომელია საჯარო სესიაში.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">გადატვირთვა და გადაყენება</translation> <translation id="495046168593986294">ზემოთ გადაადგილება</translation> <translation id="4961318399572185831">ეკრანის ტრანსლირება</translation> -<translation id="5018302031617932556">ღამის განათება გაგიმარტივებთ ეკრანზე კითხვას ან მის ყურებას მკრთალი განათების პირობებში. შეეხეთ აღნიშნულის შესაცვლელად.</translation> <translation id="5030687792513154421">დრო ამოიწურა</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> დაკავშირებულია ახალ ტელეფონთან</translation> <translation id="5083553833479578423">განბლოკეთ ასისტენტის დამატებითი ფუნქციები.</translation>
diff --git a/ash/strings/ash_strings_kk.xtb b/ash/strings/ash_strings_kk.xtb index b3b04d8c0..93f541e 100644 --- a/ash/strings/ash_strings_kk.xtb +++ b/ash/strings/ash_strings_kk.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Пернетақтаны ауыстыру үшін <ph name="KEYBOARD_SHORTCUT" /> пернелерін басыңыз.</translation> <translation id="2501920221385095727">Жабысқақ пернелер</translation> <translation id="2509468283778169019">CAPS LOCK қосулы</translation> -<translation id="2517825809102302935">Түнде өшіріп қою</translation> <translation id="2519465031217098801">Қосулы</translation> <translation id="2542089167727451762">Профиль суретіңізді түртіңіз.</translation> <translation id="255671100581129685">Google Assistant жалпыға қолжетімді сеанста жұмыс істемейді.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Қайта қосу және бастапқы күйге қайтару</translation> <translation id="495046168593986294">Жоғарыға айналдыру</translation> <translation id="4961318399572185831">Экран трансляциясы</translation> -<translation id="5018302031617932556">Night Light режимін қосып қойсаңыз, айнала күңгірттеніп тұрғанда, экран жарығы көзіңізді ауыртпайды. Оны өзгерту үшін түртіңіз.</translation> <translation id="5030687792513154421">Уақыт бітті</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> жаңа телефонға жалғанды</translation> <translation id="5083553833479578423">Басқа да Assistant мүмкіндіктерін ашыңыз.</translation>
diff --git a/ash/strings/ash_strings_km.xtb b/ash/strings/ash_strings_km.xtb index b85c20f..d87e3ad 100644 --- a/ash/strings/ash_strings_km.xtb +++ b/ash/strings/ash_strings_km.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">ចុច <ph name="KEYBOARD_SHORTCUT" /> ដើម្បីប្តូរប្លង់ក្តារចុច។</translation> <translation id="2501920221385095727">គ្រាប់ចុចស្អិត</translation> <translation id="2509468283778169019">CAPS LOCK ត្រូវបានបើក</translation> -<translation id="2517825809102302935">បិទសម្រាប់យប់នេះ</translation> <translation id="2519465031217098801">បើក</translation> <translation id="2542089167727451762">ចុចរូបភាពកម្រងព័ត៌មានរបស់អ្នក</translation> <translation id="255671100581129685">Google ជំនួយការមិនអាចប្រើនៅក្នុងរយៈពេលចូលប្រើជាសាធារណៈបានទេ។</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ចាប់ផ្តើមឡើងវិញ និងកំណត់ឡើងវិញ</translation> <translation id="495046168593986294">រំកិលឡើងលើ</translation> <translation id="4961318399572185831">ខាសអេក្រង់</translation> -<translation id="5018302031617932556">ពន្លឺពេលយប់ធ្វើឱ្យមានភាពងាយស្រួលជាងមុនក្នុងការមើលអេក្រង់របស់អ្នក ឬអាននៅពេលមានពន្លឺតិច។ ចុចដើម្បីប្ដូរវា។</translation> <translation id="5030687792513154421">ដល់ពេលហើយ</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> បានភ្ជាប់ទៅទូរសព្ទថ្មី</translation> <translation id="5083553833479578423">ដោះសោមុខងារជំនួយការជាច្រើនទៀត។</translation>
diff --git a/ash/strings/ash_strings_kn.xtb b/ash/strings/ash_strings_kn.xtb index cab0120..b5b1c78 100644 --- a/ash/strings/ash_strings_kn.xtb +++ b/ash/strings/ash_strings_kn.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">ಕೀಬೋರ್ಡ್ ಲೇಔಟ್ ಬದಲಾಯಿಸಲು <ph name="KEYBOARD_SHORTCUT" /> ಒತ್ತಿರಿ.</translation> <translation id="2501920221385095727">ಸ್ಟಿಕಿ ಕೀಗಳು</translation> <translation id="2509468283778169019">CAPS LOCK ಆನ್ ಆಗಿದೆ</translation> -<translation id="2517825809102302935">ಇಂದುರಾತ್ರಿ ಆಫ್ ಮಾಡಿ</translation> <translation id="2519465031217098801">ಆನ್</translation> <translation id="2542089167727451762">ನಿಮ್ಮ ಪ್ರೊಫೈಲ್ ಚಿತ್ರದ ಮೇಲೆ ಟ್ಯಾಪ್ ಮಾಡಿ</translation> <translation id="255671100581129685">Google ಅಸಿಸ್ಟೆಂಟ್ ಸಾರ್ವಜನಿಕ ಸೆಶನ್ನಲ್ಲಿ ಲಭ್ಯವಿಲ್ಲ.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ಮರುಪ್ರಾರಂಭಿಸಿ ಮತ್ತು ಮರುಹೊಂದಿಸಿ</translation> <translation id="495046168593986294">ಮೇಲಕ್ಕೆ ಸ್ಕ್ರಾಲ್ ಮಾಡಿ</translation> <translation id="4961318399572185831">ಪರದೆಯನ್ನು ಬಿತ್ತರಿಸಿ</translation> -<translation id="5018302031617932556">ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನೋಡಲು ಅಥವಾ ಮಂದ ಬೆಳಕಿನಲ್ಲಿ ಓದಲು ನೈಟ್ ಲೈಟ್ ನಿಮಗೆ ಸುಲಭವಾಗಿಸುತ್ತದೆ. ಇದನ್ನು ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ.</translation> <translation id="5030687792513154421">ಸಮಯ ಮುಗಿದಿದೆ</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ಸಾಧನವು ಹೊಸ ಫೋನ್ ಒಂದಕ್ಕೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ</translation> <translation id="5083553833479578423">ಇನ್ನಷ್ಟು ಅಸಿಸ್ಟೆಂಟ್ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ.</translation>
diff --git a/ash/strings/ash_strings_ko.xtb b/ash/strings/ash_strings_ko.xtb index 2e4459e..0b197967 100644 --- a/ash/strings/ash_strings_ko.xtb +++ b/ash/strings/ash_strings_ko.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">키보드 레이아웃을 전환하려면 <ph name="KEYBOARD_SHORTCUT" />을(를) 누르세요.</translation> <translation id="2501920221385095727">고정키</translation> <translation id="2509468283778169019">CAPS LOCK이 켜져 있습니다.</translation> -<translation id="2517825809102302935">오늘 밤 사용 안함</translation> <translation id="2519465031217098801">사용</translation> <translation id="2542089167727451762">프로필 이미지 탭</translation> <translation id="255671100581129685">공개 세션에서는 Google 어시스턴트를 사용할 수 없습니다.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">다시 시작 및 재설정</translation> <translation id="495046168593986294">위로 스크롤</translation> <translation id="4961318399572185831">화면 전송</translation> -<translation id="5018302031617932556">야간 조명을 사용하면 희미한 빛에서도 편안하게 화면을 보고 읽을 수 있습니다. 변경하려면 탭하세요.</translation> <translation id="5030687792513154421">시간이 다 됨</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" />이(가) 새 휴대전화에 연결되었습니다.</translation> <translation id="5083553833479578423">더 많은 어시스턴트 기능을 사용해 보세요.</translation>
diff --git a/ash/strings/ash_strings_ky.xtb b/ash/strings/ash_strings_ky.xtb index 991f1c4..9367794 100644 --- a/ash/strings/ash_strings_ky.xtb +++ b/ash/strings/ash_strings_ky.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Баскычтоптун калыбын которуу үчүн <ph name="KEYBOARD_SHORTCUT" /> басып коюңуз.</translation> <translation id="2501920221385095727">Жабышчаак баскычтар функциясы</translation> <translation id="2509468283778169019">Caps Lock күйүп турат</translation> -<translation id="2517825809102302935">Бүгүн иштетилсин</translation> <translation id="2519465031217098801">Күйүк</translation> <translation id="2542089167727451762">Профилиңиздин сүрөтүн таптап коюңуз</translation> <translation id="255671100581129685">Google Жардамчысы жалпыга ачык сеанста жеткиликсиз.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Өчүрүп-күйгүзүү жана баштапкы абалга келтирүү</translation> <translation id="495046168593986294">Өйдө сыдыруу</translation> <translation id="4961318399572185831">Экранды тышкы экранга чыгаруу</translation> -<translation id="5018302031617932556">Түнкү режим күңүрт жерде көзүңүзгө күч келтирбөөгө жардам берет. Аны өзгөртүү үчүн таптап коюңуз.</translation> <translation id="5030687792513154421">Убакыт бүттү</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> жаңы телефонго туташты</translation> <translation id="5083553833479578423">Жардамчынын башка функцияларын иштетиңиз.</translation>
diff --git a/ash/strings/ash_strings_lo.xtb b/ash/strings/ash_strings_lo.xtb index 52a2dd9..e2df362 100644 --- a/ash/strings/ash_strings_lo.xtb +++ b/ash/strings/ash_strings_lo.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">ແຕະ <ph name="KEYBOARD_SHORTCUT" /> ເພື່ອປ່ຽນໂຄງຮ່າງແປ້ນພິມ.</translation> <translation id="2501920221385095727">ປຸ່ມສະຕິກກີ້</translation> <translation id="2509468283778169019">CAPS LOCK ເປີດຢູ່</translation> -<translation id="2517825809102302935">ປິດສຳລັບຄືນນີ້</translation> <translation id="2519465031217098801">ເປີດ</translation> <translation id="2542089167727451762">ແຕະຮູບໂປຣໄຟລ໌ຂອງທ່ານ</translation> <translation id="255671100581129685">ຜູ້ຊ່ວຍ Google ບໍ່ສາມາດໃຊ້ໄດ້ໃນເຊດຊັນສາທາລະນະ.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ປິດເປີດຄືນໃໝ່ ແລະ ຣິເຊັດ</translation> <translation id="495046168593986294">ເລື່ອນຂຶ້ນ</translation> <translation id="4961318399572185831">ຄາສທ໌ໜ້າຈໍ</translation> -<translation id="5018302031617932556">ແສງກາງຄືນເຮັດໃຫ້ມັນງ່າຍກວ່າໃນການເບິ່ງໜ້າຈໍຂອງທ່ານ ຫຼື ອ່ານໃນແສງທີ່ມືດ. ແຕະເພື່ອປ່ຽນການຕັ້ງຄ່ານີ້.</translation> <translation id="5030687792513154421">ໝົດເວລາແລ້ວ</translation> <translation id="5035236842988137213">ເຊື່ອມຕໍ່ <ph name="DEVICE_NAME" />ກັບໂທລະສັບໃໝ່ແລ້ວ</translation> <translation id="5083553833479578423">ປົດລັອກຄຸນສົມບັດເພີ່ມເຕີມຂອງຜູ້ຊ່ວຍ.</translation>
diff --git a/ash/strings/ash_strings_lt.xtb b/ash/strings/ash_strings_lt.xtb index 5accca5..98cca469 100644 --- a/ash/strings/ash_strings_lt.xtb +++ b/ash/strings/ash_strings_lt.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Paspauskite <ph name="KEYBOARD_SHORTCUT" />, kad perjungtumėte klaviatūros išdėstymą.</translation> <translation id="2501920221385095727">Fiksuotos pozicijos klavišai</translation> <translation id="2509468283778169019">DIDŽIŲJŲ RAIDŽIŲ RAŠYMAS įjungtas</translation> -<translation id="2517825809102302935">Išjungti šiandien</translation> <translation id="2519465031217098801">Įjungta</translation> <translation id="2542089167727451762">Palieskite profilio vaizdą</translation> <translation id="255671100581129685">„Google“ padėjėjas nepasiekiamas viešoje sesijoje.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Paleisti ir nustatyti iš naujo</translation> <translation id="495046168593986294">Slinkti į viršų</translation> <translation id="4961318399572185831">Perduoti ekraną</translation> -<translation id="5018302031617932556">Naudojant „Nakties šviesos“ funkciją bus patogiau žiūrėti į ekraną ar skaityti prietemoje. Palieskite, kad tai pakeistumėte.</translation> <translation id="5030687792513154421">Laikas baigėsi</translation> <translation id="5035236842988137213">„<ph name="DEVICE_NAME" />“ įrenginys buvo susietas su telefonu</translation> <translation id="5083553833479578423">Atrakinkite daugiau Padėjėjo funkcijų.</translation>
diff --git a/ash/strings/ash_strings_lv.xtb b/ash/strings/ash_strings_lv.xtb index bff93476..efc3ab0 100644 --- a/ash/strings/ash_strings_lv.xtb +++ b/ash/strings/ash_strings_lv.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Nospiediet īsinājumtaustiņu <ph name="KEYBOARD_SHORTCUT" />, lai pārslēgtu tastatūras izkārtojumu.</translation> <translation id="2501920221385095727">Taustiņu ķēde</translation> <translation id="2509468283778169019">Funkcija Caps Lock ir ieslēgta</translation> -<translation id="2517825809102302935">Izslēgt šai naktij</translation> <translation id="2519465031217098801">Ieslēgts</translation> <translation id="2542089167727451762">Pieskarieties profila attēlam</translation> <translation id="255671100581129685">Google asistents nav pieejams publiskā sesijā.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Restartēt un atiestatīt</translation> <translation id="495046168593986294">Ritināt uz augšu</translation> <translation id="4961318399572185831">Ekrāna apraide</translation> -<translation id="5018302031617932556">Izmantojot nakts režīmu, tiek atvieglota skatīšanās ekrānā un lasīšana blāvā apgaismojumā. Pieskarieties, lai to mainītu.</translation> <translation id="5030687792513154421">Izmantošanas laiks beidzies</translation> <translation id="5035236842988137213">Ierīce <ph name="DEVICE_NAME" /> ir savienota ar jaunu tālruni</translation> <translation id="5083553833479578423">Piekļūstiet citām Asistenta funkcijām</translation>
diff --git a/ash/strings/ash_strings_mk.xtb b/ash/strings/ash_strings_mk.xtb index 4d721825..ce3318d 100644 --- a/ash/strings/ash_strings_mk.xtb +++ b/ash/strings/ash_strings_mk.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Притиснете <ph name="KEYBOARD_SHORTCUT" /> за да го префрлите распоредот на тастатурата.</translation> <translation id="2501920221385095727">Лепливи копчиња</translation> <translation id="2509468283778169019">Вклучено е CAPS LOCK</translation> -<translation id="2517825809102302935">Исклучи за вечерва</translation> <translation id="2519465031217098801">Вклучено</translation> <translation id="2542089167727451762">Допрете ја сликата на профилот</translation> <translation id="255671100581129685">„Помошникот на Google“ не е достапен во јавна сесија.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Рестартирај и ресетирај</translation> <translation id="495046168593986294">Оди нагоре</translation> <translation id="4961318399572185831">Емитувај го екранот</translation> -<translation id="5018302031617932556">„Ноќно светло“ го олеснува гледањето во екранот или читањето при слаба светлина. Допрете за да го смените ова.</translation> <translation id="5030687792513154421">Времето истече</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> е поврзан со нов телефон</translation> <translation id="5083553833479578423">Отклучете повеќе функции на „Помошникот“.</translation>
diff --git a/ash/strings/ash_strings_ml.xtb b/ash/strings/ash_strings_ml.xtb index d694923..4fd2eb88 100644 --- a/ash/strings/ash_strings_ml.xtb +++ b/ash/strings/ash_strings_ml.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">കീബോര്ഡ് ലേഔട്ട് മാറാൻ <ph name="KEYBOARD_SHORTCUT" /> അമർത്തുക.</translation> <translation id="2501920221385095727">സ്റ്റിക്കി കീകൾ</translation> <translation id="2509468283778169019">CAPS LOCK ഓൺ ആണ്</translation> -<translation id="2517825809102302935">ഇന്ന് രാത്രിയിലേക്ക് ഓഫാക്കുക</translation> <translation id="2519465031217098801">ഓണാണ്</translation> <translation id="2542089167727451762">നിങ്ങളുടെ പ്രൊഫൈൽ ചിത്രത്തിൽ ടാപ്പ് ചെയ്യുക</translation> <translation id="255671100581129685">പൊതു സെഷനില് Google അസിസ്റ്റന്റ് ലഭ്യമല്ല.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">പുനഃരാരംഭിച്ച് പുനഃസജ്ജീകരിക്കുക</translation> <translation id="495046168593986294">മുകളിലേക്ക് സ്ക്രോള് ചെയ്യുക</translation> <translation id="4961318399572185831">സ്ക്രീൻ കാസ്റ്റ് ചെയ്യുക</translation> -<translation id="5018302031617932556">മങ്ങിയ വെളിച്ചത്തിൽ സ്ക്രീനിൽ നോക്കുന്നതോ വായിക്കുന്നതോ നൈറ്റ് ലൈറ്റ് എളുപ്പമാക്കുന്നു. ഇത് മാറ്റാൻ ടാപ്പ് ചെയ്യുക.</translation> <translation id="5030687792513154421">സമയം കഴിഞ്ഞു</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> പുതിയ ഫോണിലേക്ക് കണക്റ്റ് ചെയ്തു</translation> <translation id="5083553833479578423">കൂടുതൽ അസിസ്റ്റന്റ് ഫീച്ചറുകൾ അൺലോക്ക് ചെയ്യുക.</translation>
diff --git a/ash/strings/ash_strings_mn.xtb b/ash/strings/ash_strings_mn.xtb index a979b21..c199b25 100644 --- a/ash/strings/ash_strings_mn.xtb +++ b/ash/strings/ash_strings_mn.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Гарын бүдүүвчийг солихын тулд <ph name="KEYBOARD_SHORTCUT" />-г дарна уу.</translation> <translation id="2501920221385095727">Холбогч түлхүүр</translation> <translation id="2509468283778169019">CAPS LOCK асаалттай байна</translation> -<translation id="2517825809102302935">Өнөө шөнийн хувьд унтраах</translation> <translation id="2519465031217098801">Асаалттай</translation> <translation id="2542089167727451762">Профайл зургаа товшино уу</translation> <translation id="255671100581129685">Олон нийтийн харилцан үйлдэлд Google Туслах боломжгүй байна.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Дахин эхлүүлэх болон шинэчлэх</translation> <translation id="495046168593986294">Дээш гүйлгэх</translation> <translation id="4961318399572185831">Дэлгэцийг каст хийх</translation> -<translation id="5018302031617932556">Шөнийн гэрэл нь бүдэг гэрэлтэй үед дэлгэцээ харах эсвэл уншихад илүү хялбар болгодог. Үүнийг өөрчлөхийн тулд товшино уу.</translation> <translation id="5030687792513154421">Хугацаа дууслаа</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> шинэ утсанд холбогдсон байна</translation> <translation id="5083553833479578423">Tуслахын бусад онцлогийн түгжээг тайлна уу.</translation>
diff --git a/ash/strings/ash_strings_mr.xtb b/ash/strings/ash_strings_mr.xtb index bfdf1313..4f56669 100644 --- a/ash/strings/ash_strings_mr.xtb +++ b/ash/strings/ash_strings_mr.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">कीबोर्डचा लेआउट स्विच करण्यासाठी <ph name="KEYBOARD_SHORTCUT" /> दाबा.</translation> <translation id="2501920221385095727">स्टिकी की</translation> <translation id="2509468283778169019">CAPS LOCK सुरु आहे</translation> -<translation id="2517825809102302935">आज रात्रीसाठी बंद करा</translation> <translation id="2519465031217098801">सुरू</translation> <translation id="2542089167727451762">तुमच्या प्रोफाइल इमेजवर टॅप करा</translation> <translation id="255671100581129685">सार्वजनिक सेशनमध्ये Google असिस्टंट उपलब्ध नाही.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">रीस्टार्ट करा आणि रीसेट करा</translation> <translation id="495046168593986294">वर स्क्रोल करा</translation> <translation id="4961318399572185831">स्क्रीन कास्ट करा</translation> -<translation id="5018302031617932556">रात्रीचा प्रकाश तुमच्या स्क्रीनकडे पाहणे किंवा मंद प्रकाशात वाचणे आणखी सोपे करतो. हे बदलण्यासाठी टॅप करा.</translation> <translation id="5030687792513154421">वेळ संपली</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> नवीन फोनशी कनेक्ट केले</translation> <translation id="5083553833479578423">असिस्टंटची आणखी वैशिष्ट्ये अनलॉक करा.</translation>
diff --git a/ash/strings/ash_strings_ms.xtb b/ash/strings/ash_strings_ms.xtb index 03beda1..c61d199 100644 --- a/ash/strings/ash_strings_ms.xtb +++ b/ash/strings/ash_strings_ms.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Tekan <ph name="KEYBOARD_SHORTCUT" /> untuk menukar atur letak papan kekunci.</translation> <translation id="2501920221385095727">Kekunci lekit</translation> <translation id="2509468283778169019">Kekunci CAPS LOCK dihidupkan</translation> -<translation id="2517825809102302935">Matikan untuk malam ini</translation> <translation id="2519465031217098801">Hidupkan</translation> <translation id="2542089167727451762">Ketik imej profil anda</translation> <translation id="255671100581129685">Google Assistant tidak tersedia dalam sesi awam.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">Mulakan semula dan tetapkan semula</translation> <translation id="495046168593986294">Tatal ke atas</translation> <translation id="4961318399572185831">Hantar skrin</translation> -<translation id="5018302031617932556">Cahaya Malam memudahkan anda melihat skrin atau membaca dalam cahaya malap. Ketik untuk menukar tetapan ini.</translation> <translation id="5030687792513154421">Masa sudah tamat</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> disambungkan ke telefon baharu</translation> <translation id="5083553833479578423">Buka kunci pelbagai lagi ciri Assistant.</translation>
diff --git a/ash/strings/ash_strings_my.xtb b/ash/strings/ash_strings_my.xtb index f7605fd..1b5e348a 100644 --- a/ash/strings/ash_strings_my.xtb +++ b/ash/strings/ash_strings_my.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">ကီးဘုတ်လက်ကွက် ပြောင်းရန် <ph name="KEYBOARD_SHORTCUT" /> ကို နှိပ်ပါ။</translation> <translation id="2501920221385095727">Sticky keys</translation> <translation id="2509468283778169019">စာလုံးကြီးရန် သော့ခလုတ် ပွင့်နေ</translation> -<translation id="2517825809102302935">ယနေ့ညအတွက် ပိတ်ရန်</translation> <translation id="2519465031217098801">ဖွင့်ရန်</translation> <translation id="2542089167727451762">သင့်ပရိုဖိုင်ပုံကို တို့ရန်</translation> <translation id="255671100581129685">အများသုံးစက်ရှင်တွင် Google Assistant အသုံးပြု၍ မရပါ။</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ပြန်လည်စတင်ပြီး ပြင်ဆင်သတ်မှတ်ရန်</translation> <translation id="495046168593986294">အပေါ်သို့ လှိမ့်ရန်</translation> <translation id="4961318399572185831">Cast ဖန်မျက်နှာပြင်</translation> -<translation id="5018302031617932556">'ညအလင်းရောင်' သည် ဖန်သားပြင်ကို ကြည့်ရှုရန် သို့မဟုတ် အလင်းအားနည်းချိန် စာဖတ်ရန် လွယ်ကူစေသည်။ ၎င်းကို ပြောင်းရန် တို့ပါ။</translation> <translation id="5030687792513154421">အချိန်စေ့ပါပြီ</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> က ဖုန်းအသစ်သို့ ချိတ်ဆက်ထားသည်</translation> <translation id="5083553833479578423">နောက်ထပ် Assistant ဝန်ဆောင်မှုများကို ဖွင့်ပါ</translation>
diff --git a/ash/strings/ash_strings_ne.xtb b/ash/strings/ash_strings_ne.xtb index 6b4119e..a2f8d32 100644 --- a/ash/strings/ash_strings_ne.xtb +++ b/ash/strings/ash_strings_ne.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">किबोर्डको लेआउट स्विच गर्न <ph name="KEYBOARD_SHORTCUT" /> मा थिच्नुहोस्।</translation> <translation id="2501920221385095727">स्टिकी कुञ्जीहरू</translation> <translation id="2509468283778169019">CAPS LOCK खुला छ</translation> -<translation id="2517825809102302935">आजको रातको लागि निष्क्रिय पार्नुहोस्</translation> <translation id="2519465031217098801">सक्रिय छ</translation> <translation id="2542089167727451762">आफ्नो प्रोफाइल छविमा ट्याप गर्नुहोस्</translation> <translation id="255671100581129685">Google सहायक सार्वजनिक सत्रमा उपलब्ध छैन।</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">पुनः सुरु गरी रिसेट गर्नुहोस्</translation> <translation id="495046168593986294">माथि स्क्रोल गर्नुहोस्</translation> <translation id="4961318399572185831">स्क्रिन cast गर्नुहोस्</translation> -<translation id="5018302031617932556">रात्रि प्रकाशले आफ्नो स्क्रिनमा हेर्न वा मधुरो प्रकाशमा पढ्न अझ सजिलो बनाउँछ। यसलाई परिवर्तन गर्न ट्याप गर्नुहोस्।</translation> <translation id="5030687792513154421">समय सकियो</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> कुनै नयाँ फोनसँग जोडियो</translation> <translation id="5083553833479578423">सहायकका थप सुविधाहरू अनलक गर्नुहोस्।</translation>
diff --git a/ash/strings/ash_strings_nl.xtb b/ash/strings/ash_strings_nl.xtb index 3a459cf0..ca35d94 100644 --- a/ash/strings/ash_strings_nl.xtb +++ b/ash/strings/ash_strings_nl.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Druk op <ph name="KEYBOARD_SHORTCUT" /> om van toetsenbordindeling te wisselen.</translation> <translation id="2501920221385095727">Plaktoetsen</translation> <translation id="2509468283778169019">CAPS LOCK is ingeschakeld</translation> -<translation id="2517825809102302935">Uitschakelen voor vanavond</translation> <translation id="2519465031217098801">Aan</translation> <translation id="2542089167727451762">Tik op je profielafbeelding</translation> <translation id="255671100581129685">De Google Assistent is niet beschikbaar in een openbare sessie.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Opnieuw opstarten en resetten</translation> <translation id="495046168593986294">Omhoog scrollen</translation> <translation id="4961318399572185831">Scherm casten</translation> -<translation id="5018302031617932556">Met Nachtverlichting kun je je scherm beter zien en lezen bij weinig licht. Tik om dit te wijzigen.</translation> <translation id="5030687792513154421">De tijd is voorbij</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> verbonden met nieuwe telefoon</translation> <translation id="5083553833479578423">Ontgrendel meer functies van de Assistent.</translation>
diff --git a/ash/strings/ash_strings_no.xtb b/ash/strings/ash_strings_no.xtb index 3397df40..6a6704d2 100644 --- a/ash/strings/ash_strings_no.xtb +++ b/ash/strings/ash_strings_no.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Trykk på <ph name="KEYBOARD_SHORTCUT" /> for å bytte tastaturoppsett.</translation> <translation id="2501920221385095727">Trege taster</translation> <translation id="2509468283778169019">Caps Lock er på</translation> -<translation id="2517825809102302935">Slå av for kvelden</translation> <translation id="2519465031217098801">På</translation> <translation id="2542089167727451762">Trykk på profilbildet ditt</translation> <translation id="255671100581129685">Google-assistenten er ikke tilgjengelig i offentlige økter.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Start på nytt og tilbakestill</translation> <translation id="495046168593986294">Rull opp</translation> <translation id="4961318399572185831">Cast skjermen</translation> -<translation id="5018302031617932556">Nattlys gjør det lettere å se på skjermen og lese i svakt lys. Trykk for å endre dette.</translation> <translation id="5030687792513154421">Tiden er ute</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> koblet til en ny telefon</translation> <translation id="5083553833479578423">Lås opp flere Assistent-funksjoner.</translation>
diff --git a/ash/strings/ash_strings_or.xtb b/ash/strings/ash_strings_or.xtb index 7984e7b4b..04e2de8 100644 --- a/ash/strings/ash_strings_or.xtb +++ b/ash/strings/ash_strings_or.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">କୀ'ବୋର୍ଡ ଲେଆଉଟ୍କୁ ସ୍ଵିଚ୍ କରିବା ପାଇଁ <ph name="KEYBOARD_SHORTCUT" /> ଦବାନ୍ତୁ।</translation> <translation id="2501920221385095727">ଷ୍ଟିକି କୀ'ଗୁଡ଼ିକ</translation> <translation id="2509468283778169019">CAPS LOCK ଅନ୍ ଅଛି</translation> -<translation id="2517825809102302935">ଆଜି ରାତି ପାଇଁ ବନ୍ଦ କରନ୍ତୁ</translation> <translation id="2519465031217098801">ଚାଲୁ ଅଛି</translation> <translation id="2542089167727451762">ଆପଣଙ୍କର ପ୍ରୋଫାଇଲ୍ ଛବି ଟାପ୍ କରନ୍ତୁ</translation> <translation id="255671100581129685">Google ଆସିଷ୍ଟାଣ୍ଟ ଏକ ସାର୍ବଜନିକ ଅବଧିରେ ଉପଲବ୍ଧ ନୁହେଁ।</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ରିର୍ଷ୍ଟାଟ୍ ଏବଂ ରିସେଟ୍ କରନ୍ତୁ</translation> <translation id="495046168593986294">ଉପରକୁ ସ୍କ୍ରୋଲ୍ କରନ୍ତୁ</translation> <translation id="4961318399572185831">କାଷ୍ଟ ସ୍କ୍ରିନ୍</translation> -<translation id="5018302031617932556">ନାଇଟ୍ ଲାଇଟ୍ କମ୍ ଆଲୋକରେ ଆପଣଙ୍କର ସ୍କ୍ରିନ୍କୁ ଦେଖିବା କିମ୍ବା ପଢ଼ିବା ସହଜ କରିଥାଏ। ଏହାକୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।</translation> <translation id="5030687792513154421">ସମୟ ଶେଷ ହୋଇଛି</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ଏକ ନୂଆ ଫୋନ୍ ସହ ସଂଯୁକ୍ତ ହୋଇଛି</translation> <translation id="5083553833479578423">ଆହୁରି ଆସିଷ୍ଟାଣ୍ଟ ବୈଶିଷ୍ଟ୍ୟଗୁଡ଼ିକ ଅନ୍ଲକ୍ କରନ୍ତୁ</translation>
diff --git a/ash/strings/ash_strings_pa.xtb b/ash/strings/ash_strings_pa.xtb index b9842eaa..d5a12eea7 100644 --- a/ash/strings/ash_strings_pa.xtb +++ b/ash/strings/ash_strings_pa.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">ਕੀ-ਬੋਰਡ ਖਾਕਾ ਬਦਲਣ ਲਈ <ph name="KEYBOARD_SHORTCUT" /> ਦਬਾਓ।</translation> <translation id="2501920221385095727">ਸਟਿਕੀ ਕੁੰਜੀਆਂ</translation> <translation id="2509468283778169019">CAPS LOCK ਔਨ ਹੈ</translation> -<translation id="2517825809102302935">ਅੱਜ ਰਾਤ ਲਈ ਬੰਦ ਕਰੋ</translation> <translation id="2519465031217098801">ਚਾਲੂ</translation> <translation id="2542089167727451762">ਆਪਣੇ ਪ੍ਰੋਫਾਈਲ ਚਿੱਤਰ 'ਤੇ ਟੈਪ ਕਰੋ</translation> <translation id="255671100581129685">'Google ਅਸਿਸਟੈਂਟ' ਕਿਸੇ ਜਨਤਕ ਸੈਸ਼ਨ ਵਿੱਚ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ਮੁੜ-ਸ਼ੁਰੂ ਕਰਕੇ ਰੀਸੈੱਟ ਕਰੋ</translation> <translation id="495046168593986294">ਉੱਪਰ ਵੱਲ ਸਕ੍ਰੋਲ ਕਰੋ</translation> <translation id="4961318399572185831">ਸਕ੍ਰੀਨ ਕਾਸਟ ਕਰੋ</translation> -<translation id="5018302031617932556">ਰਾਤ ਦੀ ਰੋਸ਼ਨੀ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਨੂੰ ਘੱਟ ਰੋਸ਼ਨੀ ਵਿੱਚ ਦੇਖਣਾ ਜਾਂ ਪੜ੍ਹਨਾ ਵਧੇਰੇ ਆਸਾਨ ਬਣਾਉਂਦੀ ਹੈ। ਇਸ ਨੂੰ ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।</translation> <translation id="5030687792513154421">ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" />ਨੂੰ ਨਵੇਂ ਫ਼ੋਨ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ</translation> <translation id="5083553833479578423">'ਸਹਾਇਕ' ਦੀਆਂ ਹੋਰ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਬਾਰੇ ਜਾਣੋ।</translation>
diff --git a/ash/strings/ash_strings_pl.xtb b/ash/strings/ash_strings_pl.xtb index 53384f6..ef0eaf4 100644 --- a/ash/strings/ash_strings_pl.xtb +++ b/ash/strings/ash_strings_pl.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Naciśnij <ph name="KEYBOARD_SHORTCUT" />, by przełączyć układ klawiatury.</translation> <translation id="2501920221385095727">Klawisze trwałe</translation> <translation id="2509468283778169019">CAPS LOCK jest włączony.</translation> -<translation id="2517825809102302935">Dzisiaj wyłącz</translation> <translation id="2519465031217098801">Włączono</translation> <translation id="2542089167727451762">Kliknij swoje zdjęcie profilowe</translation> <translation id="255671100581129685">Asystent Google jest niedostępny w sesji publicznej.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Uruchom ponownie i zresetuj</translation> <translation id="495046168593986294">Przewiń w górę</translation> <translation id="4961318399572185831">Przesyłanie ekranu</translation> -<translation id="5018302031617932556">Dzięki Podświetleniu nocnemu oczy mniej się męczą podczas patrzenia na ekran lub czytania przy słabym oświetleniu. Kliknij, by to zmienić.</translation> <translation id="5030687792513154421">Czas minął</translation> <translation id="5035236842988137213">Urządzenie <ph name="DEVICE_NAME" /> zostało połączone z nowym telefonem</translation> <translation id="5083553833479578423">Poznaj więcej funkcji Asystenta.</translation>
diff --git a/ash/strings/ash_strings_pt-BR.xtb b/ash/strings/ash_strings_pt-BR.xtb index ca94620..a9ce9b2 100644 --- a/ash/strings/ash_strings_pt-BR.xtb +++ b/ash/strings/ash_strings_pt-BR.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Pressione <ph name="KEYBOARD_SHORTCUT" /> para alterar o layout do teclado.</translation> <translation id="2501920221385095727">Teclas aderentes</translation> <translation id="2509468283778169019">CAPS LOCK está ativado</translation> -<translation id="2517825809102302935">Desativar esta noite</translation> <translation id="2519465031217098801">Ativado</translation> <translation id="2542089167727451762">Toque na imagem do seu perfil</translation> <translation id="255671100581129685">O Google Assistente não está disponível para uma sessão pública.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Reiniciar e redefinir</translation> <translation id="495046168593986294">Rolar para cima</translation> <translation id="4961318399572185831">Transmitir tela</translation> -<translation id="5018302031617932556">O Modo noturno facilita a visualização da sua tela ou a leitura com pouca luz. Toque para mudar isso.</translation> <translation id="5030687792513154421">Tempo esgotado</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> conectado a um novo smartphone</translation> <translation id="5083553833479578423">Desbloqueie mais recursos do Assistente.</translation>
diff --git a/ash/strings/ash_strings_pt-PT.xtb b/ash/strings/ash_strings_pt-PT.xtb index df2aa638..b7cd298d 100644 --- a/ash/strings/ash_strings_pt-PT.xtb +++ b/ash/strings/ash_strings_pt-PT.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Prima <ph name="KEYBOARD_SHORTCUT" /> para mudar o esquema do teclado.</translation> <translation id="2501920221385095727">Teclas aderentes</translation> <translation id="2509468283778169019">CAPS LOCK está ativado</translation> -<translation id="2517825809102302935">Desativar para hoje à noite</translation> <translation id="2519465031217098801">Ativado</translation> <translation id="2542089167727451762">Toque na imagem do perfil.</translation> <translation id="255671100581129685">O Assistente Google não está disponível para sessões públicas.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Reiniciar e repor</translation> <translation id="495046168593986294">Deslocar para cima</translation> <translation id="4961318399572185831">Transmitir ecrã</translation> -<translation id="5018302031617932556">A Luz noturna torna mais fácil olhar para o ecrã ou ler com pouca luz. Toque para alterar esta opção.</translation> <translation id="5030687792513154421">O tempo terminou</translation> <translation id="5035236842988137213">O dispositivo <ph name="DEVICE_NAME" /> estabeleceu ligação a um novo telemóvel.</translation> <translation id="5083553833479578423">Desbloqueie mais funcionalidades do Assistente.</translation>
diff --git a/ash/strings/ash_strings_ro.xtb b/ash/strings/ash_strings_ro.xtb index 9045de0fb..6a223659 100644 --- a/ash/strings/ash_strings_ro.xtb +++ b/ash/strings/ash_strings_ro.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Apasă <ph name="KEYBOARD_SHORTCUT" /> pentru a schimba aspectul tastaturii.</translation> <translation id="2501920221385095727">Taste adezive</translation> <translation id="2509468283778169019">Tasta CAPS LOCK este activată</translation> -<translation id="2517825809102302935">Dezactivează în seara aceasta</translation> <translation id="2519465031217098801">Activat</translation> <translation id="2542089167727451762">Atinge imaginea de profil</translation> <translation id="255671100581129685">Asistentul Google nu este disponibil într-o sesiune publică.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Repornește și resetează</translation> <translation id="495046168593986294">Derulează în sus</translation> <translation id="4961318399572185831">Proiectează ecranul</translation> -<translation id="5018302031617932556">Lumină de noapte îți oferă mai multă comoditate când privești ecranul sau citești într-o lumină slabă. Atinge pentru a modifica opțiunea.</translation> <translation id="5030687792513154421">Timpul a expirat</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> conectat la un telefon nou</translation> <translation id="5083553833479578423">Deblochează mai multe funcții ale Asistentului.</translation>
diff --git a/ash/strings/ash_strings_ru.xtb b/ash/strings/ash_strings_ru.xtb index 3b5b3ca..f3720ca 100644 --- a/ash/strings/ash_strings_ru.xtb +++ b/ash/strings/ash_strings_ru.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Чтобы переключить раскладку клавиатуры, нажмите клавиши <ph name="KEYBOARD_SHORTCUT" />.</translation> <translation id="2501920221385095727">Залипание клавиш</translation> <translation id="2509468283778169019">Включен режим CAPS LOCK</translation> -<translation id="2517825809102302935">Не включать сегодня</translation> <translation id="2519465031217098801">Включено</translation> <translation id="2542089167727451762">Нажмите на фото профиля</translation> <translation id="255671100581129685">Google Ассистент не работает в сеансе общего доступа.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Перезапустить и сбросить настройки</translation> <translation id="495046168593986294">Прокрутить вверх</translation> <translation id="4961318399572185831">Трансляция экрана</translation> -<translation id="5018302031617932556">Он помогает снизить напряжение глаз при тусклом свете. Нажмите, чтобы изменить эту настройку.</translation> <translation id="5030687792513154421">Время вышло</translation> <translation id="5035236842988137213">Устройство <ph name="DEVICE_NAME" /> подключено к новому телефону</translation> <translation id="5083553833479578423">Получите доступ к другим возможностям Ассистента.</translation>
diff --git a/ash/strings/ash_strings_si.xtb b/ash/strings/ash_strings_si.xtb index 0e4c322..95bc8b0 100644 --- a/ash/strings/ash_strings_si.xtb +++ b/ash/strings/ash_strings_si.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">යතුරු පුවරු පිරිසැලසුම මාරු කිරීමට <ph name="KEYBOARD_SHORTCUT" /> ඔබන්න.</translation> <translation id="2501920221385095727">ඇලෙන යතුරු</translation> <translation id="2509468283778169019">කැප්ස් ලොක් සක්රීයයි</translation> -<translation id="2517825809102302935">අද රෑ සඳහා ක්රියාවිරහිත කරන්න</translation> <translation id="2519465031217098801">සක්රීය</translation> <translation id="2542089167727451762">ඔබේ පැතිකඩ රූපයට තට්ටු කරන්න</translation> <translation id="255671100581129685">ප්රසිද්ධ සැසියකදී Google සහකරු නොලැබේ.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">නැවත ඇරඹීම සහ නැවත සැකසීම</translation> <translation id="495046168593986294">ඉහළට අනුචලනය කරන්න</translation> <translation id="4961318399572185831">තිරය විකාශය කරන්න</translation> -<translation id="5018302031617932556">රාත්රී ආලෝකය ඔබේ තිරය දෙස බැලීම හෝ අඳුරු ආලෝකයෙන් කියවීම පහසු කරයි. මෙය වෙනස් කිරීමට තට්ටු කරන්න.</translation> <translation id="5030687792513154421">වේලාව අවසන්</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> නව දුරකථනයකට සම්බන්ධයි</translation> <translation id="5083553833479578423">තව සහායක අංග අගුලු හරින්න</translation>
diff --git a/ash/strings/ash_strings_sk.xtb b/ash/strings/ash_strings_sk.xtb index 00f00cf..68b00b46 100644 --- a/ash/strings/ash_strings_sk.xtb +++ b/ash/strings/ash_strings_sk.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Stlačením klávesov <ph name="KEYBOARD_SHORTCUT" /> zmeníte rozloženie klávesnice.</translation> <translation id="2501920221385095727">Funkcia sticky keys</translation> <translation id="2509468283778169019">Kláves CAPS LOCK je zapnutý</translation> -<translation id="2517825809102302935">Nadnes vypnúť</translation> <translation id="2519465031217098801">Zapnuté</translation> <translation id="2542089167727451762">Klepnite na svoj profilový obrázok</translation> <translation id="255671100581129685">Asistent Google nie je k dispozícii vo verejnej relácii.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Reštartovať a resetovať</translation> <translation id="495046168593986294">Posunúť nahor</translation> <translation id="4961318399572185831">Prenášanie obrazovky</translation> -<translation id="5018302031617932556">Vďaka nočnému režimu bude vaša obrazovka pri tlmenom osvetlení menej rušivá aj čitateľnejšia. Túto funkciu zmeníte klepnutím.</translation> <translation id="5030687792513154421">Čas vypršal</translation> <translation id="5035236842988137213">Zariadenie <ph name="DEVICE_NAME" /> bolo pripojené k novému telefónu</translation> <translation id="5083553833479578423">Odblokujte ďalšie funkcie Asistenta.</translation>
diff --git a/ash/strings/ash_strings_sl.xtb b/ash/strings/ash_strings_sl.xtb index 97805d24..acdb624 100644 --- a/ash/strings/ash_strings_sl.xtb +++ b/ash/strings/ash_strings_sl.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Pritisnite <ph name="KEYBOARD_SHORTCUT" />, če želite preklopiti postavitev tipkovnice</translation> <translation id="2501920221385095727">Zaklepanje tipk</translation> <translation id="2509468283778169019">Tipka CAPS LOCK je vklopljena</translation> -<translation id="2517825809102302935">Izklopi za nocoj</translation> <translation id="2519465031217098801">Vklopljeno</translation> <translation id="2542089167727451762">Dotaknite se slike profila</translation> <translation id="255671100581129685">Pomočnik Google ni na voljo v javni seji.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Znova zaženi in ponastavi</translation> <translation id="495046168593986294">Pomik navzgor</translation> <translation id="4961318399572185831">Predvajanje zaslona</translation> -<translation id="5018302031617932556">Nočna svetloba olajša gledanje na zaslon ali branje pri šibki svetlobi. Dotaknite se, če želite to spremeniti.</translation> <translation id="5030687792513154421">Dovoljeni čas je potekel</translation> <translation id="5035236842988137213">Naprava <ph name="DEVICE_NAME" /> je povezana z novim telefonom</translation> <translation id="5083553833479578423">Odklenite več funkcij Pomočnika.</translation>
diff --git a/ash/strings/ash_strings_sq.xtb b/ash/strings/ash_strings_sq.xtb index d9496d82..7e33d25c 100644 --- a/ash/strings/ash_strings_sq.xtb +++ b/ash/strings/ash_strings_sq.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Shtyp <ph name="KEYBOARD_SHORTCUT" /> për të ndryshuar planin e tastierës.</translation> <translation id="2501920221385095727">Tastet e përhershme</translation> <translation id="2509468283778169019">KYÇJA E KAPITALEVE është aktive</translation> -<translation id="2517825809102302935">Çaktivizoje për sonte</translation> <translation id="2519465031217098801">Aktiv</translation> <translation id="2542089167727451762">Trokit imazhin e profilit tënd</translation> <translation id="255671100581129685">"Asistenti i Google" nuk ofrohet në një sesion publik.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Rinis dhe rivendos</translation> <translation id="495046168593986294">Lëviz lart</translation> <translation id="4961318399572185831">Ekrani i transmetimit</translation> -<translation id="5018302031617932556">"Drita e natës" e bën më të lehtë shikimin e ekranit ose leximin në dritë të zbehtë. Trokit për ta ndryshuar këtë.</translation> <translation id="5030687792513154421">Koha mbaroi</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> u lidh me një telefon të ri</translation> <translation id="5083553833479578423">Shkyç më shumë funksione të "Asistentit".</translation>
diff --git a/ash/strings/ash_strings_sr.xtb b/ash/strings/ash_strings_sr.xtb index 6e750f7..57f8182 100644 --- a/ash/strings/ash_strings_sr.xtb +++ b/ash/strings/ash_strings_sr.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Притисните <ph name="KEYBOARD_SHORTCUT" /> да бисте променили распоред тастатуре.</translation> <translation id="2501920221385095727">Лепљиви тастери</translation> <translation id="2509468283778169019">CAPS LOCK је укључен</translation> -<translation id="2517825809102302935">Искључи вечерас</translation> <translation id="2519465031217098801">Укључено</translation> <translation id="2542089167727451762">Додирните слику профила</translation> <translation id="255671100581129685">Google помоћник није доступан у јавној сесији.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Рестартуј и ресетуј</translation> <translation id="495046168593986294">Помери нагоре</translation> <translation id="4961318399572185831">Пребацивање екрана</translation> -<translation id="5018302031617932556">Ноћно светло вам олакшава да прегледате садржај екрана или да читате при пригушеном светлу. Додирните да бисте променили ово.</translation> <translation id="5030687792513154421">Време је истекло</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> се повезао са новим телефоном</translation> <translation id="5083553833479578423">Откључајте још функција Помоћника.</translation>
diff --git a/ash/strings/ash_strings_sv.xtb b/ash/strings/ash_strings_sv.xtb index 3756e33..ec3e85d 100644 --- a/ash/strings/ash_strings_sv.xtb +++ b/ash/strings/ash_strings_sv.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Tryck på <ph name="KEYBOARD_SHORTCUT" /> om du vill byta tangentbordslayout.</translation> <translation id="2501920221385095727">Tröga tangenter</translation> <translation id="2509468283778169019">CAPS LOCK är på</translation> -<translation id="2517825809102302935">Stäng av för i kväll</translation> <translation id="2519465031217098801">På</translation> <translation id="2542089167727451762">Tryck på profilbilden</translation> <translation id="255671100581129685">Google-assistenten är inte tillgänglig i en offentlig session.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Starta om och återställ</translation> <translation id="495046168593986294">Rulla upp</translation> <translation id="4961318399572185831">Casta skärmen</translation> -<translation id="5018302031617932556">Med Nattljus blir det behagligare för ögonen att titta på skärmen eller läsa i svag belysning Tryck för att ändra detta.</translation> <translation id="5030687792513154421">Tiden är slut</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> har anslutits till en ny mobil</translation> <translation id="5083553833479578423">Lås upp fler funktioner för Assistent</translation>
diff --git a/ash/strings/ash_strings_sw.xtb b/ash/strings/ash_strings_sw.xtb index 8ef3a892..b14d6ada 100644 --- a/ash/strings/ash_strings_sw.xtb +++ b/ash/strings/ash_strings_sw.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Gusa <ph name="KEYBOARD_SHORTCUT" /> ili ubadilishe mpangilio wa kibodi.</translation> <translation id="2501920221385095727">Vitufe vya kusalia kwa muda</translation> <translation id="2509468283778169019">Caps Lock imewashwa.</translation> -<translation id="2517825809102302935">Zima leo usiku</translation> <translation id="2519465031217098801">Imewashwa</translation> <translation id="2542089167727451762">Gusa picha yako ya wasifu</translation> <translation id="255671100581129685">Programu ya Mratibu wa Google haipatikani katika kipindi cha umma.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Zima kisha uwashe na uweke upya</translation> <translation id="495046168593986294">Sogeza juu</translation> <translation id="4961318399572185831">Tuma skrini</translation> -<translation id="5018302031617932556">Mwanga wa Usiku hufanya uangalie skrini yako au usome katika mwangaza hafifu kwa urahisi. Gusa ili ubadilishe kipengele hiki.</translation> <translation id="5030687792513154421">Muda wa kutumia kifaa umeisha</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> imeunganishwa kwenye simu mpya</translation> <translation id="5083553833479578423">Fungua vipengele zaidi vya programu yako ya Mratibu.</translation>
diff --git a/ash/strings/ash_strings_ta.xtb b/ash/strings/ash_strings_ta.xtb index c14a44f..909b3f1a 100644 --- a/ash/strings/ash_strings_ta.xtb +++ b/ash/strings/ash_strings_ta.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">விசைப்பலகைத் தளவமைப்பை மாற்ற, <ph name="KEYBOARD_SHORTCUT" /> விசையை அழுத்தவும்.</translation> <translation id="2501920221385095727">ஸ்டிக்கி விசைகள்</translation> <translation id="2509468283778169019">CAPS LOCK இயக்கத்தில்</translation> -<translation id="2517825809102302935">இன்று இரவு ஆஃப் செய்</translation> <translation id="2519465031217098801">ஆன்</translation> <translation id="2542089167727451762">உங்கள் சுயவிவரப் படத்தைத் தட்டவும்</translation> <translation id="255671100581129685">பொது அமர்வில் Google அசிஸ்டண்ட்டைப் பயன்படுத்த முடியாது.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">மீண்டும் தொடங்கி, மீட்டமை</translation> <translation id="495046168593986294">மேலே உருட்டு</translation> <translation id="4961318399572185831">திரையை அலைபரப்பு</translation> -<translation id="5018302031617932556">மங்கலான ஒளியில் திரையைப் பார்ப்பதையோ படிப்பதையோ நைட் லைட் அம்சம் எளிதாக்கும். இதை மாற்ற தட்டவும்.</translation> <translation id="5030687792513154421">நேரம் முடிந்தது</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ஒரு புதிய ஃபோனுடன் இணைக்கப்பட்டுள்ளது</translation> <translation id="5083553833479578423">மேலும் பல அசிஸ்டண்ட் அம்சங்களைப் பெறுக.</translation>
diff --git a/ash/strings/ash_strings_te.xtb b/ash/strings/ash_strings_te.xtb index b7071b3..9fc6b57 100644 --- a/ash/strings/ash_strings_te.xtb +++ b/ash/strings/ash_strings_te.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">కీబోర్డ్ లేఅవుట్ను మార్చడానికి <ph name="KEYBOARD_SHORTCUT" />ని నొక్కండి.</translation> <translation id="2501920221385095727">స్టిక్కీ కీలు</translation> <translation id="2509468283778169019">CAPS LOCK ఆన్లో ఉంది</translation> -<translation id="2517825809102302935">ఈరోజు రాత్రికి ఆఫ్ చేయండి</translation> <translation id="2519465031217098801">ఆన్లో ఉంది</translation> <translation id="2542089167727451762">మీ ప్రొఫైల్ చిత్రాన్ని నొక్కండి</translation> <translation id="255671100581129685">Google అసిస్టెంట్ పబ్లిక్ సెషన్లో అందుబాటులో లేదు.</translation> @@ -301,7 +300,6 @@ <translation id="4924411785043111640">మళ్లీ ప్రారంభించి, రీసెట్ చేయండి</translation> <translation id="495046168593986294">పైకి స్క్రోల్ చేయి</translation> <translation id="4961318399572185831">స్క్రీన్ ప్రసారం చేయండి</translation> -<translation id="5018302031617932556">రాత్రి కాంతి ఫీచర్ అనేది తక్కువ కాంతి ఉన్న సందర్భాలలో మీ స్క్రీన్ను స్పష్టంగా చూడటాన్ని లేదా చదవడాన్ని మరింత సులభతరం చేస్తుంది. దీనిని మార్చడానికి నొక్కండి.</translation> <translation id="5030687792513154421">సమయం ముగిసింది</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> ఒక కొత్త ఫోన్కి కనెక్ట్ చేయబడింది</translation> <translation id="5083553833479578423">మరిన్ని Assistant ఫీచర్లను అన్లాక్ చేయండి.</translation>
diff --git a/ash/strings/ash_strings_th.xtb b/ash/strings/ash_strings_th.xtb index f8bad3f..9709e7a 100644 --- a/ash/strings/ash_strings_th.xtb +++ b/ash/strings/ash_strings_th.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">กด <ph name="KEYBOARD_SHORTCUT" /> เพื่อสลับรูปแบบแป้นพิมพ์</translation> <translation id="2501920221385095727">คีย์ติดหนึบ</translation> <translation id="2509468283778169019">Caps Lock เปิดอยู่</translation> -<translation id="2517825809102302935">ปิดสำหรับคืนนี้</translation> <translation id="2519465031217098801">เปิด</translation> <translation id="2542089167727451762">แตะรูปโปรไฟล์</translation> <translation id="255671100581129685">Google Assistant ไม่พร้อมใช้งานในเซสชันสาธารณะ</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">รีสตาร์ทและรีเซ็ต</translation> <translation id="495046168593986294">เลื่อนขึ้น</translation> <translation id="4961318399572185831">แคสต์หน้าจอ</translation> -<translation id="5018302031617932556">แสงตอนกลางคืนช่วยให้มองหรืออ่านหน้าจอในแสงสลัวได้ง่ายขึ้น แตะเพื่อเปลี่ยนการตั้งค่า</translation> <translation id="5030687792513154421">หมดเวลา</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> เชื่อมต่อโทรศัพท์เครื่องใหม่แล้ว</translation> <translation id="5083553833479578423">ใช้ฟีเจอร์จาก Assistant ได้มากขึ้น</translation>
diff --git a/ash/strings/ash_strings_tr.xtb b/ash/strings/ash_strings_tr.xtb index 52a1cb88..c4261a4 100644 --- a/ash/strings/ash_strings_tr.xtb +++ b/ash/strings/ash_strings_tr.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Klavye düzenini değiştirmek için <ph name="KEYBOARD_SHORTCUT" /> tuşlarına basın.</translation> <translation id="2501920221385095727">Yapışkan tuşlar</translation> <translation id="2509468283778169019">CAPS LOCK açık</translation> -<translation id="2517825809102302935">Bu gece için kapat</translation> <translation id="2519465031217098801">Açık</translation> <translation id="2542089167727451762">Profil resminize dokunun</translation> <translation id="255671100581129685">Google Asistan, herkese açık oturumda kullanılamaz.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Yeniden başlat ve sıfırla</translation> <translation id="495046168593986294">Yukarı kaydır</translation> <translation id="4961318399572185831">Ekranı yayınla</translation> -<translation id="5018302031617932556">Gece Işığı, loş ışıkta ekranınızı daha iyi görmenizi ve daha kolay okumanızı sağlar. Bunu değiştirmek için dokunun.</translation> <translation id="5030687792513154421">Süre doldu</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" />, yeni bir telefona bağlandı</translation> <translation id="5083553833479578423">Diğer Asistan özelliklerinin kilidini açın.</translation>
diff --git a/ash/strings/ash_strings_uk.xtb b/ash/strings/ash_strings_uk.xtb index fa3dab6..f8ff0e6b 100644 --- a/ash/strings/ash_strings_uk.xtb +++ b/ash/strings/ash_strings_uk.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Натисніть комбінацію клавіш <ph name="KEYBOARD_SHORTCUT" />, щоб змінити розкладку клавіатури.</translation> <translation id="2501920221385095727">Залипання клавіш</translation> <translation id="2509468283778169019">Режим CAPS LOCK увімкнено</translation> -<translation id="2517825809102302935">Вимкнути на сьогодні</translation> <translation id="2519465031217098801">Увімкнено</translation> <translation id="2542089167727451762">Натисніть зображення профілю</translation> <translation id="255671100581129685">Google Асистент недоступний у сеансі для всіх.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Перезапустити й скинути</translation> <translation id="495046168593986294">Прокрутити вгору</translation> <translation id="4961318399572185831">Трансляція екрана</translation> -<translation id="5018302031617932556">У нічному режимі зручніше переглядати або читати контент на екрані в умовах тьмяного освітлення. Торкніться, щоб змінити це налаштування.</translation> <translation id="5030687792513154421">Час закінчився</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> під’єднано до нового телефона</translation> <translation id="5083553833479578423">Розблокуйте інші функції Асистента.</translation>
diff --git a/ash/strings/ash_strings_ur.xtb b/ash/strings/ash_strings_ur.xtb index d29a588..27665bb 100644 --- a/ash/strings/ash_strings_ur.xtb +++ b/ash/strings/ash_strings_ur.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">کی بورڈ کا لے آؤٹ سوئچ کرنے کے لیے <ph name="KEYBOARD_SHORTCUT" /> دبائیں۔</translation> <translation id="2501920221385095727">اسٹکی کلیدیں</translation> <translation id="2509468283778169019">CAPS LOCK آن ہے</translation> -<translation id="2517825809102302935">آج رات کے لیے آف کریں</translation> <translation id="2519465031217098801">آن</translation> <translation id="2542089167727451762">اپنے پروفائل کی تصویر پر تھپتھپائیں</translation> <translation id="255671100581129685">Google اسسٹنٹ عوامی سیشن میں دستیاب نہیں ہے۔</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">ری سٹارٹ اور ری سیٹ کریں</translation> <translation id="495046168593986294">اوپر اسکرول کریں</translation> <translation id="4961318399572185831">اسکرین کاسٹ کریں</translation> -<translation id="5018302031617932556">نائٹ لائٹ سے مدھم روشنی میں اپنی اسکرین کو دیکھنا یا پڑھنا آسان ہو جاتا ہے۔ اسے تبدیل کرنے کے لیے تھپتھپائیں۔</translation> <translation id="5030687792513154421">وقت ختم ہو گیا</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> نئے فون سے منسلک ہو گیا</translation> <translation id="5083553833479578423">اسسٹنٹ کی مزید خصوصیات کو غیر مقفل کریں۔</translation>
diff --git a/ash/strings/ash_strings_uz.xtb b/ash/strings/ash_strings_uz.xtb index a8581b0b..7d7cea0 100644 --- a/ash/strings/ash_strings_uz.xtb +++ b/ash/strings/ash_strings_uz.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Klaviatura terilmasini almashtirish uchun <ph name="KEYBOARD_SHORTCUT" /> tugmalarini bosing.</translation> <translation id="2501920221385095727">Yopishqoq tugmalar</translation> <translation id="2509468283778169019">CAPS LOCK yoniq</translation> -<translation id="2517825809102302935">Bugun ishga tushmasin</translation> <translation id="2519465031217098801">Yoniq</translation> <translation id="2542089167727451762">Profil rasmingizni bosing</translation> <translation id="255671100581129685">Google Assistent demo seansda ishlamaydi.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Qayta ishga tushirish va asliga qaytarish</translation> <translation id="495046168593986294">Tepaga chiqish</translation> <translation id="4961318399572185831">Ekranni translatsiya qilish</translation> -<translation id="5018302031617932556">Tungi rejim xira yorugʻlikda koʻzlarni charchatmaslikka yordam beradi. Buni oʻzgartirish uchun bosing.</translation> <translation id="5030687792513154421">Vaqt tugadi</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> yangi telefonga ulandi</translation> <translation id="5083553833479578423">Assistentning boshqa imkoniyatlarini oching.</translation>
diff --git a/ash/strings/ash_strings_vi.xtb b/ash/strings/ash_strings_vi.xtb index 6f0256b5..25d5ee3 100644 --- a/ash/strings/ash_strings_vi.xtb +++ b/ash/strings/ash_strings_vi.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Hãy nhấn <ph name="KEYBOARD_SHORTCUT" /> để chuyển bố cục bàn phím.</translation> <translation id="2501920221385095727">Phím cố định</translation> <translation id="2509468283778169019">Đang bật CAPS LOCK</translation> -<translation id="2517825809102302935">Tắt trong đêm nay</translation> <translation id="2519465031217098801">Đang bật</translation> <translation id="2542089167727451762">Nhấn vào ảnh hồ sơ của bạn</translation> <translation id="255671100581129685">Bạn không thể sử dụng Trợ lý Google trong phiên công khai.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Khởi động lại và đặt lại</translation> <translation id="495046168593986294">Cuộn lên</translation> <translation id="4961318399572185831">Truyền màn hình</translation> -<translation id="5018302031617932556">Chế độ Ánh sáng đêm giúp bạn cảm thấy dễ chịu khi nhìn màn hình hoặc đọc trong điều kiện ánh sáng yếu. Hãy nhấn để thay đổi chế độ này.</translation> <translation id="5030687792513154421">Đã hết thời gian</translation> <translation id="5035236842988137213">Đã kết nối <ph name="DEVICE_NAME" /> với một điện thoại mới</translation> <translation id="5083553833479578423">Mở khóa các tính năng khác của Trợ lý.</translation>
diff --git a/ash/strings/ash_strings_zh-CN.xtb b/ash/strings/ash_strings_zh-CN.xtb index 5498299f..ee551d2 100644 --- a/ash/strings/ash_strings_zh-CN.xtb +++ b/ash/strings/ash_strings_zh-CN.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">按 <ph name="KEYBOARD_SHORTCUT" />键可切换键盘布局。</translation> <translation id="2501920221385095727">粘滞键</translation> <translation id="2509468283778169019">CAPS LOCK 已打开</translation> -<translation id="2517825809102302935">今晚暂且关闭</translation> <translation id="2519465031217098801">已开启</translation> <translation id="2542089167727451762">请点按您的个人资料图片</translation> <translation id="255671100581129685">无法在公用自助终端使用 Google 助理。</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">重启并重置</translation> <translation id="495046168593986294">向上滚动</translation> <translation id="4961318399572185831">投射屏幕</translation> -<translation id="5018302031617932556">护眼模式可让您更舒适地在黯淡的光线下查看屏幕或阅读文字。点按即可更改。</translation> <translation id="5030687792513154421">时间到</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" />已连接到新手机</translation> <translation id="5083553833479578423">启用更多 Google 助理功能。</translation>
diff --git a/ash/strings/ash_strings_zh-HK.xtb b/ash/strings/ash_strings_zh-HK.xtb index e88d3998..52f4b5f 100644 --- a/ash/strings/ash_strings_zh-HK.xtb +++ b/ash/strings/ash_strings_zh-HK.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">按下 <ph name="KEYBOARD_SHORTCUT" /> 鍵可切換鍵盤配置。</translation> <translation id="2501920221385095727">相黏鍵</translation> <translation id="2509468283778169019">大寫鍵已啟用</translation> -<translation id="2517825809102302935">今晚關閉</translation> <translation id="2519465031217098801">開啟</translation> <translation id="2542089167727451762">輕按您的個人檔案圖片</translation> <translation id="255671100581129685">「Google 助理」不適用於公開工作階段。</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">重新啟動並重設</translation> <translation id="495046168593986294">向上捲動</translation> <translation id="4961318399572185831">投放螢幕</translation> -<translation id="5018302031617932556">「夜燈模式」讓您更易在光線昏暗的環境下觀看螢幕內容或閱讀。輕按即可變更模式。</translation> <translation id="5030687792513154421">使用時間結束</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> 已連接至新手機</translation> <translation id="5083553833479578423">啟用更多「Google 助理」功能。</translation>
diff --git a/ash/strings/ash_strings_zh-TW.xtb b/ash/strings/ash_strings_zh-TW.xtb index 0ae54ff..e22d7a4 100644 --- a/ash/strings/ash_strings_zh-TW.xtb +++ b/ash/strings/ash_strings_zh-TW.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">按下 <ph name="KEYBOARD_SHORTCUT" />可切換鍵盤配置。</translation> <translation id="2501920221385095727">相黏鍵</translation> <translation id="2509468283778169019">大寫鍵已啟用</translation> -<translation id="2517825809102302935">今晚關閉</translation> <translation id="2519465031217098801">開啟</translation> <translation id="2542089167727451762">輕觸你的個人資料圖片</translation> <translation id="255671100581129685">Google 助理不適用於公開工作階段。</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">重新啟動並重設</translation> <translation id="495046168593986294">向上捲動</translation> <translation id="4961318399572185831">投放螢幕</translation> -<translation id="5018302031617932556">夜燈功能可讓你在光線昏暗的環境下更容易看清畫面內容或閱讀文字。輕觸即可變更設定。</translation> <translation id="5030687792513154421">使用時間結束</translation> <translation id="5035236842988137213"><ph name="DEVICE_NAME" /> 已連結到新手機</translation> <translation id="5083553833479578423">啟用更多 Google 助理功能。</translation>
diff --git a/ash/strings/ash_strings_zu.xtb b/ash/strings/ash_strings_zu.xtb index 165030a..2c0af9c 100644 --- a/ash/strings/ash_strings_zu.xtb +++ b/ash/strings/ash_strings_zu.xtb
@@ -122,7 +122,6 @@ <translation id="2484513351006226581">Shaya u-<ph name="KEYBOARD_SHORTCUT" /> ukuze ushintshe isendlalelo sekhibhodi.</translation> <translation id="2501920221385095727">Okhiye abanamathelayo</translation> <translation id="2509468283778169019">I-CAPS LOCK ivuliwe</translation> -<translation id="2517825809102302935">Vala okwasebusuku</translation> <translation id="2519465031217098801">Vuliwe</translation> <translation id="2542089167727451762">Thepha isithombe sakho sephrofayela</translation> <translation id="255671100581129685">Umsizi we-Google akatholakali kuseshini esesidlangalaleni.</translation> @@ -300,7 +299,6 @@ <translation id="4924411785043111640">Qalisa kabusha futhi usethe kabusha</translation> <translation id="495046168593986294">Skrolela phezulu</translation> <translation id="4961318399572185831">Sakaza isikrini</translation> -<translation id="5018302031617932556">Ukukhanya kwasebusuku kwenza kubelula ukubheka esikrinini sakho noma ukufunda ngomkhanyo ofiphele. Thepha ukuze ushintshe lokhu.</translation> <translation id="5030687792513154421">Isikhathi siphelile</translation> <translation id="5035236842988137213">I-<ph name="DEVICE_NAME" /> ixhumeke kufoni entsha</translation> <translation id="5083553833479578423">Vula izici eziningi zomsizi.</translation>
diff --git a/ash/system/accessibility/autoclick_menu_bubble_controller.cc b/ash/system/accessibility/autoclick_menu_bubble_controller.cc index 076ca5c8..d0424c0 100644 --- a/ash/system/accessibility/autoclick_menu_bubble_controller.cc +++ b/ash/system/accessibility/autoclick_menu_bubble_controller.cc
@@ -4,7 +4,6 @@ #include "ash/system/accessibility/autoclick_menu_bubble_controller.h" -#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" @@ -225,15 +224,16 @@ init_params.max_width = kAutoclickMenuWidth; init_params.corner_radius = kUnifiedTrayCornerRadius; init_params.has_shadow = false; + init_params.translucent = true; bubble_view_ = new AutoclickMenuBubbleView(init_params); menu_view_ = new AutoclickMenuView(type, position); - menu_view_->SetBackground(UnifiedSystemTrayView::CreateBackground()); menu_view_->SetBorder( views::CreateEmptyBorder(kUnifiedTopShortcutSpacing, 0, 0, 0)); bubble_view_->AddChildView(menu_view_); - bubble_view_->set_color(SK_ColorTRANSPARENT); - bubble_view_->layer()->SetFillsBoundsOpaquely(false); + + menu_view_->SetPaintToLayer(); + menu_view_->layer()->SetFillsBoundsOpaquely(false); bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_); TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_); @@ -242,11 +242,6 @@ CollisionDetectionUtils::RelativePriority::kAutomaticClicksMenu); bubble_view_->InitializeAndShowBubble(); - if (features::IsBackgroundBlurEnabled()) { - bubble_widget_->client_view()->layer()->SetBackgroundBlur( - kUnifiedMenuBackgroundBlur); - } - SetPosition(position); }
diff --git a/ash/system/accessibility/autoclick_scroll_bubble_controller.cc b/ash/system/accessibility/autoclick_scroll_bubble_controller.cc index 2dcc4d51..983255d 100644 --- a/ash/system/accessibility/autoclick_scroll_bubble_controller.cc +++ b/ash/system/accessibility/autoclick_scroll_bubble_controller.cc
@@ -4,7 +4,6 @@ #include "ash/system/accessibility/autoclick_scroll_bubble_controller.h" -#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" @@ -200,16 +199,16 @@ init_params.max_height = kAutoclickScrollMenuSizeDips; init_params.corner_radius = kUnifiedTrayCornerRadius; init_params.has_shadow = false; + init_params.translucent = true; bubble_view_ = new AutoclickScrollBubbleView(init_params); bubble_view_->SetArrow(alignment); scroll_view_ = new AutoclickScrollView(); - scroll_view_->SetBackground(UnifiedSystemTrayView::CreateBackground()); scroll_view_->SetBorder( views::CreateEmptyBorder(kUnifiedTopShortcutSpacing, 0, 0, 0)); bubble_view_->AddChildView(scroll_view_); - bubble_view_->set_color(SK_ColorTRANSPARENT); - bubble_view_->layer()->SetFillsBoundsOpaquely(false); + scroll_view_->SetPaintToLayer(); + scroll_view_->layer()->SetFillsBoundsOpaquely(false); bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_); TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_); @@ -217,11 +216,6 @@ bubble_widget_->GetNativeWindow(), CollisionDetectionUtils::RelativePriority::kAutomaticClicksScrollMenu); bubble_view_->InitializeAndShowBubble(); - - if (features::IsBackgroundBlurEnabled()) { - bubble_widget_->client_view()->layer()->SetBackgroundBlur( - kUnifiedMenuBackgroundBlur); - } } void AutoclickScrollBubbleController::CloseBubble() {
diff --git a/ash/system/message_center/arc/arc_notification_content_view_unittest.cc b/ash/system/message_center/arc/arc_notification_content_view_unittest.cc index 660e0f9..73ae1777 100644 --- a/ash/system/message_center/arc/arc_notification_content_view_unittest.cc +++ b/ash/system/message_center/arc/arc_notification_content_view_unittest.cc
@@ -44,6 +44,7 @@ #include "ui/message_center/views/notification_control_buttons_view.h" #include "ui/message_center/views/padded_button.h" #include "ui/views/test/views_test_base.h" +#include "ui/views/widget/native_widget_delegate.h" using message_center::MessageCenter; using message_center::Notification; @@ -377,6 +378,15 @@ std::make_unique<Notification>(notification)); ASSERT_TRUE(notification_view); + // Make sure that the native host can process the located event. + auto* widget = notification_view->GetWidget(); + auto* root_layer = widget->GetNativeWindow()->layer(); + auto* child_window = notification_view->GetNativeContainerWindowForTest(); + views::internal::NativeWidgetDelegate* native_widget_delegate = widget; + EXPECT_TRUE(native_widget_delegate->ShouldDescendIntoChildForEventHandling( + root_layer, child_window, child_window->layer(), + gfx::Rect(root_layer->bounds().size()).CenterPoint())); + // Cache notification id because |notification_item| will be gone when the // close button is pressed. const std::string notification_id = notification_item->GetNotificationId();
diff --git a/ash/system/message_center/arc/arc_notification_view.cc b/ash/system/message_center/arc/arc_notification_view.cc index cd7a3dc9..9b67d9c8 100644 --- a/ash/system/message_center/arc/arc_notification_view.cc +++ b/ash/system/message_center/arc/arc_notification_view.cc
@@ -245,4 +245,8 @@ item_ = nullptr; } +aura::Window* ArcNotificationView::GetNativeContainerWindowForTest() const { + return content_view_->GetNativeViewContainer(); +} + } // namespace ash
diff --git a/ash/system/message_center/arc/arc_notification_view.h b/ash/system/message_center/arc/arc_notification_view.h index 0fe506ac..2b4932a 100644 --- a/ash/system/message_center/arc/arc_notification_view.h +++ b/ash/system/message_center/arc/arc_notification_view.h
@@ -9,6 +9,10 @@ #include "base/macros.h" #include "ui/message_center/views/message_view.h" +namespace aura { +class Window; +} + namespace arc { class ArcAccessibilityHelperBridgeTest; } @@ -72,6 +76,9 @@ // ArcNotificationItem::Observer void OnItemDestroying() override; + // Returns the native container view for notification surface. + aura::Window* GetNativeContainerWindowForTest() const; + private: friend class ArcNotificationContentViewTest; friend class ArcNotificationViewTest;
diff --git a/ash/system/tray/tray_bubble_view.cc b/ash/system/tray/tray_bubble_view.cc index 2bbfa72..653cbaa8 100644 --- a/ash/system/tray/tray_bubble_view.cc +++ b/ash/system/tray/tray_bubble_view.cc
@@ -8,6 +8,8 @@ #include <numeric> #include "ash/public/cpp/ash_features.h" +#include "ash/system/tray/tray_constants.h" +#include "ash/system/unified/unified_system_tray_view.h" #include "base/macros.h" #include "base/numerics/ranges.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -238,7 +240,25 @@ set_notify_enter_exit_on_child(true); set_close_on_deactivate(init_params.close_on_deactivate); set_margins(gfx::Insets()); - SetPaintToLayer(); + + if (init_params.translucent) { + // The following code will not work with bubble's shadow. + DCHECK(!init_params.has_shadow); + SetPaintToLayer(ui::LAYER_SOLID_COLOR); + + layer()->SetRoundedCornerRadius( + gfx::RoundedCornersF{kUnifiedTrayCornerRadius}); + layer()->SetColor(UnifiedSystemTrayView::GetBackgroundColor()); + layer()->SetFillsBoundsOpaquely(false); + layer()->SetIsFastRoundedCorner(true); + if (features::IsBackgroundBlurEnabled()) + layer()->SetBackgroundBlur(kUnifiedMenuBackgroundBlur); + } else { + // Create a layer so that the layer for FocusRing stays in this view's + // layer. Without it, the layer for FocusRing goes above the + // NativeViewHost and may steal events. + SetPaintToLayer(ui::LAYER_NOT_DRAWN); + } auto layout = std::make_unique<BottomAlignedBoxLayout>(this); layout->SetDefaultFlex(1); @@ -267,10 +287,6 @@ } void TrayBubbleView::InitializeAndShowBubble() { - int radius = bubble_border_->corner_radius(); - layer()->parent()->SetRoundedCornerRadius({radius, radius, radius, radius}); - layer()->parent()->SetIsFastRoundedCorner(true); - GetWidget()->Show(); UpdateBubble(); @@ -380,6 +396,12 @@ BubbleDialogDelegateView::OnWidgetActivationChanged(widget, active); } +ui::LayerType TrayBubbleView::GetLayerType() const { + if (params_.translucent) + return ui::LAYER_NOT_DRAWN; + return ui::LAYER_TEXTURED; +} + NonClientFrameView* TrayBubbleView::CreateNonClientFrameView(Widget* widget) { BubbleFrameView* frame = static_cast<BubbleFrameView*>( BubbleDialogDelegateView::CreateNonClientFrameView(widget)); @@ -466,14 +488,6 @@ SizeToContents(); } -void TrayBubbleView::ViewHierarchyChanged( - const views::ViewHierarchyChangedDetails& details) { - if (details.is_add && details.child == this) { - details.parent->SetPaintToLayer(); - details.parent->layer()->SetMasksToBounds(true); - } -} - void TrayBubbleView::SetBubbleBorderInsets(gfx::Insets insets) { bubble_border_->set_insets(insets); }
diff --git a/ash/system/tray/tray_bubble_view.h b/ash/system/tray/tray_bubble_view.h index 45e1caf2..1bd77b5 100644 --- a/ash/system/tray/tray_bubble_view.h +++ b/ash/system/tray/tray_bubble_view.h
@@ -95,6 +95,8 @@ base::Optional<int> corner_radius; base::Optional<gfx::Insets> insets; bool has_shadow = true; + // Use half opaque widget instead of fully opaque. + bool translucent = false; }; explicit TrayBubbleView(const InitParams& init_params); @@ -164,6 +166,7 @@ views::Widget* bubble_widget) const override; void OnWidgetClosing(views::Widget* widget) override; void OnWidgetActivationChanged(views::Widget* widget, bool active) override; + ui::LayerType GetLayerType() const override; // Overridden from views::View. gfx::Size CalculatePreferredSize() const override; @@ -182,8 +185,6 @@ // Overridden from views::View. void ChildPreferredSizeChanged(View* child) override; - void ViewHierarchyChanged( - const views::ViewHierarchyChangedDetails& details) override; // Changes the insets from the bubble border. These were initially set using // the InitParams.insets, but may need to be reset programmatically.
diff --git a/ash/system/unified/page_indicator_view.cc b/ash/system/unified/page_indicator_view.cc index 98acd58..9ba8232a 100644 --- a/ash/system/unified/page_indicator_view.cc +++ b/ash/system/unified/page_indicator_view.cc
@@ -169,11 +169,11 @@ expanded_amount_(initially_expanded ? 1 : 0), buttons_container_(new views::View) { SetVisible(initially_expanded); - SetPaintToLayer(); - layer()->SetFillsBoundsOpaquely(false); buttons_container_->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets())); + buttons_container_->SetPaintToLayer(); + buttons_container_->layer()->SetFillsBoundsOpaquely(false); AddChildView(buttons_container_); @@ -209,9 +209,11 @@ DCHECK(0.0 <= expanded_amount && expanded_amount <= 1.0); SetVisible(expanded_amount > 0.0); expanded_amount_ = expanded_amount; - InvalidateLayout(); // TODO(amehfooz): Confirm animation curve with UX. - layer()->SetOpacity(std::max(0., 6 * expanded_amount_ - 5.)); + buttons_container_->layer()->SetOpacity( + std::max(0., 6 * expanded_amount_ - 5.)); + if (CalculatePreferredSize() != size()) + InvalidateLayout(); } int PageIndicatorView::GetExpandedHeight() {
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc index b3df4fc4..be0593b 100644 --- a/ash/system/unified/unified_slider_bubble_controller.cc +++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -4,7 +4,6 @@ #include "ash/system/unified/unified_slider_bubble_controller.h" -#include "ash/public/cpp/ash_features.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller_impl.h" #include "ash/shelf/shelf.h" @@ -35,7 +34,6 @@ } void ConfigureSliderViewStyle(views::View* slider_view) { - slider_view->SetBackground(UnifiedSystemTrayView::CreateBackground()); slider_view->SetBorder(views::CreateEmptyBorder(kUnifiedSliderBubblePadding)); } @@ -171,25 +169,19 @@ init_params.insets = GetTrayBubbleInsets(); init_params.corner_radius = kUnifiedTrayCornerRadius; init_params.has_shadow = false; + init_params.translucent = true; bubble_view_ = new TrayBubbleView(init_params); UnifiedSliderView* slider_view = static_cast<UnifiedSliderView*>(slider_controller_->CreateView()); ConfigureSliderViewStyle(slider_view); bubble_view_->AddChildView(slider_view); - bubble_view_->set_color(SK_ColorTRANSPARENT); - bubble_view_->layer()->SetFillsBoundsOpaquely(false); bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_); TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_); bubble_view_->InitializeAndShowBubble(); - if (features::IsBackgroundBlurEnabled()) { - bubble_widget_->client_view()->layer()->SetBackgroundBlur( - kUnifiedMenuBackgroundBlur); - } - // Notify value change accessibility event because the popup is triggered by // changing value using an accessor key like VolUp. slider_view->slider()->NotifyAccessibilityEvent(
diff --git a/ash/system/unified/unified_slider_view.cc b/ash/system/unified/unified_slider_view.cc index 635b575..1466b1ef 100644 --- a/ash/system/unified/unified_slider_view.cc +++ b/ash/system/unified/unified_slider_view.cc
@@ -148,6 +148,9 @@ layout->SetFlexForView(slider_, 1); layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); + + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); } void UnifiedSliderView::SetSliderValue(float value, bool by_user) {
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc index 573db0ae..630c02f 100644 --- a/ash/system/unified/unified_system_tray_bubble.cc +++ b/ash/system/unified/unified_system_tray_bubble.cc
@@ -92,6 +92,7 @@ init_params.has_shadow = false; init_params.show_by_click = show_by_click; init_params.close_on_deactivate = false; + init_params.translucent = true; bubble_view_ = new TrayBubbleView(init_params); @@ -104,20 +105,12 @@ controller_->ResetToCollapsedIfRequired(); bubble_view_->AddChildView(new ContainerView(unified_view_)); - bubble_view_->set_color(SK_ColorTRANSPARENT); - bubble_view_->layer()->SetFillsBoundsOpaquely(false); - bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_); bubble_widget_->AddObserver(this); TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_); bubble_view_->InitializeAndShowBubble(); - if (features::IsBackgroundBlurEnabled()) { - bubble_widget_->client_view()->layer()->SetBackgroundBlur( - kUnifiedMenuBackgroundBlur); - } - tray->tray_event_filter()->AddBubble(this); tray->shelf()->AddObserver(this); Shell::Get()->tablet_mode_controller()->AddObserver(this); @@ -234,7 +227,7 @@ if (!unified_view_->IsTransformEnabled()) { unified_view_->SetTransform(gfx::Transform()); - DestroyBlurLayerForAnimation(); + OnAnimationFinished(); SetFrameVisible(true); return; } @@ -251,13 +244,9 @@ transform.Translate(0, y_offset); unified_view_->SetTransform(transform); - CreateBlurLayerForAnimation(); - - if (blur_layer_) { - gfx::Rect blur_bounds = bubble_widget_->client_view()->layer()->bounds(); - blur_bounds.Inset(gfx::Insets(y_offset, 0, 0, 0)); - blur_layer_->layer()->SetBounds(blur_bounds); - } + gfx::Rect blur_bounds = bubble_view_->bounds(); + blur_bounds.Inset(gfx::Insets(y_offset, 0, 0, 0)); + bubble_view_->layer()->SetClipRect(blur_bounds); } TrayBackgroundView* UnifiedSystemTrayBubble::GetTray() const { @@ -385,44 +374,8 @@ tray_->message_center_bubble()->UpdatePosition(); } -void UnifiedSystemTrayBubble::CreateBlurLayerForAnimation() { - if (!features::IsBackgroundBlurEnabled()) - return; - - if (blur_layer_) - return; - - DCHECK(bubble_widget_); - - bubble_widget_->client_view()->layer()->SetBackgroundBlur(0); - - blur_layer_ = std::make_unique<ui::LayerOwner>( - std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR)); - blur_layer_->layer()->SetColor(SK_ColorTRANSPARENT); - blur_layer_->layer()->SetRoundedCornerRadius( - {kUnifiedTrayCornerRadius, kUnifiedTrayCornerRadius, - kUnifiedTrayCornerRadius, kUnifiedTrayCornerRadius}); - blur_layer_->layer()->SetFillsBoundsOpaquely(false); - - bubble_widget_->GetLayer()->Add(blur_layer_->layer()); - bubble_widget_->GetLayer()->StackAtBottom(blur_layer_->layer()); - - blur_layer_->layer()->SetBounds( - bubble_widget_->client_view()->layer()->bounds()); - blur_layer_->layer()->SetBackgroundBlur(kUnifiedMenuBackgroundBlur); -} - -void UnifiedSystemTrayBubble::DestroyBlurLayerForAnimation() { - if (!features::IsBackgroundBlurEnabled()) - return; - - if (!blur_layer_) - return; - - blur_layer_.reset(); - - bubble_widget_->client_view()->layer()->SetBackgroundBlur( - kUnifiedMenuBackgroundBlur); +void UnifiedSystemTrayBubble::OnAnimationFinished() { + bubble_widget_->GetNativeWindow()->layer()->SetClipRect(gfx::Rect()); } void UnifiedSystemTrayBubble::SetFrameVisible(bool visible) {
diff --git a/ash/system/unified/unified_system_tray_bubble.h b/ash/system/unified/unified_system_tray_bubble.h index a75a77c..4e0b301 100644 --- a/ash/system/unified/unified_system_tray_bubble.h +++ b/ash/system/unified/unified_system_tray_bubble.h
@@ -19,10 +19,6 @@ #include "ui/views/widget/widget_observer.h" #include "ui/wm/public/activation_change_observer.h" -namespace ui { -class LayerOwner; -} // namespace ui - namespace views { class Widget; } // namespace views @@ -146,9 +142,8 @@ void UpdateBubbleBounds(); - // Create / destroy background blur layer that is used during animation. - void CreateBlurLayerForAnimation(); - void DestroyBlurLayerForAnimation(); + // Called when the tray animation is finished. + void OnAnimationFinished(); // Set visibility of bubble frame border. Used for disabling the border during // animation. @@ -175,9 +170,6 @@ // click (|show_by_click| in ctor is false), it is not set. base::Optional<base::TimeTicks> time_shown_by_click_; - // Background blur layer that is used during animation. - std::unique_ptr<ui::LayerOwner> blur_layer_; - TrayBubbleView* bubble_view_ = nullptr; UnifiedSystemTrayView* unified_view_ = nullptr;
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc index 93f0772..7ba090c 100644 --- a/ash/system/unified/unified_system_tray_view.cc +++ b/ash/system/unified/unified_system_tray_view.cc
@@ -96,8 +96,6 @@ SystemTrayContainer() { SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical)); - SetBackground(UnifiedSystemTrayView::CreateBackground()); - if (!features::IsUnifiedMessageCenterRefactorEnabled()) SetBorder(std::make_unique<TopCornerBorder>()); } @@ -118,8 +116,6 @@ class DetailedViewContainer : public views::View { public: DetailedViewContainer() { - SetBackground(UnifiedSystemTrayView::CreateBackground()); - if (!features::IsUnifiedMessageCenterRefactorEnabled()) SetBorder(std::make_unique<TopCornerBorder>()); } @@ -317,9 +313,11 @@ auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical)); - SetBackground(CreateBackground()); - SetPaintToLayer(); - layer()->SetFillsBoundsOpaquely(false); + auto add_layered_child = [](views::View* parent, views::View* child) { + parent->AddChildView(child); + child->SetPaintToLayer(); + child->layer()->SetFillsBoundsOpaquely(false); + }; SessionControllerImpl* session_controller = Shell::Get()->session_controller(); @@ -327,7 +325,7 @@ if (!features::IsUnifiedMessageCenterRefactorEnabled()) { message_center_view_ = new UnifiedMessageCenterView( this, controller->model(), nullptr /* message_center_bubble */); - AddChildView(message_center_view_); + add_layered_child(this, message_center_view_); layout->SetFlexForView(message_center_view_, 1); } @@ -335,15 +333,15 @@ session_controller->GetUserSession(0) && session_controller->IsScreenLocked() && !AshMessageCenterLockScreenController::IsEnabled()); - AddChildView(notification_hidden_view_); + add_layered_child(this, notification_hidden_view_); AddChildView(system_tray_container_); - system_tray_container_->AddChildView(top_shortcuts_view_); + add_layered_child(system_tray_container_, top_shortcuts_view_); system_tray_container_->AddChildView(feature_pods_container_); system_tray_container_->AddChildView(page_indicator_view_); system_tray_container_->AddChildView(sliders_container_); - system_tray_container_->AddChildView(system_info_view_); + add_layered_child(system_tray_container_, system_info_view_); if (features::IsManagedDeviceUIRedesignEnabled()) { managed_device_view_ = new UnifiedManagedDeviceView(); @@ -351,7 +349,7 @@ } detailed_view_container_->SetVisible(false); - AddChildView(detailed_view_container_); + add_layered_child(this, detailed_view_container_); // UnifiedSystemTrayView::FocusSearch makes focus traversal start from // |system_tray_container_|, but we have to complete the cycle by setting
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 91c7b3d3..d602b44 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -53,16 +53,6 @@ # keep binary size down. Setting this flag to true disables such optimization android_full_debug = false - # Whether to use the binary binutils checked into third_party/binutils. - # These are not multi-arch so cannot be used except on x86 and x86-64 (the - # only two architectures that are currently checked in). Turn this off when - # you are using a custom toolchain and need to control -B in cflags. - linux_use_bundled_binutils = - linux_use_bundled_binutils_override && is_linux && - (current_cpu == "x64" || current_cpu == "x86") - binutils_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin", - root_build_dir) - # Compile in such a way as to make it possible for the profiler to unwind full # stack frames. Setting this flag has a large effect on the performance of the # generated code than just setting profiling, but gives the profiler more
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index b848861..cdd85c77 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -42,6 +42,16 @@ # example, don't omit the frame pointer and leave in symbols. enable_profiling = false + # Whether to use the binary binutils checked into third_party/binutils. + # These are not multi-arch so cannot be used except on x86 and x86-64 (the + # only two architectures that are currently checked in). Turn this off when + # you are using a custom toolchain and need to control -B in cflags. + linux_use_bundled_binutils = + linux_use_bundled_binutils_override && is_linux && + (current_cpu == "x64" || current_cpu == "x86") + binutils_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin", + root_build_dir) + # use_debug_fission: whether to use split DWARF debug info # files. This can reduce link time significantly, but is incompatible # with some utilities such as icecc and ccache. Requires gold and
diff --git a/build/config/linux/gtk/BUILD.gn b/build/config/linux/gtk/BUILD.gn index d78f740..a58b089 100644 --- a/build/config/linux/gtk/BUILD.gn +++ b/build/config/linux/gtk/BUILD.gn
@@ -36,7 +36,7 @@ "//remoting/host:remoting_me2me_host_static", "//remoting/test:it2me_standalone_host_main", "//webrtc/examples:peerconnection_client", - "//chrome/browser/ui/libgtkui:*", + "//chrome/browser/ui/gtk:*", ] public_configs = [ ":gtk_internal_config" ] @@ -48,6 +48,6 @@ } group("gtkprint") { - visibility = [ "//chrome/browser/ui/libgtkui:*" ] + visibility = [ "//chrome/browser/ui/gtk:*" ] public_configs = [ ":gtkprint_internal_config" ] }
diff --git a/cc/input/browser_controls_offset_manager.cc b/cc/input/browser_controls_offset_manager.cc index 80c45af..ad5ac24 100644 --- a/cc/input/browser_controls_offset_manager.cc +++ b/cc/input/browser_controls_offset_manager.cc
@@ -152,12 +152,12 @@ // Don't do anything if there is no change in offset. float final_top_shown_ratio = 1.f; float final_bottom_shown_ratio = 1.f; - AnimationDirection direction = SHOWING_CONTROLS; + AnimationDirection direction = AnimationDirection::SHOWING_CONTROLS; if (constraints == BrowserControlsState::kHidden || current == BrowserControlsState::kHidden) { final_top_shown_ratio = TopControlsMinShownRatio(); final_bottom_shown_ratio = BottomControlsMinShownRatio(); - direction = HIDING_CONTROLS; + direction = AnimationDirection::HIDING_CONTROLS; } if (final_top_shown_ratio == TopControlsShownRatio() && final_bottom_shown_ratio == BottomControlsShownRatio()) { @@ -438,9 +438,11 @@ void BrowserControlsOffsetManager::SetupAnimation( AnimationDirection direction) { - DCHECK_NE(NO_ANIMATION, direction); - DCHECK(direction != HIDING_CONTROLS || TopControlsShownRatio() > 0.f); - DCHECK(direction != SHOWING_CONTROLS || TopControlsShownRatio() < 1.f); + DCHECK_NE(AnimationDirection::NO_ANIMATION, direction); + DCHECK(direction != AnimationDirection::HIDING_CONTROLS || + TopControlsShownRatio() > 0.f); + DCHECK(direction != AnimationDirection::SHOWING_CONTROLS || + TopControlsShownRatio() < 1.f); if (top_controls_animation_.IsInitialized() && top_controls_animation_.Direction() == direction && @@ -449,14 +451,15 @@ return; if (!TopControlsHeight() && !BottomControlsHeight()) { - float ratio = direction == HIDING_CONTROLS ? 0.f : 1.f; + float ratio = direction == AnimationDirection::HIDING_CONTROLS ? 0.f : 1.f; client_->SetCurrentBrowserControlsShownRatio(ratio, ratio); return; } // Providing artificially larger/smaller stop ratios to make the animation // faster if the start ratio is closer to stop ratio. - const float max_stop_ratio = direction == SHOWING_CONTROLS ? 1 : -1; + const float max_stop_ratio = + direction == AnimationDirection::SHOWING_CONTROLS ? 1 : -1; float top_start_ratio = TopControlsShownRatio(); float top_stop_ratio = top_start_ratio + max_stop_ratio; top_controls_animation_.Initialize(direction, top_start_ratio, top_stop_ratio, @@ -486,16 +489,17 @@ (1.f - TopControlsMinShownRatio()); if (normalized_top_ratio >= 1.f - controls_hide_threshold_) { // If we're showing so much that the hide threshold won't trigger, show. - SetupAnimation(SHOWING_CONTROLS); + SetupAnimation(AnimationDirection::SHOWING_CONTROLS); } else if (normalized_top_ratio <= controls_show_threshold_) { // If we're showing so little that the show threshold won't trigger, hide. - SetupAnimation(HIDING_CONTROLS); + SetupAnimation(AnimationDirection::HIDING_CONTROLS); } else { // If we could be either showing or hiding, we determine which one to // do based on whether or not the total scroll delta was moving up or // down. - SetupAnimation(accumulated_scroll_delta_ <= 0.f ? SHOWING_CONTROLS - : HIDING_CONTROLS); + SetupAnimation(accumulated_scroll_delta_ <= 0.f + ? AnimationDirection::SHOWING_CONTROLS + : AnimationDirection::HIDING_CONTROLS); } } @@ -509,8 +513,9 @@ Animation* animation, float start_ratio, float stop_ratio) { - AnimationDirection direction = - start_ratio < stop_ratio ? SHOWING_CONTROLS : HIDING_CONTROLS; + AnimationDirection direction = start_ratio < stop_ratio + ? AnimationDirection::SHOWING_CONTROLS + : AnimationDirection::HIDING_CONTROLS; animation->Initialize(direction, start_ratio, stop_ratio, kHeightChangeDurationMs, /*jump_to_end_on_reset=*/true); } @@ -597,7 +602,7 @@ start_value_ = 0.f; stop_time_ = base::TimeTicks(); stop_value_ = 0.f; - direction_ = NO_ANIMATION; + direction_ = AnimationDirection::NO_ANIMATION; duration_ = base::TimeDelta(); min_value_ = 0.f; max_value_ = 1.f; @@ -607,9 +612,9 @@ } bool BrowserControlsOffsetManager::Animation::IsComplete(float value) { - return (direction_ == SHOWING_CONTROLS && + return (direction_ == AnimationDirection::SHOWING_CONTROLS && (value >= stop_value_ || value >= max_value_)) || - (direction_ == HIDING_CONTROLS && + (direction_ == AnimationDirection::HIDING_CONTROLS && (value <= stop_value_ || value <= min_value_)); }
diff --git a/cc/input/browser_controls_offset_manager.h b/cc/input/browser_controls_offset_manager.h index 2d09cde..8d9c66e1 100644 --- a/cc/input/browser_controls_offset_manager.h +++ b/cc/input/browser_controls_offset_manager.h
@@ -21,7 +21,11 @@ // Manages the position of the browser controls. class CC_EXPORT BrowserControlsOffsetManager { public: - enum AnimationDirection { NO_ANIMATION, SHOWING_CONTROLS, HIDING_CONTROLS }; + enum class AnimationDirection { + NO_ANIMATION, + SHOWING_CONTROLS, + HIDING_CONTROLS + }; static std::unique_ptr<BrowserControlsOffsetManager> Create( BrowserControlsOffsetManagerClient* client, @@ -142,7 +146,7 @@ // Whether the animation is initialized with a direction and start and stop // values. bool IsInitialized() { return initialized_; } - bool Direction() { return direction_; } + AnimationDirection Direction() { return direction_; } void Initialize(AnimationDirection direction, float start_value, float stop_value, @@ -170,7 +174,7 @@ // Whether the animation is initialized by setting start and stop time and // values. bool initialized_ = false; - AnimationDirection direction_ = NO_ANIMATION; + AnimationDirection direction_ = AnimationDirection::NO_ANIMATION; // Monotonic start and stop times. base::TimeTicks start_time_; base::TimeTicks stop_time_;
diff --git a/chrome/VERSION b/chrome/VERSION index b068947..c51468745 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=81 MINOR=0 -BUILD=4036 +BUILD=4037 PATCH=0
diff --git a/chrome/android/DEPS b/chrome/android/DEPS index 0cdae9d..baebb3b 100644 --- a/chrome/android/DEPS +++ b/chrome/android/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+chrome/browser/flags", "+chrome/browser/notifications", "+chrome/browser/preferences/android/java", "+chrome/browser/settings/android",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 80c9772..bf6a2c0d9 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -493,6 +493,7 @@ "javatests/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java", "javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java", "javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java", + "javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarWithStartSurfaceTest.java", "javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java", "javatests/src/org/chromium/chrome/browser/toolbar/top/BrandColorTest.java", "javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java index 01399b06..c941b97 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.Destroyable; +import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabImpl; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; @@ -27,23 +28,39 @@ /** * Coordinator object for gesture navigation. */ -public class HistoryNavigationCoordinator - implements InsetObserverView.WindowInsetObserver, Destroyable { +public class HistoryNavigationCoordinator implements InsetObserverView.WindowInsetObserver, + Destroyable, PauseResumeWithNativeObserver { private CompositorViewHolder mCompositorViewHolder; private HistoryNavigationLayout mNavigationLayout; private InsetObserverView mInsetObserverView; private ActivityTabTabObserver mActivityTabObserver; private ActivityLifecycleDispatcher mActivityLifecycleDispatcher; private Tab mTab; + private boolean mEnabled; /** - * Initializes the navigation layout and internal objects. + * Creates the coordinator for gesture navigation and initializes internal objects. + * @param lifecycleDispatcher Lifecycle dispatcher for the associated activity. * @param compositorViewHolder Parent view for navigation layout. * @param tabProvider Activity tab provider. * @param insetObserverView View that provides information about the inset and inset * capabilities of the device. + * @return HistoryNavigationCoordinator object or null if not enabled via feature flag. */ - public void init(ActivityLifecycleDispatcher lifecycleDispatcher, + public static HistoryNavigationCoordinator create( + ActivityLifecycleDispatcher lifecycleDispatcher, + CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider, + InsetObserverView insetObserverView) { + if (!isFeatureFlagEnabled()) return null; + HistoryNavigationCoordinator coordinator = new HistoryNavigationCoordinator(); + coordinator.init(lifecycleDispatcher, compositorViewHolder, tabProvider, insetObserverView); + return coordinator; + } + + /** + * Initializes the navigation layout and internal objects. + */ + private void init(ActivityLifecycleDispatcher lifecycleDispatcher, CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider, InsetObserverView insetObserverView) { mNavigationLayout = new HistoryNavigationLayout(compositorViewHolder.getContext()); @@ -56,14 +73,16 @@ mActivityTabObserver = new ActivityTabProvider.ActivityTabTabObserver(tabProvider) { @Override protected void onObservingDifferentTab(Tab tab) { - if (mTab == tab) return; - onTabSwitched(tab); + if (mTab != null && mTab.isInitialized()) { + SwipeRefreshHandler.from(mTab).setNavigationHandler(null); + } + mTab = tab; + updateNavigationHandler(); } @Override public void onContentChanged(Tab tab) { - initNavigationHandler( - tab, createDelegate(tab), tab.getWebContents(), tab.isNativePage()); + updateNavigationHandler(); } @Override @@ -74,7 +93,10 @@ // We wouldn't hear about the first tab until the content changed or we switched tabs // if tabProvider.get() != null. Do here what we do when tab switching happens. - if (tabProvider.get() != null) onTabSwitched(tabProvider.get()); + if (tabProvider.get() != null) { + mTab = tabProvider.get(); + onNavigationStateChanged(); + } mNavigationLayout.setVisibility(View.INVISIBLE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { @@ -87,9 +109,7 @@ * Creates {@link HistoryNavigationDelegate} for native/rendered pages on Tab. */ private static HistoryNavigationDelegate createDelegate(Tab tab) { - if (!isFeatureFlagEnabled() || ((TabImpl) tab).getActivity() == null) { - return HistoryNavigationDelegate.DEFAULT; - } + if (((TabImpl) tab).getActivity() == null) return HistoryNavigationDelegate.DEFAULT; return new HistoryNavigationDelegate() { // TODO(jinsukkim): Avoid getting activity from tab. @@ -121,49 +141,55 @@ return ChromeFeatureList.isEnabled(ChromeFeatureList.OVERSCROLL_HISTORY_NAVIGATION); } - @Override - public void onInsetChanged(int left, int top, int right, int bottom) { - // Resets navigation handler when the feature becomes disabled. - if (!isNavigationEnabled(mCompositorViewHolder)) { - initNavigationHandler(mTab, HistoryNavigationDelegate.DEFAULT, null, false); + /** + * @return {@code} true if the feature is enabled. + */ + private boolean isFeatureEnabled() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + return true; + } else { + assert mCompositorViewHolder.isAttachedToWindow(); + Insets insets = mCompositorViewHolder.getRootWindowInsets().getSystemGestureInsets(); + return insets.left == 0 && insets.right == 0; } } - private void onTabSwitched(Tab tab) { - WebContents webContents = tab != null ? tab.getWebContents() : null; - HistoryNavigationDelegate delegate = - webContents != null && isNavigationEnabled(mCompositorViewHolder) - ? createDelegate(tab) - : HistoryNavigationDelegate.DEFAULT; - - // Also resets NavigationHandler when there's no tab (going into TabSwitcher). - if (tab == null || webContents != null) { - initNavigationHandler( - tab, delegate, webContents, tab != null ? tab.isNativePage() : false); - } + @Override + public void onInsetChanged(int left, int top, int right, int bottom) { + onNavigationStateChanged(); } /** - * @param view {@link View} object to obtain the navigation setting from. - * @return {@code true} if overscroll navigation is allowed to run on this page. + * Called when an event that can change the state of navigation feature. Update enabled status + * and (re)initialize NavigationHandler if necessary. */ - private static boolean isNavigationEnabled(View view) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true; - Insets insets = view.getRootWindowInsets().getSystemGestureInsets(); - return insets.left == 0 && insets.right == 0; + private void onNavigationStateChanged() { + boolean oldEnabled = mEnabled; + mEnabled = isFeatureEnabled(); + if (mEnabled != oldEnabled) updateNavigationHandler(); } - private void initNavigationHandler(Tab tab, HistoryNavigationDelegate delegate, - WebContents webContents, boolean isNativePage) { - assert mNavigationLayout != null; - mNavigationLayout.initNavigationHandler(delegate, webContents, isNativePage); - if (mTab != tab) { - if (mTab != null) SwipeRefreshHandler.from(mTab).setNavigationHandler(null); - if (tab != null) { - SwipeRefreshHandler.from(tab).setNavigationHandler( - mNavigationLayout.getNavigationHandler()); + /** + * Initialize or reset {@link NavigationHandler} using the enabled state. + */ + private void updateNavigationHandler() { + if (mEnabled) { + WebContents webContents = mTab != null ? mTab.getWebContents() : null; + + // Also updates NavigationHandler when tab == null (going into TabSwitcher). + if (mTab == null || webContents != null) { + HistoryNavigationDelegate delegate = webContents != null + ? createDelegate(mTab) + : HistoryNavigationDelegate.DEFAULT; + boolean isNativePage = mTab != null ? mTab.isNativePage() : false; + mNavigationLayout.initNavigationHandler(delegate, webContents, isNativePage); } - mTab = tab; + } else { + mNavigationLayout.destroy(); + } + if (mTab != null) { + SwipeRefreshHandler.from(mTab).setNavigationHandler( + mNavigationLayout.getNavigationHandler()); } } @@ -171,6 +197,16 @@ public void onSafeAreaChanged(Rect area) {} @Override + public void onResumeWithNative() { + // Check the enabled status again since the system gesture settings might have changed. + // Post the task to work around wrong gesture insets returned from the framework. + mNavigationLayout.post(this::onNavigationStateChanged); + } + + @Override + public void onPauseWithNative() {} + + @Override public void destroy() { if (mActivityTabObserver != null) { mActivityTabObserver.destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java index 906f9e01..43e08c08 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java
@@ -157,5 +157,7 @@ mNavigationHandler.setDelegate(mDelegate); mNavigationHandler = null; } + mDetector = null; + mWebContents = null; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java index 768f208..f1e2b88 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java
@@ -11,6 +11,8 @@ import android.os.Build; import android.util.Pair; +import androidx.annotation.VisibleForTesting; + import org.chromium.base.ApplicationStatus; import org.chromium.base.ContextUtils; import org.chromium.base.annotations.NativeMethods; @@ -28,6 +30,7 @@ * Utilities for working with incognito tabs spread across multiple activities. */ public class IncognitoUtils { + private static Boolean sIsEnabledForTesting; private IncognitoUtils() {} @@ -127,6 +130,9 @@ * @return true if incognito mode is enabled. */ public static boolean isIncognitoModeEnabled() { + if (sIsEnabledForTesting != null) { + return sIsEnabledForTesting; + } return IncognitoUtilsJni.get().getIncognitoModeEnabled(); } @@ -137,6 +143,11 @@ return IncognitoUtilsJni.get().getIncognitoModeManaged(); } + @VisibleForTesting + public static void setEnabledForTesting(Boolean enabled) { + sIsEnabledForTesting = enabled; + } + @NativeMethods interface Natives { boolean getIncognitoModeEnabled();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java index 7a70672..0fa6f08c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java
@@ -24,6 +24,9 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.document.ChromeLauncherActivity; +import org.chromium.chrome.browser.init.BrowserParts; +import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.init.EmptyBrowserParts; import org.chromium.chrome.browser.notifications.ChromeNotification; import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder; import org.chromium.chrome.browser.notifications.NotificationBuilderFactory; @@ -37,6 +40,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareNotificationInteraction; import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareNotificationInteraction.InteractionType; +import org.chromium.chrome.browser.util.IntentUtils; /** * Manages all SendTabToSelf related notifications for Android. This includes displaying, handling @@ -44,34 +48,44 @@ */ public class NotificationManager { private static final String NOTIFICATION_GUID_EXTRA = "send_tab_to_self.notification.guid"; + // Action constants for the registered BroadcastReceiver. + private static final String NOTIFICATION_ACTION_TAP = "send_tab_to_self.tap"; + private static final String NOTIFICATION_ACTION_DISMISS = "send_tab_to_self.dismiss"; + private static final String NOTIFICATION_ACTION_TIMEOUT = "send_tab_to_self.timeout"; - /** Records dismissal when notification is swiped away. */ - public static final class DeleteReceiver extends BroadcastReceiver { + /** Handles changes to notifications based on user action or timeout. */ + public static final class SendTabToSelfNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - String guid = intent.getStringExtra(NOTIFICATION_GUID_EXTRA); - hideNotification(guid, InteractionType.DISMISSED); - SendTabToSelfAndroidBridge.dismissEntry(Profile.getLastUsedProfile(), guid); - } - } + final BrowserParts parts = new EmptyBrowserParts() { + @Override + public void finishNativeInitialization() { + final String action = intent.getAction(); + final String guid = + IntentUtils.safeGetStringExtra(intent, NOTIFICATION_GUID_EXTRA); + switch (action) { + case NOTIFICATION_ACTION_TAP: + openUrl(intent.getData()); + hideNotification(guid, InteractionType.OPENED); + SendTabToSelfAndroidBridge.deleteEntry( + Profile.getLastUsedProfile(), guid); + break; + case NOTIFICATION_ACTION_DISMISS: + hideNotification(guid, InteractionType.DISMISSED); + SendTabToSelfAndroidBridge.dismissEntry( + Profile.getLastUsedProfile(), guid); + break; + case NOTIFICATION_ACTION_TIMEOUT: + SendTabToSelfAndroidBridge.dismissEntry( + Profile.getLastUsedProfile(), guid); + break; + } + } + }; - /** Handles the tapping of a notification by opening the URL and hiding the notification. */ - public static final class TapReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - openUrl(intent.getData()); - String guid = intent.getStringExtra(NOTIFICATION_GUID_EXTRA); - hideNotification(guid, InteractionType.OPENED); - SendTabToSelfAndroidBridge.deleteEntry(Profile.getLastUsedProfile(), guid); - } - } - - /** Removes the notification after a timeout period. */ - public static final class TimeoutReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String guid = intent.getStringExtra(NOTIFICATION_GUID_EXTRA); - SendTabToSelfAndroidBridge.dismissEntry(Profile.getLastUsedProfile(), guid); + // Try to load native. + ChromeBrowserInitializer.getInstance().handlePreNativeStartup(parts); + ChromeBrowserInitializer.getInstance().handlePostNativeStartup(true, parts); } } @@ -154,13 +168,15 @@ int nextId = NotificationSharedPrefManager.getNextNotificationId(); Uri uri = Uri.parse(url); PendingIntentProvider contentIntent = PendingIntentProvider.getBroadcast(context, nextId, - new Intent(context, TapReceiver.class) + new Intent(context, SendTabToSelfNotificationReceiver.class) .setData(uri) + .setAction(NOTIFICATION_ACTION_TAP) .putExtra(NOTIFICATION_GUID_EXTRA, guid), 0); PendingIntentProvider deleteIntent = PendingIntentProvider.getBroadcast(context, nextId, - new Intent(context, DeleteReceiver.class) + new Intent(context, SendTabToSelfNotificationReceiver.class) .setData(uri) + .setAction(NOTIFICATION_ACTION_DISMISS) .putExtra(NOTIFICATION_GUID_EXTRA, guid), 0); // IDS_SEND_TAB_TO_SELF_NOTIFICATION_CONTEXT_TEXT @@ -200,8 +216,9 @@ if (timeoutAtMillis != Long.MAX_VALUE) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - Intent timeoutIntent = new Intent(context, TimeoutReceiver.class) + Intent timeoutIntent = new Intent(context, SendTabToSelfNotificationReceiver.class) .setData(Uri.parse(url)) + .setAction(NOTIFICATION_ACTION_TIMEOUT) .putExtra(NOTIFICATION_GUID_EXTRA, guid); alarmManager.set(AlarmManager.RTC, timeoutAtMillis, PendingIntent.getBroadcast(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS index 81c8f9da..650e5bf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -8,6 +8,7 @@ "+chrome/android/java/src/org/chromium/chrome/browser/ssl/SecurityStateModel.java", "+chrome/android/java/src/org/chromium/chrome/browser/tab", "+chrome/android/java/src/org/chromium/chrome/browser/webapps/WebDisplayMode.java", + "+chrome/browser/flags", "+chrome/browser/preferences", "+chrome/browser/ui/android/native_page", "+chrome/browser/ui/android/widget",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java index 085a51e0..ba9e5d8e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -49,7 +49,6 @@ private StatusIndicatorCoordinator mStatusIndicatorCoordinator; private StatusIndicatorCoordinator.StatusIndicatorObserver mStatusIndicatorObserver; private @Nullable ToolbarButtonInProductHelpController mToolbarButtonInProductHelpController; - private HistoryNavigationCoordinator mHistoryNavigationCoordinator; private boolean mIntentWithEffect; /** @@ -97,10 +96,6 @@ if (mImmersiveModeManager != null) { getToolbarManager().setImmersiveModeManager(mImmersiveModeManager); } - mHistoryNavigationCoordinator = new HistoryNavigationCoordinator(); - mHistoryNavigationCoordinator.init(mActivity.getLifecycleDispatcher(), - mActivity.getCompositorViewHolder(), mActivity.getActivityTabProvider(), - mActivity.getInsetObserverView()); } /** @@ -134,6 +129,9 @@ super.onLayoutManagerAvailable(layoutManager); initStatusIndicatorCoordinator(layoutManager); + HistoryNavigationCoordinator.create(mActivity.getLifecycleDispatcher(), + mActivity.getCompositorViewHolder(), mActivity.getActivityTabProvider(), + mActivity.getInsetObserverView()); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java index 31ad72d3..1870482 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java
@@ -43,6 +43,7 @@ */ void destroy() { mToolbarMediator.destroy(); + if (mIncognitoSwitchCoordinator != null) mIncognitoSwitchCoordinator.destroy(); } /** * @param appMenuButtonHelper The helper for managing menu button interactions.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentHandlerChangePaymentMethodTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentHandlerChangePaymentMethodTest.java index 6cf4e9f..0ee24ef 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentHandlerChangePaymentMethodTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentHandlerChangePaymentMethodTest.java
@@ -26,7 +26,8 @@ /** An integration test for PaymentRequestEvent.changePaymentMethod(). */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - "enable-blink-features=PaymentMethodChangeEvent,PaymentHandlerChangePaymentMethod"}) + "enable-blink-features=PaymentMethodChangeEvent,PaymentHandlerChangePaymentMethod", + "disable-field-trial-config"}) @MediumTest public class PaymentHandlerChangePaymentMethodTest { // Disable animations to reduce flakiness. @@ -193,4 +194,4 @@ + "\"paymentMethodErrors\":{\"country\":\"Unsupported country\"}," + "\"total\":{\"currency\":\"GBP\",\"value\":\"0.02\"}}"}); } -} \ No newline at end of file +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java index 49593b1f..3c0aeabe 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
@@ -37,7 +37,8 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, // For all the tests in this file, we expect abort exception when there is no supported // payment instruments instead of showing payment request UI. - "enable-features=" + ChromeFeatureList.STRICT_HAS_ENROLLED_AUTOFILL_INSTRUMENT}) + "enable-features=" + ChromeFeatureList.STRICT_HAS_ENROLLED_AUTOFILL_INSTRUMENT, + "disable-field-trial-config"}) public class PaymentRequestServiceWorkerPaymentAppTest { // Disable animations to reduce flakiness. @ClassRule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java index cdf951db..ff97355e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarTest.java
@@ -4,6 +4,15 @@ package org.chromium.chrome.browser.toolbar.bottom; +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR; +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR_HOME; +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR_NEW_TAB; +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR_SEARCH; +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR_SHARE; +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR_TAB_SWITCHER; +import static org.chromium.chrome.test.util.ToolbarTestUtils.checkToolbarButtonVisibility; +import static org.chromium.chrome.test.util.ToolbarTestUtils.checkToolbarVisibility; + import android.support.test.filters.MediumTest; import android.view.View; import android.view.ViewGroup; @@ -17,7 +26,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Restriction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.flags.FeatureUtilities; @@ -53,27 +61,19 @@ @Test @MediumTest - public void testBottomToolbarVisibility() { - mActivityTestRule.startMainActivityOnBlankPage(); - Assert.assertNotNull("BottomToolbarCoordinator should be constructed.", - mActivityTestRule.getActivity().getToolbarManager().getBottomToolbarCoordinator()); - - View bottomToolbar = mActivityTestRule.getActivity().findViewById(R.id.bottom_toolbar); - Assert.assertEquals("Bottom toolbar view should be visible.", View.VISIBLE, - bottomToolbar.getVisibility()); - } - - @Test - @MediumTest - public void testBottomToolbarTabSwitcherButton_Home_Search_Tab_Switcher() - throws ExecutionException { + public void testBottomToolbar_Home_Search_Tab_Switcher() throws ExecutionException { BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_TAB_SWITCHER); mActivityTestRule.startMainActivityOnBlankPage(); - Assert.assertFalse("Tab switcher should not be visible.", - mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible()); - ViewGroup bottomToolbar = mActivityTestRule.getActivity().findViewById(R.id.bottom_toolbar); - View tabSwitcherButton = bottomToolbar.findViewById(R.id.bottom_tab_switcher_button); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_HOME, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_SEARCH, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_TAB_SWITCHER, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_NEW_TAB, false); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_SHARE, false); + + ViewGroup bottomToolbar = mActivityTestRule.getActivity().findViewById(BOTTOM_TOOLBAR); + View tabSwitcherButton = bottomToolbar.findViewById(BOTTOM_TOOLBAR_TAB_SWITCHER); OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher( mActivityTestRule.getActivity().getOverviewModeBehavior(), true, false); @@ -83,4 +83,40 @@ Assert.assertTrue("Tab switcher should be visible.", mActivityTestRule.getActivity().getOverviewModeBehavior().overviewVisible()); } + + @Test + @MediumTest + public void testBottomToolbar_New_Tab_Search_Share() throws ExecutionException { + BottomToolbarVariationManager.setVariation(Variations.NEW_TAB_SEARCH_SHARE); + mActivityTestRule.startMainActivityOnBlankPage(); + + checkToolbarVisibility(BOTTOM_TOOLBAR, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_NEW_TAB, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_SEARCH, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_SHARE, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_HOME, false); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_TAB_SWITCHER, false); + + int tabCount = mActivityTestRule.getActivity().getCurrentTabModel().getCount(); + ViewGroup bottomToolbar = mActivityTestRule.getActivity().findViewById(BOTTOM_TOOLBAR); + View newTabButton = bottomToolbar.findViewById(BOTTOM_TOOLBAR_NEW_TAB); + TestThreadUtils.runOnUiThreadBlocking(() -> newTabButton.callOnClick()); + + Assert.assertEquals( + tabCount + 1, mActivityTestRule.getActivity().getCurrentTabModel().getCount()); + } + + @Test + @MediumTest + public void testBottomToolbar_Home_Search_Share() { + BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_SHARE); + mActivityTestRule.startMainActivityOnBlankPage(); + + checkToolbarVisibility(BOTTOM_TOOLBAR, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_HOME, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_SEARCH, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_SHARE, true); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_NEW_TAB, false); + checkToolbarButtonVisibility(BOTTOM_TOOLBAR, BOTTOM_TOOLBAR_TAB_SWITCHER, false); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarWithStartSurfaceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarWithStartSurfaceTest.java new file mode 100644 index 0000000..60662d1 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarWithStartSurfaceTest.java
@@ -0,0 +1,93 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.toolbar.bottom; + +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR; +import static org.chromium.chrome.test.util.ToolbarTestUtils.checkToolbarVisibility; + +import android.support.test.filters.MediumTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.compositor.layouts.OverviewModeState; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.FeatureUtilities; +import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager.Variations; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.test.util.UiRestriction; + +/** + * Test bottom toolbar when start surface is enabled. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + "enable-features=" + ChromeFeatureList.START_SURFACE_ANDROID + "<Study", + "force-fieldtrials=Study/Group", + "force-fieldtrial-params=Study.Group:start_surface_variation/single"}) +public class BottomToolbarWithStartSurfaceTest { + @Rule + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + @Before + public void setUp() { + FeatureUtilities.setIsBottomToolbarEnabledForTesting(true); + FeatureUtilities.setStartSurfaceEnabledForTesting(true); + } + + @After + public void tearDown() { + FeatureUtilities.setIsBottomToolbarEnabledForTesting(null); + FeatureUtilities.setStartSurfaceEnabledForTesting(null); + } + + private void launchActivity(@Variations String variation) { + BottomToolbarVariationManager.setVariation(variation); + mActivityTestRule.startMainActivityFromLauncher(); + } + + @Test + @MediumTest + public void testShowAndHideSingleSurface() { + launchActivity(Variations.HOME_SEARCH_SHARE); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); + TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity() + .getStartSurface() + .getController() + .setOverviewState(OverviewModeState.SHOWING_HOMEPAGE)); + TestThreadUtils.runOnUiThreadBlocking( + () -> mActivityTestRule.getActivity().getLayoutManager().showOverview(false)); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); + TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity() + .getStartSurface() + .getController() + .setOverviewState(OverviewModeState.SHOWING_TABSWITCHER)); + TestThreadUtils.runOnUiThreadBlocking( + () -> mActivityTestRule.getActivity().getLayoutManager().showOverview(false)); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); + TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity() + .getStartSurface() + .getController() + .setOverviewState(OverviewModeState.NOT_SHOWN)); + TestThreadUtils.runOnUiThreadBlocking( + () -> mActivityTestRule.getActivity().getLayoutManager().hideOverview(false)); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java index 356ca52..e709337 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/AdaptiveToolbarTest.java
@@ -4,23 +4,27 @@ package org.chromium.chrome.browser.toolbar.top; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.matcher.ViewMatchers.withId; - -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.enterTabSwitcher; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.rotateDeviceToOrientation; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.verifyTabSwitcherCardCount; +import static org.chromium.chrome.test.util.ToolbarTestUtils.BOTTOM_TOOLBAR; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TAB_SWITCHER_TOOLBAR; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TAB_SWITCHER_TOOLBAR_MENU; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TAB_SWITCHER_TOOLBAR_NEW_TAB; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TOP_TOOLBAR; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TOP_TOOLBAR_HOME; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TOP_TOOLBAR_MENU; +import static org.chromium.chrome.test.util.ToolbarTestUtils.TOP_TOOLBAR_TAB_SWITCHER; +import static org.chromium.chrome.test.util.ToolbarTestUtils.checkToolbarButtonVisibility; +import static org.chromium.chrome.test.util.ToolbarTestUtils.checkToolbarVisibility; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.support.test.filters.MediumTest; -import android.view.View; import org.junit.After; import org.junit.Before; @@ -31,12 +35,12 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Restriction; -import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.FeatureUtilities; +import org.chromium.chrome.browser.incognito.IncognitoUtils; import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager; import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarVariationManager.Variations; import org.chromium.chrome.features.start_surface.StartSurfaceLayout; @@ -98,18 +102,65 @@ final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); Layout layout = cta.getLayoutManager().getOverviewLayout(); assertTrue(layout instanceof StartSurfaceLayout); + + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_TAB_SWITCHER, false); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_HOME, false); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 1); // Both menu and new tab button should be visible in top tab switcher toolbar. - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + + checkToolbarVisibility(BOTTOM_TOOLBAR, false); rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); // Both menu and new tab button should be visible in top tab switcher toolbar. - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); + } + + @Test + @MediumTest + // clang-format off + @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + + "<Study", "force-fieldtrials=Study/Group", NO_NEW_TAB_VARIATION_PARAMS}) + public void testTopToolbar_WithGTS_WithBottomToolbar_Home_Search_Tab_Switcher_IncognitoDisabled() { + // clang-format on + IncognitoUtils.setEnabledForTesting(false); + BottomToolbarVariationManager.setVariation(Variations.HOME_SEARCH_TAB_SWITCHER); + setupFlagsAndLaunchActivity(true, true); + final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + Layout layout = cta.getLayoutManager().getOverviewLayout(); + assertTrue(layout instanceof StartSurfaceLayout); + + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_TAB_SWITCHER, false); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_HOME, false); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); + enterTabSwitcher(cta); + verifyTabSwitcherCardCount(cta, 1); + + // Both menu and new tab button should be visible in top tab switcher toolbar. + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + + // Show bottom toolbar when incognito is disabled. + checkToolbarVisibility(BOTTOM_TOOLBAR, true); + + rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); + + // Both menu and new tab button should be visible in top tab switcher toolbar. + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); + + // Reset incognito. + IncognitoUtils.setEnabledForTesting(null); } @Test @@ -124,18 +175,25 @@ final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); Layout layout = cta.getLayoutManager().getOverviewLayout(); assertTrue(layout instanceof StartSurfaceLayout); + + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_TAB_SWITCHER, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_HOME, false); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 1); // Both menu and new tab button should be visible in top tab switcher toolbar. - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); // Both menu and new tab button should be visible in top tab switcher toolbar. - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); } @Test @@ -150,19 +208,26 @@ final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); Layout layout = cta.getLayoutManager().getOverviewLayout(); assertTrue(layout instanceof StartSurfaceLayout); + + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_TAB_SWITCHER, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 1); // Menu button should be visible and new tab button should be invisible // in top tab switcher toolbar. - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(false, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, false); + // Bottom toolbar should be visible. + checkToolbarVisibility(BOTTOM_TOOLBAR, true); rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); // Both menu and new tab button should be visible in top tab switcher toolbar. - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); } @Test @@ -179,13 +244,13 @@ enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 1); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); } @Test @@ -196,15 +261,26 @@ final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); Layout layout = cta.getLayoutManager().getOverviewLayout(); assertFalse(layout instanceof StartSurfaceLayout); + + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_TAB_SWITCHER, false); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_HOME, false); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); enterTabSwitcher(cta); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarButtonVisibility( + TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON, false); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarButtonVisibility( + TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); } @Test @@ -215,15 +291,26 @@ final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); Layout layout = cta.getLayoutManager().getOverviewLayout(); assertFalse(layout instanceof StartSurfaceLayout); + + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_TAB_SWITCHER, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_HOME, false); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); enterTabSwitcher(cta); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarButtonVisibility( + TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarButtonVisibility( + TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); } @Test @@ -234,42 +321,23 @@ final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); Layout layout = cta.getLayoutManager().getOverviewLayout(); assertFalse(layout instanceof StartSurfaceLayout); + + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TOP_TOOLBAR, TOP_TOOLBAR_TAB_SWITCHER, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); enterTabSwitcher(cta); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(false, true); - + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, false); + checkToolbarButtonVisibility( + TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, true); rotateDeviceToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE); - checkTopToolbarButtonsExistence(true); - checkTopToolbarButtonsVisibility(true); - } - - private void checkTopToolbarButtonsExistence(boolean isNotNull) { - onView(withId(R.id.tab_switcher_toolbar)).check((v, noMatchingViewException) -> { - View newTabButton = v.findViewById(R.id.new_tab_button); - View menuButton = v.findViewById(R.id.menu_button_wrapper); - if (isNotNull) { - assertNotNull(newTabButton); - assertNotNull(menuButton); - } else { - assertNull(newTabButton); - assertNull(menuButton); - } - }); - } - - private void checkTopToolbarButtonsVisibility(boolean isVisible) { - checkTopToolbarButtonsVisibility(isVisible, isVisible); - } - - private void checkTopToolbarButtonsVisibility( - boolean isNewTabButtonVisible, boolean isMenuButtonVisible) { - onView(withId(R.id.tab_switcher_toolbar)).check((v, noMatchingViewException) -> { - View newTabButton = v.findViewById(R.id.new_tab_button); - View menuButton = v.findViewById(R.id.menu_button_wrapper); - assertEquals(isNewTabButtonVisible, newTabButton.getVisibility() == View.VISIBLE); - assertEquals(isMenuButtonVisible, menuButton.getVisibility() == View.VISIBLE); - }); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_MENU, true); + checkToolbarButtonVisibility(TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_NEW_TAB, true); + checkToolbarButtonVisibility( + TAB_SWITCHER_TOOLBAR, TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON, true); + checkToolbarVisibility(BOTTOM_TOOLBAR, false); } }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 6125b89..a6c8555 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -4205,13 +4205,13 @@ Contact the device admin for your organization </message> <message name="IDS_PLUGIN_VM_REMOVING_NOTIFICATION_IN_PROGRESS_MESSAGE" desc="Message in the notification shown when removing the 'Plugin VM' app."> - Removing Plugin VM... + Uninstalling Plugin VM... </message> <message name="IDS_PLUGIN_VM_REMOVING_NOTIFICATION_COMPLETE_MESSAGE" desc="Message in the notification shown when removing the 'Plugin VM' app has completed successfully."> - Plugin VM has been removed + Plugin VM has been uninstalled </message> <message name="IDS_PLUGIN_VM_REMOVING_NOTIFICATION_FAILED_MESSAGE" desc="Message in the notification shown when removing the 'Plugin VM' app failed."> - Failed to remove Plugin VM + Couldn't uninstall Plugin VM </message> <!-- Strings for Account Manager error screen -->
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 71a12e24..007bcee5a 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -614,6 +614,9 @@ <message name="IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_HEADING" desc="Label for list of shared folders."> Shared folders </message> + <message name="IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_EMPTY_MESSAGE" desc="Message shown when the user has not yet shared any folders in Crostini."> + Shared folders will appear here + </message> <message name="IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_ADD" desc="Instructions for how to add shared folders in Crostini."> To share, right-click on a folder in Files app, then select "Share with Linux". </message> @@ -725,10 +728,10 @@ Remove sharing </message> <message name="IDS_SETTINGS_PLUGIN_VM_REMOVE_LABEL" desc="Label for the row to open a dialog confirming removal of Plugin VM."> - Remove Plugin VM + Uninstall Plugin VM </message> <message name="IDS_SETTINGS_PLUGIN_VM_REMOVE_BUTTON" desc="Label for the button to open a dialog confirming removal of Plugin VM."> - Remove + Uninstall </message> <message name="IDS_SETTINGS_PLUGIN_VM_CONFIRM_REMOVE_DIALOG_BODY" desc="Message of the confirmation dialog displayed before removal begins."> Removing Plugin VM will delete your VM. This includes its applications, settings, and data. Are you sure you wish to continue?
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_EMPTY_MESSAGE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_EMPTY_MESSAGE.png.sha1 new file mode 100644 index 0000000..7985997a --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_EMPTY_MESSAGE.png.sha1
@@ -0,0 +1 @@ +256f503e7b6893e324c1159c72e05c1895f4830d \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f6d0089f..64b88be 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4333,7 +4333,7 @@ "//ui/snapshot", ] if (use_gtk) { - deps += [ "//chrome/browser/ui/libgtkui" ] + deps += [ "//chrome/browser/ui/gtk" ] } }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 07f75f1c..ff26d8e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2785,10 +2785,6 @@ flag_descriptions::kCrostiniUsbAllowUnsupportedName, flag_descriptions::kCrostiniUsbAllowUnsupportedDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kCrostiniUsbAllowUnsupported)}, - {"file-manager-feedback-panel", - flag_descriptions::kFileManagerFeedbackPanelName, - flag_descriptions::kFileManagerFeedbackPanelDescription, kOsCrOS, - FEATURE_VALUE_TYPE(chromeos::features::kEnableFileManagerFeedbackPanel)}, {"files-ng", flag_descriptions::kFilesNGName, flag_descriptions::kFilesNGDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kFilesNG)}, @@ -2807,6 +2803,11 @@ #endif // defined(OS_WIN) #if defined(OS_ANDROID) + {"omnibox-assistant-voice-search", + flag_descriptions::kOmniboxAssistantVoiceSearchName, + flag_descriptions::kOmniboxAssistantVoiceSearchDescription, kOsAndroid, + FEATURE_VALUE_TYPE(omnibox::kOmniboxAssistantVoiceSearch)}, + {"omnibox-search-engine-logo", flag_descriptions::kOmniboxSearchEngineLogoName, flag_descriptions::kOmniboxSearchEngineLogoDescription, kOsAndroid,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index f48256c8..21512ee4 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -233,10 +233,11 @@ &offline_pages::kPrefetchingOfflinePagesFeature, &omnibox::kHideSteadyStateUrlScheme, &omnibox::kHideSteadyStateUrlTrivialSubdomains, + &omnibox::kOmniboxAssistantVoiceSearch, &omnibox::kOmniboxRichEntitySuggestions, + &omnibox::kOmniboxSearchEngineLogo, &omnibox::kQueryInOmnibox, &omnibox::kUIExperimentShowSuggestionFavicons, - &omnibox::kOmniboxSearchEngineLogo, &password_manager::features::kGooglePasswordManager, &password_manager::features::kPasswordEditingAndroid, &password_manager::features::kPasswordManagerOnboardingAndroid,
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc index e09cbeb..6852c192 100644 --- a/chrome/browser/captive_portal/captive_portal_browsertest.cc +++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -28,21 +28,17 @@ #include "base/test/bind_test_util.h" #include "base/values.h" #include "build/build_config.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/captive_portal/captive_portal_service.h" #include "chrome/browser/captive_portal/captive_portal_service_factory.h" #include "chrome/browser/captive_portal/captive_portal_tab_helper.h" #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/net/dns_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/ssl_error_handler.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_navigator_params.h" -#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/navigation_correction_tab_observer.h" #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -88,10 +84,6 @@ #include "net/url_request/url_request_status.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_WIN) -#include "base/win/win_util.h" -#endif - using captive_portal::CaptivePortalResult; using content::BrowserThread; using content::WebContents; @@ -170,11 +162,6 @@ return kServerRedirectBase + dest_url; } -// Returns the total number of tabs across all Browsers, for all Profiles. -int NumTabs() { - return std::distance(AllTabContentses().begin(), AllTabContentses().end()); -} - // Returns the total number of loading tabs across all Browsers, for all // Profiles. int NumLoadingTabs() { @@ -646,18 +633,15 @@ // captive portal test is complete. // // If |expect_open_login_tab| is true, a login tab is then expected to be - // opened. If |expect_new_login_browser| is true, this tab is expected to be - // opened in a new captive portal popup window. It waits until both the - // login tab has finished loading, and two captive portal tests complete. - // The second test is triggered by the load of the captive portal tab - // completing. + // opened. It waits until both the login tab has finished loading, and two + // captive portal tests complete. The second test is triggered by the load of + // the captive portal tab completing. // // This function must not be called when the active tab is currently loading. // Waits for the hanging request to be issued, so other functions can rely // on WaitForJobs having been called. void SlowLoadBehindCaptivePortal(Browser* browser, - bool expect_open_login_tab, - bool expect_new_login_browser); + bool expect_open_login_tab); // Same as above, but takes extra parameters. // @@ -668,7 +652,6 @@ // ignored when |expect_open_login_tab| is false. void SlowLoadBehindCaptivePortal(Browser* browser, bool expect_open_login_tab, - bool expect_new_login_browser, const GURL& hanging_url, int expected_portal_checks, int expected_login_tab_navigations); @@ -703,12 +686,9 @@ // Simulates a login by updating the URLRequestMockCaptivePortalJob's // behind captive portal state, and navigating the login tab. Waits for // all broken but not loading tabs to be reloaded. - // |captive-portal_browser| is the browser containing the login page. // |num_loading_tabs| and |num_timed_out_tabs| are used as extra checks // that nothing has gone wrong prior to the function call. - void Login(Browser* captive_portal_browser, - int num_loading_tabs, - int num_timed_out_tabs); + void Login(Browser* browser, int num_loading_tabs, int num_timed_out_tabs); // Simulates a login when the broken tab shows an SSL or captive portal // interstitial. Can't use Login() in those cases because the interstitial @@ -896,7 +876,6 @@ std::vector<content::URLLoaderInterceptor::RequestParams> ongoing_mock_requests_; std::atomic<bool> behind_captive_portal_; - const BrowserList* browser_list_; bool intercept_bad_cert_ = true; private: @@ -904,7 +883,7 @@ }; CaptivePortalBrowserTest::CaptivePortalBrowserTest() - : behind_captive_portal_(true), browser_list_(BrowserList::GetInstance()) { + : behind_captive_portal_(true) { NavigationCorrectionTabObserver::SetAllowEnableCorrectionsForTesting(true); } @@ -913,12 +892,6 @@ } void CaptivePortalBrowserTest::SetUpOnMainThread() { - // Mark as not enterprise managed to prevent the secure DNS mode from - // being downgraded to off. -#if defined(OS_WIN) - base::win::ScopedDomainStateForTesting scoped_domain(false); -#endif - url_loader_interceptor_ = std::make_unique<content::URLLoaderInterceptor>(base::Bind( &CaptivePortalBrowserTest::OnIntercept, base::Unretained(this))); @@ -1263,17 +1236,17 @@ void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal( Browser* browser, - bool expect_open_login_tab, - bool expect_new_login_browser = false) { - SlowLoadBehindCaptivePortal(browser, expect_open_login_tab, - expect_new_login_browser, GURL(kMockHttpsUrl), 1, + bool expect_open_login_tab) { + SlowLoadBehindCaptivePortal(browser, + expect_open_login_tab, + GURL(kMockHttpsUrl), + 1, 1); } void CaptivePortalBrowserTest::SlowLoadBehindCaptivePortal( Browser* browser, bool expect_open_login_tab, - bool expect_new_login_browser, const GURL& hanging_url, int expected_portal_checks, int expected_login_tab_navigations) { @@ -1295,7 +1268,6 @@ int initial_active_index = tab_strip_model->active_index(); int initial_loading_tabs = NumLoadingTabs(); int expected_broken_tabs = NumBrokenTabs(); - size_t initial_browser_count = browser_list_->size(); if (CaptivePortalTabReloader::STATE_BROKEN_BY_PORTAL != GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())) { ++expected_broken_tabs; @@ -1310,39 +1282,19 @@ if (expect_open_login_tab) { ASSERT_GE(expected_login_tab_navigations, 1); + navigation_observer.WaitForNavigations(expected_login_tab_navigations); - WebContents* login_tab; - if (expect_new_login_browser) { - ASSERT_EQ(initial_browser_count + 1, browser_list_->size()); - - // Check the original browser - ASSERT_EQ(initial_tab_count, tab_strip_model->count()); - EXPECT_EQ(initial_tab_count - 1, tab_strip_model->active_index()); - EXPECT_NE(browser_list_->get(initial_browser_count - 1), - browser_list_->GetLastActive()); - - // Check the new popup browser - Browser* popup_browser = browser_list_->get(initial_browser_count); - EXPECT_EQ(popup_browser, browser_list_->GetLastActive()); - EXPECT_EQ(Browser::TYPE_POPUP, popup_browser->type()); - login_tab = popup_browser->tab_strip_model()->GetWebContentsAt(0); - EXPECT_TRUE(CaptivePortalTabHelper::FromWebContents(login_tab) - ->is_captive_portal_window()); - } else { - ASSERT_EQ(initial_browser_count, browser_list_->size()); - ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count()); - EXPECT_EQ(initial_tab_count, tab_strip_model->active_index()); - login_tab = tab_strip_model->GetWebContentsAt(initial_tab_count); - } + ASSERT_EQ(initial_tab_count + 1, tab_strip_model->count()); + EXPECT_EQ(initial_tab_count, tab_strip_model->active_index()); EXPECT_EQ(expected_login_tab_navigations, - navigation_observer.NumNavigationsForTab(login_tab)); + navigation_observer.NumNavigationsForTab( + tab_strip_model->GetWebContentsAt(initial_tab_count))); EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, - GetStateOfTabReloader(login_tab)); - EXPECT_TRUE(IsLoginTab(login_tab)); + GetStateOfTabReloaderAt(browser, 1)); + EXPECT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(1))); } else { - ASSERT_EQ(initial_browser_count, browser_list_->size()); EXPECT_EQ(0, navigation_observer.num_navigations()); EXPECT_EQ(initial_active_index, tab_strip_model->active_index()); ASSERT_EQ(initial_tab_count, tab_strip_model->count()); @@ -1507,25 +1459,24 @@ tab_strip_model->GetWebContentsAt(login_tab_index))); } -void CaptivePortalBrowserTest::Login(Browser* captive_portal_browser, +void CaptivePortalBrowserTest::Login(Browser* browser, int num_loading_tabs, int num_timed_out_tabs) { // Simulate logging in. SetBehindCaptivePortal(false); MultiNavigationObserver navigation_observer; - CaptivePortalObserver portal_observer(captive_portal_browser->profile()); + CaptivePortalObserver portal_observer(browser->profile()); - TabStripModel* tab_strip_model = captive_portal_browser->tab_strip_model(); - size_t initial_browser_count = browser_list_->size(); - int initial_tab_count = NumTabs(); + TabStripModel* tab_strip_model = browser->tab_strip_model(); + int initial_tab_count = tab_strip_model->count(); ASSERT_EQ(num_loading_tabs, NumLoadingTabs()); EXPECT_EQ(num_timed_out_tabs, NumBrokenTabs() - NumLoadingTabs()); // Verify that the login page is on top. int login_tab_index = tab_strip_model->active_index(); EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, - GetStateOfTabReloaderAt(captive_portal_browser, login_tab_index)); + GetStateOfTabReloaderAt(browser, login_tab_index)); ASSERT_TRUE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index))); // Trigger a navigation. @@ -1545,10 +1496,9 @@ // Make sure that the broken tabs have reloaded, and there's no more // captive portal tab. - EXPECT_EQ(initial_browser_count, browser_list_->size()); - EXPECT_EQ(initial_tab_count, NumTabs()); + EXPECT_EQ(initial_tab_count, tab_strip_model->count()); EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, - GetStateOfTabReloaderAt(captive_portal_browser, login_tab_index)); + GetStateOfTabReloaderAt(browser, login_tab_index)); EXPECT_FALSE(IsLoginTab(tab_strip_model->GetWebContentsAt(login_tab_index))); // Make sure there were no unexpected navigations of the login tab. @@ -1638,9 +1588,8 @@ ASSERT_EQ(0, NumNeedReloadTabs()); EXPECT_EQ(num_loading_tabs, NumBrokenTabs()); - Browser* captive_portal_browser = browser_list_->GetLastActive(); - TabStripModel* tab_strip_model = captive_portal_browser->tab_strip_model(); - int initial_num_tabs = NumTabs(); + TabStripModel* tab_strip_model = browser->tab_strip_model(); + int initial_num_tabs = tab_strip_model->count(); int login_tab = tab_strip_model->active_index(); EXPECT_EQ(CaptivePortalTabReloader::STATE_NONE, GetStateOfTabReloader(tab_strip_model->GetActiveWebContents())); @@ -1658,7 +1607,7 @@ // should be no new tabs. EXPECT_EQ(0, portal_observer.num_results_received()); EXPECT_FALSE(CheckPending(browser)); - EXPECT_EQ(initial_num_tabs, NumTabs()); + EXPECT_EQ(initial_num_tabs, tab_strip_model->count()); EXPECT_EQ(0, NumNeedReloadTabs()); EXPECT_EQ(0, NumLoadingTabs()); @@ -1684,9 +1633,7 @@ SetBehindCaptivePortal(true); // Go to the first hanging url. - SlowLoadBehindCaptivePortal(browser, true /* expect_open_login_tab */, - false /* is-expect_new_login_browser */, - hanging_url, 1, 1); + SlowLoadBehindCaptivePortal(browser, true, hanging_url, 1, 1); // Abandon the request. WaitForJobs(1); @@ -2702,9 +2649,8 @@ IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, HttpToHttpsRedirectLogin) { ASSERT_TRUE(embedded_test_server()->Start()); SlowLoadBehindCaptivePortal( - browser(), true /* expect_open_login_tab */, - false /* expect_new_login_browser */, - embedded_test_server()->GetURL(kRedirectToMockHttpsPath), 1, 1); + browser(), true, embedded_test_server()->GetURL(kRedirectToMockHttpsPath), + 1, 1); Login(browser(), 1, 0); FailLoadsAfterLogin(browser(), 1); } @@ -2731,9 +2677,7 @@ IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, Status511) { SetUpCaptivePortalService(browser()->profile(), GURL(kMockCaptivePortal511Url)); - SlowLoadBehindCaptivePortal(browser(), true /* expect_open_login_tab */, - false /* expect_new_login_browser */, - GURL(kMockHttpsUrl), 2, 2); + SlowLoadBehindCaptivePortal(browser(), true, GURL(kMockHttpsUrl), 2, 2); Login(browser(), 1, 0); FailLoadsAfterLogin(browser(), 1); } @@ -2760,9 +2704,7 @@ TabStripModel* tab_strip_model = browser()->tab_strip_model(); int broken_tab_index = tab_strip_model->active_index(); WebContents* broken_tab_contents = tab_strip_model->GetActiveWebContents(); - SlowLoadBehindCaptivePortal(browser(), true /* expect_open_login_tab */, - false /* expect_new_login_browser */, - cert_error_url, 1, 1); + SlowLoadBehindCaptivePortal(browser(), true, cert_error_url, 1, 1); // No longer behind a captive portal. Committing the SSL page should trigger // an SSL interstitial which triggers a new captive portal check. Since there @@ -2789,34 +2731,3 @@ EXPECT_EQ(SSLBlockingPage::kTypeForTesting, GetInterstitialType(broken_tab_contents)); } - -IN_PROC_BROWSER_TEST_F(CaptivePortalBrowserTest, SecureDnsCaptivePortal) { - PrefService* local_state = g_browser_process->local_state(); - local_state->SetString(prefs::kDnsOverHttpsMode, - chrome_browser_net::kDnsOverHttpsModeSecure); - local_state->SetString(prefs::kDnsOverHttpsTemplates, - "https://bar.test/dns-query{?dns}"); - - SlowLoadBehindCaptivePortal(browser(), true /* expect_open_login_tab */, - true /* expect_new_login_browser */); - FailLoadsWithoutLogin(browser(), 1); - - // A second navigation on the same tab should not cause a new captive portal - // window to open. - SlowLoadBehindCaptivePortal(browser(), false /* expect_open_login_tab */, - false /* expect_new_login_browser */); - - // A navigation in a new tab should not cause a new captive portal window to - // open. - Browser* second_user_browser = CreateBrowser(browser()->profile()); - // Check that new window is visible. - EXPECT_TRUE(second_user_browser->window()->IsVisible()); - SlowLoadBehindCaptivePortal(second_user_browser, - false /* expect_open_login_tab */, - false /* expect_new_login_browser */); - // Check that the existing captive portal popup is visible. - EXPECT_TRUE(browser_list_->get(1)->window()->IsVisible()); - - // Login to the captive portal. - Login(browser_list_->get(1), 2, 0); -}
diff --git a/chrome/browser/captive_portal/captive_portal_tab_helper.cc b/chrome/browser/captive_portal/captive_portal_tab_helper.cc index 66dace9..e50faf31 100644 --- a/chrome/browser/captive_portal/captive_portal_tab_helper.cc +++ b/chrome/browser/captive_portal/captive_portal_tab_helper.cc
@@ -6,18 +6,14 @@ #include "base/bind.h" #include "base/debug/dump_without_crashing.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/captive_portal/captive_portal_login_detector.h" #include "chrome/browser/captive_portal/captive_portal_service_factory.h" #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" @@ -30,7 +26,6 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "net/base/net_errors.h" -#include "net/dns/dns_config.h" #include "net/ssl/ssl_info.h" using captive_portal::CaptivePortalResult; @@ -166,48 +161,6 @@ if (!browser) return; - bool insecure_stub_resolver_enabled; - net::DnsConfig::SecureDnsMode secure_dns_mode; - base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> - dns_over_https_servers; - SystemNetworkContextManager::GetStubResolverConfig( - g_browser_process->local_state(), &insecure_stub_resolver_enabled, - &secure_dns_mode, &dns_over_https_servers); - - // If the DNS mode is SECURE, captive portal login tabs should be opened in - // new popup windows where secure DNS will be disabled. - if (secure_dns_mode == net::DnsConfig::SecureDnsMode::SECURE) { - // If there is already a captive portal popup window, do not create another. - for (auto* contents : AllTabContentses()) { - CaptivePortalTabHelper* captive_portal_tab_helper = - CaptivePortalTabHelper::FromWebContents(contents); - if (captive_portal_tab_helper->IsLoginTab()) { - Browser* browser_with_login_tab = - chrome::FindBrowserWithWebContents(contents); - browser_with_login_tab->window()->Show(); - browser_with_login_tab->tab_strip_model()->ActivateTabAt( - browser_with_login_tab->tab_strip_model()->GetIndexOfWebContents( - contents)); - return; - } - } - - // Otherwise, create a captive portal popup window. - NavigateParams params( - browser, - CaptivePortalServiceFactory::GetForProfile(browser->profile()) - ->test_url(), - ui::PAGE_TRANSITION_TYPED); - params.disposition = WindowOpenDisposition::NEW_POPUP; - Navigate(¶ms); - content::WebContents* new_contents = params.navigated_or_inserted_contents; - CaptivePortalTabHelper* captive_portal_tab_helper = - CaptivePortalTabHelper::FromWebContents(new_contents); - captive_portal_tab_helper->set_is_captive_portal_window(); - captive_portal_tab_helper->SetIsLoginTab(); - return; - } - // Check if the Profile's topmost browser window already has a login tab. // If so, do nothing. // TODO(mmenke): Consider focusing that tab, at least if this is the tab
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 5d230e9..764db10 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -819,8 +819,6 @@ "child_accounts/time_limits/app_time_controller.h", "child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.cc", "child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h", - "child_accounts/time_limits/app_time_policy_helpers.cc", - "child_accounts/time_limits/app_time_policy_helpers.h", "child_accounts/time_limits/app_types.cc", "child_accounts/time_limits/app_types.h", "child_accounts/time_limits/web_time_limit_enforcer.cc", @@ -875,6 +873,8 @@ "crostini/crostini_package_operation_status.h", "crostini/crostini_package_service.cc", "crostini/crostini_package_service.h", + "crostini/crostini_port_forwarder.cc", + "crostini/crostini_port_forwarder.h", "crostini/crostini_pref_names.cc", "crostini/crostini_pref_names.h", "crostini/crostini_registry_service.cc", @@ -2715,6 +2715,7 @@ "crostini/crostini_mime_types_service_unittest.cc", "crostini/crostini_package_notification_unittest.cc", "crostini/crostini_package_service_unittest.cc", + "crostini/crostini_port_forwarder_unittest.cc", "crostini/crostini_registry_service_unittest.cc", "crostini/crostini_reporting_util_unittest.cc", "crostini/crostini_unsupported_action_notifier_unittest.cc",
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc index 74aac87..7d25ebd 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.cc
@@ -49,17 +49,6 @@ } // namespace -AppActivityRegistry::TestApi::TestApi(AppActivityRegistry* registry) - : registry_(registry) {} - -AppActivityRegistry::TestApi::~TestApi() = default; - -const base::Optional<AppLimit>& AppActivityRegistry::TestApi::GetAppLimit( - const AppId& app_id) const { - DCHECK(base::Contains(registry_->activity_registry_, app_id)); - return registry_->activity_registry_.at(app_id).limit; -} - AppActivityRegistry::AppDetails::AppDetails() = default; AppActivityRegistry::AppDetails::AppDetails(const AppActivity& activity) @@ -87,8 +76,6 @@ // sessions and app service does not. Make sure not to override cached state. if (!base::Contains(activity_registry_, app_id)) Add(app_id); - - // TODO(agawronska): Update the limit from policy when new app is installed. } void AppActivityRegistry::OnAppUninstalled(const AppId& app_id) { @@ -242,21 +229,6 @@ } } -void AppActivityRegistry::UpdateAppLimits( - const std::map<AppId, AppLimit>& app_limits) { - for (auto& entry : activity_registry_) { - const AppId& app_id = entry.first; - const base::Optional<AppLimit>& app_limit = entry.second.limit; - if (!base::Contains(app_limits, app_id)) { - if (app_limit) - entry.second.limit = base::nullopt; - } else { - entry.second.limit = app_limits.at(app_id); - } - } - // TODO(agawronska): Propagate information about the limit changes. -} - void AppActivityRegistry::Add(const AppId& app_id) { auto result = activity_registry_.emplace( app_id, AppDetails(AppActivity(AppState::kAvailable)));
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h index 925e45b..9990d7b 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h
@@ -8,7 +8,6 @@ #include <map> #include <set> -#include "base/optional.h" #include "base/time/time.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_report_interface.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h" @@ -31,18 +30,6 @@ // 30 days if upload did not happen. class AppActivityRegistry : public AppServiceWrapper::EventListener { public: - // Used for tests to get internal implementation details. - class TestApi { - public: - explicit TestApi(AppActivityRegistry* registry); - ~TestApi(); - - const base::Optional<AppLimit>& GetAppLimit(const AppId& app_id) const; - - private: - AppActivityRegistry* const registry_; - }; - explicit AppActivityRegistry(AppServiceWrapper* app_service_wrapper); AppActivityRegistry(const AppActivityRegistry&) = delete; AppActivityRegistry& operator=(const AppActivityRegistry&) = delete; @@ -80,9 +67,6 @@ // data left. void CleanRegistry(base::Time timestamp); - // Updates time limits for the installed apps. - void UpdateAppLimits(const std::map<AppId, AppLimit>& app_limits); - private: // Bundles detailed data stored for a specific app. struct AppDetails {
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc deleted file mode 100644 index 5c5828b..0000000 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc +++ /dev/null
@@ -1,296 +0,0 @@ -// Copyright 2020 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 <memory> -#include <string> - -#include "base/json/json_writer.h" -#include "base/optional.h" -#include "base/run_loop.h" -#include "base/strings/strcat.h" -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/chromeos/arc/arc_util.h" -#include "chrome/browser/chromeos/arc/session/arc_session_manager.h" -#include "chrome/browser/chromeos/child_accounts/child_user_service.h" -#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h" -#include "chrome/browser/chromeos/login/test/scoped_policy_update.h" -#include "chrome/browser/chromeos/login/test/user_policy_mixin.h" -#include "chrome/browser/chromeos/policy/user_policy_test_helper.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/supervised_user/logged_in_user_mixin.h" -#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/common/chrome_features.h" -#include "chrome/test/base/mixin_based_in_process_browser_test.h" -#include "components/arc/arc_util.h" -#include "components/arc/mojom/app.mojom.h" -#include "components/arc/mojom/app_permissions.mojom.h" -#include "components/arc/test/connection_holder_util.h" -#include "components/arc/test/fake_app_instance.h" -#include "components/user_manager/user.h" -#include "components/user_manager/user_manager.h" -#include "net/dns/mock_host_resolver.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace chromeos { -namespace app_time { - -namespace { - -arc::mojom::ArcPackageInfoPtr CreateArcAppPackage( - const std::string& package_name) { - auto package = arc::mojom::ArcPackageInfo::New(); - package->package_name = package_name; - package->package_version = 1; - package->last_backup_android_id = 1; - package->last_backup_time = 1; - package->sync = false; - package->system = false; - package->permissions = base::flat_map<::arc::mojom::AppPermission, bool>(); - return package; -} - -arc::mojom::AppInfo CreateArcAppInfo(const std::string& package_name) { - arc::mojom::AppInfo app; - app.package_name = package_name; - app.name = package_name; - app.activity = base::StrCat({package_name, ".", "activity"}); - app.sticky = true; - return app; -} - -} // namespace - -// Integration tests for Per-App Time Limits feature. -class AppTimeTest : public MixinBasedInProcessBrowserTest { - protected: - AppTimeTest() = default; - AppTimeTest(const AppTimeTest&) = delete; - AppTimeTest& operator=(const AppTimeTest&) = delete; - ~AppTimeTest() override = default; - - // MixinBasedInProcessBrowserTest: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(features::kPerAppTimeLimits); - MixinBasedInProcessBrowserTest::SetUp(); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line); - arc::SetArcAvailableCommandLineForTesting(command_line); - } - - void SetUpInProcessBrowserTestFixture() override { - MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture(); - arc::ArcSessionManager::SetUiEnabledForTesting(false); - } - - void SetUpOnMainThread() override { - MixinBasedInProcessBrowserTest::SetUpOnMainThread(); - ASSERT_TRUE(embedded_test_server()->Started()); - host_resolver()->AddIPLiteralRule("*", "127.0.0.1", "localhost"); - logged_in_user_mixin_.LogInUser(false /*issue_any_scope_token*/, - true /*wait_for_active_session*/, - true /*request_policy_update*/); - - arc::SetArcPlayStoreEnabledForProfile(browser()->profile(), true); - arc_app_list_prefs_ = ArcAppListPrefs::Get(browser()->profile()); - EXPECT_TRUE(arc_app_list_prefs_); - - base::RunLoop run_loop; - arc_app_list_prefs_->SetDefaultAppsReadyCallback(run_loop.QuitClosure()); - run_loop.Run(); - - arc_app_instance_ = - std::make_unique<arc::FakeAppInstance>(arc_app_list_prefs_); - arc_app_list_prefs_->app_connection_holder()->SetInstance( - arc_app_instance_.get()); - WaitForInstanceReady(arc_app_list_prefs_->app_connection_holder()); - arc_app_instance_->set_icon_response_type( - arc::FakeAppInstance::IconResponseType::ICON_RESPONSE_SKIP); - } - - void TearDownOnMainThread() override { - arc_app_list_prefs_->app_connection_holder()->CloseInstance( - arc_app_instance_.get()); - arc_app_instance_.reset(); - arc::ArcSessionManager::Get()->Shutdown(); - } - - void UpdatePerAppTimeLimitsPolicy(const base::Value& policy) { - std::string policy_value; - base::JSONWriter::Write(policy, &policy_value); - - logged_in_user_mixin_.GetUserPolicyMixin() - ->RequestPolicyUpdate() - ->policy_payload() - ->mutable_perapptimelimits() - ->set_value(policy_value); - - logged_in_user_mixin_.GetUserPolicyTestHelper()->RefreshPolicyAndWait( - GetCurrentProfile()); - } - - AppActivityRegistry* GetAppRegistry() { - auto child_user_service = ChildUserService::TestApi( - ChildUserServiceFactory::GetForBrowserContext(GetCurrentProfile())); - EXPECT_TRUE(child_user_service.app_time_controller()); - auto app_time_controller = - AppTimeController::TestApi(child_user_service.app_time_controller()); - return app_time_controller.app_registry(); - } - - void InstallArcApp(const AppId& app_id) { - EXPECT_EQ(apps::mojom::AppType::kArc, app_id.app_type()); - const std::string& package_name = app_id.app_id(); - arc_app_instance_->SendPackageAdded( - CreateArcAppPackage(package_name)->Clone()); - - const arc::mojom::AppInfo app = CreateArcAppInfo(package_name); - arc_app_instance_->SendPackageAppListRefreshed(package_name, {app}); - - base::RunLoop().RunUntilIdle(); - } - - void Equals(const AppLimit& limit1, const AppLimit& limit2) { - EXPECT_EQ(limit1.restriction(), limit2.restriction()); - EXPECT_EQ(limit1.daily_limit(), limit2.daily_limit()); - // Compare JavaTime, because some precision is lost when serializing - // and deserializing. - EXPECT_EQ(limit1.last_updated().ToJavaTime(), - limit2.last_updated().ToJavaTime()); - } - - private: - Profile* GetCurrentProfile() { - const user_manager::UserManager* const user_manager = - user_manager::UserManager::Get(); - Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser( - user_manager->GetActiveUser()); - EXPECT_TRUE(profile); - - return profile; - } - - chromeos::LoggedInUserMixin logged_in_user_mixin_{ - &mixin_host_, chromeos::LoggedInUserMixin::LogInType::kChild, - embedded_test_server(), this}; - - ArcAppListPrefs* arc_app_list_prefs_ = nullptr; - std::unique_ptr<arc::FakeAppInstance> arc_app_instance_; - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(AppTimeTest, AppInstallation) { - const AppId app1(apps::mojom::AppType::kArc, "com.example.app1"); - AppActivityRegistry* app_registry = GetAppRegistry(); - EXPECT_FALSE(app_registry->IsAppInstalled(app1)); - - InstallArcApp(app1); - - ASSERT_TRUE(app_registry->IsAppInstalled(app1)); - EXPECT_TRUE(app_registry->IsAppAvailable(app1)); -} - -IN_PROC_BROWSER_TEST_F(AppTimeTest, PerAppTimeLimitsPolicyUpdates) { - // Install an app. - const AppId app1(apps::mojom::AppType::kArc, "com.example.app1"); - InstallArcApp(app1); - - AppActivityRegistry* app_registry = GetAppRegistry(); - AppActivityRegistry::TestApi app_registry_test(app_registry); - ASSERT_TRUE(app_registry->IsAppInstalled(app1)); - EXPECT_TRUE(app_registry->IsAppAvailable(app1)); - EXPECT_FALSE(app_registry_test.GetAppLimit(app1)); - - // Block the app. - AppTimeLimitsPolicyBuilder block_policy; - const AppLimit block_limit = - AppLimit(AppRestriction::kBlocked, base::nullopt, base::Time::Now()); - block_policy.AddAppLimit(app1, block_limit); - block_policy.SetResetTime(6, 0); - - UpdatePerAppTimeLimitsPolicy(block_policy.value()); - EXPECT_TRUE(app_registry->IsAppAvailable(app1)); - ASSERT_TRUE(app_registry_test.GetAppLimit(app1)); - Equals(block_limit, app_registry_test.GetAppLimit(app1).value()); - - // Set time limit for the app. - AppTimeLimitsPolicyBuilder time_limit_policy; - const AppLimit time_limit = - AppLimit(AppRestriction::kTimeLimit, base::TimeDelta::FromHours(1), - base::Time::Now()); - time_limit_policy.AddAppLimit(app1, time_limit); - time_limit_policy.SetResetTime(6, 0); - - UpdatePerAppTimeLimitsPolicy(time_limit_policy.value()); - EXPECT_TRUE(app_registry->IsAppAvailable(app1)); - ASSERT_TRUE(app_registry_test.GetAppLimit(app1)); - Equals(time_limit, app_registry_test.GetAppLimit(app1).value()); - - // Remove app restricitons. - AppTimeLimitsPolicyBuilder no_limits_policy; - no_limits_policy.SetResetTime(6, 0); - - UpdatePerAppTimeLimitsPolicy(no_limits_policy.value()); - EXPECT_TRUE(app_registry->IsAppAvailable(app1)); - EXPECT_FALSE(app_registry_test.GetAppLimit(app1)); -} - -IN_PROC_BROWSER_TEST_F(AppTimeTest, PerAppTimeLimitsPolicyMultipleEntries) { - // Install apps. - const AppId app1(apps::mojom::AppType::kArc, "com.example.app1"); - InstallArcApp(app1); - const AppId app2(apps::mojom::AppType::kArc, "com.example.app2"); - InstallArcApp(app2); - const AppId app3(apps::mojom::AppType::kArc, "com.example.app3"); - InstallArcApp(app3); - const AppId app4(apps::mojom::AppType::kArc, "com.example.app4"); - InstallArcApp(app4); - - AppActivityRegistry* app_registry = GetAppRegistry(); - AppActivityRegistry::TestApi app_registry_test(app_registry); - for (const auto& app : {app1, app2, app3, app4}) { - ASSERT_TRUE(app_registry->IsAppInstalled(app)); - EXPECT_TRUE(app_registry->IsAppAvailable(app)); - EXPECT_FALSE(app_registry_test.GetAppLimit(app)); - } - - // Send policy. - AppTimeLimitsPolicyBuilder policy; - policy.SetResetTime(6, 0); - policy.AddAppLimit(app2, AppLimit(AppRestriction::kBlocked, base::nullopt, - base::Time::Now())); - policy.AddAppLimit( - app3, AppLimit(AppRestriction::kTimeLimit, - base::TimeDelta::FromMinutes(15), base::Time::Now())); - policy.AddAppLimit( - app4, AppLimit(AppRestriction::kTimeLimit, base::TimeDelta::FromHours(1), - base::Time::Now())); - - UpdatePerAppTimeLimitsPolicy(policy.value()); - - EXPECT_FALSE(app_registry_test.GetAppLimit(app1)); - - ASSERT_TRUE(app_registry_test.GetAppLimit(app2)); - EXPECT_EQ(AppRestriction::kBlocked, - app_registry_test.GetAppLimit(app2)->restriction()); - - ASSERT_TRUE(app_registry_test.GetAppLimit(app3)); - EXPECT_EQ(AppRestriction::kTimeLimit, - app_registry_test.GetAppLimit(app3)->restriction()); - - ASSERT_TRUE(app_registry_test.GetAppLimit(app4)); - EXPECT_EQ(AppRestriction::kTimeLimit, - app_registry_test.GetAppLimit(app4)->restriction()); -} - -} // namespace app_time -} // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc index 3180b2d1..69731b5 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.cc
@@ -7,12 +7,10 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/logging.h" -#include "base/optional.h" #include "base/values.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h" #include "chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" @@ -24,15 +22,6 @@ namespace chromeos { namespace app_time { -AppTimeController::TestApi::TestApi(AppTimeController* controller) - : controller_(controller) {} - -AppTimeController::TestApi::~TestApi() = default; - -AppActivityRegistry* AppTimeController::TestApi::app_registry() { - return controller_->app_registry_.get(); -} - // static bool AppTimeController::ArePerAppTimeLimitsEnabled() { return base::FeatureList::IsEnabled(features::kPerAppTimeLimits); @@ -88,21 +77,7 @@ } void AppTimeController::TimeLimitsPolicyUpdated(const std::string& pref_name) { - const base::Value* policy = - pref_registrar_->prefs()->GetDictionary(prefs::kPerAppTimeLimitsPolicy); - - if (!policy || !policy->is_dict()) { - LOG(WARNING) << "Invalid PerAppTimeLimits policy."; - return; - } - - app_registry_->UpdateAppLimits(policy::AppLimitsFromDict(*policy)); - - base::Optional<base::TimeDelta> new_reset_time = - policy::ResetTimeFromDict(*policy); - // TODO(agawronska): Propagate the information about reset time change. - if (new_reset_time && *new_reset_time != limits_reset_time_) - limits_reset_time_ = *new_reset_time; + NOTIMPLEMENTED(); } void AppTimeController::TimeLimitsWhitelistPolicyUpdated(
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h index 39ac422a..2090948 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h
@@ -7,8 +7,6 @@ #include <memory> -#include "base/time/time.h" - class Profile; class PrefRegistrySimple; class PrefChangeRegistrar; @@ -25,18 +23,6 @@ // Coordinates per-app time limit for child user. class AppTimeController { public: - // Used for tests to get internal implementation details. - class TestApi { - public: - explicit TestApi(AppTimeController* controller); - ~TestApi(); - - AppActivityRegistry* app_registry(); - - private: - AppTimeController* const controller_; - }; - static bool ArePerAppTimeLimitsEnabled(); static bool IsAppActivityReportingEnabled(); @@ -67,10 +53,6 @@ void TimeLimitsPolicyUpdated(const std::string& pref_name); void TimeLimitsWhitelistPolicyUpdated(const std::string& pref_name); - // The time of the day when app time limits should be reset. - // Defaults to 6am. - base::TimeDelta limits_reset_time_ = base::TimeDelta::FromHours(6); - std::unique_ptr<AppServiceWrapper> app_service_wrapper_; std::unique_ptr<AppActivityRegistry> app_registry_; std::unique_ptr<WebTimeLimitEnforcer> web_time_enforcer_;
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.cc deleted file mode 100644 index ff2a2a5..0000000 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h" - -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h" - -namespace chromeos { -namespace app_time { - -AppTimeLimitsPolicyBuilder::AppTimeLimitsPolicyBuilder() { - value_.SetKey(policy::kAppLimitsArray, base::Value(base::Value::Type::LIST)); - value_.SetKey(policy::kResetAtDict, - base::Value(base::Value::Type::DICTIONARY)); -} - -AppTimeLimitsPolicyBuilder::~AppTimeLimitsPolicyBuilder() = default; - -void AppTimeLimitsPolicyBuilder::AddAppLimit(const AppId& app_id, - const AppLimit& app_limit) { - base::Value new_entry(base::Value::Type::DICTIONARY); - new_entry.SetKey(policy::kAppInfoDict, policy::AppIdToDict(app_id)); - base::Value app_limit_value = policy::AppLimitToDict(app_limit); - new_entry.MergeDictionary(&app_limit_value); - - base::Value* list = value_.FindListKey(policy::kAppLimitsArray); - DCHECK(list); - list->Append(std::move(new_entry)); -} - -void AppTimeLimitsPolicyBuilder::SetResetTime(int hour, int minutes) { - value_.SetKey(policy::kResetAtDict, policy::ResetTimeToDict(hour, minutes)); -} - -} // namespace app_time -} // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h deleted file mode 100644 index eb6e104..0000000 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_POLICY_BUILDER_H_ -#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_POLICY_BUILDER_H_ - -#include "base/values.h" - -namespace chromeos { -namespace app_time { - -class AppId; -class AppLimit; - -// Builds PerAppTimeLimits policy for tests. -class AppTimeLimitsPolicyBuilder { - public: - AppTimeLimitsPolicyBuilder(); - AppTimeLimitsPolicyBuilder(const AppTimeLimitsPolicyBuilder&) = delete; - AppTimeLimitsPolicyBuilder& operator=(const AppTimeLimitsPolicyBuilder&) = - delete; - ~AppTimeLimitsPolicyBuilder(); - - // Adds app limit data to the policy. - void AddAppLimit(const AppId& app_id, const AppLimit& app_limit); - - // Sets reset time in the policy. - void SetResetTime(int hour, int minutes); - - const base::Value& value() const { return value_; } - - private: - base::Value value_{base::Value::Type::DICTIONARY}; -}; - -} // namespace app_time -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_POLICY_BUILDER_H_
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.cc index 7860a78..3bf66fdd 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.cc +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.cc
@@ -4,8 +4,6 @@ #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h" namespace chromeos { namespace app_time { @@ -18,8 +16,8 @@ void AppTimeLimitsWhitelistPolicyBuilder::SetUp() { value_ = base::Value(base::Value::Type::DICTIONARY); - value_.SetKey(policy::kUrlList, base::Value(base::Value::Type::LIST)); - value_.SetKey(policy::kAppList, base::Value(base::Value::Type::LIST)); + value_.SetKey(kUrlList, base::Value(base::Value::Type::LIST)); + value_.SetKey(kAppList, base::Value(base::Value::Type::LIST)); } void AppTimeLimitsWhitelistPolicyBuilder::Clear() { @@ -30,17 +28,16 @@ void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistUrlList( const std::string& scheme) { - AppendToList(policy::kUrlList, base::Value(scheme)); + AppendToList(kUrlList, base::Value(scheme)); } void AppTimeLimitsWhitelistPolicyBuilder::AppendToWhitelistAppList( const AppId& app_id) { base::Value value_to_append(base::Value::Type::DICTIONARY); - value_to_append.SetKey(policy::kAppId, base::Value(app_id.app_id())); - value_to_append.SetKey( - policy::kAppType, - base::Value(policy::AppTypeToPolicyString(app_id.app_type()))); - AppendToList(policy::kAppList, std::move(value_to_append)); + value_to_append.SetKey(kAppId, base::Value(app_id.app_id())); + value_to_append.SetKey(kAppType, + base::Value(AppTypeToString(app_id.app_type()))); + AppendToList(kAppList, std::move(value_to_append)); } void AppTimeLimitsWhitelistPolicyBuilder::AppendToList(const std::string& key,
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h index ffe404d..55883e00 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_LIMITS_WHITELIST_POLICY_TEST_UTILS_H_ #include <string> - #include "base/values.h" namespace chromeos {
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.cc index bf12138..3d51e052 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.cc +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.cc
@@ -4,13 +4,48 @@ #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h" -#include "base/optional.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h" - namespace chromeos { namespace app_time { +const char kUrlList[] = "url_list"; +const char kAppList[] = "app_list"; +const char kAppId[] = "app_id"; +const char kAppType[] = "app_type"; + +std::string AppTypeToString(apps::mojom::AppType app_type) { + switch (app_type) { + case apps::mojom::AppType::kArc: + return "ARC"; + case apps::mojom::AppType::kBuiltIn: + return "BUILT-IN"; + case apps::mojom::AppType::kCrostini: + return "CROSTINI"; + case apps::mojom::AppType::kExtension: + return "EXTENSION"; + case apps::mojom::AppType::kWeb: + return "WEB"; + default: + NOTREACHED(); + return ""; + } +} + +apps::mojom::AppType StringToAppType(const std::string& app_type) { + if (app_type == "ARC") + return apps::mojom::AppType::kArc; + if (app_type == "BUILD-IN") + return apps::mojom::AppType::kBuiltIn; + if (app_type == "CROSTINI") + return apps::mojom::AppType::kCrostini; + if (app_type == "EXTENSION") + return apps::mojom::AppType::kExtension; + if (app_type == "WEB") + return apps::mojom::AppType::kWeb; + + NOTREACHED(); + return apps::mojom::AppType::kUnknown; +} + AppTimeLimitsWhitelistPolicyWrapper::AppTimeLimitsWhitelistPolicyWrapper( const base::Value* value) : value_(value) {} @@ -20,7 +55,7 @@ std::vector<std::string> AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistURLList() const { - const base::Value* list = value_->FindListKey(policy::kUrlList); + const base::Value* list = value_->FindListKey(kUrlList); DCHECK(list); base::Value::ConstListView list_view = list->GetList(); @@ -33,15 +68,19 @@ std::vector<AppId> AppTimeLimitsWhitelistPolicyWrapper::GetWhitelistAppList() const { - const base::Value* app_list = value_->FindListKey(policy::kAppList); + const base::Value* app_list = value_->FindListKey(kAppList); DCHECK(app_list); base::Value::ConstListView list_view = app_list->GetList(); std::vector<AppId> return_value; for (const base::Value& value : list_view) { - base::Optional<AppId> app_id = policy::AppIdFromDict(value); - if (app_id) - return_value.push_back(*app_id); + const std::string* app_id = value.FindStringKey(kAppId); + DCHECK(app_id); + + const std::string* app_type = value.FindStringKey(kAppType); + DCHECK(app_type); + + return_value.push_back(AppId(StringToAppType(*app_type), *app_id)); } return return_value;
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h index 569fc74a..651f958 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h
@@ -7,14 +7,23 @@ #include <string> #include <vector> - #include "base/values.h" +#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h" + namespace chromeos { namespace app_time { class AppId; +extern const char kUrlList[]; +extern const char kAppList[]; +extern const char kAppId[]; +extern const char kAppType[]; + +std::string AppTypeToString(apps::mojom::AppType app_type); +apps::mojom::AppType StringToAppType(const std::string& app_type); + class AppTimeLimitsWhitelistPolicyWrapper { public: explicit AppTimeLimitsWhitelistPolicyWrapper(const base::Value* value);
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.cc deleted file mode 100644 index 76a816e4..0000000 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.cc +++ /dev/null
@@ -1,250 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h" - -#include <utility> - -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "base/time/time.h" -#include "base/values.h" -#include "chrome/browser/chromeos/child_accounts/time_limits/app_types.h" - -namespace chromeos { -namespace app_time { -namespace policy { - -const char kUrlList[] = "url_list"; -const char kAppList[] = "app_list"; -const char kAppId[] = "app_id"; -const char kAppType[] = "app_type"; -const char kAppLimitsArray[] = "app_limits"; -const char kAppInfoDict[] = "app_info"; -const char kRestrictionEnum[] = "restriction"; -const char kDailyLimitInt[] = "daily_limit_mins"; -const char kLastUpdatedString[] = "last_updated_millis"; -const char kResetAtDict[] = "reset_at"; -const char kHourInt[] = "hour"; -const char kMinInt[] = "minute"; - -apps::mojom::AppType PolicyStringToAppType(const std::string& app_type) { - if (app_type == "ARC") - return apps::mojom::AppType::kArc; - if (app_type == "BUILD-IN") - return apps::mojom::AppType::kBuiltIn; - if (app_type == "CROSTINI") - return apps::mojom::AppType::kCrostini; - if (app_type == "EXTENSION") - return apps::mojom::AppType::kExtension; - if (app_type == "WEB") - return apps::mojom::AppType::kWeb; - - NOTREACHED(); - return apps::mojom::AppType::kUnknown; -} - -std::string AppTypeToPolicyString(apps::mojom::AppType app_type) { - switch (app_type) { - case apps::mojom::AppType::kArc: - return "ARC"; - case apps::mojom::AppType::kBuiltIn: - return "BUILT-IN"; - case apps::mojom::AppType::kCrostini: - return "CROSTINI"; - case apps::mojom::AppType::kExtension: - return "EXTENSION"; - case apps::mojom::AppType::kWeb: - return "WEB"; - default: - NOTREACHED(); - return ""; - } -} - -AppRestriction PolicyStringToAppRestriction(const std::string& restriction) { - if (restriction == "BLOCK") - return AppRestriction::kBlocked; - if (restriction == "TIME_LIMIT") - return AppRestriction::kTimeLimit; - - NOTREACHED(); - return AppRestriction::kUnknown; -} - -std::string AppRestrictionToPolicyString(const AppRestriction& restriction) { - switch (restriction) { - case AppRestriction::kBlocked: - return "BLOCK"; - case AppRestriction::kTimeLimit: - return "TIME_LIMIT"; - default: - NOTREACHED(); - return ""; - } -} - -base::Optional<AppId> AppIdFromDict(const base::Value& dict) { - if (!dict.is_dict()) - return base::nullopt; - - const base::Value* app_info = dict.FindKey(kAppInfoDict); - if (!app_info || !app_info->is_dict()) { - DLOG(ERROR) << "Invalid app info dictionary."; - return base::nullopt; - } - - const std::string* id = app_info->FindStringKey(kAppId); - if (!id || id->empty()) { - DLOG(ERROR) << "Invalid id."; - return base::nullopt; - } - - const std::string* type_string = app_info->FindStringKey(kAppType); - if (!type_string || type_string->empty()) { - DLOG(ERROR) << "Invalid type."; - return base::nullopt; - } - - return AppId(PolicyStringToAppType(*type_string), *id); -} - -base::Value AppIdToDict(const AppId& app_id) { - base::Value value(base::Value::Type::DICTIONARY); - value.SetKey(kAppId, base::Value(app_id.app_id())); - value.SetKey(kAppType, base::Value(AppTypeToPolicyString(app_id.app_type()))); - - return value; -} - -base::Optional<AppLimit> AppLimitFromDict(const base::Value& dict) { - if (!dict.is_dict()) - return base::nullopt; - - const std::string* restriction_string = dict.FindStringKey(kRestrictionEnum); - if (!restriction_string || restriction_string->empty()) { - DLOG(ERROR) << "Invalid restriction."; - return base::nullopt; - } - const AppRestriction restriction = - PolicyStringToAppRestriction(*restriction_string); - - base::Optional<int> daily_limit_mins = dict.FindIntKey(kDailyLimitInt); - if ((restriction == AppRestriction::kTimeLimit && !daily_limit_mins) || - (restriction == AppRestriction::kBlocked && daily_limit_mins)) { - DLOG(ERROR) << "Invalid restriction."; - return base::nullopt; - } - - base::Optional<base::TimeDelta> daily_limit; - if (daily_limit_mins) { - daily_limit = base::TimeDelta::FromMinutes(*daily_limit_mins); - if (daily_limit && (*daily_limit < base::TimeDelta::FromHours(0) || - *daily_limit > base::TimeDelta::FromHours(24))) { - DLOG(ERROR) << "Invalid daily limit."; - return base::nullopt; - } - } - - const std::string* last_updated_string = - dict.FindStringKey(kLastUpdatedString); - int64_t last_updated_millis; - if (!last_updated_string || last_updated_string->empty() || - !base::StringToInt64(*last_updated_string, &last_updated_millis)) { - DLOG(ERROR) << "Invalid last updated time."; - return base::nullopt; - } - - const base::Time last_updated = - base::Time::UnixEpoch() + - base::TimeDelta::FromMilliseconds(last_updated_millis); - - return AppLimit(restriction, daily_limit, last_updated); -} - -base::Value AppLimitToDict(const AppLimit& limit) { - base::Value value(base::Value::Type::DICTIONARY); - value.SetKey(kRestrictionEnum, - base::Value(AppRestrictionToPolicyString(limit.restriction()))); - if (limit.daily_limit()) - value.SetKey(kDailyLimitInt, base::Value(limit.daily_limit()->InMinutes())); - const std::string last_updated_string = base::NumberToString( - (limit.last_updated() - base::Time::UnixEpoch()).InMilliseconds()); - value.SetKey(kLastUpdatedString, base::Value(last_updated_string)); - - return value; -} - -base::Optional<base::TimeDelta> ResetTimeFromDict(const base::Value& dict) { - if (!dict.is_dict()) - return base::nullopt; - - const base::Value* reset_dict = dict.FindKey(kResetAtDict); - if (!reset_dict || !reset_dict->is_dict()) { - DLOG(ERROR) << "Invalid reset time dictionary."; - return base::nullopt; - } - - base::Optional<int> hour = reset_dict->FindIntKey(kHourInt); - if (!hour) { - DLOG(ERROR) << "Invalid reset hour."; - return base::nullopt; - } - - base::Optional<int> minutes = reset_dict->FindIntKey(kMinInt); - if (!minutes) { - DLOG(ERROR) << "Invalid reset minutes."; - return base::nullopt; - } - - const int hour_in_mins = base::TimeDelta::FromHours(1).InMinutes(); - return base::TimeDelta::FromMinutes(hour.value() * hour_in_mins + - minutes.value()); -} - -base::Value ResetTimeToDict(int hour, int minutes) { - base::Value value(base::Value::Type::DICTIONARY); - value.SetKey(kHourInt, base::Value(hour)); - value.SetKey(kMinInt, base::Value(minutes)); - - return value; -} - -std::map<AppId, AppLimit> AppLimitsFromDict(const base::Value& dict) { - std::map<AppId, AppLimit> app_limits; - - const base::Value* limits_array = dict.FindListKey(kAppLimitsArray); - if (!limits_array) { - DLOG(ERROR) << "Invalid app limits list."; - return app_limits; - } - - base::Value::ConstListView list_view = limits_array->GetList(); - for (const base::Value& dict : list_view) { - if (!dict.is_dict()) { - DLOG(ERROR) << "Invalid app limits entry. "; - continue; - } - - base::Optional<AppId> app_id = AppIdFromDict(dict); - if (!app_id) { - DLOG(ERROR) << "Invalid app id."; - continue; - } - - base::Optional<AppLimit> app_limit = AppLimitFromDict(dict); - if (!app_limit) { - DLOG(ERROR) << "Invalid app limit."; - continue; - } - - app_limits.emplace(*app_id, *app_limit); - } - - return app_limits; -} - -} // namespace policy -} // namespace app_time -} // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h b/chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h deleted file mode 100644 index bf10a8b..0000000 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_policy_helpers.h +++ /dev/null
@@ -1,80 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_POLICY_HELPERS_H_ -#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_POLICY_HELPERS_H_ - -#include <map> -#include <string> - -#include "base/optional.h" -#include "chrome/services/app_service/public/mojom/types.mojom.h" - -namespace base { -class TimeDelta; -class Value; -} // namespace base - -namespace chromeos { -namespace app_time { - -class AppId; -class AppLimit; -enum class AppRestriction; - -namespace policy { - -// Dictionary keys for app time limits related policies. -extern const char kUrlList[]; -extern const char kAppList[]; -extern const char kAppId[]; -extern const char kAppType[]; -extern const char kAppLimitsArray[]; -extern const char kAppInfoDict[]; -extern const char kRestrictionEnum[]; -extern const char kDailyLimitInt[]; -extern const char kLastUpdatedString[]; -extern const char kResetAtDict[]; -extern const char kHourInt[]; -extern const char kMinInt[]; - -// Converts between apps::mojom::AppType and string used by app time limits -// policies. -apps::mojom::AppType PolicyStringToAppType(const std::string& app_type); -std::string AppTypeToPolicyString(apps::mojom::AppType app_type); - -// Converts between AppRestriction and string used by app time limits policies. -AppRestriction PolicyStringToAppRestriction(const std::string& restriction); -std::string AppRestrictionToPolicyString(const AppRestriction& restriction); - -// Deserializes AppId from |dict|. -// Returns value if |dict| contains valid app information. -base::Optional<AppId> AppIdFromDict(const base::Value& dict); - -// Serializes AppId to the dictionary. -base::Value AppIdToDict(const AppId& app_id); - -// Deserializes AppLimit from |dict|. -// Returns value if |dict| contains valid app limit information. -base::Optional<AppLimit> AppLimitFromDict(const base::Value& dict); - -// Serializes AppLimit to the dictionary. -base::Value AppLimitToDict(const AppLimit& limit); - -// Deserializes daily limits reset time from |dict|. -// Returns value if |dict| contains valid reset time information. -base::Optional<base::TimeDelta> ResetTimeFromDict(const base::Value& dict); - -// Serializes daily limits reset to the dictionary. -base::Value ResetTimeToDict(int hour, int minutes); - -// Deserializes app limits data from the |dict|. -// Will return empty map if |dict| is invalid. -std::map<AppId, AppLimit> AppLimitsFromDict(const base::Value& dict); - -} // namespace policy -} // namespace app_time -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_TIME_POLICY_HELPERS_H_
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_types.h b/chrome/browser/chromeos/child_accounts/time_limits/app_types.h index 46d01044..26e315f 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_types.h +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_types.h
@@ -85,7 +85,6 @@ ~AppLimit(); AppRestriction restriction() const { return restriction_; } - base::Time last_updated() const { return last_updated_; } const base::Optional<base::TimeDelta>& daily_limit() const { return daily_limit_; }
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index e932a77..e2d2b6b 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -127,8 +127,7 @@ RestartOptions&&) = default; class CrostiniManager::CrostiniRestarter - : public base::RefCountedThreadSafe<CrostiniRestarter>, - public crostini::VmShutdownObserver, + : public crostini::VmShutdownObserver, public chromeos::disks::DiskMountManager::Observer, public chromeos::SchedulerConfigurationManagerBase::Observer { public: @@ -167,13 +166,15 @@ base::PostTask( FROM_HERE, {content::BrowserThread::UI}, base::BindOnce(&CrostiniRestarter::StartLxdContainerFinished, - base::WrapRefCounted(this), CrostiniResult::SUCCESS)); + weak_ptr_factory_.GetWeakPtr(), + CrostiniResult::SUCCESS)); return; } StartStage(mojom::InstallerState::kInstallImageLoader); - crostini_manager_->InstallTerminaComponent(base::BindOnce( - &CrostiniRestarter::LoadComponentFinished, base::WrapRefCounted(this))); + crostini_manager_->InstallTerminaComponent( + base::BindOnce(&CrostiniRestarter::LoadComponentFinished, + weak_ptr_factory_.GetWeakPtr())); } void AddObserver(CrostiniManager::RestartObserver* observer) { @@ -205,9 +206,14 @@ result_ = CrostiniResult::RESTART_ABORTED; } + // If this method returns true, then |this| may have been deleted and it is + // unsafe to refer to any member variables. bool ReturnEarlyIfAborted() { if (is_aborted_ && abort_callback_) { std::move(abort_callback_).Run(); + // The abort callback may delete this, so it's not safe to + // refer to |is_aborted_| after this point. + return true; } return is_aborted_; } @@ -227,9 +233,6 @@ bool is_aborted() const { return is_aborted_; } CrostiniResult result_ = CrostiniResult::NEVER_FINISHED; - private: - friend class base::RefCountedThreadSafe<CrostiniRestarter>; - ~CrostiniRestarter() override { // Do not record results if this restart was triggered by the installer. // The crostini installer has its own histograms that should be kept @@ -246,6 +249,7 @@ mount_manager->RemoveObserver(this); } + private: void StartStage(mojom::InstallerState stage) { for (auto& observer : observer_list_) { observer.OnStageStarted(stage); @@ -274,8 +278,8 @@ // Set the pref here, after we first successfully install something profile_->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, true); StartStage(mojom::InstallerState::kStartConcierge); - crostini_manager_->StartConcierge( - base::BindOnce(&CrostiniRestarter::ConciergeStarted, this)); + crostini_manager_->StartConcierge(base::BindOnce( + &CrostiniRestarter::ConciergeStarted, weak_ptr_factory_.GetWeakPtr())); } void ConciergeStarted(bool is_started) { @@ -300,8 +304,8 @@ base::FilePath(vm_name_), vm_tools::concierge::StorageLocation::STORAGE_CRYPTOHOME_ROOT, disk_size_bytes, - base::BindOnce(&CrostiniRestarter::CreateDiskImageFinished, this, - disk_size_bytes)); + base::BindOnce(&CrostiniRestarter::CreateDiskImageFinished, + weak_ptr_factory_.GetWeakPtr(), disk_size_bytes)); } void CreateDiskImageFinished(int64_t disk_size_bytes, @@ -347,7 +351,8 @@ StartStage(mojom::InstallerState::kStartTerminaVm); crostini_manager_->StartTerminaVm( vm_name_, disk_path_, num_cores_disabled, - base::BindOnce(&CrostiniRestarter::StartTerminaVmFinished, this)); + base::BindOnce(&CrostiniRestarter::StartTerminaVmFinished, + weak_ptr_factory_.GetWeakPtr())); } void StartTerminaVmFinished(bool success) { @@ -368,13 +373,15 @@ crostini::prefs::kReportCrostiniUsageEnabled) && vm_name_ == kCrostiniDefaultVmName && container_name_ == kCrostiniDefaultContainerName) { - crostini_manager_->GetTerminaVmKernelVersion(base::BindOnce( - &CrostiniRestarter::GetTerminaVmKernelVersionFinished, this)); + crostini_manager_->GetTerminaVmKernelVersion( + base::BindOnce(&CrostiniRestarter::GetTerminaVmKernelVersionFinished, + weak_ptr_factory_.GetWeakPtr())); } StartStage(mojom::InstallerState::kCreateContainer); crostini_manager_->CreateLxdContainer( vm_name_, container_name_, - base::BindOnce(&CrostiniRestarter::CreateLxdContainerFinished, this)); + base::BindOnce(&CrostiniRestarter::CreateLxdContainerFinished, + weak_ptr_factory_.GetWeakPtr())); } void GetTerminaVmKernelVersionFinished( @@ -410,7 +417,7 @@ options_.container_username.value_or( DefaultContainerUserNameForProfile(profile_)), base::BindOnce(&CrostiniRestarter::SetUpLxdContainerUserFinished, - this)); + weak_ptr_factory_.GetWeakPtr())); } void SetUpLxdContainerUserFinished(bool success) { @@ -430,7 +437,8 @@ StartStage(mojom::InstallerState::kStartContainer); crostini_manager_->StartLxdContainer( vm_name_, container_name_, - base::BindOnce(&CrostiniRestarter::StartLxdContainerFinished, this)); + base::BindOnce(&CrostiniRestarter::StartLxdContainerFinished, + weak_ptr_factory_.GetWeakPtr())); } void StartLxdContainerFinished(CrostiniResult result) { @@ -468,8 +476,8 @@ StartStage(mojom::InstallerState::kFetchSshKeys); crostini_manager_->GetContainerSshKeys( vm_name_, container_name_, - base::BindOnce(&CrostiniRestarter::GetContainerSshKeysFinished, this, - info->username)); + base::BindOnce(&CrostiniRestarter::GetContainerSshKeysFinished, + weak_ptr_factory_.GetWeakPtr(), info->username)); } else { FinishRestart(result); } @@ -583,6 +591,8 @@ bool is_running_ = false; static CrostiniManager::RestartId next_restart_id_; + + base::WeakPtrFactory<CrostiniRestarter> weak_ptr_factory_{this}; }; CrostiniManager::RestartId @@ -1856,20 +1866,25 @@ return kUninitializedRestartId; } - auto restarter = base::MakeRefCounted<CrostiniRestarter>( + auto restarter = std::make_unique<CrostiniRestarter>( profile_, this, std::move(vm_name), std::move(container_name), std::move(options), std::move(callback)); + auto restart_id = restarter->restart_id(); if (observer) restarter->AddObserver(observer); auto key = ContainerId(restarter->vm_name(), restarter->container_name()); - restarters_by_container_.emplace(key, restarter->restart_id()); - restarters_by_id_[restarter->restart_id()] = restarter; + restarters_by_container_.emplace(key, restart_id); + restarters_by_id_[restart_id] = std::move(restarter); if (restarters_by_container_.count(key) > 1) { VLOG(1) << "Already restarting " << key; } else { - restarter->Restart(); + // ::Restart needs to be called after the restarter is inserted into + // restarters_by_id_ because some tests will make the restart process + // complete before ::Restart returns. + restarters_by_id_[restart_id]->Restart(); } - return restarter->restart_id(); + + return restart_id; } void CrostiniManager::AbortRestartCrostini( @@ -1909,8 +1924,7 @@ // Kick off the "next" (in no order) pending Restart() if any. auto pending_it = restarters_by_container_.find(key); if (pending_it != restarters_by_container_.end()) { - auto restarter = restarters_by_id_[pending_it->second]; - restarter->Restart(); + restarters_by_id_[pending_it->second]->Restart(); } std::move(callback).Run(); @@ -2132,10 +2146,6 @@ vm_name, base::BindOnce(&CrostiniManager::OnStartTremplin, weak_ptr_factory_.GetWeakPtr(), vm_name, std::move(callback))); - - // Share folders from Downloads, etc with VM. - guest_os::GuestOsSharePath::GetForProfile(profile_)->SharePersistedPaths( - vm_name, base::DoNothing()); } void CrostiniManager::OnStartTremplin(std::string vm_name, @@ -2145,6 +2155,14 @@ << vm_name; UpdateVmState(vm_name, VmState::STARTED); + // Share fonts directory with the VM but don't persist as a shared path. + guest_os::GuestOsSharePath::GetForProfile(profile_)->SharePath( + vm_name, base::FilePath(file_manager::util::kSystemFontsPath), + /*persist=*/false, base::DoNothing()); + // Share folders from Downloads, etc with VM. + guest_os::GuestOsSharePath::GetForProfile(profile_)->SharePersistedPaths( + vm_name, base::DoNothing()); + // Run the original callback. std::move(callback).Run(/*success=*/true); } @@ -2822,7 +2840,7 @@ }, crostini_remover)); - for (auto restarter_it : restarters_by_id_) { + for (const auto& restarter_it : restarters_by_id_) { AbortRestartCrostini(restarter_it.first, abort_callback); } } @@ -2838,11 +2856,11 @@ CrostiniResult result) { auto key = ContainerId(restarter->vm_name(), restarter->container_name()); auto range = restarters_by_container_.equal_range(key); - std::vector<scoped_refptr<CrostiniRestarter>> pending_restarters; + std::vector<std::unique_ptr<CrostiniRestarter>> pending_restarters; // Erase first, because restarter->RunCallback() may modify our maps. for (auto it = range.first; it != range.second; ++it) { CrostiniManager::RestartId restart_id = it->second; - pending_restarters.emplace_back(restarters_by_id_[restart_id]); + pending_restarters.emplace_back(std::move(restarters_by_id_[restart_id])); restarters_by_id_.erase(restart_id); } restarters_by_container_.erase(range.first, range.second);
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h index bd70179..f7956a5 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.h +++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -845,7 +845,7 @@ std::multimap<ContainerId, CrostiniManager::RestartId> restarters_by_container_; - std::map<CrostiniManager::RestartId, scoped_refptr<CrostiniRestarter>> + std::map<CrostiniManager::RestartId, std::unique_ptr<CrostiniRestarter>> restarters_by_id_; // True when the installer dialog is showing. At that point, it is invalid
diff --git a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc index a5608d169..5afb2d9 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/barrier_closure.h" #include "base/base64.h" #include "base/bind.h" #include "base/files/file_util.h" @@ -625,11 +626,22 @@ Abort(); } if (abort_then_stop_vm_) { - Abort(); + auto barrier_closure = base::BarrierClosure(2, run_loop()->QuitClosure()); + + // Don't use the Abort() method because it terminates the run loop + // immediately, and we want to wait for the OnVmStopped task to complete. + crostini_manager()->AbortRestartCrostini(restart_id_, barrier_closure); + + // Signal that the VM has stopped by posting a task to avoid deleting + // CrostiniRestarter inside a CrostiniRestarter call. vm_tools::concierge::VmStoppedSignal signal; signal.set_owner_id(CryptohomeIdForProfile(profile())); signal.set_name(kVmName); - crostini_manager()->OnVmStopped(signal); + base::ThreadTaskRunnerHandle::Get()->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&CrostiniManager::OnVmStopped, + base::Unretained(crostini_manager()), signal), + barrier_closure); } } @@ -1305,6 +1317,16 @@ EXPECT_FALSE(fake_cicerone_client_->configure_for_arc_sideload_called()); } +TEST_F(CrostiniManagerRestartTest, RestartWhileShuttingDown) { + restart_id_ = crostini_manager()->RestartCrostini( + kVmName, kContainerName, + base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, + base::Unretained(this), run_loop()->QuitClosure()), + this); + // crostini_manager() is destructed during test teardown, mimicking the effect + // of shutting down chrome while a restart is running. +} + class CrostiniManagerEnterpriseReportingTest : public CrostiniManagerRestartTest { public:
diff --git a/chrome/browser/chromeos/crostini/crostini_port_forwarder.cc b/chrome/browser/chromeos/crostini/crostini_port_forwarder.cc new file mode 100644 index 0000000..6b9c79a --- /dev/null +++ b/chrome/browser/chromeos/crostini/crostini_port_forwarder.cc
@@ -0,0 +1,181 @@ +// Copyright 2020 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 <fcntl.h> + +#include "chrome/browser/chromeos/crostini/crostini_port_forwarder.h" + +#include "base/bind.h" +#include "base/no_destructor.h" +#include "chrome/browser/profiles/profile.h" +#include "chromeos/dbus/permission_broker/permission_broker_client.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace crostini { + +// Currently, we are not supporting ethernet/mlan/usb port forwarding. +constexpr char kDefaultInterfaceToForward[] = "wlan0"; + +class CrostiniPortForwarderFactory : public BrowserContextKeyedServiceFactory { + public: + static CrostiniPortForwarder* GetForProfile(Profile* profile) { + return static_cast<CrostiniPortForwarder*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); + } + + static CrostiniPortForwarderFactory* GetInstance() { + static base::NoDestructor<CrostiniPortForwarderFactory> factory; + return factory.get(); + } + + private: + friend class base::NoDestructor<CrostiniPortForwarderFactory>; + + CrostiniPortForwarderFactory() + : BrowserContextKeyedServiceFactory( + "CrostiniPortForwarderService", + BrowserContextDependencyManager::GetInstance()) {} + + ~CrostiniPortForwarderFactory() override = default; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override { + Profile* profile = Profile::FromBrowserContext(context); + return new CrostiniPortForwarder(profile); + } +}; + +CrostiniPortForwarder* CrostiniPortForwarder::GetForProfile(Profile* profile) { + return CrostiniPortForwarderFactory::GetForProfile(profile); +} + +CrostiniPortForwarder::CrostiniPortForwarder(Profile* profile) + : profile_(profile) { + // TODO(matterchen): Profile will be used later, this is to remove warnings. + (void)profile_; +} + +CrostiniPortForwarder::~CrostiniPortForwarder() = default; + +void CrostiniPortForwarder::OnActivatePortCompleted( + ResultCallback result_callback, + const PortRuleKey& key, + bool success) { + if (!success) { + forwarded_ports_.erase(key); + LOG(ERROR) << "Failed to activate port, port preference not added: " + << key.port_number; + std::move(result_callback).Run(success); + return; + } + // TODO(matterchen): Update current port forwarding preference. + std::move(result_callback).Run(success); +} + +void CrostiniPortForwarder::OnAddPortCompleted(ResultCallback result_callback, + const std::string& label, + const PortRuleKey& key, + bool success) { + if (!success) { + forwarded_ports_.erase(key); + LOG(ERROR) << "Failed to activate port, port preference not added: " + << key.port_number; + std::move(result_callback).Run(success); + return; + } + // TODO(matterchen): Add new port forwarding preference. + std::move(result_callback).Run(success); +} + +void CrostiniPortForwarder::TryActivatePort( + uint16_t port_number, + const Protocol& protocol_type, + const std::string& ipv4_addr, + chromeos::PermissionBrokerClient::ResultCallback result_callback) { + chromeos::PermissionBrokerClient* client = + chromeos::PermissionBrokerClient::Get(); + if (!client) { + LOG(ERROR) << "Could not get permission broker client."; + std::move(result_callback).Run(false); + return; + } + + int lifeline[2] = {-1, -1}; + if (pipe(lifeline) < 0) { + LOG(ERROR) << "Failed to create a lifeline pipe"; + std::move(result_callback).Run(false); + return; + } + + PortRuleKey port_key = { + .port_number = port_number, + .protocol_type = protocol_type, + .input_ifname = kDefaultInterfaceToForward, + }; + + base::ScopedFD lifeline_local(lifeline[0]); + base::ScopedFD lifeline_remote(lifeline[1]); + + forwarded_ports_[port_key] = std::move(lifeline_local); + + if (Protocol::TCP == protocol_type) { + client->RequestTcpPortForward( + port_number, kDefaultInterfaceToForward, ipv4_addr, port_number, + std::move(lifeline_remote.get()), std::move(result_callback)); + } else if (Protocol::UDP == protocol_type) { + client->RequestUdpPortForward( + port_number, kDefaultInterfaceToForward, ipv4_addr, port_number, + std::move(lifeline_remote.get()), std::move(result_callback)); + } +} + +void CrostiniPortForwarder::AddPort(uint16_t port_number, + const Protocol& protocol_type, + const std::string& label, + ResultCallback result_callback) { + PortRuleKey new_port_key = { + .port_number = port_number, + .protocol_type = protocol_type, + .input_ifname = kDefaultInterfaceToForward, + }; + + if (forwarded_ports_.find(new_port_key) != forwarded_ports_.end()) { + LOG(ERROR) << "Trying to add an already forwarded port."; + std::move(result_callback).Run(false); + return; + } + + base::OnceCallback<void(bool)> on_add_port_completed = + base::BindOnce(&CrostiniPortForwarder::OnAddPortCompleted, + weak_ptr_factory_.GetWeakPtr(), std::move(result_callback), + label, new_port_key); + + // TODO(matterchen): Extract container IPv4 address. + TryActivatePort(port_number, protocol_type, "PLACEHOLDER_IP_ADDRESS", + std::move(on_add_port_completed)); +} + +void CrostiniPortForwarder::ActivatePort(uint16_t port_number, + ResultCallback result_callback) { + // TODO(matterchen): Find the current port setting from profile preferences. + PortRuleKey existing_port_key = { + .port_number = port_number, + .protocol_type = Protocol::TCP, + .input_ifname = kDefaultInterfaceToForward, + }; + + base::OnceCallback<void(bool)> on_activate_port_completed = + base::BindOnce(&CrostiniPortForwarder::OnActivatePortCompleted, + weak_ptr_factory_.GetWeakPtr(), std::move(result_callback), + existing_port_key); + + // TODO(matterchen): Extract container IPv4 address. + CrostiniPortForwarder::TryActivatePort(port_number, Protocol::TCP, + "PLACEHOLDER_IP_ADDRESS", + std::move(on_activate_port_completed)); +} + +} // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_port_forwarder.h b/chrome/browser/chromeos/crostini/crostini_port_forwarder.h new file mode 100644 index 0000000..9ee3617 --- /dev/null +++ b/chrome/browser/chromeos/crostini/crostini_port_forwarder.h
@@ -0,0 +1,93 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_PORT_FORWARDER_H_ +#define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_PORT_FORWARDER_H_ + +#include <string> + +#include "base/files/scoped_file.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "components/keyed_service/core/keyed_service.h" + +class Profile; + +namespace crostini { + +class CrostiniPortForwarder : public KeyedService { + public: + enum class Protocol { + TCP, + UDP, + }; + + struct PortRuleKey { + uint16_t port_number; + const Protocol& protocol_type; + std::string input_ifname; + + bool operator==(const PortRuleKey& other) const { + return port_number == other.port_number && + protocol_type == other.protocol_type && + input_ifname == other.input_ifname; + } + }; + + // Helper for using PortRuleKey as key entries in std::unordered_maps. + struct PortRuleKeyHasher { + std::size_t operator()(const PortRuleKey& k) const { + return ((std::hash<uint16_t>()(k.port_number) ^ + (std::hash<Protocol>()(k.protocol_type) << 1)) >> + 1) ^ + (std::hash<std::string>()(k.input_ifname) << 1); + } + }; + + using ResultCallback = base::OnceCallback<void(bool)>; + void ActivatePort(uint16_t port_number, ResultCallback result_callback); + void AddPort(uint16_t port_number, + const Protocol& protocol_type, + const std::string& label, + ResultCallback result_callback); + + static CrostiniPortForwarder* GetForProfile(Profile* profile); + + explicit CrostiniPortForwarder(Profile* profile); + ~CrostiniPortForwarder() override; + + private: + FRIEND_TEST_ALL_PREFIXES(CrostiniPortForwarderTest, AddPortDuplicateFail); + FRIEND_TEST_ALL_PREFIXES(CrostiniPortForwarderTest, AddPortMultipleSuccess); + FRIEND_TEST_ALL_PREFIXES(CrostiniPortForwarderTest, AddPortUdpAndTcpSuccess); + FRIEND_TEST_ALL_PREFIXES(CrostiniPortForwarderTest, + TryActivatePortPermissionBrokerClientFail); + void OnActivatePortCompleted(ResultCallback result_callback, + const PortRuleKey& key, + bool success); + void OnAddPortCompleted(ResultCallback result_callback, + const std::string& label, + const PortRuleKey& key, + bool success); + void TryActivatePort(uint16_t port_number, + const Protocol& protocol_type, + const std::string& ipv4_addr, + base::OnceCallback<void(bool)> result_callback); + + // For each port rule (protocol, port, interface), keep track of the fd which + // requested it so we can release it on removal / deactivate. + std::unordered_map<PortRuleKey, base::ScopedFD, PortRuleKeyHasher> + forwarded_ports_; + + Profile* profile_; + + base::WeakPtrFactory<CrostiniPortForwarder> weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(CrostiniPortForwarder); + +}; // class + +} // namespace crostini + +#endif // CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_PORT_FORWARDER_H_
diff --git a/chrome/browser/chromeos/crostini/crostini_port_forwarder_unittest.cc b/chrome/browser/chromeos/crostini/crostini_port_forwarder_unittest.cc new file mode 100644 index 0000000..b10fc1e --- /dev/null +++ b/chrome/browser/chromeos/crostini/crostini_port_forwarder_unittest.cc
@@ -0,0 +1,183 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/crostini/crostini_port_forwarder.h" + +#include "chrome/browser/chromeos/crostini/crostini_test_helper.h" +#include "chrome/test/base/testing_profile.h" +#include "chromeos/dbus/permission_broker/fake_permission_broker_client.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Mock; +using testing::Return; + +void TestingCallback(bool* out, bool in) { + *out = in; +} + +namespace crostini { + +class CrostiniPortForwarderTest : public testing::Test { + public: + CrostiniPortForwarderTest() {} + + ~CrostiniPortForwarderTest() override {} + + void SetUp() override { + chromeos::PermissionBrokerClient::InitializeFake(); + profile_ = std::make_unique<TestingProfile>(); + test_helper_ = std::make_unique<CrostiniTestHelper>(profile_.get()); + crostini_port_forwarder_ = + std::make_unique<CrostiniPortForwarder>(profile()); + } + + void TearDown() override { + chromeos::PermissionBrokerClient::Shutdown(); + crostini_port_forwarder_.reset(); + test_helper_.reset(); + profile_.reset(); + } + + protected: + Profile* profile() { return profile_.get(); } + + std::unique_ptr<CrostiniTestHelper> test_helper_; + std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<CrostiniPortForwarder> crostini_port_forwarder_; + content::BrowserTaskEnvironment task_environment_; + + private: + DISALLOW_COPY_AND_ASSIGN(CrostiniPortForwarderTest); +}; + +TEST_F(CrostiniPortForwarderTest, AddPortTcpSuccess) { + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + + bool success = false; + crostini_port_forwarder_->AddPort(5000, CrostiniPortForwarder::Protocol::TCP, + "label0", + base::BindOnce(&TestingCallback, &success)); + EXPECT_TRUE(success); + EXPECT_TRUE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); +} + +TEST_F(CrostiniPortForwarderTest, AddPortUdpSuccess) { + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + + bool success = false; + crostini_port_forwarder_->AddPort(5000, CrostiniPortForwarder::Protocol::UDP, + "label0", + base::BindOnce(&TestingCallback, &success)); + EXPECT_TRUE(success); + EXPECT_TRUE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); +} + +TEST_F(CrostiniPortForwarderTest, AddPortDuplicateFail) { + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + + bool success = false; + crostini_port_forwarder_->AddPort(5000, CrostiniPortForwarder::Protocol::UDP, + "label0", + base::BindOnce(&TestingCallback, &success)); + EXPECT_TRUE(success); + EXPECT_TRUE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + EXPECT_EQ(crostini_port_forwarder_->forwarded_ports_.size(), 1U); + + // Leave success as == true. + crostini_port_forwarder_->AddPort(5000, CrostiniPortForwarder::Protocol::UDP, + "label1", + base::BindOnce(&TestingCallback, &success)); + EXPECT_FALSE(success); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_TRUE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + EXPECT_EQ(crostini_port_forwarder_->forwarded_ports_.size(), 1U); +} + +TEST_F(CrostiniPortForwarderTest, AddPortUdpAndTcpSuccess) { + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + + bool success = false; + crostini_port_forwarder_->AddPort(5000, CrostiniPortForwarder::Protocol::UDP, + "label0", + base::BindOnce(&TestingCallback, &success)); + EXPECT_TRUE(success); + + success = false; + crostini_port_forwarder_->AddPort(5000, CrostiniPortForwarder::Protocol::TCP, + "label0", + base::BindOnce(&TestingCallback, &success)); + EXPECT_TRUE(success); + EXPECT_EQ(crostini_port_forwarder_->forwarded_ports_.size(), 2U); +} + +TEST_F(CrostiniPortForwarderTest, AddPortMultipleSuccess) { + EXPECT_EQ(crostini_port_forwarder_->forwarded_ports_.size(), 0U); + crostini_port_forwarder_->AddPort(5000, CrostiniPortForwarder::Protocol::UDP, + "label0", base::DoNothing()); + crostini_port_forwarder_->AddPort(5001, CrostiniPortForwarder::Protocol::TCP, + "label1", base::DoNothing()); + crostini_port_forwarder_->AddPort(5002, CrostiniPortForwarder::Protocol::UDP, + "label2", base::DoNothing()); + EXPECT_EQ(crostini_port_forwarder_->forwarded_ports_.size(), 3U); +} + +TEST_F(CrostiniPortForwarderTest, ActivatePortTcpSuccess) { + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); + + bool success = false; + crostini_port_forwarder_->ActivatePort( + 5000, base::BindOnce(&TestingCallback, &success)); + EXPECT_TRUE(success); + EXPECT_TRUE(chromeos::FakePermissionBrokerClient::Get()->HasTcpPortForward( + 5000, "wlan0")); + EXPECT_FALSE(chromeos::FakePermissionBrokerClient::Get()->HasUdpPortForward( + 5000, "wlan0")); +} + +TEST_F(CrostiniPortForwarderTest, TryActivatePortPermissionBrokerClientFail) { + bool success = false; + crostini_port_forwarder_->TryActivatePort( + 5000, CrostiniPortForwarder::Protocol::TCP, "label0", + base::BindOnce(&TestingCallback, &success)); + EXPECT_TRUE(success); + EXPECT_EQ(crostini_port_forwarder_->forwarded_ports_.size(), 1U); + chromeos::PermissionBrokerClient::Shutdown(); + + // Leave success as == true. + crostini_port_forwarder_->TryActivatePort( + 5001, CrostiniPortForwarder::Protocol::TCP, "label1", + base::BindOnce(&TestingCallback, &success)); + EXPECT_FALSE(success); + EXPECT_EQ(crostini_port_forwarder_->forwarded_ports_.size(), 1U); + // Re-initialize otherwise Shutdown in TearDown phase will break. + chromeos::PermissionBrokerClient::InitializeFake(); +} + +} // namespace crostini
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc index 4552da0..1fc1b42 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -42,9 +42,6 @@ dict->SetBoolean("CROSTINI_ENABLED", crostini::CrostiniFeatures::Get()->IsEnabled( Profile::FromBrowserContext(browser_context()))); - dict->SetBoolean("FEEDBACK_PANEL_ENABLED", - base::FeatureList::IsEnabled( - chromeos::features::kEnableFileManagerFeedbackPanel)); dict->SetBoolean("PLUGIN_VM_ENABLED", plugin_vm::IsPluginVmEnabled( Profile::FromBrowserContext(browser_context())));
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc index 9877293a..29e504d2 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -30,6 +30,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/ash/wallpaper_controller_client.h" +#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h" #include "chrome/common/chrome_paths.h" #include "chrome/grit/generated_resources.h" #include "chromeos/constants/chromeos_features.h" @@ -307,7 +308,8 @@ // OS-level sync as a whole and wallpaper sync must be enabled. bool os_wallpaper_sync_enabled = sync_service->GetUserSettings()->IsOsSyncFeatureEnabled() && - profile->GetPrefs()->GetBoolean(syncer::prefs::kSyncOsWallpaper); + profile->GetPrefs()->GetBoolean( + chromeos::settings::prefs::kSyncOsWallpaper); dict->SetBoolean(kSyncThemes, os_wallpaper_sync_enabled); Respond(OneArgument(std::move(dict))); return;
diff --git a/chrome/browser/chromeos/file_manager/path_util.cc b/chrome/browser/chromeos/file_manager/path_util.cc index 3753a742..12da6d3 100644 --- a/chrome/browser/chromeos/file_manager/path_util.cc +++ b/chrome/browser/chromeos/file_manager/path_util.cc
@@ -116,6 +116,9 @@ const base::FilePath::CharType kAndroidFilesPath[] = FILE_PATH_LITERAL("/run/arc/sdcard/write/emulated/0"); +const base::FilePath::CharType kSystemFontsPath[] = + FILE_PATH_LITERAL("/usr/share/fonts"); + base::FilePath GetDownloadsFolderForProfile(Profile* profile) { // Check if FilesApp has a registered path already. This happens for tests. const std::string mount_point_name =
diff --git a/chrome/browser/chromeos/file_manager/path_util.h b/chrome/browser/chromeos/file_manager/path_util.h index 1290321..6536852c 100644 --- a/chrome/browser/chromeos/file_manager/path_util.h +++ b/chrome/browser/chromeos/file_manager/path_util.h
@@ -24,6 +24,9 @@ // Absolute path for the folder containing Android files. extern const base::FilePath::CharType kAndroidFilesPath[]; +// Absolute path for the folder containing font files. +extern const base::FilePath::CharType kSystemFontsPath[]; + // Gets the absolute path for the 'Downloads' folder for the |profile|. base::FilePath GetDownloadsFolderForProfile(Profile* profile);
diff --git a/chrome/browser/chromeos/guest_os/guest_os_share_path.cc b/chrome/browser/chromeos/guest_os/guest_os_share_path.cc index d9e8776..063b08e 100644 --- a/chrome/browser/chromeos/guest_os/guest_os_share_path.cc +++ b/chrome/browser/chromeos/guest_os/guest_os_share_path.cc
@@ -222,6 +222,7 @@ file_manager::util::GetMyFilesFolderForProfile(profile_); base::FilePath android_files(file_manager::util::kAndroidFilesPath); base::FilePath removable_media(file_manager::util::kRemovableMediaPath); + base::FilePath system_fonts(file_manager::util::kSystemFontsPath); base::FilePath linux_files = file_manager::util::GetCrostiniMountDirectory(profile_); if (my_files == path || my_files.AppendRelativePath(path, &relative_path)) { @@ -292,6 +293,10 @@ request.set_storage_location( vm_tools::seneschal::SharePathRequest::LINUX_FILES); request.set_owner_id(crostini::CryptohomeIdForProfile(profile_)); + } else if (path == system_fonts || + system_fonts.AppendRelativePath(path, &relative_path)) { + allowed_path = true; + request.set_storage_location(vm_tools::seneschal::SharePathRequest::FONTS); } if (!allowed_path) {
diff --git a/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc b/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc index 033c224f..3c07f3c 100644 --- a/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc +++ b/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc
@@ -502,6 +502,17 @@ run_loop()->Run(); } +TEST_F(GuestOsSharePathTest, SuccessSystemFonts) { + SetUpVolume(); + guest_os_share_path_->SharePath( + "vm-running", base::FilePath("/usr/share/fonts"), PERSIST_NO, + base::BindOnce( + &GuestOsSharePathTest::SharePathCallback, base::Unretained(this), + "vm-running", Persist::NO, SeneschalClientCalled::YES, + &vm_tools::seneschal::SharePathRequest::FONTS, "", Success::YES, "")); + run_loop()->Run(); +} + TEST_F(GuestOsSharePathTest, SharePathErrorSeneschal) { features_.InitWithFeatures({features::kCrostini}, {}); GetFakeUserManager()->LoginUser(account_id_);
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc index 288781e..8535f57 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc
@@ -182,16 +182,8 @@ } DCHECK_EQ(state_, State::DOWNLOADING_DLC); - if (err == dlcservice::kErrorInvalidDlc) { - LOG(ERROR) << "PluginVM DLC is not supported, need to enable PluginVM DLC."; - state_ = State::DOWNLOAD_DLC_FAILED; - if (observer_) - observer_->OnDownloadFailed(FailureReason::DLC_DOWNLOAD_FAILED); - RecordPluginVmDlcUseResultHistogram( - PluginVmDlcUseResult::kFallbackToRootFsInvalidDlcError); - return; - } - + // TODO(b/145814572): As soon as the DLC support is added to the ebuild, we + // should make dlcservice::kErrorInvalidDlc fail the installation. if (err != dlcservice::kErrorNone) { // TODO(b/145814572): Remove this log once PluginVM is converted to DLC and // invoke |OnDownloadFailed()|. The temporary passthrough is safe as
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc index bc90637c..9d2d1606a 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
@@ -666,13 +666,8 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_dlcservice_client_->SetInstallError(dlcservice::kErrorInvalidDlc); - EXPECT_CALL(*observer_, OnDlcDownloadCompleted()).Times(0); - EXPECT_CALL(*observer_, OnDownloadFailed(_)).Times(1); - + EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); StartAndRunToCompletion(); - histogram_tester_->ExpectUniqueSample( - kPluginVmDlcUseResultHistogram, - PluginVmDlcUseResult::kFallbackToRootFsInvalidDlcError, 1); } } // namespace plugin_vm
diff --git a/chrome/browser/devtools/protocol/page_handler.cc b/chrome/browser/devtools/protocol/page_handler.cc index edb6539..e65bfd9f 100644 --- a/chrome/browser/devtools/protocol/page_handler.cc +++ b/chrome/browser/devtools/protocol/page_handler.cc
@@ -68,9 +68,30 @@ // static void PageHandler::GotInstallabilityErrors( std::unique_ptr<GetInstallabilityErrorsCallback> callback, - std::vector<std::string> errors) { + std::vector<std::string> errors, + std::vector<content::InstallabilityError> installability_errors) { + auto result_installability_errors = + std::make_unique<protocol::Array<protocol::Page::InstallabilityError>>(); + for (const auto& installability_error : installability_errors) { + auto installability_error_arguments = std::make_unique< + protocol::Array<protocol::Page::InstallabilityErrorArgument>>(); + for (const auto& error_argument : + installability_error.installability_error_arguments) { + installability_error_arguments->emplace_back( + protocol::Page::InstallabilityErrorArgument::Create() + .SetName(error_argument.name) + .SetValue(error_argument.value) + .Build()); + } + result_installability_errors->emplace_back( + protocol::Page::InstallabilityError::Create() + .SetErrorId(installability_error.error_id) + .SetErrorArguments(std::move(installability_error_arguments)) + .Build()); + } callback->sendSuccess( - std::make_unique<protocol::Array<std::string>>(std::move(errors))); + std::make_unique<protocol::Array<std::string>>(std::move(errors)), + std::move(result_installability_errors)); } void PageHandler::GetManifestIcons(
diff --git a/chrome/browser/devtools/protocol/page_handler.h b/chrome/browser/devtools/protocol/page_handler.h index dc267311..19db7e6c 100644 --- a/chrome/browser/devtools/protocol/page_handler.h +++ b/chrome/browser/devtools/protocol/page_handler.h
@@ -10,6 +10,7 @@ #include "content/public/browser/web_contents_observer.h" namespace content { +struct InstallabilityError; class WebContents; } @@ -37,7 +38,8 @@ private: static void GotInstallabilityErrors( std::unique_ptr<GetInstallabilityErrorsCallback> callback, - std::vector<std::string> errors); + std::vector<std::string> errors, + std::vector<content::InstallabilityError> installability_errors); static void GotManifestIcons( std::unique_ptr<GetManifestIconsCallback> callback,
diff --git a/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc index b83956b..bc30353 100644 --- a/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc
@@ -6,6 +6,9 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/test/simple_test_clock.h" +#include "base/test/test_mock_time_task_runner.h" +#include "base/time/time.h" #include "chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "content/public/common/resource_type.h" @@ -149,24 +152,27 @@ request_2); } + // No need to trim non-active rules because all requests are from active tabs. + const bool trim_non_active_rules = false; + // For |extension_1|, one rule match should be recorded for |rules_tracked_| // and one for |pending_navigation_actions_|. - EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest(extension_1->id(), - tab_id)); + EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest( + extension_1->id(), tab_id, trim_non_active_rules)); EXPECT_EQ(1, action_tracker()->GetPendingRuleCountForTest(extension_1->id(), kNavigationId)); // Since |extension_2| does not have the feedback permission, no rule matches // should be recorded. - EXPECT_EQ(0, action_tracker()->GetMatchedRuleCountForTest(extension_2->id(), - tab_id)); + EXPECT_EQ(0, action_tracker()->GetMatchedRuleCountForTest( + extension_2->id(), tab_id, trim_non_active_rules)); EXPECT_EQ(0, action_tracker()->GetPendingRuleCountForTest(extension_2->id(), kNavigationId)); // While |extension_3| does not have the feedback permission, it does have the // activeTab permission and therefore rule matches should be recorded. - EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest(extension_3->id(), - tab_id)); + EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest( + extension_3->id(), tab_id, trim_non_active_rules)); EXPECT_EQ(1, action_tracker()->GetPendingRuleCountForTest(extension_3->id(), kNavigationId)); @@ -175,6 +181,134 @@ action_tracker()->ClearTabData(tab_id); } +// Test that rules associated with a non-active tab past their lifetime will be +// removed, and not returned by getMatchedRules +TEST_P(ActionTrackerTest, GetMatchedRulesLifespan) { + base::SimpleTestClock clock_; + clock_.SetNow(base::Time::Now()); + action_tracker()->SetClockForTests(&clock_); + + // Load an extension with the declarativeNetRequestFeedback permission. + ASSERT_NO_FATAL_FAILURE(LoadExtension("test_extension", + true /* has_feedback_permission */, + false /* has_active_tab_permission */)); + const Extension* extension_1 = last_loaded_extension(); + + const int tab_id = 1; + + // Record a rule match for a non-navigation request. + WebRequestInfo request_1(GetRequestParamsForURL( + "http://one.com", content::ResourceType::kSubResource, tab_id)); + action_tracker()->OnRuleMatched(CreateRequestAction(extension_1->id()), + request_1); + + // Half life of a matched rule associated with a non-active tab, with 50ms + // added. + base::TimeDelta half_life = (ActionTracker::kNonActiveTabRuleLifespan / 2) + + base::TimeDelta::FromMilliseconds(50); + + // Advance the clock by half of the lifespan of a matched rule for the unknown + // tab ID. + clock_.Advance(half_life); + + // Record another rule match. + action_tracker()->OnRuleMatched(CreateRequestAction(extension_1->id()), + request_1); + + // Close the tab with |tab_id|. + action_tracker()->ClearTabData(tab_id); + + // Since some requests are not from an active tab, and the rule count for the + // unknown tab will be queried, we should emulate the getMatchedRules API call + // and trim non-active rules. + const bool trim_non_active_rules = true; + + // Both rules should now be attributed to the unknown tab ID since the tab in + // which they were matched is no longer active. + EXPECT_EQ(2, action_tracker()->GetMatchedRuleCountForTest( + extension_1->id(), extension_misc::kUnknownTabId, + trim_non_active_rules)); + + // Advance the clock so one of the matched rules will be older than the + // lifespan for rules not associated with an active tab. + clock_.Advance(half_life); + + // Rules not attributed to an active tab have a fixed lifespan, + // so only one rule should be returned. + EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest( + extension_1->id(), extension_misc::kUnknownTabId, + trim_non_active_rules)); + + // Advance the clock so both rules will be older than the matched rule + // lifespan. + clock_.Advance(ActionTracker::kNonActiveTabRuleLifespan); + + // Since both rules are older than the lifespan, they should be cleared and no + // rules are returned. + EXPECT_EQ(0, action_tracker()->GetMatchedRuleCountForTest( + extension_1->id(), extension_misc::kUnknownTabId, + trim_non_active_rules)); + + action_tracker()->SetClockForTests(nullptr); +} + +// Test that matched rules not associated with an active tab will be +// automatically cleaned up by a recurring task. +TEST_P(ActionTrackerTest, RulesClearedOnTimer) { + scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner = + base::MakeRefCounted<base::TestMockTimeTaskRunner>( + base::Time::Now(), base::TimeTicks::Now()); + // Mock the clock and the timer. Clock is used to check whether the rule + // should be removed and the timer is used to set up a recurrent task to clean + // up old rules. + action_tracker()->SetClockForTests(mock_time_task_runner->GetMockClock()); + + auto mock_trim_timer = std::make_unique<base::RetainingOneShotTimer>( + mock_time_task_runner->GetMockTickClock()); + + mock_trim_timer->SetTaskRunner(mock_time_task_runner); + action_tracker()->SetTimerForTest(std::move(mock_trim_timer)); + + // Load an extension with the declarativeNetRequestFeedback permission. + ASSERT_NO_FATAL_FAILURE(LoadExtension("test_extension", + true /* has_feedback_permission */, + false /* has_active_tab_permission */)); + const Extension* extension_1 = last_loaded_extension(); + + // Record a rule match for |extension_1| for the unknown tab. + WebRequestInfo request_1(GetRequestParamsForURL( + "http://one.com", content::ResourceType::kSubResource, + extension_misc::kUnknownTabId)); + action_tracker()->OnRuleMatched(CreateRequestAction(extension_1->id()), + request_1); + + // Since this test explicitly tests that the recurring task will remove + // non-active rules, ensure that calls to GetmatchedRuleCountForTest will not + // remove non-active rules. + const bool trim_non_active_rules = false; + + // Verify that the rule has been matched. + EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest( + extension_1->id(), extension_misc::kUnknownTabId, + trim_non_active_rules)); + + // Advance the clock by more than the lifespan of a rule through + // |mock_time_task_runner|. + mock_time_task_runner->FastForwardBy( + ActionTracker::kNonActiveTabRuleLifespan + + base::TimeDelta::FromSeconds(1)); + + // Verify that the rule has been cleared by the recurring task. + EXPECT_EQ(0, action_tracker()->GetMatchedRuleCountForTest( + extension_1->id(), extension_misc::kUnknownTabId, + trim_non_active_rules)); + + // Reset the ActionTracker's state. + action_tracker()->SetClockForTests(nullptr); + action_tracker()->SetTimerForTest( + std::make_unique<base::RetainingOneShotTimer>()); +} + INSTANTIATE_TEST_SUITE_P(All, ActionTrackerTest, ::testing::Values(ExtensionLoadType::PACKED,
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index a61ac1ea..ba7272c 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -3931,6 +3931,154 @@ base::nullopt /* timestamp */)); } +// Tests the allowAllRequests action. +IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowAllRequests) { + struct RuleData { + int id; + int priority; + std::string action_type; + std::string url_filter; + bool is_regex_rule; + base::Optional<std::vector<std::string>> resource_types; + }; + + auto run_test = [this](const GURL& page_url, + const std::vector<RuleData>& rule_data, + const std::vector<std::string>& paths_seen, + const std::vector<std::string>& paths_not_seen) { + std::vector<TestRule> test_rules; + for (const auto& rule : rule_data) { + TestRule test_rule = CreateGenericRule(); + test_rule.id = rule.id; + test_rule.priority = rule.priority; + test_rule.action->type = rule.action_type; + test_rule.condition->url_filter.reset(); + if (rule.is_regex_rule) + test_rule.condition->regex_filter = rule.url_filter; + else + test_rule.condition->url_filter = rule.url_filter; + test_rule.condition->resource_types = rule.resource_types; + test_rules.push_back(test_rule); + } + + ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(test_rules)); + + ui_test_utils::NavigateToURL(browser(), page_url); + + const std::set<GURL> requests_seen = GetAndResetRequestsToServer(); + + for (const auto& path : paths_seen) { + GURL expected_request_url = embedded_test_server()->GetURL(path); + EXPECT_TRUE(base::Contains(requests_seen, expected_request_url)) + << expected_request_url.spec() + << " was not requested from the server."; + } + + for (const auto& path : paths_not_seen) { + GURL expected_request_url = embedded_test_server()->GetURL(path); + EXPECT_FALSE(base::Contains(requests_seen, expected_request_url)) + << expected_request_url.spec() << " request seen unexpectedly."; + } + + UninstallExtension(last_loaded_extension_id()); + }; + + // This page causes the following requests. + GURL page_url = embedded_test_server()->GetURL("example.com", + "/page_with_two_frames.html"); + std::vector<std::string> requests = { + {"/page_with_two_frames.html"}, // 0 + {"/subresources/script.js"}, // 1 + {"/child_frame.html?frame=1"}, // 2 + {"/subresources/script.js?frameId=1"}, // 3 + {"/child_frame.html?frame=2"}, // 4 + {"/subresources/script.js?frameId=2"}, // 5 + }; + + { + SCOPED_TRACE("Testing case 1"); + std::vector<RuleData> rule_data = { + {1, 4, "allowAllRequests", "page_with_two_frames\\.html", true, + std::vector<std::string>({"main_frame"})}, + {2, 3, "block", "script.js|", false}, + {3, 5, "block", "script.js?frameId=1", false}, + {4, 3, "block", "script\\.js?frameId=2", true}}; + // Requests: + // -/page_with_two_frames.html (Matching rule=1) + // -/subresources/script.js (Matching rule=[1,2] Winner=1) + // -/child_frame.html?frame=1 (Matching Rule=1) + // -/subresources/script.js?frameId=1 (Matching Rule=[1,3] Winner=3) + // -/child_frame.html?frame=2 (Matching Rule=1) + // -/subresources/script.js?frameId=2 (Matching Rule=1,4 Winner=1) + // Hence only requests[3] is blocked. + run_test(page_url, rule_data, + {requests[0], requests[1], requests[2], requests[4], requests[5]}, + {requests[3]}); + } + + { + SCOPED_TRACE("Testing case 2"); + std::vector<RuleData> rule_data = { + {1, 4, "allowAllRequests", "page_with_two_frames.html", false, + std::vector<std::string>({"main_frame"})}, + {2, 5, "block", "script\\.js", true}, + {3, 6, "allowAllRequests", "child_frame.html", false, + std::vector<std::string>({"sub_frame"})}, + {4, 7, "block", "frame=1", true}}; + + // Requests: + // -/page_with_two_frames.html (Matching rule=1) + // -/subresources/script.js (Matching rule=[1,2] Winner=2, Blocked) + // -/child_frame.html?frame=1 (Matching Rule=[1,3,4] Winner=4, Blocked) + // -/subresources/script.js?frameId=1 (Source Frame was blocked) + // -/child_frame.html?frame=2 (Matching Rule=[1,3] Winner=3) + // -/subresources/script.js?frameId=2 (Matching Rule=[1,2,3] Winner=3) + run_test(page_url, rule_data, {requests[0], requests[4], requests[5]}, + {requests[1], requests[2], requests[3]}); + } + + { + SCOPED_TRACE("Testing case 3"); + std::vector<RuleData> rule_data = { + {1, 1, "allowAllRequests", "page_with_two_frames.html", false, + std::vector<std::string>({"main_frame"})}, + {2, 5, "block", ".*", true}, + }; + + // Requests: + // -/page_with_two_frames.html (Matching rule=1) + // -/subresources/script.js (Matching rule=[1,2] Winner=2) + // -/child_frame.html?frame=1 (Matching Rule=[1,2] Winner=2) + // -/subresources/script.js?frameId=1 (Source Frame was blocked) + // -/child_frame.html?frame=2 (Matching Rule=[1,2] Winner=2) + // -/subresources/script.js?frameId=2 (Source frame was blocked) + // Hence only the main-frame request goes through. + run_test(page_url, rule_data, {requests[0]}, + {requests[1], requests[2], requests[3], requests[4], requests[5]}); + } + { + SCOPED_TRACE("Testing case 4"); + std::vector<RuleData> rule_data = { + {1, 6, "allowAllRequests", "page_with_two_frames\\.html", true, + std::vector<std::string>({"main_frame"})}, + {2, 5, "block", "*", false}, + }; + + // Requests: + // -/page_with_two_frames.html (Matching rule=1) + // -/subresources/script.js (Matching rule=[1,2] Winner=1) + // -/child_frame.html?frame=1 (Matching Rule=[1,2] Winner=1) + // -/subresources/script.js?frameId=1 (Matching Rule=[1,2] Winner=1) + // -/child_frame.html?frame=2 (Matching Rule=[1,2] Winner=1) + // -/subresources/script.js?frameId=2 (Matching Rule=[1,2] Winner=1) + // Hence all requests go through. + run_test(page_url, rule_data, + {requests[0], requests[1], requests[2], requests[3], requests[4], + requests[5]}, + {}); + } +} + // Test fixture to verify that host permissions for the request url and the // request initiator are properly checked when redirecting requests. Loads an // example.com url with four sub-frames named frame_[1..4] from hosts
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 13da3904..cac4fb12 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -49,6 +49,7 @@ #include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" +#include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" @@ -445,6 +446,10 @@ (*s_whitelist)[guest_os::prefs::kGuestOSPathsSharedToVms] = settings_api::PrefType::PREF_TYPE_DICTIONARY; + // Plugin Vm + (*s_whitelist)[plugin_vm::prefs::kPluginVmImageExists] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; + // Android Apps. (*s_whitelist)[arc::prefs::kArcEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN;
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc index 797cc5c..8d78be4 100644 --- a/chrome/browser/extensions/tab_helper.cc +++ b/chrome/browser/extensions/tab_helper.cc
@@ -45,6 +45,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/frame_navigate_params.h" #include "extensions/browser/api/declarative/rules_registry_service.h" +#include "extensions/browser/api/declarative_net_request/web_contents_helper.h" #include "extensions/browser/disable_reason.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_system.h" @@ -79,7 +80,8 @@ profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), extension_app_(NULL), script_executor_(new ScriptExecutor(web_contents)), - extension_action_runner_(new ExtensionActionRunner(web_contents)) { + extension_action_runner_(new ExtensionActionRunner(web_contents)), + declarative_net_request_helper_(web_contents) { // The ActiveTabPermissionManager requires a session ID; ensure this // WebContents has one. CreateSessionServiceTabHelper(web_contents);
diff --git a/chrome/browser/extensions/tab_helper.h b/chrome/browser/extensions/tab_helper.h index dd0e100..eba79c8 100644 --- a/chrome/browser/extensions/tab_helper.h +++ b/chrome/browser/extensions/tab_helper.h
@@ -20,6 +20,7 @@ #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_receiver_set.h" #include "content/public/browser/web_contents_user_data.h" +#include "extensions/browser/api/declarative_net_request/web_contents_helper.h" #include "extensions/browser/extension_function_dispatcher.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" @@ -153,6 +154,8 @@ std::unique_ptr<ExtensionActionRunner> extension_action_runner_; + declarative_net_request::WebContentsHelper declarative_net_request_helper_; + std::unique_ptr<ActiveTabPermissionGranter> active_tab_permission_granter_; ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index fe9977c1..5aefe00 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -397,7 +397,7 @@ { "name": "calculate-native-win-occlusion", "owners": [ "davidbienvenu", "fdoray" ], - "expiry_milestone": 81 + "expiry_milestone": 84 }, { "name": "camera-system-web-app", @@ -1362,7 +1362,7 @@ { "name": "enable-experimental-productivity-features", "owners": [ "feature-control@chromium.org" ], - "expiry_milestone": 81 + "expiry_milestone": 86 }, { "name": "enable-experimental-web-platform-features", @@ -2255,11 +2255,6 @@ "expiry_milestone": 82 }, { - "name": "file-manager-feedback-panel", - "owners": [ "adanilo" ], - "expiry_milestone": 81 - }, - { "name": "files-ng", "owners": [ "adanilo", "noel" ], "expiry_milestone": 82 @@ -2776,6 +2771,11 @@ "expiry_milestone": 76 }, { + "name": "omnibox-assistant-voice-search", + "owners": [ "wylieb", "chrome-omnibox-team@google.com" ], + "expiry_milestone": 85 + }, + { "name": "omnibox-autocomplete-titles", "owners": [ "manukh", "chrome-omnibox-team@google.com" ], "expiry_milestone": 85 @@ -2995,7 +2995,7 @@ { "name": "overscroll-history-navigation", "owners": [ "mohsen", "jinsukkim" ], - "expiry_milestone": 80 + "expiry_milestone": 82 }, { "name": "paint-preview-test", @@ -3365,7 +3365,7 @@ { "name": "split-settings-sync", "owners": [ "jamescook", "cros-system-services@google.com" ], - "expiry_milestone": 82 + "expiry_milestone": 84 }, { "name": "stop-in-background", @@ -3683,8 +3683,8 @@ }, { "name": "web-contents-occlusion", - "owners": [ "davidbienvenu" ], - "expiry_milestone": 81 + "owners": [ "davidbienvenu", "fdoray" ], + "expiry_milestone": 84 }, { "name": "webui-a11y-enhancements",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 4638c5cd..921895e 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1391,6 +1391,12 @@ "Show the checkbox to offer local saving of a credit card downloaded from " "the server."; +const char kOmniboxAssistantVoiceSearchName[] = + "Omnibox Assistant Voice Search"; +const char kOmniboxAssistantVoiceSearchDescription[] = + "When enabled, use Assistant for omnibox voice query recognition instead of" + " Android's built-in voice recognition service. Only works on Android."; + const char kOmniboxAutocompleteTitlesName[] = "Omnibox Autocomplete Titles"; const char kOmniboxAutocompleteTitlesDescription[] = "Allows autocompleting bookmark, history, and document suggestions when the" @@ -3647,10 +3653,6 @@ "Enable experimental or in-progress Switch Access features for improved " "text input"; -const char kFileManagerFeedbackPanelDescription[] = - "Enable feedback panel in the Files app."; -const char kFileManagerFeedbackPanelName[] = "Files App. feedback panel"; - const char kFileManagerTouchModeName[] = "Files App. touch mode"; const char kFileManagerTouchModeDescription[] = "Touchscreen-specific interactions of the Files app.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 136d9c8..5112a3e 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -847,6 +847,9 @@ extern const char kOfferStoreUnmaskedWalletCardsName[]; extern const char kOfferStoreUnmaskedWalletCardsDescription[]; +extern const char kOmniboxAssistantVoiceSearchName[]; +extern const char kOmniboxAssistantVoiceSearchDescription[]; + extern const char kOmniboxAutocompleteTitlesName[]; extern const char kOmniboxAutocompleteTitlesDescription[]; @@ -2175,9 +2178,6 @@ extern const char kExperimentalAccessibilitySwitchAccessTextName[]; extern const char kExperimentalAccessibilitySwitchAccessTextDescription[]; -extern const char kFileManagerFeedbackPanelDescription[]; -extern const char kFileManagerFeedbackPanelName[]; - extern const char kFileManagerTouchModeName[]; extern const char kFileManagerTouchModeDescription[];
diff --git a/chrome/browser/installable/installable_logging.cc b/chrome/browser/installable/installable_logging.cc index e5432efd0..a695e4b 100644 --- a/chrome/browser/installable/installable_logging.cc +++ b/chrome/browser/installable/installable_logging.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/installable/installable_logging.h" +#include <vector> + #include "base/no_destructor.h" #include "base/strings/stringprintf.h" #include "chrome/browser/installable/installable_manager.h" @@ -58,6 +60,35 @@ static const char kPreferRelatedApplications[] = "Manifest specifies prefer_related_applications: true"; +static const char kNotInMainFrameId[] = "not-in-main-frame"; +static const char kNotFromSecureOriginId[] = "not-from-secure-origin"; +static const char kNoManifestId[] = "no-manifest"; +static const char kManifestEmptyId[] = "manifest-empty"; +static const char kStartUrlNotValidId[] = "start-url-not-valid"; +static const char kManifestMissingNameOrShortNameId[] = + "manifest-missing-name-or-short-name"; +static const char kManifestDisplayNotSupportedId[] = + "manifest-display-not-supported"; +static const char kManifestMissingSuitableIconId[] = + "manifest-missing-suitable-icon"; +static const char kMinimumIconSizeInPixelsId[] = "minimum-icon-size-in-pixels"; +static const char kNoMatchingServiceWorkerId[] = "no-matching-service-worker"; +static const char kNoAcceptableIconId[] = "no-acceptable-icon"; +static const char kCannotDownloadIconId[] = "cannot-download-icon"; +static const char kNoIconAvailableId[] = "no-icon-available"; +static const char kPlatformNotSupportedOnAndroidId[] = + "platform-not-supported-on-android"; +static const char kNoIdSpecifiedId[] = "no-id-specified"; +static const char kIdsDoNotMatchId[] = "ids-do-not-match"; +static const char kAlreadyInstalledId[] = "already-installed"; +static const char kUrlNotSupportedForWebApkId[] = + "url-not-supported-for-webapk"; +static const char kInIncognitoId[] = "in-incognito"; +static const char kNotOfflineCapableId[] = "not-offline-capable"; +static const char kNoUrlForServiceWorkerId[] = "no-url-for-service-worker"; +static const char kPreferRelatedApplicationsId[] = + "prefer-related-applications"; + const std::string& GetMessagePrefix() { static base::NoDestructor<std::string> message_prefix( "Site cannot be installed: "); @@ -160,6 +191,106 @@ return message; } +content::InstallabilityError GetInstallabilityError( + InstallableStatusCode code) { + content::InstallabilityError error; + std::string error_id; + std::vector<content::InstallabilityErrorArgument> error_arguments; + switch (code) { + case NO_ERROR_DETECTED: + // These codes are solely used for UMA reporting. + case RENDERER_EXITING: + case RENDERER_CANCELLED: + case USER_NAVIGATED: + case INSUFFICIENT_ENGAGEMENT: + case PACKAGE_NAME_OR_START_URL_EMPTY: + case PREVIOUSLY_BLOCKED: + case PREVIOUSLY_IGNORED: + case SHOWING_NATIVE_APP_BANNER: + case SHOWING_WEB_APP_BANNER: + case FAILED_TO_CREATE_BANNER: + case WAITING_FOR_MANIFEST: + case WAITING_FOR_INSTALLABLE_CHECK: + case NO_GESTURE: + case WAITING_FOR_NATIVE_DATA: + case SHOWING_APP_INSTALLATION_DIALOG: + case MAX_ERROR_CODE: + break; + case NOT_IN_MAIN_FRAME: + error_id = kNotInMainFrameId; + break; + case NOT_FROM_SECURE_ORIGIN: + error_id = kNotFromSecureOriginId; + break; + case NO_MANIFEST: + error_id = kNoManifestId; + break; + case MANIFEST_EMPTY: + error_id = kManifestEmptyId; + break; + case START_URL_NOT_VALID: + error_id = kStartUrlNotValidId; + break; + case MANIFEST_MISSING_NAME_OR_SHORT_NAME: + error_id = kManifestMissingNameOrShortNameId; + break; + case MANIFEST_DISPLAY_NOT_SUPPORTED: + error_id = kManifestDisplayNotSupportedId; + break; + case MANIFEST_MISSING_SUITABLE_ICON: + error_id = kManifestMissingSuitableIconId; + error_arguments.push_back(content::InstallabilityErrorArgument( + kMinimumIconSizeInPixelsId, + base::NumberToString(InstallableManager::GetMinimumIconSizeInPx()))); + break; + case NO_MATCHING_SERVICE_WORKER: + error_id = kNoMatchingServiceWorkerId; + break; + case NO_ACCEPTABLE_ICON: + error_id = kNoAcceptableIconId; + error_arguments.push_back(content::InstallabilityErrorArgument( + kMinimumIconSizeInPixelsId, + base::NumberToString(InstallableManager::GetMinimumIconSizeInPx()))); + break; + case CANNOT_DOWNLOAD_ICON: + error_id = kCannotDownloadIconId; + break; + case NO_ICON_AVAILABLE: + error_id = kNoIconAvailableId; + break; + case PLATFORM_NOT_SUPPORTED_ON_ANDROID: + error_id = kPlatformNotSupportedOnAndroidId; + break; + case NO_ID_SPECIFIED: + error_id = kNoIdSpecifiedId; + break; + case IDS_DO_NOT_MATCH: + error_id = kIdsDoNotMatchId; + break; + case ALREADY_INSTALLED: + error_id = kAlreadyInstalledId; + break; + case URL_NOT_SUPPORTED_FOR_WEBAPK: + error_id = kUrlNotSupportedForWebApkId; + break; + case IN_INCOGNITO: + error_id = kInIncognitoId; + break; + case NOT_OFFLINE_CAPABLE: + error_id = kNotOfflineCapableId; + break; + case NO_URL_FOR_SERVICE_WORKER: + error_id = kNoUrlForServiceWorkerId; + break; + case PREFER_RELATED_APPLICATIONS: + error_id = kPreferRelatedApplicationsId; + break; + } + error.error_id = error_id; + error.installability_error_arguments = error_arguments; + return error; +} + void LogErrorToConsole(content::WebContents* web_contents, InstallableStatusCode code) { if (!web_contents)
diff --git a/chrome/browser/installable/installable_logging.h b/chrome/browser/installable/installable_logging.h index 85cb924..2e61a8ae 100644 --- a/chrome/browser/installable/installable_logging.h +++ b/chrome/browser/installable/installable_logging.h
@@ -8,6 +8,7 @@ #include <string> namespace content { +struct InstallabilityError; class WebContents; } @@ -60,6 +61,7 @@ // Returns a user-readable description for |code|, or an empty string if |code| // should not be exposed. std::string GetErrorMessage(InstallableStatusCode code); +content::InstallabilityError GetInstallabilityError(InstallableStatusCode code); // Logs a message associated with |code| to the devtools console attached to // |web_contents|. Does nothing if |web_contents| is nullptr.
diff --git a/chrome/browser/installable/installable_manager.cc b/chrome/browser/installable/installable_manager.cc index a6f396cf..d54e676 100644 --- a/chrome/browser/installable/installable_manager.cc +++ b/chrome/browser/installable/installable_manager.cc
@@ -180,16 +180,25 @@ } void OnDidCompleteGetAllErrors( - base::OnceCallback<void(std::vector<std::string> errors)> callback, + base::OnceCallback<void(std::vector<std::string> errors, + std::vector<content::InstallabilityError> + installability_errors)> callback, const InstallableData& data) { std::vector<std::string> error_messages; + std::vector<content::InstallabilityError> installability_errors; for (auto error : data.errors) { std::string message = GetErrorMessage(error); if (!message.empty()) error_messages.push_back(std::move(message)); + + content::InstallabilityError installability_error = + GetInstallabilityError(error); + if (!installability_error.error_id.empty()) + installability_errors.push_back(installability_error); } - std::move(callback).Run(std::move(error_messages)); + std::move(callback).Run(std::move(error_messages), + std::move(installability_errors)); } void OnDidCompleteGetPrimaryIcon( @@ -292,7 +301,9 @@ } void InstallableManager::GetAllErrors( - base::OnceCallback<void(std::vector<std::string> errors)> callback) { + base::OnceCallback<void(std::vector<std::string> errors, + std::vector<content::InstallabilityError> + installability_errors)> callback) { InstallableParams params; params.check_eligibility = true; params.valid_manifest = true;
diff --git a/chrome/browser/installable/installable_manager.h b/chrome/browser/installable/installable_manager.h index fb41115..b90125b 100644 --- a/chrome/browser/installable/installable_manager.h +++ b/chrome/browser/installable/installable_manager.h
@@ -18,6 +18,7 @@ #include "chrome/browser/installable/installable_logging.h" #include "chrome/browser/installable/installable_params.h" #include "chrome/browser/installable/installable_task_queue.h" +#include "content/public/browser/installability_error.h" #include "content/public/browser/service_worker_context.h" #include "content/public/browser/service_worker_context_observer.h" #include "content/public/browser/web_contents_observer.h" @@ -64,7 +65,9 @@ // passing a list of human-readable strings describing the errors encountered // during the run. The list is empty if no errors were encountered. void GetAllErrors( - base::OnceCallback<void(std::vector<std::string> errors)> callback); + base::OnceCallback<void(std::vector<std::string> errors, + std::vector<content::InstallabilityError> + installability_errors)> callback); void GetPrimaryIcon( base::OnceCallback<void(const SkBitmap* primaryIcon)> callback);
diff --git a/chrome/browser/installable/installable_manager_browsertest.cc b/chrome/browser/installable/installable_manager_browsertest.cc index fc81f26..6ae34b6 100644 --- a/chrome/browser/installable/installable_manager_browsertest.cc +++ b/chrome/browser/installable/installable_manager_browsertest.cc
@@ -252,8 +252,9 @@ base::RunLoop run_loop; std::vector<std::string> result; - manager->GetAllErrors( - base::BindLambdaForTesting([&](std::vector<std::string> errors) { + manager->GetAllErrors(base::BindLambdaForTesting( + [&](std::vector<std::string> errors, + std::vector<content::InstallabilityError> installability_errors) { result = std::move(errors); run_loop.Quit(); })); @@ -261,6 +262,26 @@ return result; } + std::vector<content::InstallabilityError> + NavigateAndGetAllInstallabilityErrors(Browser* browser, + const std::string& url) { + GURL test_url = embedded_test_server()->GetURL(url); + ui_test_utils::NavigateToURL(browser, test_url); + InstallableManager* manager = GetManager(browser); + + base::RunLoop run_loop; + std::vector<content::InstallabilityError> result; + + manager->GetAllErrors(base::BindLambdaForTesting( + [&](std::vector<std::string> errors, + std::vector<content::InstallabilityError> installability_errors) { + result = std::move(installability_errors); + run_loop.Quit(); + })); + run_loop.Run(); + return result; + } + void RunInstallableManager(Browser* browser, CallbackTester* tester, const InstallableParams& params) { @@ -1516,6 +1537,34 @@ "/banners/play_app_manifest.json"))); } +IN_PROC_BROWSER_TEST_F(InstallableManagerBrowserTest, + GetAllInatallabilityErrorsNoErrors) { + EXPECT_EQ(std::vector<content::InstallabilityError>{}, + NavigateAndGetAllInstallabilityErrors( + browser(), "/banners/manifest_test_page.html")); +} + +IN_PROC_BROWSER_TEST_F(InstallableManagerBrowserTest, + GetAllInatallabilityErrorsWithNoManifest) { + EXPECT_EQ(std::vector<content::InstallabilityError>{GetInstallabilityError( + NO_MANIFEST)}, + NavigateAndGetAllInstallabilityErrors( + browser(), "/banners/no_manifest_test_page.html")); +} + +IN_PROC_BROWSER_TEST_F(InstallableManagerBrowserTest, + GetAllInatallabilityErrorsWithPlayAppManifest) { + EXPECT_EQ(std::vector<content::InstallabilityError>( + {GetInstallabilityError(START_URL_NOT_VALID), + GetInstallabilityError(MANIFEST_MISSING_NAME_OR_SHORT_NAME), + GetInstallabilityError(MANIFEST_DISPLAY_NOT_SUPPORTED), + GetInstallabilityError(MANIFEST_MISSING_SUITABLE_ICON), + GetInstallabilityError(NO_ACCEPTABLE_ICON)}), + NavigateAndGetAllInstallabilityErrors( + browser(), GetURLOfPageWithServiceWorkerAndManifest( + "/banners/play_app_manifest.json"))); +} + IN_PROC_BROWSER_TEST_F(InstallableManagerAllowlistOriginBrowserTest, SecureOriginCheckRespectsUnsafeFlag) { // The allowlisted origin should be regarded as secure.
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc index d2e8d71c..8d13efb 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc
@@ -115,6 +115,11 @@ receiver_connection_receiver); void RemovePresentation(const std::string& presentation_id); + const base::small_map<std::map<std::string, MediaRoute>>& + presentation_id_to_route() const { + return presentation_id_to_route_; + } + private: base::small_map<std::map<std::string, MediaRoute>> presentation_id_to_route_; base::small_map< @@ -502,8 +507,7 @@ const MediaRoute& route) { auto* presentation_frame = GetOrAddPresentationFrame(render_frame_host_id); presentation_frame->AddPresentation(presentation_info, route); - // TODO(crbug.com/1031672): Notify WebContentsPresentationManager::Observer - // that the presentation routes have changed for the WebContents. + NotifyMediaRoutesChanged(); } void PresentationServiceDelegateImpl::RemovePresentation( @@ -512,8 +516,7 @@ const auto it = presentation_frames_.find(render_frame_host_id); if (it != presentation_frames_.end()) it->second->RemovePresentation(presentation_id); - // TODO(crbug.com/1031672): Notify WebContentsPresentationManager::Observer - // that the presentation routes have changed for the WebContents. + NotifyMediaRoutesChanged(); } void PresentationServiceDelegateImpl::StartPresentation( @@ -538,7 +541,8 @@ request, base::BindOnce( &PresentationServiceDelegateImpl::OnStartPresentationSucceeded, - GetWeakPtr(), render_frame_host_id, std::move(success_cb)), + weak_factory_.GetWeakPtr(), render_frame_host_id, + std::move(success_cb)), std::move(error_cb)); if (start_presentation_cb_) { start_presentation_cb_.Run(std::move(presentation_context)); @@ -609,8 +613,8 @@ MediaSource::ForPresentationUrl(presentation_url).id(), presentation_id, request.frame_origin, web_contents_, base::BindOnce(&PresentationServiceDelegateImpl::OnJoinRouteResponse, - GetWeakPtr(), render_frame_host_id, presentation_url, - presentation_id, std::move(success_cb), + weak_factory_.GetWeakPtr(), render_frame_host_id, + presentation_url, presentation_id, std::move(success_cb), std::move(error_cb)), base::TimeDelta(), incognito); } @@ -718,7 +722,7 @@ } } -base::WeakPtr<PresentationServiceDelegateImpl> +base::WeakPtr<WebContentsPresentationManager> PresentationServiceDelegateImpl::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -802,10 +806,20 @@ void PresentationServiceDelegateImpl::NotifyDefaultPresentationChanged( const content::PresentationRequest* request) { - for (WebContentsPresentationManager::Observer& presentation_observer : - presentation_observers_) { + for (auto& presentation_observer : presentation_observers_) presentation_observer.OnDefaultPresentationChanged(request); +} + +void PresentationServiceDelegateImpl::NotifyMediaRoutesChanged() { + std::vector<MediaRoute> routes; + for (const auto& presentation_frame : presentation_frames_) { + for (const auto& route : + presentation_frame.second->presentation_id_to_route()) { + routes.push_back(route.second); + } } + for (auto& presentation_observer : presentation_observers_) + presentation_observer.OnMediaRoutesChanged(routes); } WEB_CONTENTS_USER_DATA_KEY_IMPL(PresentationServiceDelegateImpl)
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h index a183bb0..33579ad 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h
@@ -158,8 +158,7 @@ void OnPresentationResponse(const content::PresentationRequest& request, mojom::RoutePresentationConnectionPtr connection, const RouteRequestResult& result) override; - - base::WeakPtr<PresentationServiceDelegateImpl> GetWeakPtr(); + base::WeakPtr<WebContentsPresentationManager> GetWeakPtr() override; // Returns the WebContents that owns this instance. content::WebContents* web_contents() const { return web_contents_; } @@ -254,6 +253,7 @@ void NotifyDefaultPresentationChanged( const content::PresentationRequest* request); + void NotifyMediaRoutesChanged(); // References to the WebContents that owns this instance, and associated // browser profile's MediaRouter instance. @@ -261,7 +261,7 @@ MediaRouter* router_; // References to the observers listening for changes to the default - // presentation of the associated WebContents. + // presentation and presentation MediaRoutes associated with the WebContents. base::ObserverList<WebContentsPresentationManager::Observer> presentation_observers_;
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc index b3cbe43..cd46837b 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl_unittest.cc
@@ -393,8 +393,7 @@ RunDefaultPresentationUrlCallbackTest(true); } -TEST_F(PresentationServiceDelegateImplTest, - NotifyWebContentsPresentationObservers) { +TEST_F(PresentationServiceDelegateImplTest, NotifyDefaultPresentationChanged) { auto callback = base::BindRepeating( &PresentationServiceDelegateImplTest::OnDefaultPresentationStarted, base::Unretained(this)); @@ -431,6 +430,28 @@ callback); } +TEST_F(PresentationServiceDelegateImplTest, NotifyMediaRoutesChanged) { + const int render_process_id = 100; + const int render_frame_id = 200; + content::PresentationRequest request( + content::GlobalFrameRoutingId(render_process_id, render_frame_id), + {presentation_url1_}, frame_origin_); + MediaRoute media_route("differentRouteId", source1_, "mediaSinkId", "", true, + true); + std::unique_ptr<RouteRequestResult> result = + RouteRequestResult::FromSuccess(media_route, kPresentationId); + StrictMock<MockWebContentsPresentationObserver> observer(GetWebContents()); + + EXPECT_CALL(observer, + OnMediaRoutesChanged(std::vector<MediaRoute>({media_route}))); + delegate_impl_->OnPresentationResponse(request, + /** connection */ nullptr, *result); + + EXPECT_CALL(observer, OnMediaRoutesChanged(std::vector<MediaRoute>())); + delegate_impl_->Terminate(render_process_id, render_frame_id, + kPresentationId); +} + TEST_F(PresentationServiceDelegateImplTest, ListenForConnnectionStateChange) { content::WebContentsTester::For(GetWebContents()) ->NavigateAndCommit(frame_url_);
diff --git a/chrome/browser/media/router/presentation/web_contents_presentation_manager.cc b/chrome/browser/media/router/presentation/web_contents_presentation_manager.cc index 17d69184..c0a761c 100644 --- a/chrome/browser/media/router/presentation/web_contents_presentation_manager.cc +++ b/chrome/browser/media/router/presentation/web_contents_presentation_manager.cc
@@ -8,14 +8,27 @@ namespace media_router { +namespace { +WebContentsPresentationManager* g_test_instance = nullptr; +} // namespace + // static base::WeakPtr<WebContentsPresentationManager> WebContentsPresentationManager::Get(content::WebContents* web_contents) { + if (g_test_instance) + return g_test_instance->GetWeakPtr(); + return PresentationServiceDelegateImpl::GetOrCreateForWebContents( web_contents) ->GetWeakPtr(); } +// static +void WebContentsPresentationManager::SetTestInstance( + WebContentsPresentationManager* test_instance) { + g_test_instance = test_instance; +} + WebContentsPresentationManager::~WebContentsPresentationManager() = default; } // namespace media_router
diff --git a/chrome/browser/media/router/presentation/web_contents_presentation_manager.h b/chrome/browser/media/router/presentation/web_contents_presentation_manager.h index d3158a166..ba3861fa 100644 --- a/chrome/browser/media/router/presentation/web_contents_presentation_manager.h +++ b/chrome/browser/media/router/presentation/web_contents_presentation_manager.h
@@ -46,6 +46,10 @@ static base::WeakPtr<WebContentsPresentationManager> Get( content::WebContents* web_contents); + // Sets the instance to be returned by Get(). If this is set, Get() ignores + // the |web_contents| argument. + static void SetTestInstance(WebContentsPresentationManager* test_instance); + virtual ~WebContentsPresentationManager() = 0; virtual void AddObserver(Observer* observer) = 0; @@ -68,6 +72,8 @@ mojom::RoutePresentationConnectionPtr connection, const RouteRequestResult& result) = 0; + virtual base::WeakPtr<WebContentsPresentationManager> GetWeakPtr() = 0; + protected: WebContentsPresentationManager() = default; };
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc index 66cdd8f..3692d3c 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
@@ -581,18 +581,17 @@ } void OptimizationGuideHintsManager::OnPageNavigationHintsFetched( + const base::flat_set<std::string>& page_navigation_hosts_requested, base::Optional<std::unique_ptr<optimization_guide::proto::GetHintsResponse>> get_hints_response) { - if (!get_hints_response.has_value() || !get_hints_response.value()) { - page_navigation_hosts_being_fetched_.clear(); + if (!get_hints_response.has_value() || !get_hints_response.value()) return; - } hint_cache_->UpdateFetchedHints( std::move(*get_hints_response), clock_->Now() + kUpdateFetchedHintsDelay, base::BindOnce( &OptimizationGuideHintsManager::OnFetchedPageNavigationHintsStored, - ui_weak_ptr_factory_.GetWeakPtr())); + ui_weak_ptr_factory_.GetWeakPtr(), page_navigation_hosts_requested)); } void OptimizationGuideHintsManager::OnFetchedTopHostsHintsStored() { @@ -607,12 +606,11 @@ &OptimizationGuideHintsManager::ScheduleTopHostsHintsFetch); } -void OptimizationGuideHintsManager::OnFetchedPageNavigationHintsStored() { +void OptimizationGuideHintsManager::OnFetchedPageNavigationHintsStored( + const base::flat_set<std::string>& page_navigation_hosts_requested) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - for (const auto& host : page_navigation_hosts_being_fetched_) + for (const auto& host : page_navigation_hosts_requested) LoadHintForHost(host, base::DoNothing()); - - page_navigation_hosts_being_fetched_.clear(); } base::Time OptimizationGuideHintsManager::GetLastHintsFetchAttemptTime() const { @@ -688,6 +686,7 @@ // Extract the target hosts. Use a flat set to remove duplicates. // |target_hosts_serialized| is the ordered list of non-duplicate hosts. + // TODO(sophiechang): See if we can make this logic simpler. base::flat_set<std::string> target_hosts; std::vector<std::string> target_hosts_serialized; for (const auto& url : prediction->sorted_predicted_urls()) { @@ -709,10 +708,6 @@ if (target_hosts.empty()) return; - page_navigation_hosts_being_fetched_.clear(); - for (const auto& host : target_hosts) - page_navigation_hosts_being_fetched_.push_back(host); - if (!hints_fetcher_) { hints_fetcher_ = std::make_unique<optimization_guide::HintsFetcher>( url_loader_factory_, @@ -728,7 +723,7 @@ optimization_guide::proto::CONTEXT_PAGE_NAVIGATION, base::BindOnce( &OptimizationGuideHintsManager::OnPageNavigationHintsFetched, - ui_weak_ptr_factory_.GetWeakPtr())); + ui_weak_ptr_factory_.GetWeakPtr(), target_hosts)); for (const auto& host : target_hosts) LoadHintForHost(host, base::DoNothing()); @@ -896,7 +891,7 @@ const optimization_guide::proto::Hint* url_keyed_hint = hint_cache_->GetURLKeyedHint(url); if (url_keyed_hint) { - DCHECK(url_keyed_hint->page_hints_size() == 1); + DCHECK_EQ(url_keyed_hint->page_hints_size(), 1); if (url_keyed_hint->page_hints_size() > 0 && IsOptimizationTypeSupportedByPageHint(&url_keyed_hint->page_hints(0), optimization_type, @@ -906,10 +901,6 @@ } if (!loaded_hint) { - if (IsHintBeingFetched(url.host())) { - return optimization_guide::OptimizationTypeDecision:: - kHintFetchStartedButNotAvailableInTime; - } // If we do not have a hint already loaded and we do not have one in the // cache, we do not know what to do with the URL so just return. // Otherwise, we do have information, but we just do not know it yet. @@ -917,6 +908,13 @@ return optimization_guide::OptimizationTypeDecision:: kHadHintButNotLoadedInTime; } + + if (hints_fetcher_ && + hints_fetcher_->IsHintForHostBeingFetched(url.host())) { + return optimization_guide::OptimizationTypeDecision:: + kHintFetchStartedButNotAvailableInTime; + } + return optimization_guide::OptimizationTypeDecision::kNoHintAvailable; } @@ -1012,10 +1010,6 @@ return; } - page_navigation_hosts_being_fetched_.clear(); - page_navigation_hosts_being_fetched_.push_back( - navigation_handle->GetURL().host()); - if (!hints_fetcher_) { hints_fetcher_ = std::make_unique<optimization_guide::HintsFetcher>( url_loader_factory_, @@ -1028,7 +1022,8 @@ optimization_guide::proto::CONTEXT_PAGE_NAVIGATION, base::BindOnce( &OptimizationGuideHintsManager::OnPageNavigationHintsFetched, - ui_weak_ptr_factory_.GetWeakPtr())); + ui_weak_ptr_factory_.GetWeakPtr(), + base::flat_set<std::string>({navigation_handle->GetURL().host()}))); if (!hosts.empty() && !urls.empty()) { race_navigation_recorder.set_race_attempt_status( @@ -1042,10 +1037,3 @@ optimization_guide::HintsFetcher::ClearHostsSuccessfullyFetched( pref_service_); } - -bool OptimizationGuideHintsManager::IsHintBeingFetched( - const std::string& host) const { - return std::find(page_navigation_hosts_being_fetched_.begin(), - page_navigation_hosts_being_fetched_.end(), - host) != page_navigation_hosts_being_fetched_.end(); -}
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.h b/chrome/browser/optimization_guide/optimization_guide_hints_manager.h index 26d6639..83c9a4c6 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.h +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_HINTS_MANAGER_H_ #include <memory> +#include <string> #include <vector> #include "base/callback_forward.h" @@ -217,8 +218,10 @@ // Called when the hints for a navigation have been fetched from the remote // Optimization Guide Service and are ready for parsing. This is used when - // fetching hints in real-time. + // fetching hints in real-time. |page_navigation_hosts_requested| contains the + // hosts that were requested to be fetched. void OnPageNavigationHintsFetched( + const base::flat_set<std::string>& page_navigation_hosts_requested, base::Optional< std::unique_ptr<optimization_guide::proto::GetHintsResponse>> get_hints_response); @@ -229,7 +232,10 @@ // Called when the fetched hints have been stored in |hint_cache| and are // ready to be used. This is used when hints were fetched in real-time. - void OnFetchedPageNavigationHintsStored(); + // |page_navigation_hosts_requested| contains the hosts whose hints should be + // loaded into memory when invoked. + void OnFetchedPageNavigationHintsStored( + const base::flat_set<std::string>& page_navigation_hosts_requested); // Returns the time when a hints fetch request was last attempted. base::Time GetLastHintsFetchAttemptTime() const; @@ -267,10 +273,6 @@ const base::Optional<NavigationPredictorKeyedService::Prediction>& prediction) override; - // Returns whether a hint for |host| is currently being fetched from the - // remote Optimization Guide Service. - bool IsHintBeingFetched(const std::string& host) const; - // Creates a hints fetch for |navigation_handle| if it is allowed. The // fetch will include the host and URL of the |navigation_handle| if the // associated hints for each are not already in the cache. @@ -345,11 +347,6 @@ // Used in testing to subscribe to an update event in this class. base::OnceClosure next_update_closure_; - // Hosts for which hints are currently being fetched with the PAGE_NAVIGATION - // request context. - // This will be cleared at request completion. - std::vector<std::string> page_navigation_hosts_being_fetched_; - // Used to get |weak_ptr_| to self on the UI thread. base::WeakPtrFactory<OptimizationGuideHintsManager> ui_weak_ptr_factory_{ this};
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc index 54a48dd..76b8984 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc
@@ -192,11 +192,13 @@ std::move(hints_fetched_callback).Run(base::nullopt); return false; case HintsFetcherEndState::kFetchSuccessWithHostHints: + hosts_fetched_ = hosts; hints_fetched_ = true; std::move(hints_fetched_callback) .Run(BuildHintsResponse({"host.com"}, {})); return true; case HintsFetcherEndState::kFetchSuccessWithURLHints: + hosts_fetched_ = hosts; hints_fetched_ = true; std::move(hints_fetched_callback) .Run(BuildHintsResponse({}, @@ -210,9 +212,15 @@ return true; } + bool IsHintForHostBeingFetched(const std::string& host) const override { + return std::find(hosts_fetched_.begin(), hosts_fetched_.end(), host) != + hosts_fetched_.end(); + } + bool hints_fetched() { return hints_fetched_; } private: + std::vector<std::string> hosts_fetched_; bool hints_fetched_ = false; HintsFetcherEndState fetch_state_; }; @@ -2543,7 +2551,7 @@ CreateMockNavigationHandleWithOptimizationGuideWebContentsObserver( url_without_hints()); hints_manager()->SetHintsFetcherForTesting( - BuildTestHintsFetcher(HintsFetcherEndState::kFetchSuccessWithNoHints)); + BuildTestHintsFetcher(HintsFetcherEndState::kFetchSuccessWithHostHints)); hints_manager()->OnNavigationStartOrRedirect(navigation_handle.get(), base::DoNothing()); optimization_guide::OptimizationMetadata optimization_metadata;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index ba79fe4..1ee3be64 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -314,6 +314,7 @@ #include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h" #include "chrome/browser/upgrade_detector/upgrade_detector_chromeos.h" #include "chromeos/audio/audio_devices_pref_handler_impl.h" #include "chromeos/components/account_manager/account_manager.h" @@ -978,6 +979,7 @@ chromeos::RegisterSamlProfilePrefs(registry); chromeos::ScreenTimeController::RegisterProfilePrefs(registry); chromeos::ServicesCustomizationDocument::RegisterProfilePrefs(registry); + chromeos::settings::OSSettingsUI::RegisterProfilePrefs(registry); chromeos::UserImageSyncObserver::RegisterProfilePrefs(registry); crostini::prefs::RegisterProfilePrefs(registry); chromeos::attestation::TpmChallengeKey::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/automation_predicate.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/automation_predicate.js index ace0056e..e5cab8c 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/automation_predicate.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/automation_predicate.js
@@ -383,7 +383,7 @@ Role.ALERT_DIALOG, Role.CLIENT, Role.DIALOG, Role.LAYOUT_TABLE, Role.LAYOUT_TABLE_CELL, Role.LAYOUT_TABLE_ROW, Role.ROOT_WEB_AREA, Role.WEB_VIEW, Role.WINDOW, Role.EMBEDDED_OBJECT, Role.IFRAME, - Role.IFRAME_PRESENTATIONAL, Role.IGNORED, Role.UNKNOWN + Role.IFRAME_PRESENTATIONAL, Role.IGNORED, Role.PLUGIN_OBJECT, Role.UNKNOWN ]); /**
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js index c6715aa..758c77ac 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -441,7 +441,7 @@ entered .filter((f) => { return f.role == RoleType.EMBEDDED_OBJECT || - f.role == RoleType.IFRAME; + f.role == RoleType.PLUGIN_OBJECT || f.role == RoleType.IFRAME; }) .forEach((container) => { if (!container.state[StateType.FOCUSED]) {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js index 2f9c31a..fec78fd 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
@@ -333,7 +333,7 @@ // Discard focus events on embeddedObject and webView. if (node.role == RoleType.EMBEDDED_OBJECT || - node.role == RoleType.WEB_VIEW) { + node.role == RoleType.PLUGIN_OBJECT || node.role == RoleType.WEB_VIEW) { return; }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js index eaef285e..9f3bf00 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output_test.js
@@ -990,20 +990,36 @@ var notStated = [ RoleType.CLIENT, RoleType.EMBEDDED_OBJECT, RoleType.INLINE_TEXT_BOX, RoleType.LINE_BREAK, RoleType.LIST_MARKER, RoleType.PARAGRAPH, - RoleType.ROOT_WEB_AREA, RoleType.STATIC_TEXT, RoleType.WINDOW + RoleType.ROOT_WEB_AREA, RoleType.STATIC_TEXT, RoleType.PLUGIN_OBJECT, + RoleType.WINDOW ]; var notRestricted = [ - RoleType.ALERT, RoleType.ALERT_DIALOG, RoleType.CELL, RoleType.CLIENT, - RoleType.EMBEDDED_OBJECT, RoleType.GENERIC_CONTAINER, RoleType.IMAGE, - RoleType.INLINE_TEXT_BOX, RoleType.LINE_BREAK, RoleType.LIST, - RoleType.LIST_MARKER, RoleType.PARAGRAPH, RoleType.REGION, - RoleType.ROOT_WEB_AREA, RoleType.ROW_HEADER, RoleType.STATIC_TEXT, - RoleType.TABLE_HEADER_CONTAINER, RoleType.TIMER, RoleType.WINDOW + RoleType.ALERT, + RoleType.ALERT_DIALOG, + RoleType.CELL, + RoleType.CLIENT, + RoleType.EMBEDDED_OBJECT, + RoleType.GENERIC_CONTAINER, + RoleType.IMAGE, + RoleType.INLINE_TEXT_BOX, + RoleType.LINE_BREAK, + RoleType.LIST, + RoleType.LIST_MARKER, + RoleType.PARAGRAPH, + RoleType.PLUGIN_OBJECT, + RoleType.REGION, + RoleType.ROOT_WEB_AREA, + RoleType.ROW_HEADER, + RoleType.STATIC_TEXT, + RoleType.TABLE_HEADER_CONTAINER, + RoleType.TIMER, + RoleType.WINDOW ]; var notDescribed = [ RoleType.CLIENT, RoleType.EMBEDDED_OBJECT, RoleType.INLINE_TEXT_BOX, RoleType.LINE_BREAK, RoleType.LIST_MARKER, RoleType.PARAGRAPH, - RoleType.ROOT_WEB_AREA, RoleType.STATIC_TEXT, RoleType.WINDOW + RoleType.PLUGIN_OBJECT, RoleType.ROOT_WEB_AREA, RoleType.STATIC_TEXT, + RoleType.WINDOW ]; missingState = missingState.filter(function(state) { return notStated.indexOf(state) == -1;
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.html b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.html index eb61e53..684f9c6b2 100644 --- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.html +++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.html
@@ -20,17 +20,32 @@ </span> </div> </div> - <div class="settings-box continuation"> - <h2 class="start">$i18n{crostiniSharedPathsListHeading}</h2> + <div id="crostiniListEmpty" class="settings-box secondary continuation" + hidden="[[sharedPaths_.length]]" > + $i18n{crostiniSharedPathsListEmptyMessage} </div> - <div class="list-frame vertical-list"> - <template is="dom-repeat" items="[[sharedPaths_]]"> - <div class="list-item"> - <div class="start">[[item.pathDisplayText]]</div> - <cr-icon-button class="icon-clear" on-click="onRemoveSharedPathTap_" - title="$i18n{crostiniSharedPathsRemoveSharing}"></cr-icon-button> - </div> - </template> + <div id="crostiniList" hidden="[[!sharedPaths_.length]]"> + <div class="settings-box continuation"> + <h2 id="crostiniListHeading" class="start"> + $i18n{crostiniSharedPathsListHeading} + </h2> + </div> + <div class="list-frame vertical-list" role="list" + aria-labeledby="crostiniListHeading"> + <template is="dom-repeat" items="[[sharedPaths_]]"> + <div class="list-item" role=listitem"> + <div class="start" aria-hidden="true" + id="[[generatePathDisplayTextId_(index)]]"> + [[item.pathDisplayText]] + </div> + <cr-icon-button class="icon-clear" + on-click="onRemoveSharedPathTap_" + title="$i18n{crostiniSharedPathsRemoveSharing}" + aria-labeledby$="[[generatePathDisplayTextId_(index)]]"> + </cr-icon-button> + </div> + </template> + </div> </div> </template> <script src="crostini_shared_paths.js"></script>
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.js index c4d3ac6..d0e57c70 100644 --- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.js +++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_shared_paths.js
@@ -67,5 +67,14 @@ settings.CrostiniBrowserProxyImpl.getInstance().removeCrostiniSharedPath( DEFAULT_CROSTINI_VM, event.model.item.path); }, + + /** + * @param {number} index + * @return {string} + * @private + */ + generatePathDisplayTextId_(index) { + return 'path-display-text-' + index; + }, }); })();
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/plugin_vm_page/BUILD.gn index db85b70b..b83cb40 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/BUILD.gn
@@ -22,6 +22,7 @@ deps = [ "..:os_route", "../..:router", + "../../prefs:prefs_behavior", "//ui/webui/resources/js:i18n_behavior", ] externs_list = [ "$externs_path/settings_private.js" ] @@ -38,6 +39,7 @@ deps = [ "..:os_route", "../..:router", + "../../prefs:prefs_behavior", ] }
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_browser_proxy.js b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_browser_proxy.js index 11f7da41..e5c8407f3 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_browser_proxy.js +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_browser_proxy.js
@@ -23,6 +23,9 @@ /* Removes the default vm if it is installed. */ removePluginVm() {} + + /* Show Plugin Vm installer. */ + requestPluginVmInstallerView() {} } /** @implements {settings.PluginVmBrowserProxy} */ @@ -41,6 +44,11 @@ removePluginVm() { chrome.send('removePluginVm'); } + + /** @override */ + requestPluginVmInstallerView() { + chrome.send('requestPluginVmInstallerView'); + } } // The singleton instance_ can be replaced with a test version of this wrapper
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.html b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.html index 0fd5b7b6..aae06d2 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.html +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.html
@@ -1,13 +1,16 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="../../i18n_setup.html"> +<link rel="import" href="../../prefs/prefs_behavior.html"> <link rel="import" href="../os_route.html"> <link rel="import" href="../../router.html"> <link rel="import" href="../../settings_page/settings_animated_pages.html"> <link rel="import" href="../../settings_page/settings_subpage.html"> <link rel="import" href="../../settings_shared_css.html"> +<link rel="import" href="plugin_vm_browser_proxy.html"> <link rel="import" href="plugin_vm_shared_paths.html"> <link rel="import" href="plugin_vm_subpage.html"> @@ -18,11 +21,30 @@ <settings-animated-pages id="pages" section="pluginVm" focus-config="[[focusConfig_]]"> <div route-path="default"> - <cr-link-row id="plugin-vm" - label="$i18n{pluginVmPageLabel}" - sub-label="$i18n{pluginVmPageSubtext}" - on-click="onSubpageClick_" - role-description="$i18n{subpageArrowRoleDescription}"></cr-link-row> + <div id="pluginVm" class="settings-box two-line first" + on-click="onSubpageClick_"> + <div class="start"> + $i18n{pluginVmPageLabel} + <div class="secondary" id="secondaryText"> + $i18n{pluginVmPageSubtext} + </div> + </div> + <template is="dom-if" if="[[prefs.plugin_vm.image_exists.value]]"> + <cr-icon-button class="subpage-arrow" + aria-label="i18n{pluginVmPageLabel}" + aria-describedby="secondaryText" + aria-roledescription="$i18n{subpageArrowRoleDescription}"> + </cr-icon-button> + </template> + <template is="dom-if" if="[[!prefs.plugin_vm.image_exists.value]]"> + <div class="separator"></div> + <cr-button id="enable" + on-click="onEnableClick_" + aria-describedby="secondaryText"> + $i18n{pluginVmPageEnable} + </cr-button> + </template> + </div> </div> <template is="dom-if" route-path="/pluginVm/details">
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.js b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.js index b58bce79..08e142e 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.js +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_page.js
@@ -10,6 +10,8 @@ Polymer({ is: 'settings-plugin-vm-page', + behaviors: [PrefsBehavior], + properties: { /** Preferences state. */ prefs: { @@ -33,8 +35,24 @@ }, }, - /** @private */ + /** + * @param {!Event} event + * @private + */ onSubpageClick_(event) { - settings.Router.getInstance().navigateTo(settings.routes.PLUGIN_VM_DETAILS); + if (this.getPref('plugin_vm.image_exists').value) { + settings.Router.getInstance().navigateTo( + settings.routes.PLUGIN_VM_DETAILS); + } + }, + + /** + * @param {!Event} event + * @private + */ + onEnableClick_(event) { + settings.PluginVmBrowserProxyImpl.getInstance() + .requestPluginVmInstallerView(); + event.stopPropagation(); }, });
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html index 35c7532..2b0c49e 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> +<link rel="import" href="../../prefs/prefs_behavior.html"> <link rel="import" href="../os_route.html"> <link rel="import" href="../../router.html"> <link rel="import" href="plugin_vm_remove_confirmation_dialog.html">
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js index 5fde00bc..a2c70e8 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js
@@ -10,6 +10,8 @@ Polymer({ is: 'settings-plugin-vm-subpage', + behaviors: [PrefsBehavior], + properties: { /** Preferences state. */ prefs: { @@ -24,7 +26,19 @@ }, }, - // TODO(juwa@google.com): Navigate back if plugin vm uninstalled. + observers: [ + 'onPluginVmImageExistsChanged_(prefs.plugin_vm.image_exists.value)', + ], + + /** + * @param {boolean} exists + * @private + */ + onPluginVmImageExistsChanged_(exists) { + if (!exists) { + settings.Router.getInstance().navigateTo(settings.routes.PLUGIN_VM); + } + }, /** @private */ onSharedPathsClick_() {
diff --git a/chrome/browser/resources/tab_strip/tab_group.html b/chrome/browser/resources/tab_strip/tab_group.html index a64a8fa..263f4fe 100644 --- a/chrome/browser/resources/tab_strip/tab_group.html +++ b/chrome/browser/resources/tab_strip/tab_group.html
@@ -1,14 +1,65 @@ <style> :host { - display: block; + --tabstrip-tab-group-title-height: 22px; + --tabstrip-tab-group-title-margin: var(--tabstrip-tab-spacing); + + border-radius: 8px; + box-shadow: 0 0 0 1px rgba(var(--tabstrip-tab-group-color-rgb), .24); + padding: var(--tabstrip-tab-spacing); +} + +#chip { + display: inline-block; + height: var(--tabstrip-tab-group-title-height); + margin-bottom: var(--tabstrip-tab-group-title-margin); +} + +#title { + background: rgba(var(--tabstrip-tab-group-color-rgb), 1); + border-radius: 4px; + box-sizing: border-box; + color: rgb(var(--tabstrip-tab-group-text-color-rgb)); + display: inline-block; + height: var(--tabstrip-tab-group-title-height); + line-height: var(--tabstrip-tab-group-title-height); + padding: 0 6px; +} + +#title:empty { + border-radius: 50%; + height: 16px; + margin-top: 4px; + width: 16px; } #tabs { + /* Cached CSS variable so the children could use them and override the + * original values. */ + --ungrouped-tab-thumbnail-height: var(--tabstrip-tab-thumbnail-height); + display: flex; min-width: fit-content; } + +:host ::slotted(tabstrip-tab) { + --tabstrip-tab-thumbnail-height: calc( + var(--ungrouped-tab-thumbnail-height) - + var(--tabstrip-tab-group-title-height) - + var(--tabstrip-tab-group-title-margin)); + --tabstrip-tab-thumbnail-width: calc( + var(--tabstrip-tab-thumbnail-height) * + var(--tabstrip-tab-thumbnail-aspect-ratio)); + + /* Recalculate tab heights and widths off new thumbnail sizes. */ + --tabstrip-tab-height: calc(var(--tabstrip-tab-title-height) + + var(--tabstrip-tab-thumbnail-height)); + --tabstrip-tab-width: var(--tabstrip-tab-thumbnail-width); +} </style> +<div id="chip"> + <div id="title"></div> +</div> <div id="tabs"> <slot></slot> </div>
diff --git a/chrome/browser/resources/tab_strip/tab_group.js b/chrome/browser/resources/tab_strip/tab_group.js index f4b005f..239b32d 100644 --- a/chrome/browser/resources/tab_strip/tab_group.js +++ b/chrome/browser/resources/tab_strip/tab_group.js
@@ -14,7 +14,10 @@ * @param {!TabGroupVisualData} visualData */ updateVisuals(visualData) { - // TODO(johntlee): Update the HTML with the visual data. + this.shadowRoot.querySelector('#title').innerText = visualData.title; + this.style.setProperty('--tabstrip-tab-group-color-rgb', visualData.color); + this.style.setProperty( + '--tabstrip-tab-group-text-color-rgb', visualData.textColor); } }
diff --git a/chrome/browser/resources/tab_strip/tab_list.html b/chrome/browser/resources/tab_strip/tab_list.html index c6ce9ed..e6a8430 100644 --- a/chrome/browser/resources/tab_strip/tab_list.html +++ b/chrome/browser/resources/tab_strip/tab_list.html
@@ -34,8 +34,10 @@ grid-auto-flow: column; grid-gap: 10px; grid-template-rows: repeat(3, var(--tabstrip-pinned-tab-size)); - padding: var(--tabstrip-tab-spacing); + padding-block-end: var(--tabstrip-tab-list-vertical-padding); + padding-block-start: var(--tabstrip-tab-list-vertical-padding); padding-inline-end: 0; + padding-inline-start: var(--tabstrip-tab-spacing); } #pinnedTabs:empty { @@ -45,16 +47,34 @@ #unpinnedTabs { display: flex; min-width: fit-content; - padding: var(--tabstrip-tab-spacing); + padding-block-end: var(--tabstrip-tab-list-vertical-padding); + padding-block-start: var(--tabstrip-tab-list-vertical-padding); padding-inline-end: 0; + padding-inline-start: var(--tabstrip-tab-spacing); + } + + tabstrip-tab-group { + --tabstrip-tab-spacing: 8px; + margin-block-end: calc(-1 * var(--tabstrip-tab-spacing)); + margin-block-start: calc(-1 * var(--tabstrip-tab-spacing)); + margin-inline-end: var(--tabstrip-tab-spacing); + margin-inline-start: 0; + } + + tabstrip-tab-group tabstrip-tab:last-child { + --tabstrip-tab-spacing: 0px; + } + + tabstrip-tab + tabstrip-tab-group { + margin-inline-start: calc(-1 * var(--tabstrip-tab-spacing)); } #newTabButton { --cr-icon-button-size: var(--tabstrip-new-tab-button-width); --cr-icon-button-icon-size: 32px; --cr-icon-button-fill-color: var(--tabstrip-tab-text-color); - --cr-icon-button-margin-end: var(--new-tab-button-margin); - --cr-icon-button-margin-start: 0; + --cr-icon-button-margin-end: var(--tabstrip-new-tab-button-margin); + --cr-icon-button-margin-start: 0px; background: var(--tabstrip-tab-background-color); border-radius: 50%; box-shadow: 0 1px 3px 0 rgba(var(--google-grey-800-rgb), .3),
diff --git a/chrome/browser/resources/tab_strip/tabs_api_proxy.js b/chrome/browser/resources/tab_strip/tabs_api_proxy.js index 5a8b520..d445a39 100644 --- a/chrome/browser/resources/tab_strip/tabs_api_proxy.js +++ b/chrome/browser/resources/tab_strip/tabs_api_proxy.js
@@ -71,6 +71,7 @@ /** * @typedef {{ * color: string, + * textColor: string, * title: string, * }} */
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.cc index 913673bc..9a43d46 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/base64.h" +#include "base/bind_helpers.h" #include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "chrome/browser/gcm/gcm_profile_service_factory.h" @@ -72,6 +73,10 @@ BinaryFCMService::~BinaryFCMService() { if (gcm_driver_ != nullptr) gcm_driver_->RemoveAppHandler(kBinaryFCMServiceAppId); + for (const auto& token_to_callback : message_token_map_) { + const std::string& token = token_to_callback.first; + UnregisterInstanceID(token, base::DoNothing()); + } } void BinaryFCMService::GetInstanceID(GetInstanceIDCallback callback) { @@ -94,6 +99,16 @@ message_token_map_.erase(token); } +void BinaryFCMService::UnregisterInstanceID( + const std::string& token, + UnregisterInstanceIDCallback callback) { + instance_id_driver_->GetInstanceID(kBinaryFCMServiceAppId) + ->DeleteToken(kBinaryFCMServiceSenderId, instance_id::kGCMScope, + base::BindOnce(&BinaryFCMService::OnInstanceIDUnregistered, + weakptr_factory_.GetWeakPtr(), token, + std::move(callback))); +} + void BinaryFCMService::OnGetInstanceID(GetInstanceIDCallback callback, const std::string& instance_id, instance_id::InstanceID::Result result) { @@ -154,4 +169,25 @@ return app_id == kBinaryFCMServiceAppId; } +void BinaryFCMService::OnInstanceIDUnregistered( + const std::string& token, + UnregisterInstanceIDCallback callback, + instance_id::InstanceID::Result result) { + switch (result) { + case instance_id::InstanceID::Result::SUCCESS: + std::move(callback).Run(true); + break; + case instance_id::InstanceID::Result::INVALID_PARAMETER: + case instance_id::InstanceID::Result::DISABLED: + case instance_id::InstanceID::Result::UNKNOWN_ERROR: + std::move(callback).Run(false); + break; + case instance_id::InstanceID::Result::ASYNC_OPERATION_PENDING: + case instance_id::InstanceID::Result::NETWORK_ERROR: + case instance_id::InstanceID::Result::SERVER_ERROR: + UnregisterInstanceID(token, std::move(callback)); + break; + } +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h b/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h index e538a868..d87e761d 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_SAFE_BROWSING_CLOUD_CONTENT_SCANNING_BINARY_FCM_SERVICE_H_ #define CHROME_BROWSER_SAFE_BROWSING_CLOUD_CONTENT_SCANNING_BINARY_FCM_SERVICE_H_ +#include "base/callback_forward.h" #include "base/memory/weak_ptr.h" #include "components/gcm_driver/gcm_app_handler.h" #include "components/gcm_driver/instance_id/instance_id.h" @@ -43,8 +44,11 @@ base::OnceCallback<void(const std::string& token)>; using OnMessageCallback = base::RepeatingCallback<void(DeepScanningClientResponse)>; + using UnregisterInstanceIDCallback = base::OnceCallback<void(bool)>; virtual void GetInstanceID(GetInstanceIDCallback callback); + virtual void UnregisterInstanceID(const std::string& token, + UnregisterInstanceIDCallback callback); void SetCallbackForToken(const std::string& token, OnMessageCallback callback); void ClearCallbackForToken(const std::string& token); @@ -73,6 +77,10 @@ const std::string& instance_id, instance_id::InstanceID::Result result); + void OnInstanceIDUnregistered(const std::string& token, + UnregisterInstanceIDCallback callback, + instance_id::InstanceID::Result result); + // References to the profile's GCMDriver and InstanceIDDriver. Both are // unowned. gcm::GCMDriver* gcm_driver_;
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service_unittest.cc index 4b87eeb..0d611da 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service_unittest.cc
@@ -12,6 +12,8 @@ #include "chrome/test/base/testing_profile.h" #include "components/gcm_driver/common/gcm_message.h" #include "components/gcm_driver/fake_gcm_profile_service.h" +#include "components/gcm_driver/gcm_client.h" +#include "components/gcm_driver/instance_id/instance_id.h" #include "components/safe_browsing/core/proto/webprotect.pb.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h" @@ -193,4 +195,52 @@ } } +TEST_F(BinaryFCMServiceTest, UnregisterToken) { + // Get an instance ID + std::string received_instance_id = BinaryFCMService::kInvalidId; + binary_fcm_service_->GetInstanceID(base::BindOnce( + [](std::string* target_id, const std::string& instance_id) { + *target_id = instance_id; + }, + &received_instance_id)); + content::RunAllTasksUntilIdle(); + EXPECT_NE(received_instance_id, BinaryFCMService::kInvalidId); + + // Delete it + bool unregistered = false; + binary_fcm_service_->UnregisterInstanceID( + received_instance_id, + base::BindOnce([](bool* target, bool value) { *target = value; }, + &unregistered)); + content::RunAllTasksUntilIdle(); + EXPECT_TRUE(unregistered); +} + +TEST_F(BinaryFCMServiceTest, UnregisterTokenRetriesFailures) { + // Get an instance ID + std::string received_instance_id = BinaryFCMService::kInvalidId; + binary_fcm_service_->GetInstanceID(base::BindOnce( + [](std::string* target_id, const std::string& instance_id) { + *target_id = instance_id; + }, + &received_instance_id)); + content::RunAllTasksUntilIdle(); + EXPECT_NE(received_instance_id, BinaryFCMService::kInvalidId); + + // Queue one failure, then success + gcm::FakeGCMProfileService* gcm_service = + static_cast<gcm::FakeGCMProfileService*>( + gcm::GCMProfileServiceFactory::GetForProfile(&profile_)); + gcm_service->AddExpectedUnregisterResponse(gcm::GCMClient::NETWORK_ERROR); + + // Delete it + bool unregistered = false; + binary_fcm_service_->UnregisterInstanceID( + received_instance_id, + base::BindOnce([](bool* target, bool value) { *target = value; }, + &unregistered)); + content::RunAllTasksUntilIdle(); + EXPECT_TRUE(unregistered); +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc index 5bb0128..031f4e5 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
@@ -313,6 +313,11 @@ auto token_it = active_tokens_.find(request); if (token_it != active_tokens_.end()) { binary_fcm_service_->ClearCallbackForToken(token_it->second); + + // The BinaryFCMService will handle all recoverable errors. In case of + // unrecoverable error, there's nothing we can do here. + binary_fcm_service_->UnregisterInstanceID(token_it->second, + base::DoNothing()); active_tokens_.erase(token_it); } }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service_unittest.cc index 5ec5e79c..a24cda9 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service_unittest.cc
@@ -92,6 +92,9 @@ MOCK_METHOD1(GetInstanceID, void(BinaryFCMService::GetInstanceIDCallback callback)); + MOCK_METHOD2(UnregisterInstanceID, + void(const std::string& token, + BinaryFCMService::UnregisterInstanceIDCallback callback)); }; class BinaryUploadServiceTest : public testing::Test { @@ -121,6 +124,12 @@ Invoke([id](BinaryFCMService::GetInstanceIDCallback callback) { std::move(callback).Run(id); })); + ON_CALL(*fcm_service_, UnregisterInstanceID(_, _)) + .WillByDefault( + Invoke([](const std::string& token, + BinaryFCMService::UnregisterInstanceIDCallback callback) { + std::move(callback).Run(true); + })); } void UploadForDeepScanning(
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index 97c9ef1..62ffffe 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -701,6 +701,7 @@ DCHECK(!pack->is_valid()); pack->InitEmptyPack(); + pack->set_extension_id(extension->id()); pack->SetHeaderId(extension); pack->SetTintsFromJSON(extensions::ThemeInfo::GetTints(extension)); pack->SetColorsFromJSON(extensions::ThemeInfo::GetColors(extension)); @@ -733,6 +734,7 @@ // For now data pack can only have extension type. scoped_refptr<BrowserThemePack> pack( new BrowserThemePack(ThemeType::EXTENSION)); + pack->set_extension_id(expected_id); // Scale factor parameter is moot as data pack has image resources for all // supported scale factors. pack->data_pack_.reset(
diff --git a/chrome/browser/themes/custom_theme_supplier.h b/chrome/browser/themes/custom_theme_supplier.h index 5b5bf57..de80622 100644 --- a/chrome/browser/themes/custom_theme_supplier.h +++ b/chrome/browser/themes/custom_theme_supplier.h
@@ -43,6 +43,11 @@ return theme_type_; } + const std::string& extension_id() const { + DCHECK_EQ(theme_type_, EXTENSION); + return extension_id_; + } + // Called when the theme starts being used. virtual void StartUsingTheme(); @@ -72,11 +77,17 @@ protected: virtual ~CustomThemeSupplier(); + void set_extension_id(base::StringPiece id) { + DCHECK_EQ(theme_type_, EXTENSION); + id.CopyToString(&extension_id_); + } + private: friend class base::RefCountedDeleteOnSequence<CustomThemeSupplier>; friend class base::DeleteHelper<CustomThemeSupplier>; ThemeType theme_type_; + std::string extension_id_; DISALLOW_COPY_AND_ASSIGN(CustomThemeSupplier); };
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index a8f71ec..2e6596b 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -75,6 +75,17 @@ // unpacked on the filesystem.) const char kDefaultThemeGalleryID[] = "hkacjpbfdknhflllbcmjibkdeoafencn"; +bool IsDefaultTheme(const CustomThemeSupplier* theme_supplier) { + if (!theme_supplier) + return true; + if (theme_supplier->get_theme_type() != + CustomThemeSupplier::ThemeType::EXTENSION) { + return false; + } + const std::string& id = theme_supplier->extension_id(); + return id == ThemeService::kDefaultThemeID || id == kDefaultThemeGalleryID; +} + // Wait this many seconds after startup to garbage collect unused themes. // Removing unused themes is done after a delay because there is no // reason to do it at startup. @@ -444,12 +455,16 @@ } bool ThemeService::UsingDefaultTheme() const { - std::string id = GetThemeID(); - return id == kDefaultThemeID || id == kDefaultThemeGalleryID; + return IsDefaultTheme(get_theme_supplier()); } bool ThemeService::UsingSystemTheme() const { - return UsingDefaultTheme(); + return IsSystemTheme(get_theme_supplier()); +} + +bool ThemeService::IsSystemTheme( + const CustomThemeSupplier* theme_supplier) const { + return IsDefaultTheme(theme_supplier); } bool ThemeService::UsingExtensionTheme() const {
diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h index d794912..7a5a38c 100644 --- a/chrome/browser/themes/theme_service.h +++ b/chrome/browser/themes/theme_service.h
@@ -108,14 +108,18 @@ // this platform. virtual bool IsSystemThemeDistinctFromDefaultTheme() const; - // Whether we're using the chrome default theme. Virtual so linux can check - // if we're using the GTK theme. + // Whether we're using the chrome default theme. + // Virtual for testing. virtual bool UsingDefaultTheme() const; - // Whether we are using the system theme. On GTK, the system theme is the GTK - // theme, not the "Classic" theme. + // Whether we are using the system theme. + // Virtual for testing. virtual bool UsingSystemTheme() const; + // Whether |theme_supplier| is the system theme. On GTK, the system theme is + // the GTK theme, not the "Classic" theme + virtual bool IsSystemTheme(const CustomThemeSupplier* theme_supplier) const; + // Whether we are using theme installed through extensions. // |UsingExtensionTheme| and |UsingDefaultTheme| are not mutually exclusive as // default theme can be installed through extensions.
diff --git a/chrome/browser/themes/theme_service_aura_linux.cc b/chrome/browser/themes/theme_service_aura_linux.cc index 2a59550..513c430 100644 --- a/chrome/browser/themes/theme_service_aura_linux.cc +++ b/chrome/browser/themes/theme_service_aura_linux.cc
@@ -95,12 +95,8 @@ return true; } -bool ThemeServiceAuraLinux::UsingDefaultTheme() const { - return ThemeService::UsingDefaultTheme() && !UsingSystemTheme(); -} - -bool ThemeServiceAuraLinux::UsingSystemTheme() const { - const CustomThemeSupplier* theme_supplier = get_theme_supplier(); +bool ThemeServiceAuraLinux::IsSystemTheme( + const CustomThemeSupplier* theme_supplier) const { return theme_supplier && theme_supplier->get_theme_type() == CustomThemeSupplier::NATIVE_X11; }
diff --git a/chrome/browser/themes/theme_service_aura_linux.h b/chrome/browser/themes/theme_service_aura_linux.h index 21100c1..3a1a693c 100644 --- a/chrome/browser/themes/theme_service_aura_linux.h +++ b/chrome/browser/themes/theme_service_aura_linux.h
@@ -21,8 +21,7 @@ bool ShouldInitWithSystemTheme() const override; void UseSystemTheme() override; bool IsSystemThemeDistinctFromDefaultTheme() const override; - bool UsingDefaultTheme() const override; - bool UsingSystemTheme() const override; + bool IsSystemTheme(const CustomThemeSupplier* theme_supplier) const override; void FixInconsistentPreferencesIfNeeded() override; static bool ShouldUseSystemThemeForProfile(const Profile* profile);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index cfd3f73e..771220c 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1960,6 +1960,8 @@ "webui/settings/chromeos/parental_controls_handler.h", "webui/settings/chromeos/plugin_vm_handler.cc", "webui/settings/chromeos/plugin_vm_handler.h", + "webui/settings/chromeos/pref_names.cc", + "webui/settings/chromeos/pref_names.h", "webui/settings/chromeos/wallpaper_handler.cc", "webui/settings/chromeos/wallpaper_handler.h", "webui/settings/tts_handler.cc", @@ -2598,7 +2600,7 @@ } if (use_gtk) { # This is the only component that can interact with gtk. - deps += [ "//chrome/browser/ui/libgtkui" ] + deps += [ "//chrome/browser/ui/gtk" ] } } @@ -3453,7 +3455,7 @@ sources += [ "views/linux_ui/linux_ui_factory_gtk.cc" ] # This is the only component that can interact with gtk. - deps += [ "//chrome/browser/ui/libgtkui" ] + deps += [ "//chrome/browser/ui/gtk" ] } else { sources += [ "views/linux_ui/linux_ui_factory.cc" ] }
diff --git a/chrome/browser/ui/exclusive_access/OWNERS b/chrome/browser/ui/exclusive_access/OWNERS index 21149b0..185befd 100644 --- a/chrome/browser/ui/exclusive_access/OWNERS +++ b/chrome/browser/ui/exclusive_access/OWNERS
@@ -1,4 +1,3 @@ -mgiuca@chromium.org miu@chromium.org # COMPONENT: UI>Browser>FullScreen
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.cc b/chrome/browser/ui/global_media_controls/media_notification_service.cc index 62f5dc3..2b1ce88 100644 --- a/chrome/browser/ui/global_media_controls/media_notification_service.cc +++ b/chrome/browser/ui/global_media_controls/media_notification_service.cc
@@ -63,6 +63,13 @@ return browser->tab_strip_model()->GetActiveWebContents() == web_contents; } +base::WeakPtr<media_router::WebContentsPresentationManager> +GetPresentationManager(content::WebContents* web_contents) { + return web_contents + ? media_router::WebContentsPresentationManager::Get(web_contents) + : nullptr; +} + } // anonymous namespace MediaNotificationService::Session::Session( @@ -74,14 +81,20 @@ : content::WebContentsObserver(web_contents), owner_(owner), id_(id), - item_(std::move(item)) { + item_(std::move(item)), + presentation_manager_(GetPresentationManager(web_contents)) { DCHECK(owner_); DCHECK(item_); SetController(std::move(controller)); + if (presentation_manager_) + presentation_manager_->AddObserver(this); } MediaNotificationService::Session::~Session() { + if (presentation_manager_) + presentation_manager_->RemoveObserver(this); + // If we've been marked inactive, then we've already recorded inactivity as // the dismiss reason. if (is_marked_inactive_) @@ -134,6 +147,12 @@ OnSessionInteractedWith(); } +void MediaNotificationService::Session::OnMediaRoutesChanged( + const std::vector<media_router::MediaRoute>& routes) { + if (!routes.empty()) + item_->Dismiss(); +} + void MediaNotificationService::Session::SetController( mojo::Remote<media_session::mojom::MediaController> controller) { if (controller.is_bound()) {
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.h b/chrome/browser/ui/global_media_controls/media_notification_service.h index a71cf448..e8b4da17 100644 --- a/chrome/browser/ui/global_media_controls/media_notification_service.h +++ b/chrome/browser/ui/global_media_controls/media_notification_service.h
@@ -14,6 +14,7 @@ #include "base/optional.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "chrome/browser/media/router/presentation/web_contents_presentation_manager.h" #include "chrome/browser/ui/global_media_controls/cast_media_notification_provider.h" #include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h" #include "chrome/browser/ui/global_media_controls/overlay_media_notifications_manager.h" @@ -122,8 +123,10 @@ kMaxValue = kMediaSessionStopped, }; - class Session : public content::WebContentsObserver, - public media_session::mojom::MediaControllerObserver { + class Session + : public content::WebContentsObserver, + public media_session::mojom::MediaControllerObserver, + public media_router::WebContentsPresentationManager::Observer { public: Session(MediaNotificationService* owner, const std::string& id, @@ -135,7 +138,7 @@ Session& operator=(const Session&) = delete; ~Session() override; - // content::WebContentsObserver implementation. + // content::WebContentsObserver: void WebContentsDestroyed() override; // media_session::mojom::MediaControllerObserver: @@ -152,6 +155,10 @@ void MediaSessionPositionChanged( const base::Optional<media_session::MediaPosition>& position) override; + // media_router::WebContentsPresentationManager::Observer: + void OnMediaRoutesChanged( + const std::vector<media_router::MediaRoute>& routes) override; + media_message_center::MediaSessionNotificationItem* item() { return item_.get(); } @@ -207,6 +214,9 @@ // Used to receive updates to the Media Session playback state. mojo::Receiver<media_session::mojom::MediaControllerObserver> observer_receiver_{this}; + + base::WeakPtr<media_router::WebContentsPresentationManager> + presentation_manager_; }; void OnReceivedAudioFocusRequests(
diff --git a/chrome/browser/ui/libgtkui/BUILD.gn b/chrome/browser/ui/gtk/BUILD.gn similarity index 97% rename from chrome/browser/ui/libgtkui/BUILD.gn rename to chrome/browser/ui/gtk/BUILD.gn index 7b20289..6b4cbfe2 100644 --- a/chrome/browser/ui/libgtkui/BUILD.gn +++ b/chrome/browser/ui/gtk/BUILD.gn
@@ -10,7 +10,7 @@ import("//printing/buildflags/buildflags.gni") import("//ui/ozone/ozone.gni") -jumbo_component("libgtkui") { +jumbo_component("gtk") { sources = [ "gtk_key_bindings_handler.cc", "gtk_key_bindings_handler.h", @@ -52,7 +52,7 @@ configs += [ "//printing:cups" ] } - defines = [ "IS_LIBGTKUI_IMPL" ] + defines = [ "IS_GTK_IMPL" ] deps = [ "//base",
diff --git a/chrome/browser/ui/libgtkui/DEPS b/chrome/browser/ui/gtk/DEPS similarity index 100% rename from chrome/browser/ui/libgtkui/DEPS rename to chrome/browser/ui/gtk/DEPS
diff --git a/chrome/browser/ui/libgtkui/OWNERS b/chrome/browser/ui/gtk/OWNERS similarity index 100% rename from chrome/browser/ui/libgtkui/OWNERS rename to chrome/browser/ui/gtk/OWNERS
diff --git a/chrome/browser/ui/libgtkui/gtk_event_loop_x11.cc b/chrome/browser/ui/gtk/gtk_event_loop_x11.cc similarity index 94% rename from chrome/browser/ui/libgtkui/gtk_event_loop_x11.cc rename to chrome/browser/ui/gtk/gtk_event_loop_x11.cc index 96106ef..133984b 100644 --- a/chrome/browser/ui/libgtkui/gtk_event_loop_x11.cc +++ b/chrome/browser/ui/gtk/gtk_event_loop_x11.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/gtk_event_loop_x11.h" +#include "chrome/browser/ui/gtk/gtk_event_loop_x11.h" #include "ui/gfx/x/x11.h" @@ -11,11 +11,11 @@ #include <gtk/gtk.h> #include "base/memory/singleton.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_util.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/x/x11_types.h" -namespace libgtkui { +namespace gtk { // static GtkEventLoopX11* GtkEventLoopX11::GetInstance() { @@ -83,4 +83,4 @@ XPutBackEvent(x_event.xkey.display, &x_event); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/gtk_event_loop_x11.h b/chrome/browser/ui/gtk/gtk_event_loop_x11.h similarity index 77% rename from chrome/browser/ui/libgtkui/gtk_event_loop_x11.h rename to chrome/browser/ui/gtk/gtk_event_loop_x11.h index 9b97ac6..9e785390 100644 --- a/chrome/browser/ui/libgtkui/gtk_event_loop_x11.h +++ b/chrome/browser/ui/gtk/gtk_event_loop_x11.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_GTK_EVENT_LOOP_X11_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_GTK_EVENT_LOOP_X11_H_ +#ifndef CHROME_BROWSER_UI_GTK_GTK_EVENT_LOOP_X11_H_ +#define CHROME_BROWSER_UI_GTK_GTK_EVENT_LOOP_X11_H_ #include "base/macros.h" #include "ui/base/glib/glib_integers.h" @@ -16,7 +16,7 @@ struct DefaultSingletonTraits; } -namespace libgtkui { +namespace gtk { class GtkEventLoopX11 { public: @@ -34,6 +34,6 @@ DISALLOW_COPY_AND_ASSIGN(GtkEventLoopX11); }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_GTK_EVENT_LOOP_X11_H_ +#endif // CHROME_BROWSER_UI_GTK_GTK_EVENT_LOOP_X11_H_
diff --git a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.cc b/chrome/browser/ui/gtk/gtk_key_bindings_handler.cc similarity index 97% rename from chrome/browser/ui/libgtkui/gtk_key_bindings_handler.cc rename to chrome/browser/ui/gtk/gtk_key_bindings_handler.cc index d63bdcb..b65938b48 100644 --- a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.cc +++ b/chrome/browser/ui/gtk/gtk_key_bindings_handler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h" +#include "chrome/browser/ui/gtk/gtk_key_bindings_handler.h" #include <gdk/gdkkeysyms.h> #include <stddef.h> @@ -12,7 +12,7 @@ #include "base/logging.h" #include "base/stl_util.h" #include "base/strings/string_util.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_util.h" #include "content/public/browser/native_web_keyboard_event.h" #include "ui/base/ime/text_edit_commands.h" #include "ui/events/event.h" @@ -23,7 +23,7 @@ // in a state that links. This code was adapted from the content layer GTK // code, which had some simple unit tests. However, the changes in the public // interface basically meant the tests need to be rewritten; this imposes weird -// linking requirements regarding GTK+ as we don't have a libgtkui_unittests +// linking requirements regarding GTK+ as we don't have a gtk_unittests // yet. http://crbug.com/358297. namespace { @@ -38,7 +38,7 @@ } // namespace -namespace libgtkui { +namespace gtk { GtkKeyBindingsHandler::GtkKeyBindingsHandler() : fake_window_(CreateInvisibleWindow()), handler_(CreateNewHandler()) { @@ -185,7 +185,8 @@ return; TextEditCommand commands[2] = { - TextEditCommand::INVALID_COMMAND, TextEditCommand::INVALID_COMMAND, + TextEditCommand::INVALID_COMMAND, + TextEditCommand::INVALID_COMMAND, }; switch (type) { case GTK_DELETE_CHARS: @@ -395,4 +396,4 @@ // Just for disabling the default handler. } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h b/chrome/browser/ui/gtk/gtk_key_bindings_handler.h similarity index 95% rename from chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h rename to chrome/browser/ui/gtk/gtk_key_bindings_handler.h index bb370736..ebe6f31 100644 --- a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h +++ b/chrome/browser/ui/gtk/gtk_key_bindings_handler.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_GTK_KEY_BINDINGS_HANDLER_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_GTK_KEY_BINDINGS_HANDLER_H_ +#ifndef CHROME_BROWSER_UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_ +#define CHROME_BROWSER_UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_ #include <gtk/gtk.h> @@ -17,7 +17,7 @@ class Event; } -namespace libgtkui { +namespace gtk { // This class is a convenience class for handling editor key bindings defined // in gtk keyboard theme. @@ -137,6 +137,6 @@ std::vector<ui::TextEditCommandAuraLinux> edit_commands_; }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_GTK_KEY_BINDINGS_HANDLER_H_ +#endif // CHROME_BROWSER_UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/gtk/gtk_ui.cc similarity index 97% rename from chrome/browser/ui/libgtkui/gtk_ui.cc rename to chrome/browser/ui/gtk/gtk_ui.cc index cf38ee7..8b9af0a 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.cc +++ b/chrome/browser/ui/gtk/gtk_ui.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/gtk_ui.h" +#include "chrome/browser/ui/gtk/gtk_ui.h" #include <gdk/gdk.h> #include <gdk/gdkkeysyms.h> @@ -23,15 +23,15 @@ #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "chrome/browser/themes/theme_properties.h" -#include "chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" -#include "chrome/browser/ui/libgtkui/input_method_context_impl_gtk.h" -#include "chrome/browser/ui/libgtkui/native_theme_gtk.h" -#include "chrome/browser/ui/libgtkui/nav_button_provider_gtk.h" -#include "chrome/browser/ui/libgtkui/print_dialog_gtk.h" -#include "chrome/browser/ui/libgtkui/printing_gtk_util.h" -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h" -#include "chrome/browser/ui/libgtkui/settings_provider_gtk.h" +#include "chrome/browser/ui/gtk/gtk_key_bindings_handler.h" +#include "chrome/browser/ui/gtk/gtk_util.h" +#include "chrome/browser/ui/gtk/input_method_context_impl_gtk.h" +#include "chrome/browser/ui/gtk/native_theme_gtk.h" +#include "chrome/browser/ui/gtk/nav_button_provider_gtk.h" +#include "chrome/browser/ui/gtk/print_dialog_gtk.h" +#include "chrome/browser/ui/gtk/printing_gtk_util.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl.h" +#include "chrome/browser/ui/gtk/settings_provider_gtk.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "printing/buildflags/buildflags.h" @@ -64,11 +64,11 @@ #include "ui/views/linux_ui/window_button_order_observer.h" #if defined(USE_GIO) -#include "chrome/browser/ui/libgtkui/settings_provider_gsettings.h" +#include "chrome/browser/ui/gtk/settings_provider_gsettings.h" #endif #if defined(USE_GTK_EVENT_LOOP_X11) -#include "chrome/browser/ui/libgtkui/gtk_event_loop_x11.h" +#include "chrome/browser/ui/gtk/gtk_event_loop_x11.h" #endif #if defined(USE_X11) @@ -86,7 +86,7 @@ #include "chrome/browser/ui/views/nav_button_provider.h" #endif -namespace libgtkui { +namespace gtk { namespace { @@ -685,8 +685,7 @@ std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext( ui::LinuxInputMethodContextDelegate* delegate, bool is_simple) const { - return std::unique_ptr<ui::LinuxInputMethodContext>( - new InputMethodContextImplGtk(delegate, is_simple)); + return std::make_unique<InputMethodContextImplGtk>(delegate, is_simple); } gfx::FontRenderParams GtkUi::GetDefaultFontRenderParams() const { @@ -740,10 +739,17 @@ return dark; } +bool GtkUi::AnimationsEnabled() const { + gboolean animations_enabled = false; + g_object_get(gtk_settings_get_default(), "gtk-enable-animations", + &animations_enabled, nullptr); + return animations_enabled; +} + #if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) std::unique_ptr<views::NavButtonProvider> GtkUi::CreateNavButtonProvider() { if (GtkVersionCheck(3, 14)) - return std::make_unique<libgtkui::NavButtonProviderGtk>(); + return std::make_unique<gtk::NavButtonProviderGtk>(); return nullptr; } #endif @@ -1114,8 +1120,8 @@ return device_scale_factor_; } -} // namespace libgtkui +} // namespace gtk views::LinuxUI* BuildGtkUi() { - return new libgtkui::GtkUi; + return new gtk::GtkUi; }
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.h b/chrome/browser/ui/gtk/gtk_ui.h similarity index 96% rename from chrome/browser/ui/libgtkui/gtk_ui.h rename to chrome/browser/ui/gtk/gtk_ui.h index b2d4e31..73de1b7 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.h +++ b/chrome/browser/ui/gtk/gtk_ui.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_GTK_UI_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_GTK_UI_H_ +#ifndef CHROME_BROWSER_UI_GTK_GTK_UI_H_ +#define CHROME_BROWSER_UI_GTK_GTK_UI_H_ #include <map> #include <memory> @@ -25,7 +25,7 @@ typedef struct _GtkStyle GtkStyle; typedef struct _GtkWidget GtkWidget; -namespace libgtkui { +namespace gtk { using ColorMap = std::map<int, SkColor>; class GtkKeyBindingsHandler; @@ -100,6 +100,7 @@ void RemoveDeviceScaleFactorObserver( views::DeviceScaleFactorObserver* observer) override; bool PreferDarkTheme() const override; + bool AnimationsEnabled() const override; #if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) std::unique_ptr<views::NavButtonProvider> CreateNavButtonProvider() override; #endif @@ -211,9 +212,9 @@ DISALLOW_COPY_AND_ASSIGN(GtkUi); }; -} // namespace libgtkui +} // namespace gtk // Access point to the GTK desktop system. -COMPONENT_EXPORT(LIBGTKUI) views::LinuxUI* BuildGtkUi(); +COMPONENT_EXPORT(GTK) views::LinuxUI* BuildGtkUi(); -#endif // CHROME_BROWSER_UI_LIBGTKUI_GTK_UI_H_ +#endif // CHROME_BROWSER_UI_GTK_GTK_UI_H_
diff --git a/chrome/browser/ui/libgtkui/gtk_util.cc b/chrome/browser/ui/gtk/gtk_util.cc similarity index 98% rename from chrome/browser/ui/libgtkui/gtk_util.cc rename to chrome/browser/ui/gtk/gtk_util.cc index ad76fefa..2bd955b 100644 --- a/chrome/browser/ui/libgtkui/gtk_util.cc +++ b/chrome/browser/ui/gtk/gtk_util.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_util.h" #include <dlfcn.h> #include <gdk/gdk.h> @@ -43,7 +43,7 @@ // Callers should have already called setlocale(LC_ALL, "") and // setlocale(LC_NUMERIC, "C") by now. Chrome does this in // service_manager::Main. - DCHECK_EQ(strcmp(setlocale(LC_NUMERIC, NULL), "C"), 0); + DCHECK_EQ(strcmp(setlocale(LC_NUMERIC, nullptr), "C"), 0); // This prevent GTK from calling setlocale(LC_ALL, ""), which potentially // overwrites the LC_NUMERIC locale to something other than "C". gtk_disable_setlocale(); @@ -52,7 +52,7 @@ #else const std::vector<std::string>& args = command_line.argv(); int argc = args.size(); - std::unique_ptr<char* []> argv(new char*[argc + 1]); + std::unique_ptr<char*[]> argv(new char*[argc + 1]); for (size_t i = 0; i < args.size(); ++i) { // TODO(piman@google.com): can gtk_init modify argv? Just being safe // here. @@ -126,7 +126,7 @@ } // namespace -namespace libgtkui { +namespace gtk { // TODO(thomasanderson): ThemeService has a whole interface just for reading // default constants. Figure out what to do with that more long term; for now, @@ -205,7 +205,7 @@ void* GetGtkSharedLibrary() { std::string lib_name = - "libgtk-" + std::to_string(GTK_MAJOR_VERSION) + ".so.0"; + "libgtk-" + base::NumberToString(GTK_MAJOR_VERSION) + ".so.0"; static void* gtk_lib = dlopen(lib_name.c_str(), RTLD_LAZY); DCHECK(gtk_lib); return gtk_lib; @@ -599,7 +599,7 @@ GdkDisplay* GetGdkDisplay() { GdkDisplay* display = nullptr; // TODO(crbug.com/1002674): Remove once GtkIM-based LinuxInputMethodContext - // implementation is moved out of libgtkui. + // implementation is moved out of gtk. #if defined(USE_X11) display = gdk_x11_lookup_xdisplay(gfx::GetXDisplay()); #endif @@ -647,4 +647,4 @@ return gdk_event; } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/gtk_util.h b/chrome/browser/ui/gtk/gtk_util.h similarity index 94% rename from chrome/browser/ui/libgtkui/gtk_util.h rename to chrome/browser/ui/gtk/gtk_util.h index ab87074..e8f6a1b 100644 --- a/chrome/browser/ui/libgtkui/gtk_util.h +++ b/chrome/browser/ui/gtk/gtk_util.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_GTK_UTIL_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_GTK_UTIL_H_ +#ifndef CHROME_BROWSER_UI_GTK_GTK_UTIL_H_ +#define CHROME_BROWSER_UI_GTK_GTK_UTIL_H_ #include <gtk/gtk.h> #include <string> @@ -30,7 +30,7 @@ class KeyEvent; } -namespace libgtkui { +namespace gtk { extern const color_utils::HSL kDefaultTintFrameIncognito; @@ -88,11 +88,11 @@ using ScopedStyleContext = ScopedGObject<GtkStyleContext>; using ScopedCssProvider = ScopedGObject<GtkCssProvider>; -} // namespace libgtkui +} // namespace gtk -// Template override cannot be in the libgtkui namespace. +// Template override cannot be in the gtk namespace. template <> -inline void libgtkui::ScopedStyleContext::Unref() { +inline void gtk::ScopedStyleContext::Unref() { // Versions of GTK earlier than 3.15.4 had a bug where a g_assert // would be triggered when trying to free a GtkStyleContext that had // a parent whose only reference was the child context in question. @@ -102,7 +102,7 @@ while (context) { GtkStyleContext* parent = gtk_style_context_get_parent(context); if (parent && G_OBJECT(context)->ref_count == 1 && - !libgtkui::GtkVersionCheck(3, 15, 4)) { + !gtk::GtkVersionCheck(3, 15, 4)) { g_object_ref(parent); gtk_style_context_set_parent(context, nullptr); g_object_unref(context); @@ -114,7 +114,7 @@ } } -namespace libgtkui { +namespace gtk { // Converts ui::NativeTheme::State to GtkStateFlags. GtkStateFlags StateToStateFlags(ui::NativeTheme::State state); @@ -195,6 +195,6 @@ // root aura::Window targeted by that key event. GdkEvent* GdkEventFromKeyEvent(const ui::KeyEvent& key_event); -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_GTK_UTIL_H_ +#endif // CHROME_BROWSER_UI_GTK_GTK_UTIL_H_
diff --git a/chrome/browser/ui/libgtkui/input_method_context_impl_gtk.cc b/chrome/browser/ui/gtk/input_method_context_impl_gtk.cc similarity index 97% rename from chrome/browser/ui/libgtkui/input_method_context_impl_gtk.cc rename to chrome/browser/ui/gtk/input_method_context_impl_gtk.cc index ac4f15d..848f213b 100644 --- a/chrome/browser/ui/libgtkui/input_method_context_impl_gtk.cc +++ b/chrome/browser/ui/gtk/input_method_context_impl_gtk.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/input_method_context_impl_gtk.h" +#include "chrome/browser/ui/gtk/input_method_context_impl_gtk.h" #include <gdk/gdk.h> #include <gdk/gdkkeysyms.h> @@ -11,7 +11,7 @@ #include <stddef.h> #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_util.h" #include "ui/aura/window_tree_host.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/linux/composition_text_util_pango.h" @@ -20,7 +20,7 @@ #include "ui/gfx/geometry/dip_util.h" #include "ui/views/linux_ui/linux_ui.h" -namespace libgtkui { +namespace gtk { namespace { @@ -228,4 +228,4 @@ gdk_last_set_client_window_ = window; } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/input_method_context_impl_gtk.h b/chrome/browser/ui/gtk/input_method_context_impl_gtk.h similarity index 90% rename from chrome/browser/ui/libgtkui/input_method_context_impl_gtk.h rename to chrome/browser/ui/gtk/input_method_context_impl_gtk.h index 366da92..fc09a5b 100644 --- a/chrome/browser/ui/libgtkui/input_method_context_impl_gtk.h +++ b/chrome/browser/ui/gtk/input_method_context_impl_gtk.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ +#ifndef CHROME_BROWSER_UI_GTK_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ +#define CHROME_BROWSER_UI_GTK_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ #include "base/macros.h" #include "base/strings/string16.h" @@ -15,7 +15,7 @@ typedef struct _GdkWindow GdkWindow; typedef struct _GtkIMContext GtkIMContext; -namespace libgtkui { +namespace gtk { // An implementation of LinuxInputMethodContext which uses GtkIMContext // (gtk-immodule) as a bridge from/to underlying IMEs. @@ -79,6 +79,6 @@ DISALLOW_COPY_AND_ASSIGN(InputMethodContextImplGtk); }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_INPUT_METHOD_CONTEXT_IMPL_GTK_H_ +#endif // CHROME_BROWSER_UI_GTK_INPUT_METHOD_CONTEXT_IMPL_GTK_H_
diff --git a/chrome/browser/ui/libgtkui/native_theme_gtk.cc b/chrome/browser/ui/gtk/native_theme_gtk.cc similarity index 99% rename from chrome/browser/ui/libgtkui/native_theme_gtk.cc rename to chrome/browser/ui/gtk/native_theme_gtk.cc index c34e361..26f1842 100644 --- a/chrome/browser/ui/libgtkui/native_theme_gtk.cc +++ b/chrome/browser/ui/gtk/native_theme_gtk.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/native_theme_gtk.h" +#include "chrome/browser/ui/gtk/native_theme_gtk.h" #include <gtk/gtk.h> -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_util.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/rect.h" @@ -14,7 +14,7 @@ #include "ui/gfx/skia_util.h" #include "ui/native_theme/native_theme_dark_aura.h" -namespace libgtkui { +namespace gtk { namespace { @@ -646,4 +646,4 @@ rect.x(), rect.y()); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/native_theme_gtk.h b/chrome/browser/ui/gtk/native_theme_gtk.h similarity index 93% rename from chrome/browser/ui/libgtkui/native_theme_gtk.h rename to chrome/browser/ui/gtk/native_theme_gtk.h index 302fbe8..b52e5d6 100644 --- a/chrome/browser/ui/libgtkui/native_theme_gtk.h +++ b/chrome/browser/ui/gtk/native_theme_gtk.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_NATIVE_THEME_GTK_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_NATIVE_THEME_GTK_H_ +#ifndef CHROME_BROWSER_UI_GTK_NATIVE_THEME_GTK_H_ +#define CHROME_BROWSER_UI_GTK_NATIVE_THEME_GTK_H_ #include "base/macros.h" #include "base/no_destructor.h" @@ -16,7 +16,7 @@ typedef struct _GtkParamSpec GtkParamSpec; typedef struct _GtkSettings GtkSettings; -namespace libgtkui { +namespace gtk { using ScopedCssProvider = ScopedGObject<GtkCssProvider>; @@ -89,6 +89,6 @@ DISALLOW_COPY_AND_ASSIGN(NativeThemeGtk); }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_NATIVE_THEME_GTK_H_ +#endif // CHROME_BROWSER_UI_GTK_NATIVE_THEME_GTK_H_
diff --git a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.cc b/chrome/browser/ui/gtk/nav_button_provider_gtk.cc similarity index 98% rename from chrome/browser/ui/libgtkui/nav_button_provider_gtk.cc rename to chrome/browser/ui/gtk/nav_button_provider_gtk.cc index 9652018a..fb0e485 100644 --- a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.cc +++ b/chrome/browser/ui/gtk/nav_button_provider_gtk.cc
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/nav_button_provider_gtk.h" +#include "chrome/browser/ui/gtk/nav_button_provider_gtk.h" #include <gtk/gtk.h> -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_util.h" #include "ui/base/glib/scoped_gobject.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_source.h" #include "ui/views/widget/widget.h" -namespace libgtkui { +namespace gtk { namespace { @@ -409,4 +409,4 @@ return inter_button_spacing_; } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.h b/chrome/browser/ui/gtk/nav_button_provider_gtk.h similarity index 80% rename from chrome/browser/ui/libgtkui/nav_button_provider_gtk.h rename to chrome/browser/ui/gtk/nav_button_provider_gtk.h index b878728a..e7692c3 100644 --- a/chrome/browser/ui/libgtkui/nav_button_provider_gtk.h +++ b/chrome/browser/ui/gtk/nav_button_provider_gtk.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_PROVIDER_GTK_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_PROVIDER_GTK_H_ +#ifndef CHROME_BROWSER_UI_GTK_NAV_BUTTON_PROVIDER_GTK_H_ +#define CHROME_BROWSER_UI_GTK_NAV_BUTTON_PROVIDER_GTK_H_ #include <map> @@ -13,9 +13,9 @@ #include "ui/gfx/image/image_skia.h" #include "ui/views/controls/button/button.h" -namespace libgtkui { +namespace gtk { -class COMPONENT_EXPORT(LIBGTKUI) NavButtonProviderGtk +class COMPONENT_EXPORT(GTK) NavButtonProviderGtk : public views::NavButtonProvider { public: NavButtonProviderGtk(); @@ -39,6 +39,6 @@ int inter_button_spacing_; }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_NAV_BUTTON_PROVIDER_GTK_H_ +#endif // CHROME_BROWSER_UI_GTK_NAV_BUTTON_PROVIDER_GTK_H_
diff --git a/chrome/browser/ui/libgtkui/print_dialog_gtk.cc b/chrome/browser/ui/gtk/print_dialog_gtk.cc similarity index 95% rename from chrome/browser/ui/libgtkui/print_dialog_gtk.cc rename to chrome/browser/ui/gtk/print_dialog_gtk.cc index 93b3e51..bdbba42 100644 --- a/chrome/browser/ui/libgtkui/print_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/print_dialog_gtk.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/print_dialog_gtk.h" +#include "chrome/browser/ui/gtk/print_dialog_gtk.h" #include <gtk/gtkunixprint.h> @@ -21,8 +21,8 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/values.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" -#include "chrome/browser/ui/libgtkui/printing_gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_util.h" +#include "chrome/browser/ui/gtk/printing_gtk_util.h" #include "content/public/browser/browser_task_traits.h" #include "printing/metafile.h" #include "printing/print_job_constants.h" @@ -183,10 +183,10 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); if (dialog_) { - aura::Window* parent = libgtkui::GetAuraTransientParent(dialog_); + aura::Window* parent = gtk::GetAuraTransientParent(dialog_); if (parent) { parent->RemoveObserver(this); - libgtkui::ClearAuraTransientParent(dialog_); + gtk::ClearAuraTransientParent(dialog_); } gtk_widget_destroy(dialog_); dialog_ = nullptr; @@ -316,7 +316,7 @@ DCHECK(callback_); dialog_ = gtk_print_unix_dialog_new(nullptr, nullptr); - libgtkui::SetGtkTransientForAura(dialog_, parent_view); + gtk::SetGtkTransientForAura(dialog_, parent_view); if (parent_view) parent_view->AddObserver(this); g_signal_connect(dialog_, "delete-event", @@ -336,10 +336,8 @@ // Since we only generate PDF, only show printers that support PDF. // TODO(thestig) Add more capabilities to support? GtkPrintCapabilities cap = static_cast<GtkPrintCapabilities>( - GTK_PRINT_CAPABILITY_GENERATE_PDF | - GTK_PRINT_CAPABILITY_PAGE_SET | - GTK_PRINT_CAPABILITY_COPIES | - GTK_PRINT_CAPABILITY_COLLATE | + GTK_PRINT_CAPABILITY_GENERATE_PDF | GTK_PRINT_CAPABILITY_PAGE_SET | + GTK_PRINT_CAPABILITY_COPIES | GTK_PRINT_CAPABILITY_COLLATE | GTK_PRINT_CAPABILITY_REVERSE); gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog_), cap); @@ -478,14 +476,15 @@ return; } case GTK_RESPONSE_APPLY: - default: { NOTREACHED(); } + default: { + NOTREACHED(); + } } } static void OnJobCompletedThunk(GtkPrintJob* print_job, gpointer user_data, - const GError* error - ) { + const GError* error) { static_cast<PrintDialogGtk*>(user_data)->OnJobCompleted(print_job, error); } void PrintDialogGtk::SendDocumentToPrinter( @@ -535,9 +534,9 @@ } void PrintDialogGtk::OnWindowDestroying(aura::Window* window) { - DCHECK_EQ(libgtkui::GetAuraTransientParent(dialog_), window); + DCHECK_EQ(gtk::GetAuraTransientParent(dialog_), window); - libgtkui::ClearAuraTransientParent(dialog_); + gtk::ClearAuraTransientParent(dialog_); window->RemoveObserver(this); if (callback_) std::move(callback_).Run(PrintingContextLinux::CANCEL);
diff --git a/chrome/browser/ui/libgtkui/print_dialog_gtk.h b/chrome/browser/ui/gtk/print_dialog_gtk.h similarity index 94% rename from chrome/browser/ui/libgtkui/print_dialog_gtk.h rename to chrome/browser/ui/gtk/print_dialog_gtk.h index 2522b8c..6c69906 100644 --- a/chrome/browser/ui/libgtkui/print_dialog_gtk.h +++ b/chrome/browser/ui/gtk/print_dialog_gtk.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_PRINT_DIALOG_GTK_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_PRINT_DIALOG_GTK_H_ +#ifndef CHROME_BROWSER_UI_GTK_PRINT_DIALOG_GTK_H_ +#define CHROME_BROWSER_UI_GTK_PRINT_DIALOG_GTK_H_ #include <gtk/gtk.h> #include <gtk/gtkunixprint.h> @@ -23,7 +23,7 @@ namespace printing { class MetafilePlayer; class PrintSettings; -} +} // namespace printing using printing::PrintingContextLinux; @@ -91,4 +91,4 @@ DISALLOW_COPY_AND_ASSIGN(PrintDialogGtk); }; -#endif // CHROME_BROWSER_UI_LIBGTKUI_PRINT_DIALOG_GTK_H_ +#endif // CHROME_BROWSER_UI_GTK_PRINT_DIALOG_GTK_H_
diff --git a/chrome/browser/ui/libgtkui/printing_gtk_util.cc b/chrome/browser/ui/gtk/printing_gtk_util.cc similarity index 98% rename from chrome/browser/ui/libgtkui/printing_gtk_util.cc rename to chrome/browser/ui/gtk/printing_gtk_util.cc index 7baba3c6..11abf17 100644 --- a/chrome/browser/ui/libgtkui/printing_gtk_util.cc +++ b/chrome/browser/ui/gtk/printing_gtk_util.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/printing_gtk_util.h" +#include "chrome/browser/ui/gtk/printing_gtk_util.h" #include <gtk/gtk.h> #include <gtk/gtkunixprint.h>
diff --git a/chrome/browser/ui/libgtkui/printing_gtk_util.h b/chrome/browser/ui/gtk/printing_gtk_util.h similarity index 80% rename from chrome/browser/ui/libgtkui/printing_gtk_util.h rename to chrome/browser/ui/gtk/printing_gtk_util.h index 31b3df2..16b5391 100644 --- a/chrome/browser/ui/libgtkui/printing_gtk_util.h +++ b/chrome/browser/ui/gtk/printing_gtk_util.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_PRINTING_GTK_UTIL_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_PRINTING_GTK_UTIL_H_ +#ifndef CHROME_BROWSER_UI_GTK_PRINTING_GTK_UTIL_H_ +#define CHROME_BROWSER_UI_GTK_PRINTING_GTK_UTIL_H_ #include "ui/gfx/geometry/size.h" namespace printing { class PrintingContextLinux; class PrintSettings; -} +} // namespace printing typedef struct _GtkPrintSettings GtkPrintSettings; typedef struct _GtkPageSetup GtkPageSetup; @@ -24,4 +24,4 @@ GtkPageSetup* page_setup, printing::PrintSettings* print_settings); -#endif // CHROME_BROWSER_UI_LIBGTKUI_PRINTING_GTK_UTIL_H_ +#endif // CHROME_BROWSER_UI_GTK_PRINTING_GTK_UTIL_H_
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl.cc b/chrome/browser/ui/gtk/select_file_dialog_impl.cc similarity index 92% rename from chrome/browser/ui/libgtkui/select_file_dialog_impl.cc rename to chrome/browser/ui/gtk/select_file_dialog_impl.cc index c7e2fc99..570fe9d9 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl.cc +++ b/chrome/browser/ui/gtk/select_file_dialog_impl.cc
@@ -4,7 +4,7 @@ // // This file implements common select dialog functionality between GTK and KDE. -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl.h" #include "base/environment.h" #include "base/files/file_util.h" @@ -16,17 +16,13 @@ namespace { -enum UseKdeFileDialogStatus { - UNKNOWN, - NO_KDE, - YES_KDE -}; +enum UseKdeFileDialogStatus { UNKNOWN, NO_KDE, YES_KDE }; UseKdeFileDialogStatus use_kde_ = UNKNOWN; } // namespace -namespace libgtkui { +namespace gtk { base::FilePath* SelectFileDialogImpl::last_saved_path_ = nullptr; base::FilePath* SelectFileDialogImpl::last_opened_path_ = nullptr; @@ -81,7 +77,7 @@ } } -SelectFileDialogImpl::~SelectFileDialogImpl() { } +SelectFileDialogImpl::~SelectFileDialogImpl() {} void SelectFileDialogImpl::ListenerDestroyed() { listener_ = nullptr; @@ -93,4 +89,4 @@ return base::DirectoryExists(path); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl.h b/chrome/browser/ui/gtk/select_file_dialog_impl.h similarity index 92% rename from chrome/browser/ui/libgtkui/select_file_dialog_impl.h rename to chrome/browser/ui/gtk/select_file_dialog_impl.h index bf5a4a7b..273c22e 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl.h +++ b/chrome/browser/ui/gtk/select_file_dialog_impl.h
@@ -4,8 +4,8 @@ // // This file implements common select dialog functionality between GTK and KDE. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_SELECT_FILE_DIALOG_IMPL_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_SELECT_FILE_DIALOG_IMPL_H_ +#ifndef CHROME_BROWSER_UI_GTK_SELECT_FILE_DIALOG_IMPL_H_ +#define CHROME_BROWSER_UI_GTK_SELECT_FILE_DIALOG_IMPL_H_ #include <stddef.h> @@ -19,7 +19,7 @@ #include "ui/shell_dialogs/select_file_dialog.h" #include "ui/shell_dialogs/select_file_policy.h" -namespace libgtkui { +namespace gtk { // Shared implementation SelectFileDialog used by SelectFileDialogImplGTK class SelectFileDialogImpl : public ui::SelectFileDialog { @@ -86,6 +86,6 @@ DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_SELECT_FILE_DIALOG_IMPL_H_ +#endif // CHROME_BROWSER_UI_GTK_SELECT_FILE_DIALOG_IMPL_H_
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc b/chrome/browser/ui/gtk/select_file_dialog_impl_gtk.cc similarity index 98% rename from chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc rename to chrome/browser/ui/gtk/select_file_dialog_impl_gtk.cc index 6b41ae5e..f9f4077 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc +++ b/chrome/browser/ui/gtk/select_file_dialog_impl_gtk.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl_gtk.h" #include <gdk/gdkx.h> #include <gtk/gtk.h> @@ -23,8 +23,8 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h" +#include "chrome/browser/ui/gtk/gtk_util.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl.h" #include "ui/aura/window_observer.h" #include "ui/base/l10n/l10n_util.h" #include "ui/shell_dialogs/select_file_dialog.h" @@ -75,7 +75,7 @@ } // namespace -namespace libgtkui { +namespace gtk { // The size of the preview we display for selected image files. We set height // larger than width because generally there is more free space vertically @@ -599,4 +599,4 @@ pixbuf ? TRUE : FALSE); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.h b/chrome/browser/ui/gtk/select_file_dialog_impl_gtk.h similarity index 93% rename from chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.h rename to chrome/browser/ui/gtk/select_file_dialog_impl_gtk.h index 1022a01..e7a7577f 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.h +++ b/chrome/browser/ui/gtk/select_file_dialog_impl_gtk.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_SELECT_FILE_DIALOG_IMPL_GTK_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_SELECT_FILE_DIALOG_IMPL_GTK_H_ +#ifndef CHROME_BROWSER_UI_GTK_SELECT_FILE_DIALOG_IMPL_GTK_H_ +#define CHROME_BROWSER_UI_GTK_SELECT_FILE_DIALOG_IMPL_GTK_H_ #include "base/macros.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h" +#include "chrome/browser/ui/gtk/gtk_util.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl.h" #include "ui/base/glib/glib_signal.h" -namespace libgtkui { +namespace gtk { // Implementation of SelectFileDialog that shows a Gtk common dialog for // choosing a file or folder. This acts as a modal dialog. @@ -143,6 +143,6 @@ DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImplGTK); }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_SELECT_FILE_DIALOG_IMPL_GTK_H_ +#endif // CHROME_BROWSER_UI_GTK_SELECT_FILE_DIALOG_IMPL_GTK_H_
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk_unittest.cc b/chrome/browser/ui/gtk/select_file_dialog_impl_gtk_unittest.cc similarity index 96% rename from chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk_unittest.cc rename to chrome/browser/ui/gtk/select_file_dialog_impl_gtk_unittest.cc index 503572d..31fa473 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk_unittest.cc +++ b/chrome/browser/ui/gtk/select_file_dialog_impl_gtk_unittest.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl_gtk.h" #include "base/run_loop.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "chrome/browser/ui/chrome_select_file_policy.h" -#include "chrome/browser/ui/libgtkui/gtk_ui.h" +#include "chrome/browser/ui/gtk/gtk_ui.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "content/public/browser/browser_thread.h" @@ -35,7 +35,7 @@ std::unique_ptr<views::LinuxUI> gtk_ui_; }; -namespace libgtkui { +namespace gtk { class FilePicker : public ui::SelectFileDialog::Listener { public: @@ -143,4 +143,4 @@ RunLoop().RunUntilIdle(); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc b/chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc similarity index 92% rename from chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc rename to chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc index a0a9335..2f6e6f7c 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_impl_kde.cc +++ b/chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc
@@ -24,7 +24,7 @@ #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/threading/thread_restrictions.h" -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl.h" #include "content/public/browser/browser_thread.h" #include "ui/aura/window_tree_host.h" #include "ui/base/l10n/l10n_util.h" @@ -43,7 +43,7 @@ } // namespace -namespace libgtkui { +namespace gtk { // Implementation of SelectFileDialog that shows a KDE common dialog for // choosing a file or folder. This acts as a modal dialog. @@ -127,24 +127,28 @@ // Notifies the listener that no file was chosen (the action was canceled). // Dialog is passed so we can find that |params| pointer that was passed to // us when we were told to show the dialog. - void FileNotSelected(void *params); + void FileNotSelected(void* params); void CreateSelectFolderDialog(Type type, const std::string& title, const base::FilePath& default_path, - XID parent, void* params); + XID parent, + void* params); void CreateFileOpenDialog(const std::string& title, - const base::FilePath& default_path, - XID parent, void* params); + const base::FilePath& default_path, + XID parent, + void* params); void CreateMultiFileOpenDialog(const std::string& title, const base::FilePath& default_path, - XID parent, void* params); + XID parent, + void* params); void CreateSaveAsDialog(const std::string& title, const base::FilePath& default_path, - XID parent, void* params); + XID parent, + void* params); // Common function for OnSelectSingleFileDialogResponse and // OnSelectSingleFolderDialogResponse. @@ -215,8 +219,7 @@ desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE5); } -SelectFileDialogImplKDE::~SelectFileDialogImplKDE() { -} +SelectFileDialogImplKDE::~SelectFileDialogImplKDE() {} bool SelectFileDialogImplKDE::IsRunning(gfx::NativeWindow parent_window) const { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -262,8 +265,8 @@ case SELECT_FOLDER: case SELECT_UPLOAD_FOLDER: case SELECT_EXISTING_FOLDER: - CreateSelectFolderDialog(type, title_string, default_path, - window_xid, params); + CreateSelectFolderDialog(type, title_string, default_path, window_xid, + params); return; case SELECT_OPEN_FILE: CreateFileOpenDialog(title_string, default_path, window_xid, params); @@ -291,8 +294,9 @@ for (size_t i = 0; i < file_types_.extensions.size(); ++i) { for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) { if (!file_types_.extensions[i][j].empty()) { - std::string mime_type = base::nix::GetFileMimeType(base::FilePath( - "name").ReplaceExtension(file_types_.extensions[i][j])); + std::string mime_type = + base::nix::GetFileMimeType(base::FilePath("name").ReplaceExtension( + file_types_.extensions[i][j])); filter_set.insert(mime_type); } } @@ -385,7 +389,8 @@ } void SelectFileDialogImplKDE::MultiFilesSelected( - const std::vector<base::FilePath>& files, void* params) { + const std::vector<base::FilePath>& files, + void* params) { *last_opened_path_ = files[0].DirName(); if (listener_) listener_->MultiFilesSelected(files, params); @@ -397,11 +402,14 @@ } void SelectFileDialogImplKDE::CreateSelectFolderDialog( - Type type, const std::string& title, const base::FilePath& default_path, - XID parent, void *params) { + Type type, + const std::string& title, + const base::FilePath& default_path, + XID parent, + void* params) { int title_message_id = (type == SELECT_UPLOAD_FOLDER) - ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE - : IDS_SELECT_FOLDER_DIALOG_TITLE; + ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE + : IDS_SELECT_FOLDER_DIALOG_TITLE; base::PostTaskAndReplyWithResult( pipe_task_runner_.get(), FROM_HERE, base::BindOnce( @@ -416,8 +424,10 @@ } void SelectFileDialogImplKDE::CreateFileOpenDialog( - const std::string& title, const base::FilePath& default_path, - XID parent, void* params) { + const std::string& title, + const base::FilePath& default_path, + XID parent, + void* params) { base::PostTaskAndReplyWithResult( pipe_task_runner_.get(), FROM_HERE, base::BindOnce( @@ -431,8 +441,10 @@ } void SelectFileDialogImplKDE::CreateMultiFileOpenDialog( - const std::string& title, const base::FilePath& default_path, - XID parent, void* params) { + const std::string& title, + const base::FilePath& default_path, + XID parent, + void* params) { base::PostTaskAndReplyWithResult( pipe_task_runner_.get(), FROM_HERE, base::BindOnce( @@ -446,8 +458,10 @@ } void SelectFileDialogImplKDE::CreateSaveAsDialog( - const std::string& title, const base::FilePath& default_path, - XID parent, void* params) { + const std::string& title, + const base::FilePath& default_path, + XID parent, + void* params) { base::PostTaskAndReplyWithResult( pipe_task_runner_.get(), FROM_HERE, base::BindOnce( @@ -531,4 +545,4 @@ MultiFilesSelected(filenames_fp, params); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/select_file_dialog_interactive_uitest.cc b/chrome/browser/ui/gtk/select_file_dialog_interactive_uitest.cc similarity index 81% rename from chrome/browser/ui/libgtkui/select_file_dialog_interactive_uitest.cc rename to chrome/browser/ui/gtk/select_file_dialog_interactive_uitest.cc index 0bc450b..5b416252 100644 --- a/chrome/browser/ui/libgtkui/select_file_dialog_interactive_uitest.cc +++ b/chrome/browser/ui/gtk/select_file_dialog_interactive_uitest.cc
@@ -3,10 +3,11 @@ // found in the LICENSE file. #include "base/macros.h" +#include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/chrome_select_file_policy.h" -#include "chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.h" +#include "chrome/browser/ui/gtk/select_file_dialog_impl_gtk.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" @@ -18,7 +19,7 @@ using BrowserSelectFileDialogTest = InProcessBrowserTest; -namespace libgtkui { +namespace gtk { // FilePicker opens a GtkFileChooser. class FilePicker : public ui::SelectFileDialog::Listener { @@ -31,25 +32,17 @@ ui::SelectFileDialog::FileTypeInfo file_types; file_types.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH; const base::FilePath file_path; - select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, - base::string16(), - file_path, - &file_types, - 0, - base::FilePath::StringType(), - parent_window, - nullptr); + select_file_dialog_->SelectFile( + ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(), file_path, + &file_types, 0, base::FilePath::StringType(), parent_window, nullptr); } - ~FilePicker() override { - select_file_dialog_->ListenerDestroyed(); - } + ~FilePicker() override { select_file_dialog_->ListenerDestroyed(); } void Close() { SelectFileDialogImplGTK* file_dialog = static_cast<SelectFileDialogImplGTK*>(select_file_dialog_.get()); - while (!file_dialog->dialogs_.empty()) gtk_widget_destroy(*(file_dialog->dialogs_.begin())); } @@ -58,6 +51,7 @@ void FileSelected(const base::FilePath& path, int index, void* params) override {} + private: // Dialog box used for opening and saving files. scoped_refptr<ui::SelectFileDialog> select_file_dialog_; @@ -65,7 +59,7 @@ DISALLOW_COPY_AND_ASSIGN(FilePicker); }; -} // namespace libgtkui +} // namespace gtk // Leaks in GtkFileChooserDialog. http://crbug.com/537468 // Flaky on Linux. http://crbug.com/700134 @@ -80,7 +74,7 @@ ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); ASSERT_TRUE(browser()->window()->IsActive()); - libgtkui::FilePicker file_picker(browser()->window()); + gtk::FilePicker file_picker(browser()->window()); gfx::NativeWindow window = browser()->window()->GetNativeWindow(); views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); @@ -102,8 +96,8 @@ ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window)); EXPECT_FALSE(browser()->window()->IsActive()); - ASSERT_TRUE(ui_test_utils::SendKeyPressSync( - browser(), ui::VKEY_TAB, false, false, true, false)); + ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_TAB, false, + false, true, false)); EXPECT_FALSE(browser()->window()->IsActive()); file_picker.Close();
diff --git a/chrome/browser/ui/libgtkui/settings_provider.h b/chrome/browser/ui/gtk/settings_provider.h similarity index 76% rename from chrome/browser/ui/libgtkui/settings_provider.h rename to chrome/browser/ui/gtk/settings_provider.h index ec06c6c..c4c47183 100644 --- a/chrome/browser/ui/libgtkui/settings_provider.h +++ b/chrome/browser/ui/gtk/settings_provider.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_H_ +#ifndef CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_H_ +#define CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_H_ -namespace libgtkui { +namespace gtk { // This class is just a switch between SettingsProviderGSettings and // SettingsProviderGtk. Currently, it is empty and it's only purpose is so @@ -21,6 +21,6 @@ SettingsProvider() {} }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_H_ +#endif // CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_H_
diff --git a/chrome/browser/ui/libgtkui/settings_provider_gsettings.cc b/chrome/browser/ui/gtk/settings_provider_gsettings.cc similarity index 95% rename from chrome/browser/ui/libgtkui/settings_provider_gsettings.cc rename to chrome/browser/ui/gtk/settings_provider_gsettings.cc index 340c5c8a..4492467 100644 --- a/chrome/browser/ui/libgtkui/settings_provider_gsettings.cc +++ b/chrome/browser/ui/gtk/settings_provider_gsettings.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/settings_provider_gsettings.h" +#include "chrome/browser/ui/gtk/settings_provider_gsettings.h" #include <gio/gio.h> @@ -10,8 +10,8 @@ #include "base/environment.h" #include "base/nix/xdg_util.h" -#include "chrome/browser/ui/libgtkui/gtk_ui.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_ui.h" +#include "chrome/browser/ui/gtk/gtk_util.h" namespace { @@ -29,7 +29,7 @@ } // namespace -namespace libgtkui { +namespace gtk { // Public interface: @@ -139,4 +139,4 @@ views::LinuxUI::WindowFrameActionSource::kMiddleClick, action); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/settings_provider_gsettings.h b/chrome/browser/ui/gtk/settings_provider_gsettings.h similarity index 82% rename from chrome/browser/ui/libgtkui/settings_provider_gsettings.h rename to chrome/browser/ui/gtk/settings_provider_gsettings.h index 52c4a92..44fb6154 100644 --- a/chrome/browser/ui/libgtkui/settings_provider_gsettings.h +++ b/chrome/browser/ui/gtk/settings_provider_gsettings.h
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GSETTINGS_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GSETTINGS_H_ +#ifndef CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_GSETTINGS_H_ +#define CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_GSETTINGS_H_ #include <gio/gio.h> #include <string> #include "base/macros.h" -#include "chrome/browser/ui/libgtkui/settings_provider.h" +#include "chrome/browser/ui/gtk/settings_provider.h" #include "ui/base/glib/glib_signal.h" -namespace libgtkui { +namespace gtk { class GtkUi; // On GNOME desktops, subscribes to the gsettings key which controlls button @@ -52,6 +52,6 @@ DISALLOW_COPY_AND_ASSIGN(SettingsProviderGSettings); }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GSETTINGS_H_ +#endif // CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_GSETTINGS_H_
diff --git a/chrome/browser/ui/libgtkui/settings_provider_gtk.cc b/chrome/browser/ui/gtk/settings_provider_gtk.cc similarity index 96% rename from chrome/browser/ui/libgtkui/settings_provider_gtk.cc rename to chrome/browser/ui/gtk/settings_provider_gtk.cc index 0a44cce8..2ccd73f 100644 --- a/chrome/browser/ui/libgtkui/settings_provider_gtk.cc +++ b/chrome/browser/ui/gtk/settings_provider_gtk.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/libgtkui/settings_provider_gtk.h" +#include "chrome/browser/ui/gtk/settings_provider_gtk.h" #include "base/strings/string_split.h" -#include "chrome/browser/ui/libgtkui/gtk_ui.h" -#include "chrome/browser/ui/libgtkui/gtk_util.h" +#include "chrome/browser/ui/gtk/gtk_ui.h" +#include "chrome/browser/ui/gtk/gtk_util.h" -namespace libgtkui { +namespace gtk { namespace { @@ -144,4 +144,4 @@ SetWindowButtonOrderingFromGtkLayout(layout); } -} // namespace libgtkui +} // namespace gtk
diff --git a/chrome/browser/ui/libgtkui/settings_provider_gtk.h b/chrome/browser/ui/gtk/settings_provider_gtk.h similarity index 87% rename from chrome/browser/ui/libgtkui/settings_provider_gtk.h rename to chrome/browser/ui/gtk/settings_provider_gtk.h index 889726181..06cbd6f 100644 --- a/chrome/browser/ui/libgtkui/settings_provider_gtk.h +++ b/chrome/browser/ui/gtk/settings_provider_gtk.h
@@ -2,22 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GTK_H_ -#define CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GTK_H_ +#ifndef CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_GTK_H_ +#define CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_GTK_H_ #include <memory> #include <string> #include <vector> #include "base/macros.h" -#include "chrome/browser/ui/libgtkui/settings_provider.h" +#include "chrome/browser/ui/gtk/settings_provider.h" #include "ui/base/glib/glib_signal.h" #include "ui/views/linux_ui/linux_ui.h" typedef struct _GParamSpec GParamSpec; typedef struct _GtkSettings GtkSettings; -namespace libgtkui { +namespace gtk { class GtkUi; @@ -76,6 +76,6 @@ DISALLOW_COPY_AND_ASSIGN(SettingsProviderGtk); }; -} // namespace libgtkui +} // namespace gtk -#endif // CHROME_BROWSER_UI_LIBGTKUI_SETTINGS_PROVIDER_GTK_H_ +#endif // CHROME_BROWSER_UI_GTK_SETTINGS_PROVIDER_GTK_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc index b4e4538..eaf0c5d8 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -6,6 +6,9 @@ #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/media/router/media_router_factory.h" +#include "chrome/browser/media/router/presentation/web_contents_presentation_manager.h" +#include "chrome/browser/media/router/test/mock_media_router.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/global_media_controls/media_toolbar_button_observer.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -17,6 +20,7 @@ #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/media_message_center/media_notification_view_impl.h" +#include "content/public/browser/presentation_request.h" #include "content/public/browser/web_contents.h" #include "content/public/test/media_start_stop_observer.h" #include "media/base/media_switches.h" @@ -90,6 +94,17 @@ Wait(); } + void WaitForNotificationCount(int count) { + if (GetNotificationCount() == count) + return; + + waiting_for_notification_count_ = true; + expected_notification_count_ = count; + observed_dialog_ = MediaDialogView::GetDialogViewForTesting(); + observed_dialog_->AddObserver(this); + Wait(); + } + private: void CheckDialogForText() { if (!waiting_for_dialog_to_contain_text_) @@ -102,12 +117,24 @@ MaybeStopWaiting(); } + void CheckNotificationCount() { + if (!waiting_for_notification_count_) + return; + + if (GetNotificationCount() != expected_notification_count_) + return; + + waiting_for_notification_count_ = false; + MaybeStopWaiting(); + } + void MaybeStopWaiting() { if (!run_loop_) return; if (!waiting_for_dialog_opened_ && !waiting_for_button_shown_ && - !waiting_for_dialog_to_contain_text_) { + !waiting_for_dialog_to_contain_text_ && + !waiting_for_notification_count_) { run_loop_->Quit(); } } @@ -129,26 +156,98 @@ if (view->title_label_for_testing()->GetText().find(text) != std::string::npos || view->artist_label_for_testing()->GetText().find(text) != - std::string::npos) { + std::string::npos || + view->GetSourceTitleForTesting().find(text) != std::string::npos) { return true; } } return false; } + int GetNotificationCount() { + return MediaDialogView::GetDialogViewForTesting() + ->GetNotificationsForTesting() + .size(); + } + MediaToolbarButtonView* const button_; std::unique_ptr<base::RunLoop> run_loop_; bool waiting_for_dialog_opened_ = false; bool waiting_for_button_shown_ = false; + bool waiting_for_notification_count_ = false; MediaDialogView* observed_dialog_ = nullptr; bool waiting_for_dialog_to_contain_text_ = false; base::string16 expected_text_; + int expected_notification_count_ = 0; DISALLOW_COPY_AND_ASSIGN(MediaToolbarButtonWatcher); }; +class TestWebContentsPresentationManager + : public media_router::WebContentsPresentationManager { + public: + void NotifyMediaRoutesChanged( + const std::vector<media_router::MediaRoute>& routes) { + for (auto& observer : observers_) { + observer.OnMediaRoutesChanged(routes); + } + } + + void AddObserver(Observer* observer) override { + observers_.AddObserver(observer); + } + + void RemoveObserver(Observer* observer) override { + observers_.RemoveObserver(observer); + } + + MOCK_CONST_METHOD0(HasDefaultPresentationRequest, bool()); + MOCK_CONST_METHOD0(GetDefaultPresentationRequest, + const content::PresentationRequest&()); + + void OnPresentationResponse( + const content::PresentationRequest& presentation_request, + media_router::mojom::RoutePresentationConnectionPtr connection, + const media_router::RouteRequestResult& result) override {} + + base::WeakPtr<WebContentsPresentationManager> GetWeakPtr() override { + return weak_factory_.GetWeakPtr(); + } + + private: + base::ObserverList<Observer> observers_; + base::WeakPtrFactory<TestWebContentsPresentationManager> weak_factory_{this}; +}; + +class TestMediaRouter : public media_router::MockMediaRouter { + public: + static std::unique_ptr<KeyedService> Create( + content::BrowserContext* context) { + return std::make_unique<TestMediaRouter>(); + } + + void RegisterMediaRoutesObserver( + media_router::MediaRoutesObserver* observer) override { + routes_observers_.push_back(observer); + } + + void UnregisterMediaRoutesObserver( + media_router::MediaRoutesObserver* observer) override { + base::Erase(routes_observers_, observer); + } + + void NotifyMediaRoutesChanged( + const std::vector<media_router::MediaRoute>& routes) { + for (auto* observer : routes_observers_) + observer->OnRoutesUpdated(routes, {}); + } + + private: + std::vector<media_router::MediaRoutesObserver*> routes_observers_; +}; + } // anonymous namespace class MediaDialogViewBrowserTest : public InProcessBrowserTest { @@ -163,10 +262,38 @@ } void SetUp() override { - feature_list_.InitAndEnableFeature(media::kGlobalMediaControls); + feature_list_.InitWithFeatures( + {media::kGlobalMediaControls, media::kGlobalMediaControlsForCast}, {}); + + presentation_manager_ = + std::make_unique<TestWebContentsPresentationManager>(); + media_router::WebContentsPresentationManager::SetTestInstance( + presentation_manager_.get()); + InProcessBrowserTest::SetUp(); } + void TearDown() override { + InProcessBrowserTest::TearDown(); + media_router::WebContentsPresentationManager::SetTestInstance(nullptr); + } + + void SetUpInProcessBrowserTestFixture() override { + subscription_ = + BrowserContextDependencyManager::GetInstance() + ->RegisterWillCreateBrowserContextServicesCallbackForTesting( + base::BindRepeating(&MediaDialogViewBrowserTest:: + OnWillCreateBrowserContextServices, + base::Unretained(this))); + } + + void OnWillCreateBrowserContextServices(content::BrowserContext* context) { + media_router_ = static_cast<TestMediaRouter*>( + media_router::MediaRouterFactory::GetInstance() + ->SetTestingFactoryAndUse( + context, base::BindRepeating(&TestMediaRouter::Create))); + } + MediaToolbarButtonView* GetToolbarIcon() { return BrowserView::GetBrowserViewForBrowser(browser()) ->toolbar() @@ -228,6 +355,10 @@ .WaitForDialogToContainText(text); } + void WaitForNotificationCount(int count) { + MediaToolbarButtonWatcher(GetToolbarIcon()).WaitForNotificationCount(count); + } + void ClickPauseButtonOnDialog() { base::RunLoop().RunUntilIdle(); ASSERT_TRUE(MediaDialogView::IsShowing()); @@ -252,6 +383,10 @@ return browser()->tab_strip_model()->GetActiveWebContents(); } + protected: + std::unique_ptr<TestWebContentsPresentationManager> presentation_manager_; + TestMediaRouter* media_router_ = nullptr; + private: void ClickButton(views::Button* button) { base::RunLoop closure_loop; @@ -302,6 +437,9 @@ } base::test::ScopedFeatureList feature_list_; + std::unique_ptr< + base::CallbackList<void(content::BrowserContext*)>::Subscription> + subscription_; DISALLOW_COPY_AND_ASSIGN(MediaDialogViewBrowserTest); }; @@ -408,3 +546,26 @@ ClickNotificationByTitle(base::ASCIIToUTF16("Big Buck Bunny")); EXPECT_EQ(first_web_contents, GetActiveWebContents()); } + +IN_PROC_BROWSER_TEST_F(MediaDialogViewBrowserTest, ShowsCastSession) { + OpenTestURL(); + StartPlayback(); + WaitForStart(); + + const std::string route_description = "Casting: Big Buck Bunny"; + const std::string sink_name = "My Sink"; + media_router::MediaRoute route("id", media_router::MediaSource("source_id"), + "sink_id", route_description, true, true); + route.set_media_sink_name(sink_name); + route.set_controller_type(media_router::RouteControllerType::kGeneric); + media_router_->NotifyMediaRoutesChanged({route}); + base::RunLoop().RunUntilIdle(); + presentation_manager_->NotifyMediaRoutesChanged({route}); + + WaitForVisibleToolbarIcon(); + ClickToolbarIcon(); + WaitForDialogOpened(); + WaitForDialogToContainText( + base::UTF8ToUTF16(route_description + " \xC2\xB7 " + sink_name)); + WaitForNotificationCount(1); +}
diff --git a/chrome/browser/ui/views/linux_ui/linux_ui_factory_gtk.cc b/chrome/browser/ui/views/linux_ui/linux_ui_factory_gtk.cc index 4889f4d..578cde72 100644 --- a/chrome/browser/ui/views/linux_ui/linux_ui_factory_gtk.cc +++ b/chrome/browser/ui/views/linux_ui/linux_ui_factory_gtk.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/ui/views/linux_ui/linux_ui_factory.h" -#include "chrome/browser/ui/libgtkui/gtk_ui.h" +#include "chrome/browser/ui/gtk/gtk_ui.h" namespace views {
diff --git a/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc b/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc index 909c23c..95451db 100644 --- a/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc +++ b/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc
@@ -10,6 +10,7 @@ #include "base/values.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h" #include "components/prefs/pref_service.h" #include "components/sync/base/pref_names.h" #include "components/sync/base/user_selectable_type.h" @@ -99,7 +100,7 @@ // Wallpaper sync status is stored directly to the profile's prefs. bool wallpaper_synced; CHECK(result->GetBoolean(kWallpaperEnabledKey, &wallpaper_synced)); - profile_->GetPrefs()->SetBoolean(syncer::prefs::kSyncOsWallpaper, + profile_->GetPrefs()->SetBoolean(chromeos::settings::prefs::kSyncOsWallpaper, wallpaper_synced); // Start configuring the SyncService using the configuration passed to us from @@ -171,10 +172,10 @@ // Wallpaper sync status is fetched from prefs and is considered enabled if // all OS types are enabled; this mimics behavior of GetSelectedOsTypes(). - args.SetBoolean( - kWallpaperEnabledKey, - user_settings->IsSyncAllOsTypesEnabled() || - profile_->GetPrefs()->GetBoolean(syncer::prefs::kSyncOsWallpaper)); + args.SetBoolean(kWallpaperEnabledKey, + user_settings->IsSyncAllOsTypesEnabled() || + profile_->GetPrefs()->GetBoolean( + chromeos::settings::prefs::kSyncOsWallpaper)); FireWebUIListener("os-sync-prefs-changed", base::Value(feature_enabled_), args);
diff --git a/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc b/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc index 108cde8..480e216 100644 --- a/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc +++ b/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc
@@ -11,6 +11,7 @@ #include "base/values.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/test_chrome_web_ui_controller_factory.h" #include "components/keyed_service/core/keyed_service.h" @@ -150,12 +151,13 @@ void NotifySyncStateChanged() { handler_->OnStateChanged(sync_service_); } bool GetWallperEnabledPref() { - return profile()->GetPrefs()->GetBoolean(syncer::prefs::kSyncOsWallpaper); + return profile()->GetPrefs()->GetBoolean( + chromeos::settings::prefs::kSyncOsWallpaper); } void SetWallperEnabledPref(bool enabled) { - return profile()->GetPrefs()->SetBoolean(syncer::prefs::kSyncOsWallpaper, - enabled); + return profile()->GetPrefs()->SetBoolean( + chromeos::settings::prefs::kSyncOsWallpaper, enabled); } syncer::TestSyncService* sync_service_ = nullptr;
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc index 291a8d8..3d24d6cd 100644 --- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -61,6 +61,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h" #include "chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h" +#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h" #include "chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h" #include "chrome/browser/ui/webui/settings/downloads_handler.h" #include "chrome/browser/ui/webui/settings/extension_control_handler.h" @@ -91,6 +92,7 @@ #include "chromeos/services/multidevice_setup/public/cpp/prefs.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" #include "components/password_manager/core/common/password_manager_features.h" +#include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_ui_data_source.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -100,6 +102,12 @@ namespace chromeos { namespace settings { +// static +void OSSettingsUI::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterBooleanPref(prefs::kSyncOsWallpaper, false); +} + OSSettingsUI::OSSettingsUI(content::WebUI* web_ui) : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true), webui_load_timer_(web_ui->GetWebContents(), @@ -288,7 +296,7 @@ web_ui()->AddMessageHandler( std::make_unique<chromeos::settings::WallpaperHandler>(web_ui())); - if (plugin_vm::IsPluginVmEnabled(profile)) { + if (plugin_vm::IsPluginVmAllowedForProfile(profile)) { web_ui()->AddMessageHandler( std::make_unique<chromeos::settings::PluginVmHandler>(profile)); } @@ -379,7 +387,7 @@ "allowCrostini", crostini::CrostiniFeatures::Get()->IsUIAllowed(profile)); html_source->AddBoolean("showPluginVm", - plugin_vm::IsPluginVmEnabled(profile)); + plugin_vm::IsPluginVmAllowedForProfile(profile)); html_source->AddBoolean("isDemoSession", chromeos::DemoSession::IsDeviceInDemoMode());
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h index e164181c..5f0319ca 100644 --- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
@@ -18,7 +18,11 @@ namespace content { class WebUIDataSource; class WebUIMessageHandler; -} +} // namespace content + +namespace user_prefs { +class PrefRegistrySyncable; +} // namespace user_prefs namespace chromeos { namespace settings { @@ -26,6 +30,8 @@ // The WebUI handler for chrome://os-settings. class OSSettingsUI : public ui::MojoWebUIController { public: + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + explicit OSSettingsUI(content::WebUI* web_ui); ~OSSettingsUI() override;
diff --git a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc index 5c0caed..db5d9d7 100644 --- a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/chromeos/guest_os/guest_os_share_path.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager.h" +#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_thread.h" @@ -37,6 +38,10 @@ "removePluginVm", base::BindRepeating(&PluginVmHandler::HandleRemovePluginVm, weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "requestPluginVmInstallerView", + base::BindRepeating(&PluginVmHandler::HandleRequestPluginVmInstallerView, + weak_ptr_factory_.GetWeakPtr())); } void PluginVmHandler::HandleGetPluginVmSharedPathsDisplayText( @@ -84,5 +89,17 @@ manager->UninstallPluginVm(); } +void PluginVmHandler::HandleRequestPluginVmInstallerView( + const base::ListValue* args) { + CHECK(args->empty()); + + if (plugin_vm::IsPluginVmEnabled(profile_)) { + LOG(ERROR) << "requestPluginVmInstallerView called from a profile which " + "already has Plugin VM installed."; + return; + } + plugin_vm::ShowPluginVmInstallerView(profile_); +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h index 87144e8..b003a9e3 100644 --- a/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h
@@ -34,6 +34,8 @@ void HandleRemovePluginVmSharedPath(const base::ListValue* args); // Remove Plugin VM. void HandleRemovePluginVm(const base::ListValue* args); + // Show the Plugin VM installer view if Plugin VM is not currently installed. + void HandleRequestPluginVmInstallerView(const base::ListValue* args); Profile* profile_; // weak_ptr_factory_ should always be last member.
diff --git a/chrome/browser/ui/webui/settings/chromeos/pref_names.cc b/chrome/browser/ui/webui/settings/chromeos/pref_names.cc new file mode 100644 index 0000000..c36221f --- /dev/null +++ b/chrome/browser/ui/webui/settings/chromeos/pref_names.cc
@@ -0,0 +1,20 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h" + +namespace chromeos { +namespace settings { +namespace prefs { + +// Boolean specifying whether OS wallpaper sync is enabled. This is stored +// separately from the other OS sync preferences because it's an edge case; +// wallpaper does not have its own ModelType, so it cannot be part of +// UserSelectableOsType like the other OS sync types. +// TODO(https://crbug.com/967987): Break this dependency. +const char kSyncOsWallpaper[] = "sync.os_wallpaper"; + +} // namespace prefs +} // namespace settings +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/pref_names.h b/chrome/browser/ui/webui/settings/chromeos/pref_names.h new file mode 100644 index 0000000..df2e7dce --- /dev/null +++ b/chrome/browser/ui/webui/settings/chromeos/pref_names.h
@@ -0,0 +1,18 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PREF_NAMES_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PREF_NAMES_H_ + +namespace chromeos { +namespace settings { +namespace prefs { + +extern const char kSyncOsWallpaper[]; + +} // namespace prefs +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PREF_NAMES_H_
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 47b1bb19..9045375 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -355,6 +355,8 @@ IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_REMOVE}, {"crostiniSharedPathsRemoveSharing", IDS_SETTINGS_CROSTINI_SHARED_PATHS_REMOVE_SHARING}, + {"crostiniSharedPathsListEmptyMessage", + IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_EMPTY_MESSAGE}, {"crostiniExportImportTitle", IDS_SETTINGS_CROSTINI_EXPORT_IMPORT_TITLE}, {"crostiniExport", IDS_SETTINGS_CROSTINI_EXPORT}, {"crostiniExportLabel", IDS_SETTINGS_CROSTINI_EXPORT_LABEL}, @@ -442,6 +444,7 @@ {"pluginVmPageTitle", IDS_SETTINGS_PLUGIN_VM_PAGE_TITLE}, {"pluginVmPageLabel", IDS_SETTINGS_PLUGIN_VM_PAGE_LABEL}, {"pluginVmPageSubtext", IDS_SETTINGS_PLUGIN_VM_PAGE_SUBTEXT}, + {"pluginVmPageEnable", IDS_SETTINGS_TURN_ON}, {"pluginVmPrinterAccess", IDS_SETTINGS_PLUGIN_VM_PRINTER_ACCESS}, {"pluginVmSharedPaths", IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS}, {"pluginVmSharedPathsListHeading",
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc index 78d3bf76..2e80412 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
@@ -478,10 +478,13 @@ embedder_->GetThemeProvider()->GetColor(ThemeProperties::COLOR_FRAME)); const tab_groups::TabGroupColor tab_group_color = tab_groups::GetTabGroupColorSet().at(visual_data->color()); + const SkColor group_color = is_dark_frame ? tab_group_color.dark_theme_color + : tab_group_color.light_theme_color; + visual_data_dict.SetString("color", + color_utils::SkColorToRgbString(group_color)); visual_data_dict.SetString( - "color", color_utils::SkColorToRgbaString( - is_dark_frame ? tab_group_color.dark_theme_color - : tab_group_color.light_theme_color)); + "textColor", color_utils::SkColorToRgbString( + color_utils::GetColorWithMaxContrast(group_color))); return visual_data_dict; }
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc index 4a0dd10..ba1f496 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
@@ -79,9 +79,9 @@ std::string group_color; ASSERT_TRUE(visual_data_dict->GetString("color", &group_color)); - EXPECT_EQ(color_utils::SkColorToRgbaString(tab_groups::GetTabGroupColorSet() - .at(visual_data.color()) - .light_theme_color), + EXPECT_EQ(color_utils::SkColorToRgbString(tab_groups::GetTabGroupColorSet() + .at(visual_data.color()) + .light_theme_color), group_color); }
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc index a60fc10..17bf131 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc
@@ -42,12 +42,16 @@ layout.tab_title_height); } + layout.tab_thumbnail_aspect_ratio = + layout.tab_thumbnail_size.width() / + static_cast<double>(layout.tab_thumbnail_size.height()); + return layout; } base::Value TabStripUILayout::AsDictionary() const { base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("--tabstrip-tab-list-padding", + dict.SetStringKey("--tabstrip-tab-list-vertical-padding", base::NumberToString(padding_around_tab_list) + "px"); dict.SetStringKey("--tabstrip-tab-title-height", base::NumberToString(tab_title_height) + "px"); @@ -55,6 +59,8 @@ base::NumberToString(tab_thumbnail_size.width()) + "px"); dict.SetStringKey("--tabstrip-tab-thumbnail-height", base::NumberToString(tab_thumbnail_size.height()) + "px"); + dict.SetStringKey("--tabstrip-tab-thumbnail-aspect-ratio", + base::NumberToString(tab_thumbnail_aspect_ratio)); dict.SetStringKey("--tabstrip-viewport-width", base::NumberToString(viewport_width) + "px"); return dict;
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h index 549932d..261aded 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h
@@ -26,6 +26,7 @@ int tab_title_height; int viewport_width; gfx::Size tab_thumbnail_size; + double tab_thumbnail_aspect_ratio; }; #endif // CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_LAYOUT_H_
diff --git a/chrome/browser/web_applications/components/web_app_file_handler_registration_win.cc b/chrome/browser/web_applications/components/web_app_file_handler_registration_win.cc index 8964580..081ce0d 100644 --- a/chrome/browser/web_applications/components/web_app_file_handler_registration_win.cc +++ b/chrome/browser/web_applications/components/web_app_file_handler_registration_win.cc
@@ -32,29 +32,31 @@ // Returns the app-specific-launcher filename to be used for |app_name|. base::FilePath GetAppSpecificLauncherFilename(const base::string16& app_name) { // Remove any characters that are illegal in Windows filenames. - base::FilePath sanitized_app_name = - web_app::internals::GetSanitizedFileName(app_name); + base::string16 sanitized_app_name = + web_app::internals::GetSanitizedFileName(app_name).value(); - // If |sanitized_app_name| is a reserved filename, append '_' to allow its use - // as the launcher filename (e.g. "nul" => "nul_"). If |sanitized_app_name| - // starts with a reserved filename followed by '.', replace all '.' characters - // with '_' (e.g. "nul.l" => "nul_l"). This is needed because anything after - // '.' is interpreted as part of a file extension for the purpose of - // identifying reserved filenames, so appending '_' fails to legitimize a - // reserved filename when a '.' is present (e.g. "nul.l_" is rejected). - if (net::IsReservedNameOnWindows(sanitized_app_name.value())) { - base::string16 allowed_filename = sanitized_app_name.value(); - if (!base::ReplaceChars(allowed_filename, L".", L"_", &allowed_filename)) - allowed_filename.append(L"_"); - sanitized_app_name = base::FilePath(allowed_filename); - } + // On Windows 7, where the launcher has no file extension, replace any '.' + // characters with '_' to prevent a portion of the filename from being + // interpreted as its extension. + const bool is_win_7 = base::win::GetVersion() == base::win::Version::WIN7; + if (is_win_7) + base::ReplaceChars(sanitized_app_name, L".", L"_", &sanitized_app_name); - // On Windows 8+, add .exe extension. On Windows 7, where the launcher - // filename is used as the app's display name in the Open With menu, omit the - // extension. - if (base::win::GetVersion() > base::win::Version::WIN7) - return sanitized_app_name.AddExtension(L"exe"); - return sanitized_app_name; + // If |sanitized_app_name| is a reserved filename, prepend '_' to allow its + // use as the launcher filename (e.g. "nul" => "_nul"). Prepending is + // preferred over appending in order to handle filenames containing '.', as + // Windows' logic for checking reserved filenames views characters after '.' + // as file extensions, and only the pre-file-extension portion is checked for + // legitimacy (e.g. "nul_" is allowed, but "nul.a_" is not). + if (net::IsReservedNameOnWindows(sanitized_app_name)) + sanitized_app_name = L"_" + sanitized_app_name; + + // On Windows 8+, add .exe extension. On Windows 7, where an app's display + // name in the Open With menu can't be set programmatically, omit the + // extension to use the launcher filename as the app's display name. + if (!is_win_7) + return base::FilePath(sanitized_app_name).AddExtension(L"exe"); + return base::FilePath(sanitized_app_name); } } // namespace
diff --git a/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc b/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc index 97d3b9a..632acd72 100644 --- a/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc
@@ -215,8 +215,8 @@ CreateDataDirectoryAndGetLauncherPathForApp(profile(), app_id, "app_name"); - RegisterFileHandlersWithOs(app_id, app_name, profile(), - /*file_extensions*/ {"txt"}, /*mime_types=*/{}); + RegisterFileHandlersWithOs(app_id, app_name, profile(), file_extensions, + /*mime_types=*/{}); base::ThreadPoolInstance::Get()->FlushForTesting(); base::FilePath registered_app_path = ShellUtil::GetApplicationPathForProgId( @@ -226,19 +226,19 @@ EXPECT_EQ(app_specific_launcher_path, registered_app_path); } -// Test that an app name that is a reserved filename on Windows has '_' appended -// to it when used as a filename for its launcher. +// Test that an app name that is a reserved filename on Windows has '_' +// prepended to it when used as a filename for its launcher. TEST_F(WebAppFileHandlerRegistrationWinTest, AppNameIsReservedFilename) { std::set<std::string> file_extensions({"txt"}); AppId app_id("app_id"); - // "con" is a reserved filename on Windows, so it should have '_' appended. + // "con" is a reserved filename on Windows, so it should have '_' prepended. std::string app_name("con"); base::FilePath app_specific_launcher_path = - CreateDataDirectoryAndGetLauncherPathForApp(profile(), app_id, "con_"); + CreateDataDirectoryAndGetLauncherPathForApp(profile(), app_id, "_con"); - RegisterFileHandlersWithOs(app_id, app_name, profile(), - /*file_extensions*/ {"txt"}, /*mime_types=*/{}); + RegisterFileHandlersWithOs(app_id, app_name, profile(), file_extensions, + /*mime_types=*/{}); base::ThreadPoolInstance::Get()->FlushForTesting(); base::FilePath registered_app_path = ShellUtil::GetApplicationPathForProgId( @@ -248,23 +248,22 @@ EXPECT_EQ(app_specific_launcher_path, registered_app_path); } -// Test that an app name that consists of a reserved filename on Windows plus -// '.' has all its '.' characters replaced by '_' when used as a filename for -// its launcher. -TEST_F(WebAppFileHandlerRegistrationWinTest, AppNameIsReservedFilenameWithDot) { +// Test that an app name containing '.' characters has them replaced with '_' on +// Windows 7 when used as a filename for its launcher. +TEST_F(WebAppFileHandlerRegistrationWinTest, AppNameContainsDot) { std::set<std::string> file_extensions({"txt"}); AppId app_id("app_id"); - // "con" is a reserved filename on Windows, and appending '_' won't make it - // legitimate (because any text after '.' is interpreted as part of a file - // extension), so all '.' characters should be replaced with '_'. - std::string app_name("con.nect"); + // "some.app.name" should become "some_app_name" on Windows 7. + std::string app_name("some.app.name"); base::FilePath app_specific_launcher_path = - CreateDataDirectoryAndGetLauncherPathForApp(profile(), app_id, - "con_nect"); + CreateDataDirectoryAndGetLauncherPathForApp( + profile(), app_id, + base::win::GetVersion() > base::win::Version::WIN7 ? "some.app.name" + : "some_app_name"); - RegisterFileHandlersWithOs(app_id, app_name, profile(), - /*file_extensions*/ {"txt"}, /*mime_types=*/{}); + RegisterFileHandlersWithOs(app_id, app_name, profile(), file_extensions, + /*mime_types=*/{}); base::ThreadPoolInstance::Get()->FlushForTesting(); base::FilePath registered_app_path = ShellUtil::GetApplicationPathForProgId(
diff --git a/chrome/common/extensions/docs/templates/intros/declarativeNetRequest.html b/chrome/common/extensions/docs/templates/intros/declarativeNetRequest.html index c4d3fda..4187623 100644 --- a/chrome/common/extensions/docs/templates/intros/declarativeNetRequest.html +++ b/chrome/common/extensions/docs/templates/intros/declarativeNetRequest.html
@@ -337,6 +337,7 @@ </pre> <ul> + <!--TODO(crbug.com/1038831): Add examples for allowAllRequests rules. --> <li> Consider a navigation to <code>"http://google.com"</code>. Rules with id (1) and (3) match. The request will be blocked because blocking rules have
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 67d7f6a4..829e69af 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2107,9 +2107,6 @@ "../browser/chromeos/child_accounts/parent_access_code/parent_access_test_utils.h", "../browser/chromeos/child_accounts/screen_time_controller_browsertest.cc", "../browser/chromeos/child_accounts/time_limit_test_utils.cc", - "../browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc", - "../browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.cc", - "../browser/chromeos/child_accounts/time_limits/app_time_limits_policy_builder.h", "../browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.cc", "../browser/chromeos/child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h", "../browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc", @@ -4802,8 +4799,7 @@ ] } if (use_gtk) { - sources += - [ "../browser/ui/libgtkui/select_file_dialog_impl_gtk_unittest.cc" ] + sources += [ "../browser/ui/gtk/select_file_dialog_impl_gtk_unittest.cc" ] deps += [ "//build/config/linux/gtk" ] } @@ -4824,7 +4820,7 @@ configs += [ "//build/linux:gio_config" ] } if (!is_chromeos && !use_ozone && is_linux) { - deps += [ "//chrome/browser/ui/libgtkui" ] + deps += [ "//chrome/browser/ui/gtk" ] } if (enable_service_discovery) { @@ -5563,6 +5559,9 @@ "../browser/apps/platform_apps/app_window_interactive_uitest.cc", "../browser/apps/platform_apps/app_window_interactive_uitest_base.cc", "../browser/apps/platform_apps/app_window_interactive_uitest_base.h", + "../browser/autofill/autofill_interactive_uitest.cc", + "../browser/autofill/autofill_uitest.cc", + "../browser/autofill/autofill_uitest.h", "../browser/browser_keyevents_browsertest.cc", "../browser/devtools/devtools_sanity_interactive_browsertest.cc", "../browser/extensions/api/extension_action/browser_action_interactive_test.cc", @@ -5648,16 +5647,6 @@ "ppapi/ppapi_interactive_browsertest.cc", ] - # TODO(https://crbug.com/967588): This suite of autofill tests flakily - # timeout on Windows 7. - if (!is_win) { - sources += [ - "../browser/autofill/autofill_interactive_uitest.cc", - "../browser/autofill/autofill_uitest.cc", - "../browser/autofill/autofill_uitest.h", - ] - } - if (is_win && use_aura) { sources += [ "../browser/ui/views/autofill/autofill_accessibility_win_browsertest.cc" ] } @@ -5744,6 +5733,7 @@ # Runtime dependencies data_deps = [ "//ppapi:ppapi_tests", + "//testing/buildbot/filters:interactive_ui_tests_filters", "//third_party/mesa_headers", "//ui/resources:ui_test_pak_data", ] @@ -5818,14 +5808,14 @@ "../browser/ui/views/keyboard_access_browsertest.cc", ] if (!use_ozone) { - sources += [ - "../browser/ui/libgtkui/select_file_dialog_interactive_uitest.cc", - ] + sources += + [ "../browser/ui/gtk/select_file_dialog_interactive_uitest.cc" ] deps += [ "//build/config/linux/gtk" ] } } if (!is_chromeos) { sources += [ "../browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc" ] + deps += [ "../browser/media/router:test_support" ] } if (use_aura || is_mac) { deps += [ "//ui/touch_selection" ]
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index cfe8ad3..6c8e185 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -153,6 +153,7 @@ "javatests/src/org/chromium/chrome/test/util/OverviewModeBehaviorWatcher.java", "javatests/src/org/chromium/chrome/test/util/SadTabRule.java", "javatests/src/org/chromium/chrome/test/util/TabStripUtils.java", + "javatests/src/org/chromium/chrome/test/util/ToolbarTestUtils.java", "javatests/src/org/chromium/chrome/test/util/TranslateUtil.java", "javatests/src/org/chromium/chrome/test/util/ViewUtils.java", "javatests/src/org/chromium/chrome/test/util/WaitForFocusHelper.java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ToolbarTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ToolbarTestUtils.java new file mode 100644 index 0000000..9080850 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ToolbarTestUtils.java
@@ -0,0 +1,56 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.test.util; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +import static org.hamcrest.core.AllOf.allOf; +import static org.hamcrest.core.IsNot.not; + +import androidx.annotation.IdRes; + +import org.chromium.chrome.R; + +/** + * A utility class that contains methods generic to both the top toolbar and bottom toolbar, + * and resource ids of views on the toolbar. + */ +public class ToolbarTestUtils { + // Res ids of views being tested. + public static final @IdRes int TOP_TOOLBAR = R.id.toolbar; + public static final @IdRes int TAB_SWITCHER_TOOLBAR = R.id.tab_switcher_toolbar; + public static final @IdRes int BOTTOM_TOOLBAR = R.id.bottom_toolbar; + + public static final @IdRes int TOP_TOOLBAR_MENU = R.id.menu_button_wrapper; + public static final @IdRes int TOP_TOOLBAR_HOME = R.id.home_button; + public static final @IdRes int TOP_TOOLBAR_TAB_SWITCHER = R.id.tab_switcher_button; + + public static final @IdRes int TAB_SWITCHER_TOOLBAR_MENU = R.id.menu_button_wrapper; + public static final @IdRes int TAB_SWITCHER_TOOLBAR_NEW_TAB = R.id.new_tab_button; + public static final @IdRes int TAB_SWITCHER_TOOLBAR_TAB_SWITCHER_BUTTON = + R.id.tab_switcher_mode_tab_switcher_button; + + public static final @IdRes int BOTTOM_TOOLBAR_HOME = R.id.bottom_home_button; + public static final @IdRes int BOTTOM_TOOLBAR_SEARCH = R.id.search_accelerator; + public static final @IdRes int BOTTOM_TOOLBAR_SHARE = R.id.bottom_share_button; + public static final @IdRes int BOTTOM_TOOLBAR_NEW_TAB = R.id.bottom_new_tab_button; + public static final @IdRes int BOTTOM_TOOLBAR_TAB_SWITCHER = R.id.bottom_tab_switcher_button; + + public static void checkToolbarVisibility(@IdRes int toolbarId, boolean isVisible) { + onView(withId(toolbarId)).check(matches(isVisible ? isDisplayed() : not(isDisplayed()))); + } + + public static void checkToolbarButtonVisibility( + @IdRes int toolbarId, @IdRes int buttonId, boolean isVisible) { + // We might have buttons with identical ids on both top toolbar and bottom toolbar, + // so toolbarId is required in order to get the target view correctly. + onView(allOf(withId(buttonId), isDescendantOfA(withId(toolbarId)))) + .check(matches(isVisible ? isDisplayed() : not(isDisplayed()))); + } +}
diff --git a/chrome/test/data/extensions/declarative_net_request/child_frame.html b/chrome/test/data/extensions/declarative_net_request/child_frame.html index db01dcb..ba609bd0 100644 --- a/chrome/test/data/extensions/declarative_net_request/child_frame.html +++ b/chrome/test/data/extensions/declarative_net_request/child_frame.html
@@ -1,5 +1,16 @@ <html> <head> - <script src="subresources/script.js"></script> </head> + <body> + <script type="text/javascript"> + let params = (new URL(document.location)).searchParams; + let frameId = 'none'; + if (params.has('frame')) + frameId = params.get('frame'); + + var script = document.createElement('script'); + script.src = 'subresources/script.js?frameId=' + frameId; + document.body.appendChild(script); + </script> + </body> </html>
diff --git a/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt index 710fdd7..1c5a9ee 100644 --- a/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/directional-text-runs-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/directional-text-runs-expected-win.txt b/chrome/test/data/pdf/accessibility/directional-text-runs-expected-win.txt index 35932c77..222d8c7e 100644 --- a/chrome/test/data/pdf/accessibility/directional-text-runs-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/directional-text-runs-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY
diff --git a/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt index a78adb4..b75b7b0 100644 --- a/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/hello-world-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/hello-world-expected-win.txt b/chrome/test/data/pdf/accessibility/hello-world-expected-win.txt index e162c24..8bc5c9b 100644 --- a/chrome/test/data/pdf/accessibility/hello-world-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/hello-world-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY
diff --git a/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt index 023877f..bdc3e43 100644 --- a/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/highlights-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/highlights-expected-win.txt b/chrome/test/data/pdf/accessibility/highlights-expected-win.txt index 8e292fa0..63fe49b 100644 --- a/chrome/test/data/pdf/accessibility/highlights-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/highlights-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY
diff --git a/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt index ca8c7255..e5a9bb0 100644 --- a/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/image_alt_text-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/image_alt_text-expected-win.txt b/chrome/test/data/pdf/accessibility/image_alt_text-expected-win.txt index 3743d81..2be05f7fc 100644 --- a/chrome/test/data/pdf/accessibility/image_alt_text-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/image_alt_text-expected-win.txt
@@ -1,7 +1,7 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY ++++++++ROLE_SYSTEM_GRAPHIC name='Image 1' READONLY ++++++++ROLE_SYSTEM_GRAPHIC name='Image 2' READONLY -++++++++ROLE_SYSTEM_GRAPHIC name='Image 3' READONLY \ No newline at end of file +++++++++ROLE_SYSTEM_GRAPHIC name='Image 3' READONLY
diff --git a/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt index 21bd808..288644d9 100644 --- a/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/multi-page-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 2 pages' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/multi-page-expected-win.txt b/chrome/test/data/pdf/accessibility/multi-page-expected-win.txt index cbede44..21dff1b 100644 --- a/chrome/test/data/pdf/accessibility/multi-page-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/multi-page-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 2 pages' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY
diff --git a/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt index 17a5570b..546fd00 100644 --- a/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/overlapping-links-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/overlapping-links-expected-win.txt b/chrome/test/data/pdf/accessibility/overlapping-links-expected-win.txt index 6e429e2..8e6678f 100644 --- a/chrome/test/data/pdf/accessibility/overlapping-links-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/overlapping-links-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY @@ -10,4 +10,4 @@ ++++++++ROLE_SYSTEM_LINK name='START FIRST LINK START SECOND LINK END FIRST LINK' READONLY ++++++++++ROLE_SYSTEM_STATICTEXT name='START FIRST LINK START SECOND LINK END FIRST LINK' READONLY ++++++++ROLE_SYSTEM_LINK name='START SECOND LINK END FIRST LINK END SECOND LINK' READONLY -++++++++++ROLE_SYSTEM_STATICTEXT name='START SECOND LINK END FIRST LINK END SECOND LINK' READONLY \ No newline at end of file +++++++++++ROLE_SYSTEM_STATICTEXT name='START SECOND LINK END FIRST LINK END SECOND LINK' READONLY
diff --git a/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt index 133962a..576d7f5 100644 --- a/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++heading IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-win.txt b/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-win.txt index fa6f4d3..45d423c 100644 --- a/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/paragraphs-and-heading-untagged-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_HEADING READONLY
diff --git a/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt index 2dfda340..8436f5e 100644 --- a/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/text-image-link-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 2 pages' ++++region Name='Page 1' ++++++heading IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/text-image-link-expected-win.txt b/chrome/test/data/pdf/accessibility/text-image-link-expected-win.txt index f101a958..c7b81801 100644 --- a/chrome/test/data/pdf/accessibility/text-image-link-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/text-image-link-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 2 pages' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_HEADING READONLY @@ -22,4 +22,4 @@ ++++++++ROLE_SYSTEM_GRAPHIC name='Unlabeled graphic' READONLY ++++IA2_ROLE_LANDMARK name='Page 2' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY -++++++++ROLE_SYSTEM_STATICTEXT name='Second Page' READONLY \ No newline at end of file +++++++++ROLE_SYSTEM_STATICTEXT name='Second Page' READONLY
diff --git a/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt index 56a02f5..b84f44e 100644 --- a/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-win.txt b/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-win.txt index ae02b817..6625dbb0 100644 --- a/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/text-run-style-heuristic-expected-win.txt
@@ -1,5 +1,5 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY -++++++++ROLE_SYSTEM_STATICTEXT name='Hello world! One word equals to one text run.' READONLY \ No newline at end of file +++++++++ROLE_SYSTEM_STATICTEXT name='Hello world! One word equals to one text run.' READONLY
diff --git a/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt index 51645161..3a10afc 100644 --- a/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/text-style-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/text-style-expected-win.txt b/chrome/test/data/pdf/accessibility/text-style-expected-win.txt index 91e55ca..e78a3898 100644 --- a/chrome/test/data/pdf/accessibility/text-style-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/text-style-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY @@ -8,4 +8,4 @@ ++++++IA2_ROLE_PARAGRAPH READONLY ++++++++ROLE_SYSTEM_STATICTEXT name='Case 3<newline>' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY -++++++++ROLE_SYSTEM_STATICTEXT name='Case 4' READONLY \ No newline at end of file +++++++++ROLE_SYSTEM_STATICTEXT name='Case 4' READONLY
diff --git a/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt b/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt index 311e300c..d6cae29 100644 --- a/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt +++ b/chrome/test/data/pdf/accessibility/weblinks-expected-uia-win.txt
@@ -1,4 +1,4 @@ -group +region ++document Name='PDF document containing 1 page' ++++region Name='Page 1' ++++++group IsControlElement=false
diff --git a/chrome/test/data/pdf/accessibility/weblinks-expected-win.txt b/chrome/test/data/pdf/accessibility/weblinks-expected-win.txt index 7ac0fe95..67d37be 100644 --- a/chrome/test/data/pdf/accessibility/weblinks-expected-win.txt +++ b/chrome/test/data/pdf/accessibility/weblinks-expected-win.txt
@@ -1,4 +1,4 @@ -ROLE_SYSTEM_GROUPING FOCUSABLE +IA2_ROLE_EMBEDDED_OBJECT FOCUSABLE ++ROLE_SYSTEM_DOCUMENT name='PDF document containing 1 page' READONLY FOCUSABLE ++++IA2_ROLE_LANDMARK name='Page 1' READONLY ++++++IA2_ROLE_PARAGRAPH READONLY
diff --git a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js index 1ef0660..f5fcb29 100644 --- a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
@@ -300,12 +300,14 @@ test('Sanity', function() { assertEquals( - 2, subpage.shadowRoot.querySelectorAll('.settings-box').length); + 3, subpage.shadowRoot.querySelectorAll('.settings-box').length); assertEquals(2, subpage.shadowRoot.querySelectorAll('.list-item').length); }); test('Remove', function() { assertFalse(subpage.$.crostiniInstructionsRemove.hidden); + assertFalse(subpage.$.crostiniList.hidden); + assertTrue(subpage.$.crostiniListEmpty.hidden); assertTrue(!!subpage.$$('.list-item cr-icon-button')); // Remove first shared path, still one left. subpage.$$('.list-item cr-icon-button').click(); @@ -337,8 +339,11 @@ Polymer.dom.flush(); assertEquals( 0, subpage.shadowRoot.querySelectorAll('.list-item').length); - // Verify remove instructions are hidden. + // Verify remove instructions are hidden, and empty list message + // is shown. assertTrue(subpage.$.crostiniInstructionsRemove.hidden); + assertTrue(subpage.$.crostiniList.hidden); + assertFalse(subpage.$.crostiniListEmpty.hidden); }); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/plugin_vm_page_test.js b/chrome/test/data/webui/settings/chromeos/plugin_vm_page_test.js index 93166c0..1be853f 100644 --- a/chrome/test/data/webui/settings/chromeos/plugin_vm_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/plugin_vm_page_test.js
@@ -9,6 +9,7 @@ 'getPluginVmSharedPathsDisplayText', 'removePluginVmSharedPath', 'removePluginVm', + 'requestPluginVmInstallerView', ]); } @@ -27,11 +28,87 @@ removePluginVm() { this.methodCalled('removePluginVm'); } + + /** override */ + requestPluginVmInstallerView() { + this.methodCalled('requestPluginVmInstallerView'); + } } /** @type {?TestPluginVmBrowserProxy} */ let pluginVmBrowserProxy = null; +suite('PluginVmPage', function() { + /** @type {?SettingsPluginVmElement} */ + let page = null; + + /** @type {Array<string>} */ + let routes; + /** @type {!Object} */ + let preTestSettingsRoutes; + /** @type {!function(string)} */ + let preTestRouterNavigateTo; + + setup(function() { + pluginVmBrowserProxy = new TestPluginVmBrowserProxy(); + settings.PluginVmBrowserProxyImpl.instance_ = pluginVmBrowserProxy; + PolymerTest.clearBody(); + page = document.createElement('settings-plugin-vm-page'); + + routes = []; + + preTestRouterNavigateTo = settings.Router.getInstance().navigateTo; + settings.Router.getInstance().navigateTo = (route) => routes.push(route); + + preTestSettingsRoutes = settings.routes; + settings.routes = {PLUGIN_VM_DETAILS: 'TEST_PLUGIN_VM_DETAILS_ROUTE'}; + }); + + teardown(function() { + page.remove(); + + settings.Router.getInstance().navigateTo = preTestRouterNavigateTo; + + settings.routes = preTestSettingsRoutes; + }); + + test('ImageExistsLink', function() { + page.prefs = { + plugin_vm: { + image_exists: {value: true}, + } + }; + document.body.appendChild(page); + Polymer.dom.flush(); + + const button = page.$$('cr-icon-button'); + assertTrue(!!button); + + assertDeepEquals(routes, []); + button.click(); + assertDeepEquals(routes, ['TEST_PLUGIN_VM_DETAILS_ROUTE']); + }); + + test('ImageDoesntExist', function() { + page.prefs = { + plugin_vm: { + image_exists: {value: false}, + } + }; + document.body.appendChild(page); + Polymer.dom.flush(); + + const button = page.$$('cr-button'); + assertTrue(!!button); + + assertEquals( + 0, pluginVmBrowserProxy.getCallCount('requestPluginVmInstallerView')); + button.click(); + assertEquals( + 1, pluginVmBrowserProxy.getCallCount('requestPluginVmInstallerView')); + }); +}); + suite('Details', function() { /** @type {?SettingsPluginVmSubpageElement} */ let page = null;
diff --git a/chrome/test/data/webui/tab_strip/tab_group_test.js b/chrome/test/data/webui/tab_strip/tab_group_test.js new file mode 100644 index 0000000..9f34bf4 --- /dev/null +++ b/chrome/test/data/webui/tab_strip/tab_group_test.js
@@ -0,0 +1,34 @@ +// Copyright 2020 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 'chrome://tab-strip/tab_group.js'; + +suite('TabGroup', () => { + let tabGroupElement; + + setup(() => { + document.body.innerHTML = ''; + tabGroupElement = document.createElement('tabstrip-tab-group'); + }); + + test('UpdatesVisuals', () => { + const visuals = { + color: '255, 0, 0', + textColor: '0, 0, 255', + title: 'My new title', + }; + tabGroupElement.updateVisuals(visuals); + assertEquals( + visuals.title, + tabGroupElement.shadowRoot.querySelector('#title').innerText); + assertEquals( + visuals.color, + tabGroupElement.style.getPropertyValue( + '--tabstrip-tab-group-color-rgb')); + assertEquals( + visuals.textColor, + tabGroupElement.style.getPropertyValue( + '--tabstrip-tab-group-text-color-rgb')); + }); +});
diff --git a/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js b/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js index a004d10..c25101e 100644 --- a/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js +++ b/chrome/test/data/webui/tab_strip/tab_strip_browsertest.js
@@ -75,3 +75,13 @@ TEST_F('TabStripTabSwiperTest', 'All', function() { mocha.run(); }); + +var TabStripTabGroupTest = class extends TabStripBrowserTest { + get browsePreload() { + return 'chrome://tab-strip/test_loader.html?module=tab_strip/tab_group_test.js'; + } +}; + +TEST_F('TabStripTabGroupTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index c5ece95..66ac32f 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1277,9 +1277,7 @@ // is present in the DNS cache with the NetworkIsolationKey associated with the // foreground WebContents - this is needed so as not to leak what hostnames were // looked up across tabs with different first party origins. -void CheckTestHostNameUsedWithCorrectNetworkIsolationKey( - Browser* browser, - bool include_canonical_name) { +void CheckTestHostNameUsedWithCorrectNetworkIsolationKey(Browser* browser) { network::mojom::NetworkContext* network_context = content::BrowserContext::GetDefaultStoragePartition(browser->profile()) ->GetNetworkContext(); @@ -1291,7 +1289,7 @@ // Cache only lookup. params->source = net::HostResolverSource::LOCAL_ONLY; // Match the parameters used by the test. - params->include_canonical_name = include_canonical_name; + params->include_canonical_name = true; net::NetworkIsolationKey network_isolation_key = browser->tab_strip_model() ->GetActiveWebContents() @@ -1323,8 +1321,7 @@ #define RUN_HOST_RESOLVER_SUBTESTS \ RunTestViaHTTP(LIST_TEST(HostResolver_Empty) LIST_TEST(HostResolver_Resolve) \ LIST_TEST(HostResolver_ResolveIPv4)); \ - CheckTestHostNameUsedWithCorrectNetworkIsolationKey( \ - browser(), true /* include_canonical_name */) + CheckTestHostNameUsedWithCorrectNetworkIsolationKey(browser()) IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, HostResolverCrash_Basic) { if (content::IsInProcessNetworkService()) @@ -2169,33 +2166,7 @@ TEST_PPAPI_NACL(MouseCursor) -// Proxy configuration test. The PPAPI code used by these tests is in -// ppapi/tests/test_network_proxy.cc. - -IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, NetworkProxy) { - RunTestViaHTTP(STRIP_PREFIXES(NetworkProxy)); - CheckTestHostNameUsedWithCorrectNetworkIsolationKey( - browser(), false /* include_canonical_name */); -} - -IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, NetworkProxy) { - RunTestViaHTTP(STRIP_PREFIXES(NetworkProxy)); - CheckTestHostNameUsedWithCorrectNetworkIsolationKey( - browser(), false /* include_canonical_name */); -} - -IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, MAYBE_PPAPI_NACL(NetworkProxy)) { - RunTestViaHTTP(STRIP_PREFIXES(NetworkProxy)); - CheckTestHostNameUsedWithCorrectNetworkIsolationKey( - browser(), false /* include_canonical_name */); -} - -IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClNonSfiTest, - MAYBE_PNACL_NONSFI(NetworkProxy)) { - RunTestViaHTTP(STRIP_PREFIXES(NetworkProxy)); - CheckTestHostNameUsedWithCorrectNetworkIsolationKey( - browser(), false /* include_canonical_name */); -} +TEST_PPAPI_NACL(NetworkProxy) // TODO(crbug.com/619765): get working on CrOS build. #if defined(OS_CHROMEOS)
diff --git a/chrome/test/ppapi/ppapi_test.cc b/chrome/test/ppapi/ppapi_test.cc index 54086ea..fdf7dcf 100644 --- a/chrome/test/ppapi/ppapi_test.cc +++ b/chrome/test/ppapi/ppapi_test.cc
@@ -160,24 +160,9 @@ // Smooth scrolling confuses the scrollbar test. command_line->AppendSwitch(switches::kDisableSmoothScrolling); - - // For a particular host name, resolve another specific host name (which - // should then be added to the DNS cache), and then return a particular proxy. - // Otherwise, return DIRECT. - command_line->AppendSwitchASCII(switches::kProxyPacUrl, - "data:," - "function FindProxyForURL(url, host) {" - " if (host == 'use.proxy.test') {" - " dnsResolveEx('host_resolver.test');" - " return 'PROXY proxy.test';" - " }" - " return 'DIRECT'" - "}"); } void PPAPITestBase::SetUpOnMainThread() { - host_resolver()->AddRule("host_resolver.test", - embedded_test_server()->host_port_pair().host()); host_resolver()->AddRuleWithFlags( "host_resolver.test", embedded_test_server()->host_port_pair().host(), net::HOST_RESOLVER_CANONNAME);
diff --git a/chromeos/components/quick_answers/search_result_parsers/translation_result_parser.cc b/chromeos/components/quick_answers/search_result_parsers/translation_result_parser.cc index 0b52210..f9ae04ce 100644 --- a/chromeos/components/quick_answers/search_result_parsers/translation_result_parser.cc +++ b/chromeos/components/quick_answers/search_result_parsers/translation_result_parser.cc
@@ -19,9 +19,7 @@ constexpr char kSourceLanguageLocalizedNamePath[] = "translateResult.sourceTextLanguageLocalizedName"; constexpr char kTranslatedTextPath[] = "translateResult.translatedText"; -// TODO(llin): The language localized name might contains bracket, for example -// Chinese (Traditional). Update the template after UX is finalized. -constexpr char kSourceTextTemplate[] = "%s (%s)"; +constexpr char kSourceTextTemplate[] = "%s · %s"; } // namespace
diff --git a/chromeos/components/quick_answers/search_result_parsers/translation_result_parser_unittest.cc b/chromeos/components/quick_answers/search_result_parsers/translation_result_parser_unittest.cc index f7e679a..3035158 100644 --- a/chromeos/components/quick_answers/search_result_parsers/translation_result_parser_unittest.cc +++ b/chromeos/components/quick_answers/search_result_parsers/translation_result_parser_unittest.cc
@@ -43,7 +43,7 @@ EXPECT_TRUE(parser_->Parse(&result, &quick_answer)); EXPECT_EQ(ResultType::kTranslationResult, quick_answer.result_type); EXPECT_EQ("ox\\xC3\\xADgeno", quick_answer.primary_answer); - EXPECT_EQ("oxygen (English)", quick_answer.secondary_answer); + EXPECT_EQ("oxygen · English", quick_answer.secondary_answer); } TEST_F(TranslationResultParserTest, MissingSourceText) {
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index 32f3a60..97d37de22 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -122,10 +122,6 @@ const base::Feature kEduCoexistence{"EduCoexistence", base::FEATURE_DISABLED_BY_DEFAULT}; -// If enabled shows the visual signals feedback panel. -const base::Feature kEnableFileManagerFeedbackPanel{ - "EnableFeedbackPanel", base::FEATURE_ENABLED_BY_DEFAULT}; - // Enables Device End Of Lifetime warning notifications. const base::Feature kEolWarningNotifications{"EolWarningNotifications", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index c4177fe..3090ce6 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -65,8 +65,6 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kEduCoexistence; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) -extern const base::Feature kEnableFileManagerFeedbackPanel; -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kExoPointerLock; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kFilesNG; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kMojoDBusRelay;
diff --git a/chromeos/dbus/permission_broker/fake_permission_broker_client.cc b/chromeos/dbus/permission_broker/fake_permission_broker_client.cc index f481699..225127d4 100644 --- a/chromeos/dbus/permission_broker/fake_permission_broker_client.cc +++ b/chromeos/dbus/permission_broker/fake_permission_broker_client.cc
@@ -135,6 +135,20 @@ return udp_hole_set_.find(rule) != udp_hole_set_.end(); } +bool FakePermissionBrokerClient::HasTcpPortForward( + uint16_t port, + const std::string& interface) { + auto rule = std::make_pair(port, interface); + return tcp_forwarding_set_.find(rule) != tcp_forwarding_set_.end(); +} + +bool FakePermissionBrokerClient::HasUdpPortForward( + uint16_t port, + const std::string& interface) { + auto rule = std::make_pair(port, interface); + return udp_forwarding_set_.find(rule) != udp_forwarding_set_.end(); +} + void FakePermissionBrokerClient::RequestTcpPortForward( uint16_t in_port, const std::string& in_interface, @@ -142,7 +156,10 @@ uint16_t dst_port, int lifeline_fd, ResultCallback callback) { - std::move(callback).Run(false); + // TODO(matterchen): Increase logic for adding duplicate ports. + auto rule = std::make_pair(in_port, in_interface); + tcp_forwarding_set_.insert(rule); + std::move(callback).Run(true); } void FakePermissionBrokerClient::RequestUdpPortForward( @@ -152,7 +169,9 @@ uint16_t dst_port, int lifeline_fd, ResultCallback callback) { - std::move(callback).Run(false); + auto rule = std::make_pair(in_port, in_interface); + udp_forwarding_set_.insert(rule); + std::move(callback).Run(true); } void FakePermissionBrokerClient::ReleaseTcpPortForward(
diff --git a/chromeos/dbus/permission_broker/fake_permission_broker_client.h b/chromeos/dbus/permission_broker/fake_permission_broker_client.h index 2b732df..722ddb0 100644 --- a/chromeos/dbus/permission_broker/fake_permission_broker_client.h +++ b/chromeos/dbus/permission_broker/fake_permission_broker_client.h
@@ -76,6 +76,12 @@ // Returns true if UDP port has a hole. bool HasUdpHole(uint16_t port, const std::string& interface); + // Returns true if TCP port is being forwarded. + bool HasTcpPortForward(uint16_t port, const std::string& interface); + + // Returns true if UDP port is being forwarded. + bool HasUdpPortForward(uint16_t port, const std::string& interface); + private: using RuleSet = std::set<std::pair<uint16_t /* port */, std::string /* interface */>>; @@ -88,6 +94,9 @@ RuleSet tcp_hole_set_; RuleSet udp_hole_set_; + RuleSet tcp_forwarding_set_; + RuleSet udp_forwarding_set_; + RuleSet tcp_deny_rule_set_; RuleSet udp_deny_rule_set_;
diff --git a/chromeos/dbus/shill/fake_shill_service_client.cc b/chromeos/dbus/shill/fake_shill_service_client.cc index eed2205..8daf6c8d 100644 --- a/chromeos/dbus/shill/fake_shill_service_client.cc +++ b/chromeos/dbus/shill/fake_shill_service_client.cc
@@ -373,6 +373,25 @@ call_status, base::Owned(result_properties.release()))); } +void FakeShillServiceClient::GetWiFiPassphrase( + const dbus::ObjectPath& service_path, + StringCallback callback, + ErrorCallback error_callback) { + base::DictionaryValue* service_properties = + GetModifiableServiceProperties(service_path.value(), false); + if (!service_properties) { + LOG(ERROR) << "Service not found: " << service_path.value(); + std::move(error_callback).Run("Error.InvalidService", "Invalid Service"); + return; + } + + std::string passphrase; + service_properties->GetStringWithoutPathExpansion(shill::kPassphraseProperty, + &passphrase); + + std::move(callback).Run(passphrase); +} + ShillServiceClient::TestInterface* FakeShillServiceClient::GetTestInterface() { return this; }
diff --git a/chromeos/dbus/shill/fake_shill_service_client.h b/chromeos/dbus/shill/fake_shill_service_client.h index d954d1a..f62e7fc 100644 --- a/chromeos/dbus/shill/fake_shill_service_client.h +++ b/chromeos/dbus/shill/fake_shill_service_client.h
@@ -71,6 +71,9 @@ ErrorCallback error_callback) override; void GetLoadableProfileEntries(const dbus::ObjectPath& service_path, DictionaryValueCallback callback) override; + void GetWiFiPassphrase(const dbus::ObjectPath& service_path, + StringCallback callback, + ErrorCallback error_callback) override; ShillServiceClient::TestInterface* GetTestInterface() override; // ShillServiceClient::TestInterface overrides.
diff --git a/chromeos/dbus/shill/shill_service_client.cc b/chromeos/dbus/shill/shill_service_client.cc index 8a6cfdc..f9f658d 100644 --- a/chromeos/dbus/shill/shill_service_client.cc +++ b/chromeos/dbus/shill/shill_service_client.cc
@@ -219,6 +219,17 @@ service_path, callback_adapted)); } + void GetWiFiPassphrase(const dbus::ObjectPath& service_path, + StringCallback callback, + ErrorCallback error_callback) override { + dbus::MethodCall method_call(shill::kFlimflamServiceInterface, + shill::kGetWiFiPassphraseFunction); + + GetHelper(service_path) + ->CallStringMethodWithErrorCallback(&method_call, std::move(callback), + std::move(error_callback)); + } + ShillServiceClient::TestInterface* GetTestInterface() override { return nullptr; }
diff --git a/chromeos/dbus/shill/shill_service_client.h b/chromeos/dbus/shill/shill_service_client.h index 5502dd71..6a34068 100644 --- a/chromeos/dbus/shill/shill_service_client.h +++ b/chromeos/dbus/shill/shill_service_client.h
@@ -34,6 +34,7 @@ typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback; typedef ShillClientHelper::ListValueCallback ListValueCallback; typedef ShillClientHelper::ErrorCallback ErrorCallback; + typedef ShillClientHelper::StringCallback StringCallback; // Interface for setting up services for testing. Accessed through // GetTestInterface(), only implemented in the stub implementation. @@ -203,6 +204,11 @@ virtual void GetLoadableProfileEntries(const dbus::ObjectPath& service_path, DictionaryValueCallback callback) = 0; + // Retrieves the saved passphrase for the given network. + virtual void GetWiFiPassphrase(const dbus::ObjectPath& service_path, + StringCallback callback, + ErrorCallback error_callback) = 0; + // Returns an interface for testing (stub only), or returns null. virtual TestInterface* GetTestInterface() = 0;
diff --git a/chromeos/dbus/shill/shill_service_client_unittest.cc b/chromeos/dbus/shill/shill_service_client_unittest.cc index 5df8d5c..b910b98 100644 --- a/chromeos/dbus/shill/shill_service_client_unittest.cc +++ b/chromeos/dbus/shill/shill_service_client_unittest.cc
@@ -290,4 +290,27 @@ base::RunLoop().RunUntilIdle(); } +TEST_F(ShillServiceClientTest, GetWiFiPassphrase) { + const char kPassphrase[] = "passphrase"; + + // Create response. + std::unique_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); + dbus::MessageWriter writer(response.get()); + writer.AppendString(kPassphrase); + + // Set expectations. + PrepareForMethodCall(shill::kGetWiFiPassphraseFunction, + base::BindRepeating(&ExpectNoArgument), response.get()); + // Call method. + base::MockCallback<base::OnceCallback<void(const std::string&)>> mock_closure; + base::MockCallback<ShillServiceClient::ErrorCallback> mock_error_callback; + client_->GetWiFiPassphrase(dbus::ObjectPath(kExampleServicePath), + mock_closure.Get(), mock_error_callback.Get()); + EXPECT_CALL(mock_closure, Run(kPassphrase)).Times(1); + EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0); + + // Run the message loop. + base::RunLoop().RunUntilIdle(); +} + } // namespace chromeos
diff --git a/components/dom_distiller/core/html/dom_distiller_viewer.html b/components/dom_distiller/core/html/dom_distiller_viewer.html index 8d168564..ddd6e0b 100644 --- a/components/dom_distiller/core/html/dom_distiller_viewer.html +++ b/components/dom_distiller/core/html/dom_distiller_viewer.html
@@ -20,13 +20,13 @@ <div id="main-content"> <div id="settings-container" class="desktop-only"> <button id="settings-toggle" type="button" - aria-label="Adjust appearance settings" tabindex=0> + aria-label="Customize appearance" tabindex=0> <i class="material-icons">text_format</i> </button> <dialog id="settings-dialog"> <div id="settings-header"> - <h2>Reader Mode Styling</h2> - <button id="close-settings-button" type="button" aria-label="Close settings" + <h2>Customize appearance</h2> + <button id="close-settings-button" type="button" aria-label="Close" tabindex=0> <i class="material-icons">close</i> </button> @@ -34,23 +34,23 @@ <div id="settings-fields"> <div class="setting"> <label id="font-family-label" class="screen-reader-only"> - Font Style + Font style </label> <select id="font-family-selection" aria-labelledby="font-family-label" name="font-family"> - <option value="sans-serif" selected>Sans-serif font</option> - <option value="serif">Serif font</option> - <option value="monospace">Monospace font</option> + <option value="sans-serif" selected>sans-serif font</option> + <option value="serif">serif font</option> + <option value="monospace">monospace font</option> </select> </div> <div class="setting"> <fieldset id="theme-selection"> <legend class="screen-reader-only"> - Page Theme + Page Color </legend> <ul> <li class="theme-option"> <label id="theme-option-light-label" class="screen-reader-only"> - Light + light </label> <input type="radio" name="theme" value="light" aria-labelledby="theme-option-light-label" @@ -59,7 +59,7 @@ </li> <li class="theme-option"> <label id="theme-option-sepia-label" class="screen-reader-only"> - Sepia + sepia </label> <input type="radio" name="theme" value="sepia" aria-labelledby="theme-option-sepia-label" @@ -68,7 +68,7 @@ </li> <li class="theme-option"> <label id="theme-option-dark-label" class="screen-reader-only"> - Dark + dark </label> <input type="radio" name="theme" value="dark" aria-labelledby="theme-option-dark-label"
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc index a8d4996..1ae6a3c 100644 --- a/components/error_page/common/localized_error.cc +++ b/components/error_page/common/localized_error.cc
@@ -45,8 +45,6 @@ static const char kRedirectLoopLearnMoreUrl[] = "https://support.google.com/chrome?p=rl_error"; -static const char kWeakDHKeyLearnMoreUrl[] = - "https://support.google.com/chrome?p=dh_error"; static const int kGoogleCachedCopySuggestionType = 0; enum NAV_SUGGESTIONS { @@ -260,12 +258,6 @@ SUGGEST_CHECK_CONNECTION | SUGGEST_FIREWALL_CONFIG | SUGGEST_PROXY_CONFIG, SHOW_BUTTON_RELOAD, }, - {net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY, - IDS_ERRORPAGES_HEADING_INSECURE_CONNECTION, - IDS_ERRORPAGES_SUMMARY_SSL_SECURITY_ERROR, - SUGGEST_LEARNMORE, - SHOW_NO_BUTTONS, - }, {net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN, IDS_ERRORPAGES_HEADING_INSECURE_CONNECTION, IDS_CERT_ERROR_SUMMARY_PINNING_FAILURE_DETAILS, @@ -592,9 +584,6 @@ l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_LEARNMORE_SUMMARY); switch (error_code) { - case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: - learn_more_url = GURL(kWeakDHKeyLearnMoreUrl); - break; case net::ERR_TOO_MANY_REDIRECTS: learn_more_url = GURL(kRedirectLoopLearnMoreUrl); suggestion_string = l10n_util::GetStringUTF16(
diff --git a/components/feed/tools/mockserver_textpb_to_binary.py b/components/feed/tools/mockserver_textpb_to_binary.py new file mode 100755 index 0000000..445ea2de --- /dev/null +++ b/components/feed/tools/mockserver_textpb_to_binary.py
@@ -0,0 +1,78 @@ +#!/usr/bin/python3 +# Copyright 2020 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. + +# Lint as: python3 +"""The tool converts a textpb into a binary proto using chromium protoc binary. + +After converting a feed response textpb file into a mockserver textpb file using +the proto_convertor script, then a engineer runs this script to encode the +mockserver textpb file into a binary proto file that is being used by the feed +card render test (Refers to go/create-a-feed-card-render-test for more). + +Make sure you have absl-py installed via pip install absl-py. + +Usage example: + python ./mockserver_textpb_to_binary.py + --chromium_path ~/chromium/src + --output_file /tmp/binary.pb + --source_file ~/tmp/original.textpb + --alsologtostderr +""" + +import glob +import os +import subprocess + +from absl import app +from absl import flags + +FLAGS = flags.FLAGS +FLAGS = flags.FLAGS +flags.DEFINE_string('chromium_path', '', 'The path of your chromium depot.') +flags.DEFINE_string('output_file', '', 'The target output binary file path.') +flags.DEFINE_string('source_file', '', + 'The source proto file, in textpb format, path.') + +CMD_TEMPLATE = r'cat {} | {} --encode={} -I{} -I$(find {} -name "*.proto") > {}' +ENCODE_NAMESPACE = 'components.feed.core.proto.wire.mockserver.MockServer' +COMPONENT_FEED_PROTO_PATH = 'components/feed/core/proto' +_protoc_path = None + + +def protoc_path(root_dir): + """Returns the path to the proto compiler, protoc.""" + global _protoc_path + if not _protoc_path: + protoc_list = list( + glob.glob(os.path.join(root_dir, "out") + "/*/protoc")) + list( + glob.glob(os.path.join(root_dir, "out") + "/*/*/protoc")) + if not len(protoc_list): + print("Can't find a suitable build output directory", + "(it should have protoc)") + sys.exit(1) + _protoc_path = protoc_list[0] + return _protoc_path + + +def main(argv): + if len(argv) > 1: + raise app.UsageError('Too many command-line arguments.') + if not FLAGS.chromium_path: + raise app.UsageError('chromium_path flag must be set.') + if not FLAGS.source_file: + raise app.UsageError('source_file flag must be set.') + if not FLAGS.output_file: + raise app.UsageError('output_file flag must be set.') + + protoc_cmd = CMD_TEMPLATE.format( + FLAGS.source_file, protoc_path(FLAGS.chromium_path), ENCODE_NAMESPACE, + FLAGS.chromium_path, + os.path.join(FLAGS.chromium_path, + COMPONENT_FEED_PROTO_PATH), FLAGS.output_file) + subprocess.call(protoc_cmd, shell=True) + + +if __name__ == '__main__': + app.run(main)
diff --git a/components/media_message_center/media_notification_view_impl.cc b/components/media_message_center/media_notification_view_impl.cc index a88d333..d0c7abe6c 100644 --- a/components/media_message_center/media_notification_view_impl.cc +++ b/components/media_message_center/media_notification_view_impl.cc
@@ -394,6 +394,10 @@ return header_row_; } +base::string16 MediaNotificationViewImpl::GetSourceTitleForTesting() const { + return header_row_->app_name_for_testing(); +} + void MediaNotificationViewImpl::UpdateActionButtonsVisibility() { base::flat_set<MediaSessionAction> ignored_actions = { GetPlayPauseIgnoredAction(GetActionFromButtonTag(*play_pause_button_))};
diff --git a/components/media_message_center/media_notification_view_impl.h b/components/media_message_center/media_notification_view_impl.h index e433515f..18f5455a 100644 --- a/components/media_message_center/media_notification_view_impl.h +++ b/components/media_message_center/media_notification_view_impl.h
@@ -85,6 +85,7 @@ const views::Label* artist_label_for_testing() const { return artist_label_; } views::Button* GetHeaderRowForTesting() const; + base::string16 GetSourceTitleForTesting() const; private: friend class MediaNotificationViewImplTest;
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index 72329942..f59a0c5 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -326,4 +326,9 @@ const base::Feature kOmniboxLooseMaxLimitOnDedicatedRows{ "OmniboxLooseMaxLimitOnDedicatedRows", base::FEATURE_DISABLED_BY_DEFAULT}; +// When enabled, use Assistant for omnibox voice query recognition instead of +// Android's built-in voice recognition service. Only works on Android. +const base::Feature kOmniboxAssistantVoiceSearch{ + "OmniboxAssistantVoiceSearch", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace omnibox
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h index c5425386..82dd82bb 100644 --- a/components/omnibox/common/omnibox_features.h +++ b/components/omnibox/common/omnibox_features.h
@@ -71,6 +71,10 @@ // TODO(krb): Move more flags here. extern const base::Feature kOmniboxLooseMaxLimitOnDedicatedRows; +// Omnibox UI - these affect the UI or function of the location bar (not the +// popup). +extern const base::Feature kOmniboxAssistantVoiceSearch; + } // namespace omnibox #endif // COMPONENTS_OMNIBOX_COMMON_OMNIBOX_FEATURES_H_
diff --git a/components/optimization_guide/hints_fetcher.cc b/components/optimization_guide/hints_fetcher.cc index bb29f82f7..b998ba6 100644 --- a/components/optimization_guide/hints_fetcher.cc +++ b/components/optimization_guide/hints_fetcher.cc
@@ -250,6 +250,13 @@ return true; } +bool HintsFetcher::IsHintForHostBeingFetched(const std::string& host) const { + SEQUENCE_CHECKER(sequence_checker_); + + return std::find(hosts_fetched_.begin(), hosts_fetched_.end(), host) != + hosts_fetched_.end(); +} + void HintsFetcher::HandleResponse(const std::string& get_hints_response_data, int net_status, int response_code) { @@ -286,6 +293,7 @@ HintsFetcherRequestStatus::kSuccess); std::move(hints_fetched_callback_).Run(std::move(get_hints_response)); } else { + hosts_fetched_.clear(); RecordRequestStatusHistogram(request_context_, HintsFetcherRequestStatus::kResponseError); std::move(hints_fetched_callback_).Run(base::nullopt);
diff --git a/components/optimization_guide/hints_fetcher.h b/components/optimization_guide/hints_fetcher.h index 31118b4..79db6ec 100644 --- a/components/optimization_guide/hints_fetcher.h +++ b/components/optimization_guide/hints_fetcher.h
@@ -93,6 +93,10 @@ optimization_guide::proto::RequestContext request_context, HintsFetchedCallback hints_fetched_callback); + // Returns whether a hint for the host is currently being fetched from the + // remote Optimization Guide Service. Virtualized for testing. + virtual bool IsHintForHostBeingFetched(const std::string& host) const; + // Set |time_clock_| for testing. void SetTimeClockForTesting(const base::Clock* time_clock);
diff --git a/components/optimization_guide/hints_fetcher_unittest.cc b/components/optimization_guide/hints_fetcher_unittest.cc index 04be60d..1fa42659 100644 --- a/components/optimization_guide/hints_fetcher_unittest.cc +++ b/components/optimization_guide/hints_fetcher_unittest.cc
@@ -137,6 +137,10 @@ GetMockClock()); } + bool IsHintForHostBeingFetched(const std::string& host) { + return hints_fetcher_->IsHintForHostBeingFetched(host); + } + private: void RunUntilIdle() { task_environment_.RunUntilIdle(); @@ -288,8 +292,10 @@ std::string response_content = "not proto"; EXPECT_TRUE(FetchHints({"foo.com"}, {} /* urls */)); VerifyHasPendingFetchRequests(); + EXPECT_TRUE(IsHintForHostBeingFetched("foo.com")); EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK)); EXPECT_FALSE(hints_fetched()); + EXPECT_FALSE(IsHintForHostBeingFetched("foo.com")); // Make sure histograms are recorded correctly on bad response. histogram_tester.ExpectTotalCount( @@ -307,6 +313,7 @@ std::string response_content; EXPECT_FALSE(FetchHints({"foo.com"}, {} /* urls */)); EXPECT_FALSE(hints_fetched()); + EXPECT_FALSE(IsHintForHostBeingFetched("foo.com")); // Make sure histograms are recorded correctly on bad response. histogram_tester.ExpectTotalCount( @@ -335,8 +342,12 @@ EXPECT_TRUE(FetchHints(hosts, {} /* urls */)); VerifyHasPendingFetchRequests(); + EXPECT_TRUE(IsHintForHostBeingFetched("host1.com")); + EXPECT_TRUE(IsHintForHostBeingFetched("host2.com")); EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK)); EXPECT_TRUE(hints_fetched()); + EXPECT_FALSE(IsHintForHostBeingFetched("host1.com")); + EXPECT_FALSE(IsHintForHostBeingFetched("host2.com")); const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary( prefs::kHintsFetcherHostsSuccessfullyFetched); @@ -566,8 +577,7 @@ base::HistogramTester histogram_tester; std::string response_content; - EXPECT_FALSE(FetchHints({} /* hosts */, {} /* urls */ - )); + EXPECT_FALSE(FetchHints({} /* hosts */, {} /* urls */)); EXPECT_FALSE(hints_fetched()); histogram_tester.ExpectUniqueSample( "OptimizationGuide.HintsFetcher.GetHintsRequest.RequestStatus."
diff --git a/components/safe_browsing/core/features.cc b/components/safe_browsing/core/features.cc index 64261588..892aba8 100644 --- a/components/safe_browsing/core/features.cc +++ b/components/safe_browsing/core/features.cc
@@ -10,7 +10,6 @@ #include <vector> #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" -#include "components/safe_browsing/buildflags.h" #include "base/macros.h" #include "base/values.h" @@ -68,23 +67,13 @@ const base::Feature kSendOnFocusPing { "SafeBrowsingSendOnFocusPing", -#if BUILDFLAG(FULL_SAFE_BROWSING) base::FEATURE_ENABLED_BY_DEFAULT }; -#else - base::FEATURE_DISABLED_BY_DEFAULT -}; -#endif const base::Feature kSendPasswordReusePing { "SafeBrowsingSendPasswordReusePing", -#if BUILDFLAG(FULL_SAFE_BROWSING) base::FEATURE_ENABLED_BY_DEFAULT }; -#else - base::FEATURE_DISABLED_BY_DEFAULT -}; -#endif const base::Feature kSendSampledPingsForAllowlistDomains{ "SafeBrowsingSendSampledPingsForAllowlistDomain",
diff --git a/components/security_interstitials/core/ssl_error_options_mask.cc b/components/security_interstitials/core/ssl_error_options_mask.cc index e5ed1b84..d843c28e 100644 --- a/components/security_interstitials/core/ssl_error_options_mask.cc +++ b/components/security_interstitials/core/ssl_error_options_mask.cc
@@ -28,7 +28,6 @@ case net::ERR_CERT_CONTAINS_ERRORS: case net::ERR_CERT_REVOKED: case net::ERR_CERT_INVALID: - case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN: return true; default:
diff --git a/components/sessions/BUILD.gn b/components/sessions/BUILD.gn index f7bd778..2d8c19c 100644 --- a/components/sessions/BUILD.gn +++ b/components/sessions/BUILD.gn
@@ -161,17 +161,12 @@ "//url", ] - if (!is_android && !is_ios) { - sources += [ - "core/command_storage_manager_test_helper.cc", - "core/command_storage_manager_test_helper.h", - ] - } - if (!is_ios) { sources += [ "content/content_test_helper.cc", "content/content_test_helper.h", + "core/command_storage_manager_test_helper.cc", + "core/command_storage_manager_test_helper.h", ] deps += [ "//base/test:test_support",
diff --git a/components/sessions/core/command_storage_backend.cc b/components/sessions/core/command_storage_backend.cc index 6b808eb..bb609bf 100644 --- a/components/sessions/core/command_storage_backend.cc +++ b/components/sessions/core/command_storage_backend.cc
@@ -260,6 +260,7 @@ return; inited_ = true; + base::CreateDirectory(path_.DirName()); DoInit(); }
diff --git a/components/sessions/core/command_storage_manager.cc b/components/sessions/core/command_storage_manager.cc index 6cc5e17d..200fd0fb 100644 --- a/components/sessions/core/command_storage_manager.cc +++ b/components/sessions/core/command_storage_manager.cc
@@ -17,6 +17,32 @@ #include "components/sessions/core/command_storage_manager_delegate.h" namespace sessions { +namespace { + +// Helper used by ScheduleGetLastSessionCommands. It runs callback on TaskRunner +// thread if it's not canceled. +void RunIfNotCanceled( + const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, + CommandStorageManager::GetCommandsCallback callback, + std::vector<std::unique_ptr<SessionCommand>> commands) { + if (is_canceled.Run()) + return; + std::move(callback).Run(std::move(commands)); +} + +void PostOrRunInternalGetCommandsCallback( + base::SequencedTaskRunner* task_runner, + CommandStorageManager::GetCommandsCallback callback, + std::vector<std::unique_ptr<SessionCommand>> commands) { + if (task_runner->RunsTasksInCurrentSequence()) { + std::move(callback).Run(std::move(commands)); + } else { + task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), std::move(commands))); + } +} + +} // namespace // Delay between when a command is received, and when we save it to the // backend. @@ -75,11 +101,11 @@ void CommandStorageManager::StartSaveTimer() { // Don't start a timer when testing. if (delegate_->ShouldUseDelayedSave() && - base::ThreadTaskRunnerHandle::IsSet() && !weak_factory_.HasWeakPtrs()) { + base::ThreadTaskRunnerHandle::IsSet() && !HasPendingSave()) { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce(&CommandStorageManager::Save, - weak_factory_.GetWeakPtr()), + weak_factory_for_timer_.GetWeakPtr()), kSaveDelay); } } @@ -105,6 +131,26 @@ } } +bool CommandStorageManager::HasPendingSave() const { + return weak_factory_for_timer_.HasWeakPtrs(); +} + +base::CancelableTaskTracker::TaskId +CommandStorageManager::ScheduleGetCurrentSessionCommands( + GetCommandsCallback callback, + base::CancelableTaskTracker* tracker) { + base::CancelableTaskTracker::IsCanceledCallback is_canceled; + GetCommandsCallback backend_callback; + const base::CancelableTaskTracker::TaskId id = CreateCallbackForGetCommands( + tracker, std::move(callback), &is_canceled, &backend_callback); + + backend_task_runner()->PostNonNestableTask( + FROM_HERE, + base::BindOnce(&CommandStorageBackend::ReadCurrentSessionCommands, + backend_.get(), is_canceled, std::move(backend_callback))); + return id; +} + CommandStorageManager::CommandStorageManager( scoped_refptr<CommandStorageBackend> backend, CommandStorageManagerDelegate* delegate) @@ -120,4 +166,23 @@ base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); } +base::CancelableTaskTracker::TaskId +CommandStorageManager::CreateCallbackForGetCommands( + base::CancelableTaskTracker* tracker, + GetCommandsCallback callback, + base::CancelableTaskTracker::IsCanceledCallback* is_canceled, + GetCommandsCallback* backend_callback) { + const base::CancelableTaskTracker::TaskId id = + tracker->NewTrackedTaskId(is_canceled); + + GetCommandsCallback run_if_not_canceled = + base::BindOnce(&RunIfNotCanceled, *is_canceled, std::move(callback)); + + *backend_callback = + base::BindOnce(&PostOrRunInternalGetCommandsCallback, + base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), + std::move(run_if_not_canceled)); + return id; +} + } // namespace sessions
diff --git a/components/sessions/core/command_storage_manager.h b/components/sessions/core/command_storage_manager.h index a54bdee..f6e315fe 100644 --- a/components/sessions/core/command_storage_manager.h +++ b/components/sessions/core/command_storage_manager.h
@@ -84,6 +84,15 @@ // Passes all pending commands to the backend for saving. void Save(); + // Returns true if StartSaveTimer() has been called, but a save has not yet + // occurred. + bool HasPendingSave() const; + + // Requests the commands for the current session. + base::CancelableTaskTracker::TaskId ScheduleGetCurrentSessionCommands( + GetCommandsCallback callback, + base::CancelableTaskTracker* tracker); + protected: // Provided for subclasses. CommandStorageManager(scoped_refptr<CommandStorageBackend> backend, @@ -99,6 +108,14 @@ CommandStorageBackend* backend() { return backend_.get(); } + // Creates the necessary callbacks/taskid for using CancelableTaskTracker + // with a request for the backend to fetch session commands. + base::CancelableTaskTracker::TaskId CreateCallbackForGetCommands( + base::CancelableTaskTracker* tracker, + GetCommandsCallback callback, + base::CancelableTaskTracker::IsCanceledCallback* is_canceled, + GetCommandsCallback* backend_callback); + private: friend class CommandStorageManagerTestHelper; @@ -121,8 +138,9 @@ // all tasks *must* be processed in the order they are scheduled. scoped_refptr<base::SequencedTaskRunner> backend_task_runner_; - // Used to invoke Save. - base::WeakPtrFactory<CommandStorageManager> weak_factory_{this}; + // Used solely for saving after a delay, and not to be used for any other + // purposes. + base::WeakPtrFactory<CommandStorageManager> weak_factory_for_timer_{this}; DISALLOW_COPY_AND_ASSIGN(CommandStorageManager); };
diff --git a/components/sessions/core/snapshotting_command_storage_backend.cc b/components/sessions/core/snapshotting_command_storage_backend.cc index da2f72a4..b0f87217 100644 --- a/components/sessions/core/snapshotting_command_storage_backend.cc +++ b/components/sessions/core/snapshotting_command_storage_backend.cc
@@ -88,8 +88,6 @@ } void SnapshottingCommandStorageBackend::DoInit() { - // Create the directory for session info. - base::CreateDirectory(last_file_path_.DirName()); MoveCurrentSessionToLastSession(); }
diff --git a/components/sessions/core/snapshotting_command_storage_manager.cc b/components/sessions/core/snapshotting_command_storage_manager.cc index 94a525d..8857b980 100644 --- a/components/sessions/core/snapshotting_command_storage_manager.cc +++ b/components/sessions/core/snapshotting_command_storage_manager.cc
@@ -11,37 +11,9 @@ #include "base/memory/scoped_refptr.h" #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" #include "components/sessions/core/snapshotting_command_storage_backend.h" namespace sessions { -namespace { - -// Helper used by ScheduleGetLastSessionCommands. It runs callback on TaskRunner -// thread if it's not canceled. -void RunIfNotCanceled( - const base::CancelableTaskTracker::IsCanceledCallback& is_canceled, - SnapshottingCommandStorageManager::GetCommandsCallback callback, - std::vector<std::unique_ptr<SessionCommand>> commands) { - if (is_canceled.Run()) - return; - std::move(callback).Run(std::move(commands)); -} - -void PostOrRunInternalGetCommandsCallback( - base::SequencedTaskRunner* task_runner, - SnapshottingCommandStorageManager::GetCommandsCallback callback, - std::vector<std::unique_ptr<SessionCommand>> commands) { - if (task_runner->RunsTasksInCurrentSequence()) { - std::move(callback).Run(std::move(commands)); - } else { - task_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::move(commands))); - } -} - -} // namespace SnapshottingCommandStorageManager::SnapshottingCommandStorageManager( SessionType type, @@ -78,22 +50,15 @@ GetCommandsCallback callback, base::CancelableTaskTracker* tracker) { base::CancelableTaskTracker::IsCanceledCallback is_canceled; - base::CancelableTaskTracker::TaskId id = - tracker->NewTrackedTaskId(&is_canceled); - - GetCommandsCallback run_if_not_canceled = - base::BindOnce(&RunIfNotCanceled, is_canceled, std::move(callback)); - - GetCommandsCallback callback_runner = - base::BindOnce(&PostOrRunInternalGetCommandsCallback, - base::RetainedRef(base::ThreadTaskRunnerHandle::Get()), - std::move(run_if_not_canceled)); + GetCommandsCallback backend_callback; + const base::CancelableTaskTracker::TaskId id = CreateCallbackForGetCommands( + tracker, std::move(callback), &is_canceled, &backend_callback); backend_task_runner()->PostNonNestableTask( FROM_HERE, base::BindOnce( &SnapshottingCommandStorageBackend::ReadLastSessionCommands, - GetSnapshottingBackend(), is_canceled, std::move(callback_runner))); + GetSnapshottingBackend(), is_canceled, std::move(backend_callback))); return id; }
diff --git a/components/sync/base/pref_names.cc b/components/sync/base/pref_names.cc index 1766c75..9a77d5a 100644 --- a/components/sync/base/pref_names.cc +++ b/components/sync/base/pref_names.cc
@@ -41,13 +41,6 @@ // OS user selectable types. const char kSyncOsApps[] = "sync.os_apps"; const char kSyncOsPreferences[] = "sync.os_preferences"; - -// Boolean specifying whether OS wallpaper sync is enabled. This is stored -// separately from |kSyncOsPreferences| because it's an edge case - wallpaper -// does not have its own ModelType, so it cannot be part of UserSelectableOsType -// like the other OS sync types. -// TODO(https://crbug.com/967987): Break this dependency. -const char kSyncOsWallpaper[] = "sync.os_wallpaper"; #endif // Booleans specifying whether the user has selected to sync the following
diff --git a/components/sync/base/pref_names.h b/components/sync/base/pref_names.h index 436867a..4e40b21 100644 --- a/components/sync/base/pref_names.h +++ b/components/sync/base/pref_names.h
@@ -22,7 +22,6 @@ extern const char kSyncAllOsTypes[]; extern const char kSyncOsApps[]; extern const char kSyncOsPreferences[]; -extern const char kSyncOsWallpaper[]; #endif extern const char kSyncApps[];
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc index 32733c8..f7962ac 100644 --- a/components/sync/base/sync_prefs.cc +++ b/components/sync/base/sync_prefs.cc
@@ -291,7 +291,6 @@ for (UserSelectableOsType type : UserSelectableOsTypeSet::All()) { registry->RegisterBooleanPref(GetPrefNameForOsType(type), false); } - registry->RegisterBooleanPref(prefs::kSyncOsWallpaper, false); #endif // Internal or bookkeeping prefs.
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index f214252..5c71fd14 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -42,6 +42,11 @@ const base::Feature kVizForWebView{"VizForWebView", base::FEATURE_DISABLED_BY_DEFAULT}; +// Submit CompositorFrame from SynchronousLayerTreeFrameSink directly to viz in +// WebView. +const base::Feature kVizFrameSubmissionForWebView{ + "VizFrameSubmissionForWebView", base::FEATURE_DISABLED_BY_DEFAULT}; + // Whether we should use the real buffers corresponding to overlay candidates in // order to do a pageflip test rather than allocating test buffers. const base::Feature kUseRealBuffersForPageFlipTest{ @@ -81,6 +86,15 @@ return base::FeatureList::IsEnabled(kVizForWebView); } +bool IsUsingVizFrameSubmissionForWebView() { + if (base::FeatureList::IsEnabled(kVizFrameSubmissionForWebView)) { + DCHECK(IsUsingVizForWebView()) + << "kVizFrameSubmissionForWebView requires kVizForWebView"; + return true; + } + return false; +} + bool IsUsingPreferredIntervalForVideo() { return base::FeatureList::IsEnabled(kUsePreferredIntervalForVideo); }
diff --git a/components/viz/common/features.h b/components/viz/common/features.h index 8a4bd4c..f630066 100644 --- a/components/viz/common/features.h +++ b/components/viz/common/features.h
@@ -16,6 +16,7 @@ VIZ_COMMON_EXPORT extern const base::Feature kRecordSkPicture; VIZ_COMMON_EXPORT extern const base::Feature kDisableDeJelly; VIZ_COMMON_EXPORT extern const base::Feature kVizForWebView; +VIZ_COMMON_EXPORT extern const base::Feature kVizFrameSubmissionForWebView; VIZ_COMMON_EXPORT extern const base::Feature kUsePreferredIntervalForVideo; VIZ_COMMON_EXPORT extern const base::Feature kUseRealBuffersForPageFlipTest; @@ -24,6 +25,7 @@ VIZ_COMMON_EXPORT bool IsUsingSkiaRenderer(); VIZ_COMMON_EXPORT bool IsRecordingSkPicture(); VIZ_COMMON_EXPORT bool IsUsingVizForWebView(); +VIZ_COMMON_EXPORT bool IsUsingVizFrameSubmissionForWebView(); VIZ_COMMON_EXPORT bool IsUsingPreferredIntervalForVideo(); VIZ_COMMON_EXPORT bool ShouldUseRealBuffersForPageFlipTest();
diff --git a/components/viz/common/resources/single_release_callback.cc b/components/viz/common/resources/single_release_callback.cc index 68296b1..1c69ffb 100644 --- a/components/viz/common/resources/single_release_callback.cc +++ b/components/viz/common/resources/single_release_callback.cc
@@ -15,9 +15,7 @@ << "Use a NULL SingleReleaseCallback for an empty callback."; } -SingleReleaseCallback::~SingleReleaseCallback() { - DCHECK(callback_.is_null()) << "SingleReleaseCallback was never run."; -} +SingleReleaseCallback::~SingleReleaseCallback() = default; void SingleReleaseCallback::Run(const gpu::SyncToken& sync_token, bool is_lost) {
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index a5d69a5..691f244 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -959,6 +959,9 @@ case ax::mojom::Role::kParagraph: // No role description. break; + case ax::mojom::Role::kPluginObject: + message_id = IDS_AX_ROLE_EMBEDDED_OBJECT; + break; case ax::mojom::Role::kPopUpButton: message_id = IDS_AX_ROLE_POP_UP_BUTTON; break;
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index 85784d0..ac9c02b7 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -1169,9 +1169,11 @@ void PageHandler::GetInstallabilityErrors( std::unique_ptr<GetInstallabilityErrorsCallback> callback) { auto errors = std::make_unique<protocol::Array<std::string>>(); + auto installability_errors = + std::make_unique<protocol::Array<Page::InstallabilityError>>(); // TODO: Use InstallableManager once it moves into content/. // Until then, this code is only used to return empty array in the tests. - callback->sendSuccess(std::move(errors)); + callback->sendSuccess(std::move(errors), std::move(installability_errors)); } void PageHandler::GetManifestIcons(
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index 754ab57..8a21293 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -48,11 +48,8 @@ RenderFrameProxyHost* frame_proxy_in_parent_renderer) : FrameConnectorDelegate(IsUseZoomForDSFEnabled()), frame_proxy_in_parent_renderer_(frame_proxy_in_parent_renderer) { - frame_proxy_in_parent_renderer->frame_tree_node() - ->render_manager() - ->current_frame_host() - ->GetRenderWidgetHost() - ->GetScreenInfo(&screen_info_); + current_child_frame_host()->GetRenderWidgetHost()->GetScreenInfo( + &screen_info_); } CrossProcessFrameConnector::~CrossProcessFrameConnector() { @@ -335,11 +332,7 @@ return; // TODO(https://crbug.com/1014212) Remove this CHECK when the bug is fixed. - CHECK( - frame_proxy_in_parent_renderer_->frame_tree_node()->current_frame_host()); - frame_proxy_in_parent_renderer_->frame_tree_node() - ->current_frame_host() - ->VisibilityChanged(visibility); + CHECK(current_child_frame_host()); // If there is an inner WebContents, it should be notified of the change in // the visibility. The Show/Hide methods will not be called if an inner @@ -378,17 +371,14 @@ if (!frame_proxy_in_parent_renderer_) return nullptr; - RenderFrameHostImpl* current = - frame_proxy_in_parent_renderer_->frame_tree_node()->current_frame_host(); - RenderFrameHostImpl* root = RootRenderFrameHost(current); + RenderFrameHostImpl* root = RootRenderFrameHost(current_child_frame_host()); return static_cast<RenderWidgetHostViewBase*>(root->GetView()); } RenderWidgetHostViewBase* CrossProcessFrameConnector::GetParentRenderWidgetHostView() { - RenderFrameHostImpl* current = - frame_proxy_in_parent_renderer_->frame_tree_node()->current_frame_host(); - RenderFrameHostImpl* parent = current->ParentOrOuterDelegateFrame(); + RenderFrameHostImpl* parent = + current_child_frame_host()->ParentOrOuterDelegateFrame(); return parent ? static_cast<RenderWidgetHostViewBase*>(parent->GetView()) : nullptr; } @@ -425,9 +415,7 @@ void CrossProcessFrameConnector::SetVisibilityForChildViews( bool visible) const { - frame_proxy_in_parent_renderer_->frame_tree_node() - ->current_frame_host() - ->SetVisibilityForChildViews(visible); + current_child_frame_host()->SetVisibilityForChildViews(visible); } void CrossProcessFrameConnector::SetScreenSpaceRect( @@ -539,14 +527,17 @@ return false; Visibility embedder_visibility = - frame_proxy_in_parent_renderer_->frame_tree_node() - ->current_frame_host() - ->delegate() - ->GetVisibility(); + current_child_frame_host()->delegate()->GetVisibility(); if (embedder_visibility != Visibility::VISIBLE) return false; return true; } +RenderFrameHostImpl* CrossProcessFrameConnector::current_child_frame_host() + const { + return frame_proxy_in_parent_renderer_->frame_tree_node() + ->current_frame_host(); +} + } // namespace content
diff --git a/content/browser/frame_host/cross_process_frame_connector.h b/content/browser/frame_host/cross_process_frame_connector.h index b4aead1..172b90f 100644 --- a/content/browser/frame_host/cross_process_frame_connector.h +++ b/content/browser/frame_host/cross_process_frame_connector.h
@@ -21,6 +21,7 @@ } namespace content { +class RenderFrameHostImpl; class RenderFrameProxyHost; // CrossProcessFrameConnector provides the platform view abstraction for @@ -181,6 +182,12 @@ void OnUpdateRenderThrottlingStatus(bool is_throttled, bool subtree_throttled); + // Gets the current RenderFrameHost for the + // |frame_proxy_in_parent_renderer_|'s (i.e., the child frame's) + // FrameTreeNode. This corresponds to B2 in the class-level comment + // above for CrossProcessFrameConnector. + RenderFrameHostImpl* current_child_frame_host() const; + // The RenderFrameProxyHost that routes messages to the parent frame's // renderer process. RenderFrameProxyHost* frame_proxy_in_parent_renderer_;
diff --git a/content/browser/loader/quic_transport_browsertest.cc b/content/browser/loader/quic_transport_browsertest.cc new file mode 100644 index 0000000..0125414 --- /dev/null +++ b/content/browser/loader/quic_transport_browsertest.cc
@@ -0,0 +1,181 @@ +// Copyright 2020 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 <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/strings/string16.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/bind_test_util.h" +#include "base/threading/thread.h" +#include "base/threading/thread_restrictions.h" +#include "build/build_config.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/shell/browser/shell.h" +#include "net/base/ip_endpoint.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" +#include "net/tools/quic/quic_transport_simple_server.h" +#include "services/network/public/cpp/network_switches.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/origin.h" + +// This file is placed tentively in content/browser/loader. +// TODO(yhirano): Convert tests in this file to web platform tests when they +// have a QuicTransport server. + +namespace content { +namespace { + +using base::ASCIIToUTF16; + +class QuicTransportSimpleServerWithThread final { + public: + explicit QuicTransportSimpleServerWithThread( + const std::vector<url::Origin>& origins) + : origins_(origins) {} + + ~QuicTransportSimpleServerWithThread() { + io_thread_->task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + [](std::unique_ptr<net::QuicTransportSimpleServer> server) {}, + std::move(server_))); + + base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait_for_thread_join; + io_thread_.reset(); + } + + void Start() { + CHECK(!io_thread_); + + io_thread_ = std::make_unique<base::Thread>("QuicTransport server"); + base::Thread::Options thread_options; + thread_options.message_pump_type = base::MessagePumpType::IO; + CHECK(io_thread_->StartWithOptions(thread_options)); + CHECK(io_thread_->WaitUntilThreadStarted()); + + base::WaitableEvent event; + net::IPEndPoint server_address; + io_thread_->task_runner()->PostTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + server_ = std::make_unique<net::QuicTransportSimpleServer>( + /*port=*/0, origins_, + quic::test::crypto_test_utils::ProofSourceForTesting()); + const auto result = server_->Start(); + CHECK_EQ(EXIT_SUCCESS, result); + server_address = server_->server_address(); + event.Signal(); + })); + event.Wait(); + server_address_ = server_address; + } + + const net::IPEndPoint& server_address() const { return server_address_; } + + private: + const std::vector<url::Origin> origins_; + net::IPEndPoint server_address_; + + std::unique_ptr<net::QuicTransportSimpleServer> server_; + std::unique_ptr<base::Thread> io_thread_; +}; + +class QuicTransportTest : public ContentBrowserTest { + public: + QuicTransportTest() : server_({}) { server_.Start(); } + + void SetUpCommandLine(base::CommandLine* command_line) override { + ContentBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitch( + switches::kEnableExperimentalWebPlatformFeatures); + command_line->AppendSwitchASCII( + switches::kOriginToForceQuicOn, + base::StringPrintf("localhost:%d", server_.server_address().port())); + command_line->AppendSwitch(switches::kEnableQuic); + command_line->AppendSwitchASCII(switches::kQuicVersion, + base::StringPrintf("h3-24")); + // The value is calculated from net/data/ssl/certificates/quic-chain.pem. + command_line->AppendSwitchASCII( + network::switches::kIgnoreCertificateErrorsSPKIList, + "I+ryIVl5ksb8KijTneC3y7z1wBFn5x35O5is9g5n/KM="); + } + + bool WaitForTitle(const base::string16& expected_title, + const std::vector<base::string16> additional_titles) { + TitleWatcher title_watcher(shell()->web_contents(), expected_title); + + for (const auto& title : additional_titles) { + title_watcher.AlsoWaitForTitle(title); + } + base::string16 actual_title = title_watcher.WaitAndGetTitle(); + EXPECT_EQ(expected_title, actual_title); + return expected_title == actual_title; + } + + bool WaitForTitle(const base::string16& title) { + return WaitForTitle(title, {}); + } + + protected: + QuicTransportSimpleServerWithThread server_; +}; + +// TODO(crbug.com/1044513): Run this test on Windows. +#if defined(OS_WIN) +#define MAYBE_Echo DISABLED_Echo +#else +#define MAYBE_Echo Echo +#endif +IN_PROC_BROWSER_TEST_F(QuicTransportTest, MAYBE_Echo) { + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"))); + + ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("Title Of Awesomeness"))); + + ASSERT_TRUE(ExecuteScript( + shell(), base::StringPrintf(R"JS( + async function run() { + const transport = new QuicTransport('quic-transport:localhost:%d/echo'); + + const writer = transport.sendDatagrams().getWriter(); + const reader = transport.receiveDatagrams().getReader(); + + const data = new Uint8Array([65, 66, 67]); + const id = setInterval(() => { + writer.write(data); + }, 10); + + const {done, value} = await reader.read(); + clearInterval(id); + if (done) { + throw Error('Got an unexpected DONE signal'); + } + if (value.length !== 3 || + value[0] !== 65 || value[1] !== 66 || value[2] !== 67) { + throw Error('Got invalid data'); + } + } + + run().then(() => { document.title = 'PASS'; }, + (e) => { console.log(e); document.title = 'FAIL'; }); +)JS", + server_.server_address().port()))); + + ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("PASS"), {ASCIIToUTF16("FAIL")})); +} + +} // namespace +} // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc index e3ec39c..37ec5a3 100644 --- a/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc +++ b/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -46,9 +46,9 @@ StoragePartition* storage_partition = BrowserContext::GetStoragePartition( site_instance->GetBrowserContext(), site_instance); + // TODO(https://crbug.com/1021661): Pass in a non-empty NetworkIsolationKey. storage_partition->GetNetworkContext()->LookUpProxyForURL( - url, render_frame_host->GetNetworkIsolationKey(), - std::move(proxy_lookup_client)); + url, net::NetworkIsolationKey::Todo(), std::move(proxy_lookup_client)); return true; }
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index f4aa12b..01843df 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -183,6 +183,8 @@ "hid_delegate.h", "histogram_fetcher.h", "indexed_db_context.h", + "installability_error.cc", + "installability_error.h", "interstitial_page.h", "interstitial_page_delegate.cc", "interstitial_page_delegate.h",
diff --git a/content/public/browser/installability_error.cc b/content/public/browser/installability_error.cc new file mode 100644 index 0000000..2134f0c --- /dev/null +++ b/content/public/browser/installability_error.cc
@@ -0,0 +1,39 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/browser/installability_error.h" + +#include <utility> + +namespace content { + +InstallabilityErrorArgument::InstallabilityErrorArgument(std::string name, + std::string value) + : name(std::move(name)), value(std::move(value)) {} + +bool InstallabilityErrorArgument::operator==( + const InstallabilityErrorArgument& other) const { + return name == other.name && value == other.value; +} + +InstallabilityErrorArgument::~InstallabilityErrorArgument() = default; + +InstallabilityError::InstallabilityError() = default; + +InstallabilityError::InstallabilityError(std::string error_id) + : error_id(std::move(error_id)) {} + +InstallabilityError::InstallabilityError(const InstallabilityError& other) = + default; + +InstallabilityError::InstallabilityError(InstallabilityError&& other) = default; + +bool InstallabilityError::operator==(const InstallabilityError& other) const { + return error_id == other.error_id && + installability_error_arguments == other.installability_error_arguments; +} + +InstallabilityError::~InstallabilityError() = default; + +} // namespace content
diff --git a/content/public/browser/installability_error.h b/content/public/browser/installability_error.h new file mode 100644 index 0000000..7600b27 --- /dev/null +++ b/content/public/browser/installability_error.h
@@ -0,0 +1,39 @@ +// Copyright 2020 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 CONTENT_PUBLIC_BROWSER_INSTALLABILITY_ERROR_H_ +#define CONTENT_PUBLIC_BROWSER_INSTALLABILITY_ERROR_H_ + +#include <string> +#include <vector> + +#include "content/common/content_export.h" + +namespace content { + +struct CONTENT_EXPORT InstallabilityErrorArgument { + InstallabilityErrorArgument() = default; + InstallabilityErrorArgument(std::string name, std::string value); + bool operator==(const InstallabilityErrorArgument& other) const; + ~InstallabilityErrorArgument(); + + std::string name; + std::string value; +}; + +struct CONTENT_EXPORT InstallabilityError { + InstallabilityError(); + explicit InstallabilityError(std::string error_id); + InstallabilityError(const InstallabilityError& other); + InstallabilityError(InstallabilityError&& other); + bool operator==(const InstallabilityError& other) const; + ~InstallabilityError(); + + std::string error_id; + std::vector<InstallabilityErrorArgument> installability_error_arguments; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_INSTALLABILITY_ERROR_H_
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc index 01715cc..6565a647 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -171,7 +171,8 @@ unbound_compositor_frame_sink_(std::move(compositor_frame_sink_remote)), unbound_client_(std::move(client_receiver)), synthetic_begin_frame_source_(std::move(synthetic_begin_frame_source)), - viz_for_webview_enabled_(features::IsUsingVizForWebView()) { + viz_frame_submission_enabled_( + features::IsUsingVizFrameSubmissionForWebView()) { DCHECK(registry_); DCHECK(sender_); thread_checker_.DetachFromThread(); @@ -192,7 +193,7 @@ if (!cc::LayerTreeFrameSink::BindToClient(sink_client)) return false; - if (viz_for_webview_enabled_) { + if (viz_frame_submission_enabled_) { compositor_frame_sink_.Bind(std::move(unbound_compositor_frame_sink_)); client_receiver_.Bind(std::move(unbound_client_), compositor_task_runner_); } @@ -396,7 +397,7 @@ frame.metadata.local_surface_id_allocation_time = child_local_surface_id_allocation_.allocation_time(); - if (viz_for_webview_enabled_) { + if (viz_frame_submission_enabled_) { frame.metadata.begin_frame_ack = viz::BeginFrameAck::CreateManualAckWithDamage(); @@ -409,8 +410,8 @@ submit_frame = std::move(frame); } } - // NOTE: submit_frame will be empty if viz_for_webview_enabled_ enabled, but - // it won't be used upstream + // NOTE: submit_frame will be empty if viz_frame_submission_enabled_ enabled, + // but it won't be used upstream sync_client_->SubmitCompositorFrame(layer_tree_frame_sink_id_, std::move(submit_frame)); did_submit_frame_ = true; @@ -566,7 +567,7 @@ void SynchronousLayerTreeFrameSink::DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) { DCHECK(CalledOnValidThread()); - DCHECK(viz_for_webview_enabled_); + DCHECK(viz_frame_submission_enabled_); client_->ReclaimResources(resources); // client_->DidReceiveCompositorFrameAck() is called just after frame // submission so cc won't be throttled on actual draw which can happen late @@ -576,7 +577,7 @@ void SynchronousLayerTreeFrameSink::OnBeginFrame( const viz::BeginFrameArgs& args, const viz::FrameTimingDetailsMap& timing_details) { - DCHECK(viz_for_webview_enabled_); + DCHECK(viz_frame_submission_enabled_); // We do not receive BeginFrames via CompositorFrameSink, so we do not forward // it to cc. We still might get one with FrameTimingDetailsMap, so we report @@ -592,12 +593,12 @@ void SynchronousLayerTreeFrameSink::ReclaimResources( const std::vector<viz::ReturnedResource>& resources) { DCHECK(CalledOnValidThread()); - DCHECK(viz_for_webview_enabled_); + DCHECK(viz_frame_submission_enabled_); client_->ReclaimResources(resources); } void SynchronousLayerTreeFrameSink::OnBeginFramePausedChanged(bool paused) { - DCHECK(viz_for_webview_enabled_); + DCHECK(viz_frame_submission_enabled_); } void SynchronousLayerTreeFrameSink::OnNeedsBeginFrames( @@ -610,7 +611,7 @@ void SynchronousLayerTreeFrameSink::DidPresentCompositorFrame( const viz::FrameTimingDetailsMap& timing_details) { - DCHECK(!viz_for_webview_enabled_ || timing_details.empty()); + DCHECK(!viz_frame_submission_enabled_ || timing_details.empty()); if (!client_) return;
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.h b/content/renderer/android/synchronous_layer_tree_frame_sink.h index 279a9925..a839869 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -221,7 +221,7 @@ base::ThreadChecker thread_checker_; // Indicates that webview using viz - bool viz_for_webview_enabled_; + const bool viz_frame_submission_enabled_; bool begin_frames_paused_ = false; bool needs_begin_frames_ = false;
diff --git a/content/renderer/input/synchronous_compositor_proxy.cc b/content/renderer/input/synchronous_compositor_proxy.cc index 221cdb64..0513131 100644 --- a/content/renderer/input/synchronous_compositor_proxy.cc +++ b/content/renderer/input/synchronous_compositor_proxy.cc
@@ -28,7 +28,8 @@ use_in_process_zero_copy_software_draw_( base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kSingleProcess)), - using_viz_for_webview_(features::IsUsingVizForWebView()), + viz_frame_submission_enabled_( + features::IsUsingVizFrameSubmissionForWebView()), page_scale_factor_(0.f), min_page_scale_factor_(0.f), max_page_scale_factor_(0.f), @@ -232,7 +233,7 @@ if (hardware_draw_reply_) { // For viz the CF was submitted directly via CompositorFrameSink - DCHECK(frame || using_viz_for_webview_); + DCHECK(frame || viz_frame_submission_enabled_); std::move(hardware_draw_reply_) .Run(common_renderer_params, layer_tree_frame_sink_id, NextMetadataVersion(), std::move(frame));
diff --git a/content/renderer/input/synchronous_compositor_proxy.h b/content/renderer/input/synchronous_compositor_proxy.h index 34a969cf..645a2e04 100644 --- a/content/renderer/input/synchronous_compositor_proxy.h +++ b/content/renderer/input/synchronous_compositor_proxy.h
@@ -120,7 +120,7 @@ mojo::AssociatedReceiver<mojom::SynchronousCompositor> receiver_{this}; const bool use_in_process_zero_copy_software_draw_; - const bool using_viz_for_webview_; + const bool viz_frame_submission_enabled_; bool needs_begin_frames_ = false;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index ce5afdf..ddd52df 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1780,7 +1780,7 @@ #if defined(OS_ANDROID) if (GetContentClient()->UsingSynchronousCompositing()) { // TODO(ericrk): Collapse with non-webview registration below. - if (features::IsUsingVizForWebView()) { + if (features::IsUsingVizFrameSubmissionForWebView()) { frame_sink_provider_->CreateForWidget( render_widget->routing_id(), std::move(compositor_frame_sink_receiver),
diff --git a/content/shell/test_runner/web_ax_object_proxy.cc b/content/shell/test_runner/web_ax_object_proxy.cc index e9d5b67..5476abf8 100644 --- a/content/shell/test_runner/web_ax_object_proxy.cc +++ b/content/shell/test_runner/web_ax_object_proxy.cc
@@ -282,6 +282,8 @@ return result.append("Note"); case ax::mojom::Role::kParagraph: return result.append("Paragraph"); + case ax::mojom::Role::kPluginObject: + return result.append("PluginObject"); case ax::mojom::Role::kPopUpButton: return result.append("PopUpButton"); case ax::mojom::Role::kPre:
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index a7dfe19..2f7f458 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -899,6 +899,7 @@ "../browser/loader/prefetch_browsertest.cc", "../browser/loader/prefetch_browsertest_base.cc", "../browser/loader/prefetch_browsertest_base.h", + "../browser/loader/quic_transport_browsertest.cc", "../browser/loader/reload_cache_control_browsertest.cc", "../browser/loader/resource_scheduler_browsertest.cc", "../browser/locks/lock_manager_browsertest.cc", @@ -1120,6 +1121,8 @@ "//mojo/core/embedder", "//mojo/public/cpp/bindings", "//mojo/public/cpp/test_support:test_utils", + "//net:quic_test_tools", + "//net:simple_quic_tools", "//net:test_support", "//ppapi/buildflags", "//ppapi/c:c",
diff --git a/content/test/data/accessibility/html/embed-expected-uia-win.txt b/content/test/data/accessibility/html/embed-expected-uia-win.txt index 8cf75072..f941a8a 100644 --- a/content/test/data/accessibility/html/embed-expected-uia-win.txt +++ b/content/test/data/accessibility/html/embed-expected-uia-win.txt
@@ -1,3 +1,3 @@ document ++group IsControlElement=false -++++document +++++region
diff --git a/content/test/data/accessibility/html/object-expected-blink.txt b/content/test/data/accessibility/html/object-expected-blink.txt index 0b0b3e0..719bb45 100644 --- a/content/test/data/accessibility/html/object-expected-blink.txt +++ b/content/test/data/accessibility/html/object-expected-blink.txt
@@ -1,3 +1,3 @@ rootWebArea ++genericContainer -++++embeddedObject +++++pluginObject
diff --git a/content/test/data/accessibility/html/param-expected-blink.txt b/content/test/data/accessibility/html/param-expected-blink.txt index 0b0b3e0..719bb45 100644 --- a/content/test/data/accessibility/html/param-expected-blink.txt +++ b/content/test/data/accessibility/html/param-expected-blink.txt
@@ -1,3 +1,3 @@ rootWebArea ++genericContainer -++++embeddedObject +++++pluginObject
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 404aa31..73d29f8 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -553,8 +553,9 @@ crbug.com/957807 [ chromeos ] conformance/uniforms/uniform-samplers-test.html [ Skip ] crbug.com/957807 [ chromeos ] deqp/data/gles2/shaders/conversions.html [ Skip ] crbug.com/957807 [ chromeos ] deqp/data/gles2/shaders/swizzles.html [ Skip ] -# There is a crash, likely in this test, causing all following tests in the shard to fail. -crbug.com/1043953 [ chromeos ] conformance/textures/misc/texture-size-limit.html [ Skip ] +# There is a crash, likely in this test, causing the root partition to become +# read-only. +crbug.com/1043953 [ chromeos ] conformance/textures/misc/texture-size-limit.html [ RetryOnFailure ] # ChromeOS: AMD crbug.com/995652 [ chromeos amd ] conformance/uniforms/out-of-bounds-uniform-array-access.html [ Skip ]
diff --git a/content/test/ppapi/ppapi_browsertest.cc b/content/test/ppapi/ppapi_browsertest.cc index 09b86a2b..f68b463 100644 --- a/content/test/ppapi/ppapi_browsertest.cc +++ b/content/test/ppapi/ppapi_browsertest.cc
@@ -122,6 +122,8 @@ TEST_PPAPI_OUT_OF_PROCESS(MessageLoop_Basics) TEST_PPAPI_OUT_OF_PROCESS(MessageLoop_Post) +TEST_PPAPI_OUT_OF_PROCESS(NetworkProxy) + // TODO(danakj): http://crbug.com/115286 TEST_PPAPI_IN_PROCESS(DISABLED_Scrollbar) // http://crbug.com/89961
diff --git a/docs/linux/gtk_theme_integration.md b/docs/linux/gtk_theme_integration.md index 53e6b950..9e8c117 100644 --- a/docs/linux/gtk_theme_integration.md +++ b/docs/linux/gtk_theme_integration.md
@@ -49,4 +49,4 @@ "entry". The list of CSS selectors that Chromium uses to determine its colors is in -//src/chrome/browser/ui/libgtkui/native_theme_gtk.cc. +//src/chrome/browser/ui/gtk/native_theme_gtk.cc.
diff --git a/extensions/browser/api/declarative_net_request/BUILD.gn b/extensions/browser/api/declarative_net_request/BUILD.gn index 794e9f2..5792450 100644 --- a/extensions/browser/api/declarative_net_request/BUILD.gn +++ b/extensions/browser/api/declarative_net_request/BUILD.gn
@@ -40,6 +40,8 @@ "ruleset_source.h", "utils.cc", "utils.h", + "web_contents_helper.cc", + "web_contents_helper.h", ] public_deps = [
diff --git a/extensions/browser/api/declarative_net_request/action_tracker.cc b/extensions/browser/api/declarative_net_request/action_tracker.cc index f543f4b1..bad4c5d 100644 --- a/extensions/browser/api/declarative_net_request/action_tracker.cc +++ b/extensions/browser/api/declarative_net_request/action_tracker.cc
@@ -9,6 +9,7 @@ #include "base/stl_util.h" #include "base/time/clock.h" +#include "base/timer/timer.h" #include "base/values.h" #include "extensions/browser/api/declarative_net_request/request_action.h" #include "extensions/browser/api/declarative_net_request/rules_monitor_service.h" @@ -69,9 +70,13 @@ } // namespace +// static +constexpr base::TimeDelta ActionTracker::kNonActiveTabRuleLifespan; + ActionTracker::ActionTracker(content::BrowserContext* browser_context) : browser_context_(browser_context) { extension_prefs_ = ExtensionPrefs::Get(browser_context_); + StartTrimRulesTask(); } ActionTracker::~ActionTracker() { @@ -85,11 +90,18 @@ DCHECK(pending_navigation_actions_.empty()); } -// static void ActionTracker::SetClockForTests(const base::Clock* clock) { g_test_clock = clock; } +void ActionTracker::SetTimerForTest( + std::unique_ptr<base::RetainingOneShotTimer> injected_trim_rules_timer) { + DCHECK(injected_trim_rules_timer); + + trim_rules_timer_ = std::move(injected_trim_rules_timer); + StartTrimRulesTask(); +} + void ActionTracker::OnRuleMatched(const RequestAction& request_action, const WebRequestInfo& request_info) { DispatchOnRuleMatchedDebugIfNeeded(request_action, @@ -100,12 +112,16 @@ const bool should_record_rule = ShouldRecordMatchedRule(browser_context_, extension_id, tab_id); - auto add_matched_rule_if_needed = [should_record_rule]( + auto add_matched_rule_if_needed = [this, should_record_rule]( TrackedInfo* tracked_info, const RequestAction& request_action) { if (!should_record_rule) return; + // Restart the timer if it is not running and a matched rule is being added. + if (!trim_rules_timer_->IsRunning()) + trim_rules_timer_->Reset(); + tracked_info->matched_rules.emplace_back(request_action.rule_id, request_action.source_type); }; @@ -114,7 +130,7 @@ // badge text should only be set for valid tab IDs. const bool increment_action_count = tab_id != extension_misc::kUnknownTabId && - request_action.type != RequestAction::Type::ALLOW; + !request_action.IsAllowOrAllowAllRequests(); if (IsMainFrameNavigationRequest(request_info)) { DCHECK(request_info.navigation_id); @@ -168,6 +184,10 @@ base::EraseIf(rules_tracked_, compare_by_extension_id); base::EraseIf(pending_navigation_actions_, compare_by_extension_id); + + // Stop the timer if there are no more matched rules or pending actions. + if (rules_tracked_.empty() && pending_navigation_actions_.empty()) + trim_rules_timer_->Stop(); } void ActionTracker::ClearTabData(int tab_id) { @@ -243,8 +263,9 @@ const ExtensionId& extension_id, const base::Optional<int>& tab_id, const base::Time& min_time_stamp) { - std::vector<dnr_api::MatchedRuleInfo> matched_rules; + TrimRulesFromNonActiveTabs(); + std::vector<dnr_api::MatchedRuleInfo> matched_rules; auto add_to_matched_rules = [this, &matched_rules, &min_time_stamp]( const std::list<TrackedRule>& tracked_rules, int tab_id) { @@ -279,7 +300,11 @@ } int ActionTracker::GetMatchedRuleCountForTest(const ExtensionId& extension_id, - int tab_id) { + int tab_id, + bool trim_non_active_rules) { + if (trim_non_active_rules) + TrimRulesFromNonActiveTabs(); + ExtensionTabIdKey key(extension_id, tab_id); auto tracked_info = rules_tracked_.find(key); @@ -391,6 +416,37 @@ } } +void ActionTracker::TrimRulesFromNonActiveTabs() { + const base::Time now = GetNow(); + + auto older_than_lifespan = [&now](const TrackedRule& tracked_rule) { + return tracked_rule.time_stamp <= now - kNonActiveTabRuleLifespan; + }; + + for (auto it = rules_tracked_.begin(); it != rules_tracked_.end();) { + const ExtensionTabIdKey& key = it->first; + if (key.secondary_id != extension_misc::kUnknownTabId) { + ++it; + continue; + } + + TrackedInfo& tracked_info = it->second; + base::EraseIf(tracked_info.matched_rules, older_than_lifespan); + + if (tracked_info.matched_rules.empty()) + it = rules_tracked_.erase(it); + else + ++it; + } + + trim_rules_timer_->Reset(); +} + +void ActionTracker::StartTrimRulesTask() { + trim_rules_timer_->Start(FROM_HERE, kNonActiveTabRuleLifespan, this, + &ActionTracker::TrimRulesFromNonActiveTabs); +} + dnr_api::MatchedRuleInfo ActionTracker::CreateMatchedRuleInfo( const ActionTracker::TrackedRule& tracked_rule, int tab_id) const {
diff --git a/extensions/browser/api/declarative_net_request/action_tracker.h b/extensions/browser/api/declarative_net_request/action_tracker.h index 7451306..163ce95 100644 --- a/extensions/browser/api/declarative_net_request/action_tracker.h +++ b/extensions/browser/api/declarative_net_request/action_tracker.h
@@ -15,6 +15,7 @@ namespace base { class Clock; +class RetainingOneShotTimer; } namespace content { @@ -31,14 +32,27 @@ class ActionTracker { public: + // The lifespan of matched rules in |rules_matched_| not associated with an + // active document, + static constexpr base::TimeDelta kNonActiveTabRuleLifespan = + base::TimeDelta::FromMinutes(5); + explicit ActionTracker(content::BrowserContext* browser_context); ~ActionTracker(); ActionTracker(const ActionTracker& other) = delete; ActionTracker& operator=(const ActionTracker& other) = delete; + // TODO(crbug.com/1043367): Use a task environment to avoid having to set + // clocks just for tests. + // Sets a custom Clock to use in tests. |clock| should be owned by the caller // of this function. - static void SetClockForTests(const base::Clock* clock); + void SetClockForTests(const base::Clock* clock); + + // Sets a custom RetainingOneShotTimer to use in tests, which replaces + // |trim_rules_timer_|. + void SetTimerForTest( + std::unique_ptr<base::RetainingOneShotTimer> injected_trim_rules_timer); // Called whenever a request matches with a rule. void OnRuleMatched(const RequestAction& request_action, @@ -73,8 +87,12 @@ const base::Time& min_time_stamp); // Returns the number of matched rules in |rules_tracked_| for the given - // |extension_id| and |tab_id|. Should only be used for tests. - int GetMatchedRuleCountForTest(const ExtensionId& extension_id, int tab_id); + // |extension_id| and |tab_id|. If |trim_non_active_rules| is true, + // TrimRulesFromNonActiveTabs is invoked before returning the matched rule + // count, similar to GetMatchedRules. Should only be used for tests. + int GetMatchedRuleCountForTest(const ExtensionId& extension_id, + int tab_id, + bool trim_non_active_rules); // Returns the number of matched rules in |pending_navigation_actions_| for // the given |extension_id| and |navigation_id|. Should only be used for @@ -146,14 +164,28 @@ // unknown tab ID (-1). Called by ClearTabData and ResetActionCountForTab. void TransferRulesOnTabInvalid(int tab_id); + // Removes all rules in |rules_tracked_| older than + // |kNonActiveTabRuleLifespan| from non active tabs (i.e. |tab_id| = -1). + // Called periodically to ensure no rules attributed to the unknown tab ID in + // |rules_tracked_| are older than |kNonActiveTabRuleLifespan|. + void TrimRulesFromNonActiveTabs(); + + // Schedules TrimRulesFromNonActiveTabs to be run after + // |kNonActiveTabRuleLifespan|. Called in the constructor and whenever + // |trim_rules_timer_| gets set. + void StartTrimRulesTask(); + // Converts an internally represented |tracked_rule| to a MatchedRuleInfo. api::declarative_net_request::MatchedRuleInfo CreateMatchedRuleInfo( const TrackedRule& tracked_rule, int tab_id) const; + // A timer to call TrimRulesFromNonActiveTabs with an interval of + // |kNonActiveTabRuleLifespan|. + std::unique_ptr<base::RetainingOneShotTimer> trim_rules_timer_ = + std::make_unique<base::RetainingOneShotTimer>(); + // Maps a pair of (extension ID, tab ID) to the TrackedInfo for that pair. - // TODO(crbug.com/1035106): Prune the rules for the invalid tab ID to prevent - // this from growing unbounded. std::map<ExtensionTabIdKey, TrackedInfo> rules_tracked_; // Maps a pair of (extension ID, navigation ID) to the TrackedInfo matched for
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.cc b/extensions/browser/api/declarative_net_request/composite_matcher.cc index eed6e9f..d25dccf 100644 --- a/extensions/browser/api/declarative_net_request/composite_matcher.cc +++ b/extensions/browser/api/declarative_net_request/composite_matcher.cc
@@ -117,7 +117,7 @@ base::Optional<RequestAction> action = matcher->GetBeforeRequestAction(params); params.allow_rule_cache[matcher.get()] = - action && action->type == RequestAction::Type::ALLOW; + action && action->IsAllowOrAllowAllRequests(); if (action && action->type == RequestAction::Type::REDIRECT) { // Redirecting requires host permissions. @@ -152,7 +152,7 @@ base::Optional<RequestAction> action = matcher->GetBeforeRequestAction(params); params.allow_rule_cache[matcher.get()] = - action && action->type == RequestAction::Type::ALLOW; + action && action->IsAllowOrAllowAllRequests(); } if (params.allow_rule_cache[matcher.get()]) return mask; @@ -171,6 +171,16 @@ return has_any_extra_headers_matcher_.value(); } +void CompositeMatcher::OnRenderFrameDeleted(content::RenderFrameHost* host) { + for (auto& matcher : matchers_) + matcher->OnRenderFrameDeleted(host); +} + +void CompositeMatcher::OnDidFinishNavigation(content::RenderFrameHost* host) { + for (auto& matcher : matchers_) + matcher->OnDidFinishNavigation(host); +} + bool CompositeMatcher::ComputeHasAnyExtraHeadersMatcher() const { for (const auto& matcher : matchers_) { if (matcher->IsExtraHeadersMatcher())
diff --git a/extensions/browser/api/declarative_net_request/composite_matcher.h b/extensions/browser/api/declarative_net_request/composite_matcher.h index 950897b0..3133d82 100644 --- a/extensions/browser/api/declarative_net_request/composite_matcher.h +++ b/extensions/browser/api/declarative_net_request/composite_matcher.h
@@ -15,6 +15,10 @@ #include "extensions/browser/api/declarative_net_request/ruleset_matcher.h" #include "extensions/common/permissions/permissions_data.h" +namespace content { +class RenderFrameHost; +} // namespace content + namespace extensions { namespace declarative_net_request { @@ -70,6 +74,9 @@ // Returns whether this modifies "extraHeaders". bool HasAnyExtraHeadersMatcher() const; + void OnRenderFrameDeleted(content::RenderFrameHost* host); + void OnDidFinishNavigation(content::RenderFrameHost* host); + private: bool ComputeHasAnyExtraHeadersMatcher() const;
diff --git a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc index f173985..ff07912 100644 --- a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc +++ b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc
@@ -90,37 +90,6 @@ ExtensionUrlPatternIndexMatcher::~ExtensionUrlPatternIndexMatcher() = default; -base::Optional<RequestAction> -ExtensionUrlPatternIndexMatcher::GetBeforeRequestAction( - const RequestParams& params) const { - const flat_rule::UrlRule* rule = GetMatchingRule( - params, flat::IndexType_before_request_except_allow_all_requests, - FindRuleStrategy::kHighestPriority); - if (!rule) - return base::nullopt; - - const flat::UrlRuleMetadata* metadata = - metadata_list_->LookupByKey(rule->id()); - DCHECK(metadata); - DCHECK_EQ(metadata->id(), rule->id()); - switch (metadata->action()) { - case flat::ActionType_block: - return CreateBlockOrCollapseRequestAction(params, *rule); - case flat::ActionType_allow: - return CreateAllowAction(params, *rule); - case flat::ActionType_redirect: - return CreateRedirectActionFromMetadata(params, *rule, *metadata_list_); - case flat::ActionType_upgrade_scheme: - return CreateUpgradeAction(params, *rule); - case flat::ActionType_allow_all_requests: - case flat::ActionType_remove_headers: - case flat::ActionType_count: - NOTREACHED(); - } - - return base::nullopt; -} - uint8_t ExtensionUrlPatternIndexMatcher::GetRemoveHeadersMask( const RequestParams& params, uint8_t excluded_remove_headers_mask, @@ -177,6 +146,56 @@ return mask; } +base::Optional<RequestAction> +ExtensionUrlPatternIndexMatcher::GetAllowAllRequestsAction( + const RequestParams& params) const { + const flat_rule::UrlRule* rule = + GetMatchingRule(params, flat::IndexType_allow_all_requests, + FindRuleStrategy::kHighestPriority); + if (!rule) + return base::nullopt; + + return CreateAllowAllRequestsAction(params, *rule); +} + +base::Optional<RequestAction> +ExtensionUrlPatternIndexMatcher::GetBeforeRequestActionIgnoringAncestors( + const RequestParams& params) const { + return GetMaxPriorityAction(GetBeforeRequestActionHelper(params), + GetAllowAllRequestsAction(params)); +} + +base::Optional<RequestAction> +ExtensionUrlPatternIndexMatcher::GetBeforeRequestActionHelper( + const RequestParams& params) const { + const flat_rule::UrlRule* rule = GetMatchingRule( + params, flat::IndexType_before_request_except_allow_all_requests, + FindRuleStrategy::kHighestPriority); + if (!rule) + return base::nullopt; + + const flat::UrlRuleMetadata* metadata = + metadata_list_->LookupByKey(rule->id()); + DCHECK(metadata); + DCHECK_EQ(metadata->id(), rule->id()); + switch (metadata->action()) { + case flat::ActionType_block: + return CreateBlockOrCollapseRequestAction(params, *rule); + case flat::ActionType_allow: + return CreateAllowAction(params, *rule); + case flat::ActionType_redirect: + return CreateRedirectActionFromMetadata(params, *rule, *metadata_list_); + case flat::ActionType_upgrade_scheme: + return CreateUpgradeAction(params, *rule); + case flat::ActionType_allow_all_requests: + case flat::ActionType_remove_headers: + case flat::ActionType_count: + NOTREACHED(); + } + + return base::nullopt; +} + const flat_rule::UrlRule* ExtensionUrlPatternIndexMatcher::GetMatchingRule( const RequestParams& params, flat::IndexType index,
diff --git a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h index a41222e..b095aa6 100644 --- a/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h +++ b/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h
@@ -29,8 +29,6 @@ // RulesetMatcherBase override: ~ExtensionUrlPatternIndexMatcher() override; - base::Optional<RequestAction> GetBeforeRequestAction( - const RequestParams& params) const override; uint8_t GetRemoveHeadersMask( const RequestParams& params, uint8_t excluded_remove_headers_mask, @@ -42,6 +40,17 @@ private: using UrlPatternIndexMatcher = url_pattern_index::UrlPatternIndexMatcher; + // RulesetMatcherBase override: + base::Optional<RequestAction> GetAllowAllRequestsAction( + const RequestParams& params) const override; + base::Optional<RequestAction> GetBeforeRequestActionIgnoringAncestors( + const RequestParams& params) const override; + + // Returns the highest priority action from + // |flat::IndexType_before_request_except_allow_all_requests| index. + base::Optional<RequestAction> GetBeforeRequestActionHelper( + const RequestParams& params) const; + const url_pattern_index::flat::UrlRule* GetMatchingRule( const RequestParams& params, flat::IndexType index,
diff --git a/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc b/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc index 353107d..92df5f4 100644 --- a/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc +++ b/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc
@@ -96,45 +96,6 @@ RegexRulesMatcher::~RegexRulesMatcher() = default; -base::Optional<RequestAction> RegexRulesMatcher::GetBeforeRequestAction( - const RequestParams& params) const { - const std::vector<RegexRuleInfo>& potential_matches = - GetPotentialMatches(params); - auto info = std::find_if( - potential_matches.begin(), potential_matches.end(), - [¶ms](const RegexRuleInfo& info) { - return IsBeforeRequestAction(info.regex_rule->action_type()) && - re2::RE2::PartialMatch(params.url->spec(), *info.regex); - }); - if (info == potential_matches.end()) - return base::nullopt; - - const flat_rule::UrlRule& rule = *info->regex_rule->url_rule(); - switch (info->regex_rule->action_type()) { - case flat::ActionType_block: - return CreateBlockOrCollapseRequestAction(params, rule); - case flat::ActionType_allow: - return CreateAllowAction(params, rule); - case flat::ActionType_redirect: - // If this is a regex substitution rule, handle the substitution. Else - // create the redirect action from the information in |metadata_list_| - // below. - return info->regex_rule->regex_substitution() - ? CreateRegexSubstitutionRedirectAction(params, *info) - : CreateRedirectActionFromMetadata(params, rule, - *metadata_list_); - case flat::ActionType_upgrade_scheme: - return CreateUpgradeAction(params, rule); - case flat::ActionType_allow_all_requests: - // TODO(crbug.com/1038831): Handle allowAllRequests case. - break; - default: - NOTREACHED(); - } - - return base::nullopt; -} - uint8_t RegexRulesMatcher::GetRemoveHeadersMask( const RequestParams& params, uint8_t excluded_remove_headers_mask, @@ -174,6 +135,64 @@ return mask; } +base::Optional<RequestAction> RegexRulesMatcher::GetAllowAllRequestsAction( + const RequestParams& params) const { + const std::vector<RegexRuleInfo>& potential_matches = + GetPotentialMatches(params); + auto info = std::find_if(potential_matches.begin(), potential_matches.end(), + [¶ms](const RegexRuleInfo& info) { + return info.regex_rule->action_type() == + flat::ActionType_allow_all_requests && + re2::RE2::PartialMatch(params.url->spec(), + *info.regex); + }); + if (info == potential_matches.end()) + return base::nullopt; + + return CreateAllowAllRequestsAction(params, *info->regex_rule->url_rule()); +} + +base::Optional<RequestAction> +RegexRulesMatcher::GetBeforeRequestActionIgnoringAncestors( + const RequestParams& params) const { + const std::vector<RegexRuleInfo>& potential_matches = + GetPotentialMatches(params); + auto info = std::find_if( + potential_matches.begin(), potential_matches.end(), + [¶ms](const RegexRuleInfo& info) { + return IsBeforeRequestAction(info.regex_rule->action_type()) && + re2::RE2::PartialMatch(params.url->spec(), *info.regex); + }); + if (info == potential_matches.end()) + return base::nullopt; + + const flat_rule::UrlRule& rule = *info->regex_rule->url_rule(); + switch (info->regex_rule->action_type()) { + case flat::ActionType_block: + return CreateBlockOrCollapseRequestAction(params, rule); + case flat::ActionType_allow: + return CreateAllowAction(params, rule); + case flat::ActionType_redirect: + // If this is a regex substitution rule, handle the substitution. Else + // create the redirect action from the information in |metadata_list_| + // below. + return info->regex_rule->regex_substitution() + ? CreateRegexSubstitutionRedirectAction(params, *info) + : CreateRedirectActionFromMetadata(params, rule, + *metadata_list_); + case flat::ActionType_upgrade_scheme: + return CreateUpgradeAction(params, rule); + case flat::ActionType_allow_all_requests: + return CreateAllowAllRequestsAction(params, rule); + case flat::ActionType_remove_headers: + case flat::ActionType_count: + NOTREACHED(); + break; + } + + return base::nullopt; +} + void RegexRulesMatcher::InitializeMatcher() { for (const auto* regex_rule : *regex_list_) { const flat_rule::UrlRule* rule = regex_rule->url_rule();
diff --git a/extensions/browser/api/declarative_net_request/regex_rules_matcher.h b/extensions/browser/api/declarative_net_request/regex_rules_matcher.h index 4abc8a2..d712094 100644 --- a/extensions/browser/api/declarative_net_request/regex_rules_matcher.h +++ b/extensions/browser/api/declarative_net_request/regex_rules_matcher.h
@@ -56,8 +56,6 @@ // RulesetMatcherBase override: ~RegexRulesMatcher() override; - base::Optional<RequestAction> GetBeforeRequestAction( - const RequestParams& params) const override; uint8_t GetRemoveHeadersMask( const RequestParams& params, uint8_t excluded_remove_headers_mask, @@ -67,6 +65,12 @@ } private: + // RulesetMatcherBase override: + base::Optional<RequestAction> GetAllowAllRequestsAction( + const RequestParams& params) const override; + base::Optional<RequestAction> GetBeforeRequestActionIgnoringAncestors( + const RequestParams& params) const override; + // Helper to build the necessary data structures for matching. void InitializeMatcher();
diff --git a/extensions/browser/api/declarative_net_request/request_action.cc b/extensions/browser/api/declarative_net_request/request_action.cc index eb9298f8..795d72e 100644 --- a/extensions/browser/api/declarative_net_request/request_action.cc +++ b/extensions/browser/api/declarative_net_request/request_action.cc
@@ -22,5 +22,23 @@ RequestAction::RequestAction(RequestAction&&) = default; RequestAction& RequestAction::operator=(RequestAction&&) = default; +RequestAction RequestAction::Clone() const { + // Use the private copy constructor to create a copy. + return *this; +} + +RequestAction::RequestAction(const RequestAction&) = default; + +base::Optional<RequestAction> GetMaxPriorityAction( + base::Optional<RequestAction> lhs, + base::Optional<RequestAction> rhs) { + if (!lhs) + return rhs; + if (!rhs) + return lhs; + return lhs->rule_priority > rhs->rule_priority ? std::move(lhs) + : std::move(rhs); +} + } // namespace declarative_net_request } // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/request_action.h b/extensions/browser/api/declarative_net_request/request_action.h index 07352f1..673e0b0 100644 --- a/extensions/browser/api/declarative_net_request/request_action.h +++ b/extensions/browser/api/declarative_net_request/request_action.h
@@ -34,6 +34,9 @@ UPGRADE, // Remove request/response headers. REMOVE_HEADERS, + // Allow the network request. This request is either for an allowlisted + // frame or originated from one. + ALLOW_ALL_REQUESTS, }; RequestAction(Type type, @@ -45,6 +48,9 @@ RequestAction(RequestAction&&); RequestAction& operator=(RequestAction&&); + // Helper to create a copy. + RequestAction Clone() const; + Type type = Type::BLOCK; // Valid iff |IsRedirectOrUpgrade()| is true. @@ -78,10 +84,18 @@ bool IsRedirectOrUpgrade() const { return type == Type::REDIRECT || type == Type::UPGRADE; } + bool IsAllowOrAllowAllRequests() const { + return type == Type::ALLOW || type == Type::ALLOW_ALL_REQUESTS; + } - DISALLOW_COPY_AND_ASSIGN(RequestAction); + private: + RequestAction(const RequestAction&); }; +base::Optional<RequestAction> GetMaxPriorityAction( + base::Optional<RequestAction> lhs, + base::Optional<RequestAction> rhs); + } // namespace declarative_net_request } // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/request_params.cc b/extensions/browser/api/declarative_net_request/request_params.cc index 17eebc55..041f867 100644 --- a/extensions/browser/api/declarative_net_request/request_params.cc +++ b/extensions/browser/api/declarative_net_request/request_params.cc
@@ -4,6 +4,8 @@ #include "extensions/browser/api/declarative_net_request/request_params.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/common/resource_type.h" #include "extensions/browser/api/web_request/web_request_info.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -74,15 +76,53 @@ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); } +bool IsThirdPartyRequest(const url::Origin& origin, + const url::Origin& document_origin) { + if (document_origin.opaque()) + return true; + + return !net::registry_controlled_domains::SameDomainOrHost( + origin, document_origin, + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); +} + +content::GlobalFrameRoutingId GetFrameRoutingId( + content::RenderFrameHost* host) { + if (!host) + return content::GlobalFrameRoutingId(); + + return content::GlobalFrameRoutingId(host->GetProcess()->GetID(), + host->GetRoutingID()); +} + } // namespace RequestParams::RequestParams(const WebRequestInfo& info) : url(&info.url), first_party_origin(info.initiator.value_or(url::Origin())), - element_type(GetElementType(info)) { + element_type(GetElementType(info)), + parent_routing_id(info.parent_routing_id) { is_third_party = IsThirdPartyRequest(*url, first_party_origin); } +RequestParams::RequestParams(content::RenderFrameHost* host) + : url(&host->GetLastCommittedURL()), + parent_routing_id(GetFrameRoutingId(host->GetParent())) { + if (host->GetParent()) { + // Note the discrepancy with the WebRequestInfo constructor. For a + // navigation request, we'd use the request initiator as the + // |first_party_origin|. But here we use the origin of the parent frame. + // This is the same as crbug.com/996998. + first_party_origin = host->GetParent()->GetLastCommittedOrigin(); + element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT; + } else { + first_party_origin = url::Origin(); + element_type = url_pattern_index::flat::ElementType_MAIN_FRAME; + } + is_third_party = + IsThirdPartyRequest(host->GetLastCommittedOrigin(), first_party_origin); +} + RequestParams::RequestParams() = default; RequestParams::~RequestParams() = default;
diff --git a/extensions/browser/api/declarative_net_request/request_params.h b/extensions/browser/api/declarative_net_request/request_params.h index b8a1486..bcb169e 100644 --- a/extensions/browser/api/declarative_net_request/request_params.h +++ b/extensions/browser/api/declarative_net_request/request_params.h
@@ -9,10 +9,15 @@ #include "base/macros.h" #include "base/optional.h" #include "components/url_pattern_index/url_pattern_index.h" +#include "content/public/browser/global_routing_id.h" #include "extensions/browser/api/declarative_net_request/regex_rules_matcher.h" #include "url/gurl.h" #include "url/origin.h" +namespace content { +class RenderFrameHost; +} // namespace content + namespace extensions { struct WebRequestInfo; @@ -23,6 +28,9 @@ struct RequestParams { // |info| must outlive this instance. explicit RequestParams(const WebRequestInfo& info); + // |host| must not undergo a navigation or get deleted for the duration of + // this instance. + explicit RequestParams(content::RenderFrameHost* host); RequestParams(); ~RequestParams(); @@ -33,8 +41,12 @@ url_pattern_index::flat::ElementType_OTHER; bool is_third_party = false; - // A map from RulesetMatchers to whether it has a matching allow rule. Used as - // a cache to prevent additional calls to GetBeforeRequestAction. + // ID of the parent RenderFrameHost. + content::GlobalFrameRoutingId parent_routing_id; + + // A map from RulesetMatchers to whether it has a matching allow or + // allowAllRequests rule. Used as a cache to prevent additional calls to + // GetBeforeRequestAction. mutable base::flat_map<const RulesetMatcher*, bool> allow_rule_cache; // Lower cased url, used for regex matching. Cached for performance.
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/extensions/browser/api/declarative_net_request/ruleset_manager.cc index 9c021db..b69f8768 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_manager.cc +++ b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
@@ -340,6 +340,16 @@ return false; } +void RulesetManager::OnRenderFrameDeleted(content::RenderFrameHost* host) { + for (ExtensionRulesetData& ruleset : rulesets_) + ruleset.matcher->OnRenderFrameDeleted(host); +} + +void RulesetManager::OnDidFinishNavigation(content::RenderFrameHost* host) { + for (ExtensionRulesetData& ruleset : rulesets_) + ruleset.matcher->OnDidFinishNavigation(host); +} + void RulesetManager::SetObserverForTest(TestObserver* observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); test_observer_ = observer; @@ -391,6 +401,7 @@ case RequestAction::Type::UPGRADE: return 2; case RequestAction::Type::ALLOW: + case RequestAction::Type::ALLOW_ALL_REQUESTS: return 1; case RequestAction::Type::REMOVE_HEADERS: NOTREACHED();
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.h b/extensions/browser/api/declarative_net_request/ruleset_manager.h index 7f8e4f1..85305a7 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_manager.h +++ b/extensions/browser/api/declarative_net_request/ruleset_manager.h
@@ -21,6 +21,7 @@ namespace content { class BrowserContext; +class RenderFrameHost; } namespace extensions { @@ -88,6 +89,9 @@ bool HasExtraHeadersMatcherForRequest(const WebRequestInfo& request, bool is_incognito_context) const; + void OnRenderFrameDeleted(content::RenderFrameHost* host); + void OnDidFinishNavigation(content::RenderFrameHost* host); + // Returns the number of CompositeMatchers currently being managed. size_t GetMatcherCountForTest() const { return rulesets_.size(); }
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc index 2985aee4..66169766 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_matcher.cc +++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
@@ -21,21 +21,6 @@ namespace extensions { namespace declarative_net_request { -namespace { - -base::Optional<RequestAction> GetMaxPriorityAction( - base::Optional<RequestAction> lhs, - base::Optional<RequestAction> rhs) { - if (!lhs) - return rhs; - if (!rhs) - return lhs; - return lhs->rule_priority > rhs->rule_priority ? std::move(lhs) - : std::move(rhs); -} - -} // namespace - // static RulesetMatcher::LoadRulesetResult RulesetMatcher::CreateVerifiedMatcher( const RulesetSource& source, @@ -106,6 +91,24 @@ regex_matcher_.IsExtraHeadersMatcher(); } +void RulesetMatcher::OnRenderFrameDeleted(content::RenderFrameHost* host) { + url_pattern_index_matcher_.OnRenderFrameDeleted(host); + regex_matcher_.OnRenderFrameDeleted(host); +} + +void RulesetMatcher::OnDidFinishNavigation(content::RenderFrameHost* host) { + url_pattern_index_matcher_.OnDidFinishNavigation(host); + regex_matcher_.OnDidFinishNavigation(host); +} + +base::Optional<RequestAction> +RulesetMatcher::GetAllowlistedFrameActionForTesting( + content::RenderFrameHost* host) const { + return GetMaxPriorityAction( + url_pattern_index_matcher_.GetAllowlistedFrameActionForTesting(host), + regex_matcher_.GetAllowlistedFrameActionForTesting(host)); +} + RulesetMatcher::RulesetMatcher( std::string ruleset_data, size_t id,
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher.h b/extensions/browser/api/declarative_net_request/ruleset_matcher.h index 4fb84d15..75a3e37 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_matcher.h +++ b/extensions/browser/api/declarative_net_request/ruleset_matcher.h
@@ -13,6 +13,10 @@ #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h" #include "extensions/browser/api/declarative_net_request/regex_rules_matcher.h" +namespace content { +class RenderFrameHost; +} // namespace content + namespace extensions { namespace declarative_net_request { @@ -75,6 +79,9 @@ std::vector<RequestAction>* remove_headers_actions) const; bool IsExtraHeadersMatcher() const; + void OnRenderFrameDeleted(content::RenderFrameHost* host); + void OnDidFinishNavigation(content::RenderFrameHost* host); + // ID of the ruleset. Each extension can have multiple rulesets with // their own unique ids. size_t id() const { return id_; } @@ -83,6 +90,11 @@ // their own different priorities. size_t priority() const { return priority_; } + // Returns the tracked highest priority matching allowsAllRequests action, if + // any, for |host|. + base::Optional<RequestAction> GetAllowlistedFrameActionForTesting( + content::RenderFrameHost* host) const; + private: explicit RulesetMatcher(std::string ruleset_data, size_t id, @@ -99,10 +111,10 @@ // Underlying matcher for filter-list style rules supported using the // |url_pattern_index| component. - const ExtensionUrlPatternIndexMatcher url_pattern_index_matcher_; + ExtensionUrlPatternIndexMatcher url_pattern_index_matcher_; // Underlying matcher for regex rules. - const RegexRulesMatcher regex_matcher_; + RegexRulesMatcher regex_matcher_; DISALLOW_COPY_AND_ASSIGN(RulesetMatcher); };
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc index fc29131..98f0954 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc +++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.cc
@@ -6,6 +6,8 @@ #include "base/strings/strcat.h" #include "components/url_pattern_index/flat/url_pattern_index_generated.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "extensions/browser/api/declarative_net_request/request_action.h" #include "extensions/browser/api/declarative_net_request/request_params.h" #include "net/base/url_util.h" @@ -200,6 +202,57 @@ : extension_id_(extension_id), source_type_(source_type) {} RulesetMatcherBase::~RulesetMatcherBase() = default; +base::Optional<RequestAction> RulesetMatcherBase::GetBeforeRequestAction( + const RequestParams& params) const { + base::Optional<RequestAction> action = + GetBeforeRequestActionIgnoringAncestors(params); + base::Optional<RequestAction> parent_action = + GetAllowlistedFrameAction(params.parent_routing_id); + + return GetMaxPriorityAction(std::move(action), std::move(parent_action)); +} + +void RulesetMatcherBase::OnRenderFrameDeleted(content::RenderFrameHost* host) { + DCHECK(host); + allowlisted_frames_.erase(content::GlobalFrameRoutingId( + host->GetProcess()->GetID(), host->GetRoutingID())); +} + +void RulesetMatcherBase::OnDidFinishNavigation(content::RenderFrameHost* host) { + // Note: we only start tracking frames on navigation, since a document only + // issues network requests after the corresponding navigation is committed. + // Hence we need not listen to OnRenderFrameCreated. + DCHECK(host); + + RequestParams params(host); + + // Find the highest priority allowAllRequests action corresponding to this + // frame. + base::Optional<RequestAction> parent_action = + GetAllowlistedFrameAction(params.parent_routing_id); + base::Optional<RequestAction> frame_action = + GetAllowAllRequestsAction(params); + base::Optional<RequestAction> action = + GetMaxPriorityAction(std::move(parent_action), std::move(frame_action)); + + content::GlobalFrameRoutingId frame_id(host->GetProcess()->GetID(), + host->GetRoutingID()); + if (action) + allowlisted_frames_.insert(std::make_pair(frame_id, std::move(*action))); + else + allowlisted_frames_.erase(frame_id); +} + +base::Optional<RequestAction> +RulesetMatcherBase::GetAllowlistedFrameActionForTesting( + content::RenderFrameHost* host) const { + DCHECK(host); + + content::GlobalFrameRoutingId frame_id(host->GetProcess()->GetID(), + host->GetRoutingID()); + return GetAllowlistedFrameAction(frame_id); +} + RequestAction RulesetMatcherBase::CreateBlockOrCollapseRequestAction( const RequestParams& params, const flat_rule::UrlRule& rule) const { @@ -215,6 +268,12 @@ return CreateRequestAction(RequestAction::Type::ALLOW, rule); } +RequestAction RulesetMatcherBase::CreateAllowAllRequestsAction( + const RequestParams& params, + const url_pattern_index::flat::UrlRule& rule) const { + return CreateRequestAction(RequestAction::Type::ALLOW_ALL_REQUESTS, rule); +} + base::Optional<RequestAction> RulesetMatcherBase::CreateUpgradeAction( const RequestParams& params, const url_pattern_index::flat::UrlRule& rule) const { @@ -316,5 +375,14 @@ extension_id()); } +base::Optional<RequestAction> RulesetMatcherBase::GetAllowlistedFrameAction( + content::GlobalFrameRoutingId frame_id) const { + auto it = allowlisted_frames_.find(frame_id); + if (it == allowlisted_frames_.end()) + return base::nullopt; + + return it->second.Clone(); +} + } // namespace declarative_net_request } // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h index 7a3928d..352e67a 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h +++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h
@@ -5,15 +5,22 @@ #ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_RULESET_MATCHER_BASE_H_ #define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_RULESET_MATCHER_BASE_H_ +#include <map> #include <vector> #include "base/optional.h" +#include "content/public/browser/global_routing_id.h" #include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h" #include "extensions/browser/api/declarative_net_request/request_action.h" #include "extensions/common/api/declarative_net_request.h" #include "extensions/common/extension_id.h" class GURL; + +namespace content { +class RenderFrameHost; +} // namespace content + namespace extensions { namespace declarative_net_request { @@ -30,9 +37,10 @@ // Returns the ruleset's highest priority matching RequestAction for the // onBeforeRequest phase, or base::nullopt if the ruleset has no matching - // rule. - virtual base::Optional<RequestAction> GetBeforeRequestAction( - const RequestParams& params) const = 0; + // rule. Also takes into account any matching allowAllRequests rules for the + // ancestor frames. + base::Optional<RequestAction> GetBeforeRequestAction( + const RequestParams& params) const; // Returns the bitmask of headers to remove from the request. The bitmask // corresponds to flat::RemoveHeaderType. |excluded_remove_headers_mask| @@ -54,6 +62,14 @@ return source_type_; } + void OnRenderFrameDeleted(content::RenderFrameHost* host); + void OnDidFinishNavigation(content::RenderFrameHost* host); + + // Returns the tracked highest priority matching allowsAllRequests action, if + // any, for |host|. + base::Optional<RequestAction> GetAllowlistedFrameActionForTesting( + content::RenderFrameHost* host) const; + protected: using ExtensionMetadataList = ::flatbuffers::Vector<flatbuffers::Offset<flat::UrlRuleMetadata>>; @@ -68,6 +84,11 @@ const RequestParams& params, const url_pattern_index::flat::UrlRule& rule) const; + // Helper to create a RequestAction of type |ALLOW_ALL_REQUESTS|. + RequestAction CreateAllowAllRequestsAction( + const RequestParams& params, + const url_pattern_index::flat::UrlRule& rule) const; + // Helper to create a RequestAction of type |REDIRECT| with the request // upgraded. Returns base::nullopt if the request is not upgradeable. base::Optional<RequestAction> CreateUpgradeAction( @@ -93,13 +114,38 @@ uint8_t mask) const; private: + // Returns the ruleset's highest priority matching allowAllRequests action or + // base::nullopt if there is no corresponding matching rule. Only takes into + // account the request |params| passed in. This doesn't take any account any + // matching allowAllRequests rules for ancestor frames. + virtual base::Optional<RequestAction> GetAllowAllRequestsAction( + const RequestParams& params) const = 0; + + // Returns the ruleset's highest priority matching RequestAction for the + // onBeforeRequest phase, or base::nullopt if the ruleset has no matching + // rule. This doesn't take any account any matching allowAllRequests rules for + // ancestor frames. + virtual base::Optional<RequestAction> GetBeforeRequestActionIgnoringAncestors( + const RequestParams& params) const = 0; + RequestAction CreateRequestAction( RequestAction::Type type, const url_pattern_index::flat::UrlRule& rule) const; + // Returns the matching RequestAction from |allowlisted_frames_| or + // base::nullopt if none is found. + base::Optional<RequestAction> GetAllowlistedFrameAction( + content::GlobalFrameRoutingId frame_id) const; + const ExtensionId extension_id_; const api::declarative_net_request::SourceType source_type_; + // Stores the IDs for the RenderFrameHosts which are allow-listed due to an + // allowAllRequests action and the corresponding highest priority + // RequestAction. + std::map<content::GlobalFrameRoutingId, const RequestAction> + allowlisted_frames_; + DISALLOW_COPY_AND_ASSIGN(RulesetMatcherBase); };
diff --git a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc index c956400..54799dfa 100644 --- a/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc +++ b/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
@@ -14,12 +14,18 @@ #include "base/strings/stringprintf.h" #include "components/url_pattern_index/flat/url_pattern_index_generated.h" #include "components/version_info/version_info.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/navigation_simulator.h" +#include "content/public/test/test_renderer_host.h" +#include "content/public/test/web_contents_tester.h" #include "extensions/browser/api/declarative_net_request/constants.h" #include "extensions/browser/api/declarative_net_request/request_action.h" #include "extensions/browser/api/declarative_net_request/request_params.h" #include "extensions/browser/api/declarative_net_request/ruleset_source.h" #include "extensions/browser/api/declarative_net_request/test_utils.h" #include "extensions/browser/api/declarative_net_request/utils.h" +#include "extensions/browser/extensions_test.h" #include "extensions/common/api/declarative_net_request.h" #include "extensions/common/api/declarative_net_request/constants.h" #include "extensions/common/api/declarative_net_request/test_utils.h" @@ -41,8 +47,6 @@ private: // Run this on the trunk channel to ensure the API is available. ScopedCurrentChannel channel_; - - DISALLOW_COPY_AND_ASSIGN(RulesetMatcherTest); }; // Tests a simple blocking rule. @@ -1069,6 +1073,195 @@ } } +// Test fixture to test allowAllRequests rules. We inherit from ExtensionsTest +// to ensure we can work with WebContentsTester and associated classes. +class AllowAllRequestsTest : public ExtensionsTest { + public: + AllowAllRequestsTest() : channel_(::version_info::Channel::UNKNOWN) {} + + private: + // Run this on the trunk channel to ensure the API is available. + ScopedCurrentChannel channel_; +}; + +// Tests that we track allowlisted frames (frames matching allowAllRequests +// rules) correctly. +TEST_F(AllowAllRequestsTest, AllowlistedFrameTracking) { + TestRule google_rule_1 = CreateGenericRule(); + google_rule_1.id = kMinValidID; + google_rule_1.condition->url_filter = "google.com/xyz"; + google_rule_1.condition->resource_types = + std::vector<std::string>({"main_frame"}); + google_rule_1.action->type = std::string("allowAllRequests"); + google_rule_1.priority = 2; + + TestRule google_rule_2 = CreateGenericRule(); + google_rule_2.id = kMinValidID + 1; + google_rule_2.condition->url_filter.reset(); + google_rule_2.condition->regex_filter = "xyz"; + google_rule_2.condition->resource_types = + std::vector<std::string>({"main_frame"}); + google_rule_2.action->type = std::string("allowAllRequests"); + google_rule_2.priority = 3; + + TestRule example_rule = CreateGenericRule(); + example_rule.id = kMinValidID + 2; + example_rule.condition->url_filter.reset(); + example_rule.condition->regex_filter = std::string("example"); + example_rule.condition->resource_types = + std::vector<std::string>({"sub_frame"}); + example_rule.action->type = std::string("allowAllRequests"); + example_rule.priority = 4; + + std::unique_ptr<RulesetMatcher> matcher; + ASSERT_TRUE( + CreateVerifiedMatcher({google_rule_1, google_rule_2, example_rule}, + CreateTemporarySource(), &matcher)); + + auto simulate_navigation = [&matcher](content::RenderFrameHost* host, + const GURL& url) { + content::RenderFrameHost* new_host = + content::NavigationSimulator::NavigateAndCommitFromDocument(url, host); + EXPECT_TRUE(new_host); + + // Note |host| might have been freed by now. + matcher->OnDidFinishNavigation(new_host); + return new_host; + }; + auto simulate_frame_destroyed = [&matcher](content::RenderFrameHost* host) { + matcher->OnRenderFrameDeleted(host); + }; + + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents( + browser_context(), content::SiteInstance::Create(browser_context())); + ASSERT_TRUE(web_contents); + + GURL example_url("http://example.com"); + simulate_navigation(web_contents->GetMainFrame(), example_url); + base::Optional<RequestAction> action = + matcher->GetAllowlistedFrameActionForTesting( + web_contents->GetMainFrame()); + EXPECT_FALSE(action); + + GURL google_url_1("http://google.com/xyz"); + simulate_navigation(web_contents->GetMainFrame(), google_url_1); + action = matcher->GetAllowlistedFrameActionForTesting( + web_contents->GetMainFrame()); + RequestAction google_rule_2_action = + CreateRequestActionForTesting(RequestAction::Type::ALLOW_ALL_REQUESTS, + *google_rule_2.id, *google_rule_2.priority); + EXPECT_EQ(google_rule_2_action, action); + + auto* rfh_tester = + content::RenderFrameHostTester::For(web_contents->GetMainFrame()); + content::RenderFrameHost* child = rfh_tester->AppendChild("sub_frame"); + ASSERT_TRUE(child); + + child = simulate_navigation(child, example_url); + action = matcher->GetAllowlistedFrameActionForTesting(child); + RequestAction example_rule_action = + CreateRequestActionForTesting(RequestAction::Type::ALLOW_ALL_REQUESTS, + *example_rule.id, *example_rule.priority); + EXPECT_EQ(example_rule_action, action); + + GURL yahoo_url("http://yahoo.com"); + child = simulate_navigation(child, yahoo_url); + action = matcher->GetAllowlistedFrameActionForTesting(child); + EXPECT_EQ(google_rule_2_action, action); + + simulate_frame_destroyed(child); + action = matcher->GetAllowlistedFrameActionForTesting(child); + EXPECT_FALSE(action); + + simulate_frame_destroyed(web_contents->GetMainFrame()); + action = matcher->GetAllowlistedFrameActionForTesting( + web_contents->GetMainFrame()); + EXPECT_FALSE(action); +} + +// Ensures that GetBeforeRequestAction correctly incorporates allowAllRequests +// rules. +TEST_F(AllowAllRequestsTest, GetBeforeRequestAction) { + struct { + int id; + int priority; + std::string action_type; + std::string url_filter; + bool is_regex_rule; + } rule_data[] = {{1, 1, "allowAllRequests", "google", true}, + {2, 3, "block", "||match", false}, + {3, 2, "allowAllRequests", "match1", true}, + {4, 4, "allowAllRequests", "match2", false}}; + + std::vector<TestRule> test_rules; + for (const auto& rule : rule_data) { + TestRule test_rule = CreateGenericRule(); + test_rule.id = rule.id; + test_rule.priority = rule.priority; + test_rule.action->type = rule.action_type; + test_rule.condition->url_filter.reset(); + if (rule.is_regex_rule) + test_rule.condition->regex_filter = rule.url_filter; + else + test_rule.condition->url_filter = rule.url_filter; + if (rule.action_type == "allowAllRequests") { + test_rule.condition->resource_types = + std::vector<std::string>({"main_frame", "sub_frame"}); + } + + test_rules.push_back(test_rule); + } + + std::unique_ptr<RulesetMatcher> matcher; + ASSERT_TRUE( + CreateVerifiedMatcher(test_rules, CreateTemporarySource(), &matcher)); + + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents( + browser_context(), content::SiteInstance::Create(browser_context())); + ASSERT_TRUE(web_contents); + + GURL google_url("http://google.com"); + content::WebContentsTester::For(web_contents.get()) + ->NavigateAndCommit(google_url); + matcher->OnDidFinishNavigation(web_contents->GetMainFrame()); + + struct { + std::string url; + RequestAction expected_action; + } cases[] = { + {"http://nomatch.com", + CreateRequestActionForTesting(RequestAction::Type::ALLOW_ALL_REQUESTS, + rule_data[0].id, rule_data[0].priority)}, + {"http://match1.com", + CreateRequestActionForTesting(RequestAction::Type::COLLAPSE, + rule_data[1].id, rule_data[1].priority)}, + {"http://match2.com", + CreateRequestActionForTesting(RequestAction::Type::ALLOW_ALL_REQUESTS, + rule_data[3].id, rule_data[3].priority)}, + }; + + // Simulate sub-frame requests. + for (const auto& test_case : cases) { + SCOPED_TRACE(test_case.url); + RequestParams params; + + GURL url(test_case.url); + ASSERT_TRUE(url.is_valid()); + params.url = &url; + params.first_party_origin = url::Origin::Create(google_url); + params.is_third_party = true; + params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT; + params.parent_routing_id = content::GlobalFrameRoutingId( + web_contents->GetMainFrame()->GetProcess()->GetID(), + web_contents->GetMainFrame()->GetRoutingID()); + + EXPECT_EQ(test_case.expected_action, + matcher->GetBeforeRequestAction(params)); + } +} + } // namespace } // namespace declarative_net_request } // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/test_utils.cc b/extensions/browser/api/declarative_net_request/test_utils.cc index f160a5ed..8f1a2db 100644 --- a/extensions/browser/api/declarative_net_request/test_utils.cc +++ b/extensions/browser/api/declarative_net_request/test_utils.cc
@@ -80,6 +80,9 @@ case RequestAction::Type::REMOVE_HEADERS: output << "REMOVE_HEADERS"; break; + case RequestAction::Type::ALLOW_ALL_REQUESTS: + output << "ALLOW_ALL_REQUESTS"; + break; } return output; }
diff --git a/extensions/browser/api/declarative_net_request/web_contents_helper.cc b/extensions/browser/api/declarative_net_request/web_contents_helper.cc new file mode 100644 index 0000000..8a9f786 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/web_contents_helper.cc
@@ -0,0 +1,55 @@ +// Copyright 2020 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 "extensions/browser/api/declarative_net_request/web_contents_helper.h" +#include "base/logging.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/web_contents.h" +#include "extensions/browser/api/declarative_net_request/rules_monitor_service.h" +#include "extensions/browser/api/declarative_net_request/ruleset_manager.h" + +namespace extensions { +namespace declarative_net_request { + +namespace { + +RulesetManager* GetRulesetManager(content::BrowserContext* context) { + DCHECK(context); + + auto* rules_monitor_service = + declarative_net_request::RulesMonitorService::Get(context); + + // RulesMonitorService can be null in unit tests. + return rules_monitor_service ? rules_monitor_service->ruleset_manager() + : nullptr; +} + +} // namespace + +WebContentsHelper::WebContentsHelper(content::WebContents* web_contents) + : ruleset_manager_(GetRulesetManager(web_contents->GetBrowserContext())) { + if (ruleset_manager_) + Observe(web_contents); +} + +WebContentsHelper::~WebContentsHelper() = default; + +void WebContentsHelper::RenderFrameDeleted( + content::RenderFrameHost* render_frame_host) { + DCHECK(ruleset_manager_); + ruleset_manager_->OnRenderFrameDeleted(render_frame_host); +} + +void WebContentsHelper::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + DCHECK(ruleset_manager_); + if (!navigation_handle->HasCommitted()) + return; + + ruleset_manager_->OnDidFinishNavigation( + navigation_handle->GetRenderFrameHost()); +} + +} // namespace declarative_net_request +} // namespace extensions
diff --git a/extensions/browser/api/declarative_net_request/web_contents_helper.h b/extensions/browser/api/declarative_net_request/web_contents_helper.h new file mode 100644 index 0000000..a1ae42c3 --- /dev/null +++ b/extensions/browser/api/declarative_net_request/web_contents_helper.h
@@ -0,0 +1,35 @@ +// Copyright 2020 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 EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_WEB_CONTENTS_HELPER_H_ +#define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_WEB_CONTENTS_HELPER_H_ + +#include "content/public/browser/web_contents_observer.h" + +namespace extensions { +namespace declarative_net_request { + +class RulesetManager; + +// A WebContentsObserver to route WebContents lifecycle events to the +// RulesetManager. +class WebContentsHelper : public content::WebContentsObserver { + public: + WebContentsHelper(content::WebContents* web_contents); + ~WebContentsHelper() override; + + // WebContentsObserver overrides: + void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + + private: + // Non-owned pointer. + RulesetManager* const ruleset_manager_ = nullptr; +}; + +} // namespace declarative_net_request +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_WEB_CONTENTS_HELPER_H_
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index 56e1012..f7b87269 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -1134,6 +1134,7 @@ *should_collapse_initiator = true; return net::ERR_BLOCKED_BY_CLIENT; case DNRRequestAction::Type::ALLOW: + case DNRRequestAction::Type::ALLOW_ALL_REQUESTS: DCHECK_EQ(1u, actions.size()); OnDNRActionMatched(browser_context, *request, action); break;
diff --git a/extensions/browser/api/web_request/web_request_info.cc b/extensions/browser/api/web_request/web_request_info.cc index 54cd9f5..eae6eaa1 100644 --- a/extensions/browser/api/web_request/web_request_info.cc +++ b/extensions/browser/api/web_request/web_request_info.cc
@@ -206,6 +206,7 @@ web_view_rules_registry_id = navigation_ui_data->web_view_rules_registry_id(); frame_data = navigation_ui_data->frame_data(); + parent_routing_id = navigation_ui_data->parent_routing_id(); } else if (frame_id >= 0) { // Grab any WebView-related information if relevant. WebViewRendererState::WebViewInfo web_view_info; @@ -220,6 +221,9 @@ // For subresource loads we attempt to resolve the FrameData immediately. frame_data = ExtensionApiFrameIdMap::Get()->GetFrameData(render_process_id, frame_id); + + parent_routing_id = + content::GlobalFrameRoutingId(render_process_id, frame_id); } } @@ -244,7 +248,8 @@ web_view_rules_registry_id(params.web_view_rules_registry_id), web_view_embedder_process_id(params.web_view_embedder_process_id), is_service_worker_script(params.is_service_worker_script), - navigation_id(std::move(params.navigation_id)) {} + navigation_id(std::move(params.navigation_id)), + parent_routing_id(params.parent_routing_id) {} WebRequestInfo::~WebRequestInfo() = default;
diff --git a/extensions/browser/api/web_request/web_request_info.h b/extensions/browser/api/web_request/web_request_info.h index 9e435f0d7..eeb4afb 100644 --- a/extensions/browser/api/web_request/web_request_info.h +++ b/extensions/browser/api/web_request/web_request_info.h
@@ -16,6 +16,7 @@ #include "base/memory/ref_counted.h" #include "base/optional.h" #include "base/values.h" +#include "content/public/browser/global_routing_id.h" #include "extensions/browser/api/declarative_net_request/request_action.h" #include "extensions/browser/api/web_request/web_request_resource_type.h" #include "extensions/browser/extension_api_frame_id_map.h" @@ -73,6 +74,7 @@ ExtensionApiFrameIdMap::FrameData frame_data; bool is_service_worker_script = false; base::Optional<int64_t> navigation_id; + content::GlobalFrameRoutingId parent_routing_id; private: void InitializeWebViewAndFrameData( @@ -177,6 +179,10 @@ // Valid if this request corresponds to a navigation. const base::Optional<int64_t> navigation_id; + // ID of the RenderFrameHost corresponding to the parent frame. Only valid for + // document subresource and sub-frame requests. + const content::GlobalFrameRoutingId parent_routing_id; + private: DISALLOW_COPY_AND_ASSIGN(WebRequestInfo); };
diff --git a/extensions/browser/extension_navigation_ui_data.cc b/extensions/browser/extension_navigation_ui_data.cc index 26e6f73..51786ac 100644 --- a/extensions/browser/extension_navigation_ui_data.cc +++ b/extensions/browser/extension_navigation_ui_data.cc
@@ -6,11 +6,25 @@ #include "base/memory/ptr_util.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" namespace extensions { +namespace { + +content::GlobalFrameRoutingId GetFrameRoutingId( + content::RenderFrameHost* host) { + if (!host) + return content::GlobalFrameRoutingId(); + + return content::GlobalFrameRoutingId(host->GetProcess()->GetID(), + host->GetRoutingID()); +} + +} // namespace + ExtensionNavigationUIData::ExtensionNavigationUIData() {} ExtensionNavigationUIData::ExtensionNavigationUIData( @@ -22,7 +36,8 @@ tab_id, window_id, ExtensionApiFrameIdMap::GetFrameId(navigation_handle), - ExtensionApiFrameIdMap::GetParentFrameId(navigation_handle)) { + ExtensionApiFrameIdMap::GetParentFrameId(navigation_handle), + GetFrameRoutingId(navigation_handle->GetParentFrame())) { // TODO(clamy): See if it would be possible to have just one source for the // FrameData that works both for navigations and subresources loads. } @@ -36,7 +51,8 @@ tab_id, window_id, ExtensionApiFrameIdMap::GetFrameId(frame_host), - ExtensionApiFrameIdMap::GetParentFrameId(frame_host)) {} + ExtensionApiFrameIdMap::GetParentFrameId(frame_host), + GetFrameRoutingId(frame_host->GetParent())) {} // static std::unique_ptr<ExtensionNavigationUIData> @@ -46,7 +62,8 @@ int window_id) { return base::WrapUnique(new ExtensionNavigationUIData( web_contents, tab_id, window_id, ExtensionApiFrameIdMap::kTopFrameId, - ExtensionApiFrameIdMap::kInvalidFrameId)); + ExtensionApiFrameIdMap::kInvalidFrameId, + content::GlobalFrameRoutingId())); } std::unique_ptr<ExtensionNavigationUIData> ExtensionNavigationUIData::DeepCopy() @@ -56,6 +73,7 @@ copy->is_web_view_ = is_web_view_; copy->web_view_instance_id_ = web_view_instance_id_; copy->web_view_rules_registry_id_ = web_view_rules_registry_id_; + copy->parent_routing_id_ = parent_routing_id_; return copy; } @@ -64,7 +82,8 @@ int tab_id, int window_id, int frame_id, - int parent_frame_id) + int parent_frame_id, + content::GlobalFrameRoutingId parent_routing_id) : frame_data_(frame_id, parent_frame_id, tab_id, @@ -72,7 +91,8 @@ // The RenderFrameHost may not have an associated WebContents // in cases such as interstitial pages. web_contents ? web_contents->GetLastCommittedURL() : GURL(), - base::nullopt /* pending_main_frame_url */) { + base::nullopt /* pending_main_frame_url */), + parent_routing_id_(parent_routing_id) { WebViewGuest* web_view = WebViewGuest::FromWebContents(web_contents); if (web_view) { is_web_view_ = true;
diff --git a/extensions/browser/extension_navigation_ui_data.h b/extensions/browser/extension_navigation_ui_data.h index 8d67981..e7b61da 100644 --- a/extensions/browser/extension_navigation_ui_data.h +++ b/extensions/browser/extension_navigation_ui_data.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "content/public/browser/global_routing_id.h" #include "extensions/browser/extension_api_frame_id_map.h" namespace content { @@ -43,12 +44,17 @@ int web_view_instance_id() const { return web_view_instance_id_; } int web_view_rules_registry_id() const { return web_view_rules_registry_id_; } + const content::GlobalFrameRoutingId& parent_routing_id() const { + return parent_routing_id_; + } + private: ExtensionNavigationUIData(content::WebContents* web_contents, int tab_id, int window_id, int frame_id, - int parent_frame_id); + int parent_frame_id, + content::GlobalFrameRoutingId parent_routing_id); ExtensionApiFrameIdMap::FrameData frame_data_; bool is_web_view_; @@ -56,6 +62,10 @@ int web_view_instance_id_; int web_view_rules_registry_id_; + // ID for the parent RenderFrameHost of this navigation. Will only have a + // valid value for sub-frame navigations. + content::GlobalFrameRoutingId parent_routing_id_; + DISALLOW_COPY_AND_ASSIGN(ExtensionNavigationUIData); };
diff --git a/extensions/common/api/automation.idl b/extensions/common/api/automation.idl index 56edd27..4b91a08 100644 --- a/extensions/common/api/automation.idl +++ b/extensions/common/api/automation.idl
@@ -222,6 +222,7 @@ note, pane, paragraph, + pluginObject, popUpButton, pre, presentational,
diff --git a/extensions/common/api/declarative_net_request.idl b/extensions/common/api/declarative_net_request.idl index 047da6f..303e03a 100644 --- a/extensions/common/api/declarative_net_request.idl +++ b/extensions/common/api/declarative_net_request.idl
@@ -54,9 +54,8 @@ upgradeScheme, // Remove request/response headers from the network request. removeHeaders, - // TODO(crbug.com/1038831): Add documentation once the implementation is - // complete. - [nodoc] + // Allow all requests within a frame hierarchy, including the frame request + // itself. allowAllRequests }; @@ -182,6 +181,10 @@ // List of resource types which the rule can match. An empty list is not // allowed. + // + // Note: this must be specified for <code>allowAllRequests</code> rules and + // may only include the <code>sub_frame</code> and <code>main_frame</code> + // resource types. ResourceType[]? resourceTypes; // List of resource types which the rule won't match. Only one of
diff --git a/gpu/ipc/BUILD.gn b/gpu/ipc/BUILD.gn index 7c9289d..ba08eef5 100644 --- a/gpu/ipc/BUILD.gn +++ b/gpu/ipc/BUILD.gn
@@ -19,6 +19,8 @@ "in_process_command_buffer.h", "scheduler_sequence.cc", "scheduler_sequence.h", + "shared_image_interface_in_process.cc", + "shared_image_interface_in_process.h", "single_task_sequence.h", ] @@ -66,9 +68,7 @@ defines = [ "IS_GPU_THREAD_HOLDER_IMPL" ] - public_deps = [ - "//gpu/config", - ] + public_deps = [ "//gpu/config" ] deps = [ ":gl_in_process_context",
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 3f7fc360..e3bd62b 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -54,7 +54,6 @@ #include "gpu/command_buffer/service/scheduler.h" #include "gpu/command_buffer/service/service_utils.h" #include "gpu/command_buffer/service/shared_context_state.h" -#include "gpu/command_buffer/service/shared_image_factory.h" #include "gpu/command_buffer/service/sync_point_manager.h" #include "gpu/command_buffer/service/webgpu_decoder.h" #include "gpu/config/gpu_crash_keys.h" @@ -67,10 +66,12 @@ #include "gpu/ipc/host/gpu_memory_buffer_support.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "gpu/ipc/service/image_transport_surface.h" +#include "gpu/ipc/shared_image_interface_in_process.h" #include "gpu/ipc/single_task_sequence.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_fence.h" #include "ui/gfx/gpu_fence_handle.h" +#include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_image.h" #include "ui/gl/gl_image_shared_memory.h" @@ -138,192 +139,27 @@ } // namespace -class InProcessCommandBuffer::SharedImageInterface - : public gpu::SharedImageInterface { - public: - explicit SharedImageInterface(InProcessCommandBuffer* parent) - : parent_(parent), - gpu_thread_weak_ptr_( - parent_->gpu_thread_weak_ptr_factory_.GetWeakPtr()), - command_buffer_id_(NextCommandBufferId()) {} +InProcessCommandBuffer::SharedImageInterfaceHelper::SharedImageInterfaceHelper( + InProcessCommandBuffer* command_buffer) + : command_buffer_(command_buffer) {} - ~SharedImageInterface() override = default; +void InProcessCommandBuffer::SharedImageInterfaceHelper::SetError() { + // Signal errors by losing the command buffer. + command_buffer_->command_buffer_->SetParseError(error::kLostContext); +} - Mailbox CreateSharedImage(viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage) override { - auto mailbox = Mailbox::GenerateForSharedImage(); - { - base::AutoLock lock(lock_); - // Note: we enqueue the task under the lock to guarantee monotonicity of - // the release ids as seen by the service. Unretained is safe because - // InProcessCommandBuffer synchronizes with the GPU thread at destruction - // time, cancelling tasks, before |this| is destroyed. - parent_->ScheduleGpuTask(base::BindOnce( - &InProcessCommandBuffer::CreateSharedImageOnGpuThread, - gpu_thread_weak_ptr_, mailbox, format, size, color_space, usage, - MakeSyncToken(next_fence_sync_release_++))); - } - return mailbox; - } +void InProcessCommandBuffer::SharedImageInterfaceHelper::WrapTaskWithGpuCheck( + base::OnceClosure task) { + command_buffer_->RunTaskOnGpuThread(std::move(task)); +} - Mailbox CreateSharedImage(viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage, - base::span<const uint8_t> pixel_data) override { - auto mailbox = Mailbox::GenerateForSharedImage(); - std::vector<uint8_t> pixel_data_copy(pixel_data.begin(), pixel_data.end()); - { - base::AutoLock lock(lock_); - // Note: we enqueue the task under the lock to guarantee monotonicity of - // the release ids as seen by the service. Unretained is safe because - // InProcessCommandBuffer synchronizes with the GPU thread at destruction - // time, cancelling tasks, before |this| is destroyed. - parent_->ScheduleGpuTask(base::BindOnce( - &InProcessCommandBuffer::CreateSharedImageWithDataOnGpuThread, - gpu_thread_weak_ptr_, mailbox, format, size, color_space, usage, - MakeSyncToken(next_fence_sync_release_++), - std::move(pixel_data_copy))); - } - return mailbox; - } - - Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer, - GpuMemoryBufferManager* gpu_memory_buffer_manager, - const gfx::ColorSpace& color_space, - uint32_t usage) override { - DCHECK(gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP || - gpu_memory_buffer->GetType() == gfx::ANDROID_HARDWARE_BUFFER || - gpu_memory_buffer_manager); - - // TODO(piman): DCHECK GMB format support. - DCHECK(gpu::IsImageSizeValidForGpuMemoryBufferFormat( - gpu_memory_buffer->GetSize(), gpu_memory_buffer->GetFormat())); - - auto mailbox = Mailbox::GenerateForSharedImage(); - gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle(); - bool requires_sync_token = handle.type == gfx::IO_SURFACE_BUFFER; - SyncToken sync_token; - { - base::AutoLock lock(lock_); - sync_token = MakeSyncToken(next_fence_sync_release_++); - // Note: we enqueue the task under the lock to guarantee monotonicity of - // the release ids as seen by the service. Unretained is safe because - // InProcessCommandBuffer synchronizes with the GPU thread at destruction - // time, cancelling tasks, before |this| is destroyed. - parent_->ScheduleGpuTask(base::BindOnce( - &InProcessCommandBuffer::CreateGMBSharedImageOnGpuThread, - gpu_thread_weak_ptr_, mailbox, std::move(handle), - gpu_memory_buffer->GetFormat(), gpu_memory_buffer->GetSize(), - color_space, usage, sync_token)); - } - if (requires_sync_token) { - sync_token.SetVerifyFlush(); - gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer, - sync_token); - } - return mailbox; - } - - SwapChainMailboxes CreateSwapChain(viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage) override { - NOTREACHED(); - return {}; - } - - void PresentSwapChain(const SyncToken& sync_token, - const Mailbox& mailbox) override { - NOTREACHED(); - } - -#if defined(OS_FUCHSIA) - void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id, - zx::channel token) override { - NOTREACHED(); - } - void ReleaseSysmemBufferCollection( - gfx::SysmemBufferCollectionId id) override { - NOTREACHED(); - } -#endif // defined(OS_FUCHSIA) - - void UpdateSharedImage(const SyncToken& sync_token, - const Mailbox& mailbox) override { - UpdateSharedImage(sync_token, nullptr, mailbox); - } - - void UpdateSharedImage(const SyncToken& sync_token, - std::unique_ptr<gfx::GpuFence> acquire_fence, - const Mailbox& mailbox) override { - DCHECK(!acquire_fence); - base::AutoLock lock(lock_); - // Note: we enqueue the task under the lock to guarantee monotonicity of - // the release ids as seen by the service. Unretained is safe because - // InProcessCommandBuffer synchronizes with the GPU thread at destruction - // time, cancelling tasks, before |this| is destroyed. - parent_->ScheduleGpuTask( - base::BindOnce(&InProcessCommandBuffer::UpdateSharedImageOnGpuThread, - gpu_thread_weak_ptr_, mailbox, - MakeSyncToken(next_fence_sync_release_++)), - {sync_token}); - } - - void DestroySharedImage(const SyncToken& sync_token, - const Mailbox& mailbox) override { - // Use sync token dependency to ensure that the destroy task does not run - // before sync token is released. - parent_->ScheduleGpuTask( - base::BindOnce(&InProcessCommandBuffer::DestroySharedImageOnGpuThread, - gpu_thread_weak_ptr_, mailbox), - {sync_token}); - } - - SyncToken GenUnverifiedSyncToken() override { - base::AutoLock lock(lock_); - return MakeSyncToken(next_fence_sync_release_ - 1); - } - - SyncToken GenVerifiedSyncToken() override { - base::AutoLock lock(lock_); - SyncToken sync_token = MakeSyncToken(next_fence_sync_release_ - 1); - sync_token.SetVerifyFlush(); - return sync_token; - } - - void Flush() override { - // No need to flush in this implementation. - } - - scoped_refptr<gfx::NativePixmap> GetNativePixmap( - const gpu::Mailbox& mailbox) override { - DCHECK(parent_->GetSharedImageManager()->is_thread_safe()); - return parent_->GetSharedImageManager()->GetNativePixmap(mailbox); - } - - CommandBufferId command_buffer_id() const { return command_buffer_id_; } - - private: - SyncToken MakeSyncToken(uint64_t release_id) { - return SyncToken(CommandBufferNamespace::IN_PROCESS, command_buffer_id_, - release_id); - } - - InProcessCommandBuffer* const parent_; - base::WeakPtr<InProcessCommandBuffer> gpu_thread_weak_ptr_; - - const CommandBufferId command_buffer_id_; - - // Accessed on any thread. release_id_lock_ protects access to - // next_fence_sync_release_. - base::Lock lock_; - uint64_t next_fence_sync_release_ = 1; - - DISALLOW_COPY_AND_ASSIGN(SharedImageInterface); -}; +bool InProcessCommandBuffer::SharedImageInterfaceHelper::EnableWrappedSkImage() + const { + // We need WrappedSkImage to support creating a SharedImage with pixel data + // when GL is unavailable. This is used in various unit tests. + return command_buffer_->context_state_ && + !command_buffer_->context_state_->GrContextIsGL(); +} InProcessCommandBuffer::InProcessCommandBuffer( CommandBufferTaskExecutor* task_executor, @@ -341,7 +177,6 @@ // and not the current (client) sequence except for webview (see Initialize). DETACH_FROM_SEQUENCE(gpu_sequence_checker_); DCHECK(task_executor_); - shared_image_interface_ = std::make_unique<SharedImageInterface>(this); } InProcessCommandBuffer::~InProcessCommandBuffer() { @@ -477,8 +312,14 @@ WrapTaskWithResult(std::move(init_task), &result, &completion), {}); completion.Wait(); - if (result == gpu::ContextResult::kSuccess) + if (result == gpu::ContextResult::kSuccess) { capabilities_ = capabilities; + shared_image_interface_ = std::make_unique<SharedImageInterfaceInProcess>( + task_executor_, task_sequence_, NextCommandBufferId(), + context_group_->mailbox_manager(), image_factory_, + context_group_->memory_tracker(), + std::make_unique<SharedImageInterfaceHelper>(this)); + } return result; } @@ -620,14 +461,6 @@ task_executor_->sync_point_manager()->CreateSyncPointClientState( GetNamespaceID(), GetCommandBufferID(), task_sequence_->GetSequenceId()); - // Make the SharedImageInterface use the same sequence as the command buffer, - // it's necessary for WebView because of the blocking behavior. - // TODO(piman): see if it's worth using a different sequence for non-WebView. - shared_image_client_state_ = - task_executor_->sync_point_manager()->CreateSyncPointClientState( - CommandBufferNamespace::IN_PROCESS, - shared_image_interface_->command_buffer_id(), - task_sequence_->GetSequenceId()); if (context_group_->use_passthrough_cmd_decoder()) { // When using the passthrough command decoder, never share with other @@ -807,8 +640,9 @@ client_thread_weak_ptr_factory_.InvalidateWeakPtrs(); gpu_control_client_ = nullptr; + shared_image_interface_ = nullptr; // Here we block by using a WaitableEvent to make sure DestroyOnGpuThread is - // finshed as part of Destroy. + // finished as part of Destroy. base::WaitableEvent completion( base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED); @@ -836,8 +670,6 @@ gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs(); // Clean up GL resources if possible. bool have_context = context_.get() && context_->MakeCurrent(surface_.get()); - if (shared_image_factory_) - shared_image_factory_->DestroyAllSharedImages(have_context); base::Optional<gles2::ProgramCache::ScopedCacheUse> cache_use; if (have_context) cache_use = CreateCacheUse(); @@ -860,10 +692,6 @@ sync_point_client_state_->Destroy(); sync_point_client_state_ = nullptr; } - if (shared_image_client_state_) { - shared_image_client_state_->Destroy(); - shared_image_client_state_ = nullptr; - } gl_share_group_ = nullptr; context_group_ = nullptr; if (context_state_) @@ -1488,124 +1316,6 @@ base::BindOnce(std::move(callback), std::move(gpu_fence))); } -void InProcessCommandBuffer::LazyCreateSharedImageFactory() { - if (shared_image_factory_) - return; - - // We need WrappedSkImage to support creating a SharedImage with pixel data - // when GL is unavailable. This is used in various unit tests. - const bool enable_wrapped_sk_image = - context_state_ && !context_state_->GrContextIsGL(); - shared_image_factory_ = std::make_unique<SharedImageFactory>( - GetGpuPreferences(), context_group_->feature_info()->workarounds(), - GetGpuFeatureInfo(), context_state_.get(), - context_group_->mailbox_manager(), task_executor_->shared_image_manager(), - image_factory_, context_group_->memory_tracker(), - enable_wrapped_sk_image); -} - -void InProcessCommandBuffer::CreateSharedImageOnGpuThread( - const Mailbox& mailbox, - viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage, - const SyncToken& sync_token) { - DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); - // |shared_image_factory_| never writes to the surface, so skip unnecessary - // MakeCurrent to improve performance. https://crbug.com/457431 - if (context_ && !context_->IsCurrent(nullptr) && !MakeCurrent()) - return; - LazyCreateSharedImageFactory(); - if (!shared_image_factory_->CreateSharedImage(mailbox, format, size, - color_space, usage)) { - // Signal errors by losing the command buffer. - command_buffer_->SetParseError(error::kLostContext); - return; - } - context_group_->mailbox_manager()->PushTextureUpdates(sync_token); - shared_image_client_state_->ReleaseFenceSync(sync_token.release_count()); -} - -void InProcessCommandBuffer::CreateSharedImageWithDataOnGpuThread( - const Mailbox& mailbox, - viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage, - const SyncToken& sync_token, - std::vector<uint8_t> pixel_data) { - DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); - // |shared_image_factory_| never writes to the surface, so skip unnecessary - // MakeCurrent to improve performance. https://crbug.com/457431 - if (context_ && !context_->IsCurrent(nullptr) && !MakeCurrent()) - return; - LazyCreateSharedImageFactory(); - if (!shared_image_factory_->CreateSharedImage( - mailbox, format, size, color_space, usage, pixel_data)) { - // Signal errors by losing the command buffer. - command_buffer_->SetParseError(error::kLostContext); - return; - } - context_group_->mailbox_manager()->PushTextureUpdates(sync_token); - shared_image_client_state_->ReleaseFenceSync(sync_token.release_count()); -} - -void InProcessCommandBuffer::CreateGMBSharedImageOnGpuThread( - const Mailbox& mailbox, - gfx::GpuMemoryBufferHandle handle, - gfx::BufferFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage, - const SyncToken& sync_token) { - DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); - if (!MakeCurrent()) - return; - LazyCreateSharedImageFactory(); - // TODO(piman): add support for SurfaceHandle (for backbuffers for ozone/drm). - SurfaceHandle surface_handle = kNullSurfaceHandle; - if (!shared_image_factory_->CreateSharedImage( - mailbox, kInProcessCommandBufferClientId, std::move(handle), format, - surface_handle, size, color_space, usage)) { - // Signal errors by losing the command buffer. - command_buffer_->SetParseError(error::kLostContext); - return; - } - context_group_->mailbox_manager()->PushTextureUpdates(sync_token); - shared_image_client_state_->ReleaseFenceSync(sync_token.release_count()); -} - -void InProcessCommandBuffer::UpdateSharedImageOnGpuThread( - const Mailbox& mailbox, - const SyncToken& sync_token) { - DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); - if (!MakeCurrent()) - return; - if (!shared_image_factory_ || - !shared_image_factory_->UpdateSharedImage(mailbox)) { - // Signal errors by losing the command buffer. - command_buffer_->SetParseError(error::kLostContext); - return; - } - context_group_->mailbox_manager()->PushTextureUpdates(sync_token); - shared_image_client_state_->ReleaseFenceSync(sync_token.release_count()); -} - -void InProcessCommandBuffer::DestroySharedImageOnGpuThread( - const Mailbox& mailbox) { - DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); - // |shared_image_factory_| never writes to the surface, so skip unnecessary - // MakeCurrent to improve performance. https://crbug.com/457431 - if (!context_->IsCurrent(nullptr) && !MakeCurrent()) - return; - if (!shared_image_factory_ || - !shared_image_factory_->DestroySharedImage(mailbox)) { - // Signal errors by losing the command buffer. - command_buffer_->SetParseError(error::kLostContext); - } -} - void InProcessCommandBuffer::SetLock(base::Lock*) { // No support for using on multiple threads. NOTREACHED();
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h index 584b93a..991f035 100644 --- a/gpu/ipc/in_process_command_buffer.h +++ b/gpu/ipc/in_process_command_buffer.h
@@ -71,8 +71,8 @@ class GpuProcessActivityFlags; class GpuMemoryBufferManager; class ImageFactory; -class SharedImageFactory; class SharedImageInterface; +class SharedImageInterfaceInProcess; class SyncPointClientState; struct ContextCreationAttribs; struct SwapBuffersCompleteParams; @@ -207,6 +207,22 @@ gpu::SharedImageInterface* GetSharedImageInterface() const; + // This is wrapper for VizSharedImageInterface implementation that is only + // used in InProcessCommandBuffer. + class SharedImageInterfaceHelper { + public: + explicit SharedImageInterfaceHelper(InProcessCommandBuffer* command_buffer); + ~SharedImageInterfaceHelper() = default; + + void SetError(); + void WrapTaskWithGpuCheck(base::OnceClosure task); + + bool EnableWrappedSkImage() const; + + private: + InProcessCommandBuffer* command_buffer_; + }; + // Provides a callback that can be used to preserve the back buffer for the // GLSurface associated with the command buffer, even after the command buffer // has been destroyed. The back buffer is evicted once the callback is @@ -220,8 +236,6 @@ } private: - class SharedImageInterface; - struct InitializeOnGpuThreadParams { SurfaceHandle surface_handle; const ContextCreationAttribs& attribs; @@ -297,30 +311,6 @@ void GetGpuFenceOnGpuThread( uint32_t gpu_fence_id, base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback); - void LazyCreateSharedImageFactory(); - void CreateSharedImageOnGpuThread(const Mailbox& mailbox, - viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage, - const SyncToken& sync_token); - void CreateSharedImageWithDataOnGpuThread(const Mailbox& mailbox, - viz::ResourceFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage, - const SyncToken& sync_token, - std::vector<uint8_t> pixel_data); - void CreateGMBSharedImageOnGpuThread(const Mailbox& mailbox, - gfx::GpuMemoryBufferHandle handle, - gfx::BufferFormat format, - const gfx::Size& size, - const gfx::ColorSpace& color_space, - uint32_t usage, - const SyncToken& sync_token); - void UpdateSharedImageOnGpuThread(const Mailbox& mailbox, - const SyncToken& sync_token); - void DestroySharedImageOnGpuThread(const Mailbox& mailbox); void SetDisplayTransformOnGpuThread(gfx::OverlayTransform transform); // Sets |active_url_| as the active GPU process URL. Should be called on GPU @@ -357,8 +347,6 @@ scoped_refptr<gl::GLContext> context_; scoped_refptr<gl::GLSurface> surface_; scoped_refptr<SyncPointClientState> sync_point_client_state_; - scoped_refptr<SyncPointClientState> shared_image_client_state_; - std::unique_ptr<SharedImageFactory> shared_image_factory_; // Used to throttle PerformDelayedWorkOnGpuThread. bool delayed_work_pending_ = false; @@ -393,7 +381,7 @@ // Pointer to the SingleTaskSequence that actually does the scheduling. SingleTaskSequence* task_sequence_; - std::unique_ptr<SharedImageInterface> shared_image_interface_; + std::unique_ptr<SharedImageInterfaceInProcess> shared_image_interface_; // The group of contexts that share namespaces with this context. scoped_refptr<gles2::ContextGroup> context_group_;
diff --git a/gpu/ipc/shared_image_interface_in_process.cc b/gpu/ipc/shared_image_interface_in_process.cc new file mode 100644 index 0000000..5114e910 --- /dev/null +++ b/gpu/ipc/shared_image_interface_in_process.cc
@@ -0,0 +1,425 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/ipc/shared_image_interface_in_process.h" + +#include "base/bind.h" +#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" +#include "gpu/command_buffer/common/sync_token.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/shared_image_factory.h" +#include "gpu/command_buffer/service/sync_point_manager.h" +#include "gpu/ipc/command_buffer_task_executor.h" +#include "gpu/ipc/common/gpu_client_ids.h" +#include "gpu/ipc/single_task_sequence.h" +#include "ui/gl/gl_context.h" + +namespace gpu { +SharedImageInterfaceInProcess::SharedImageInterfaceInProcess( + CommandBufferTaskExecutor* task_executor, + SingleTaskSequence* single_task_sequence, + CommandBufferId command_buffer_id, + MailboxManager* mailbox_manager, + ImageFactory* image_factory, + MemoryTracker* memory_tracker, + std::unique_ptr<CommandBufferHelper> command_buffer_helper) + : task_sequence_(single_task_sequence), + command_buffer_id_(command_buffer_id), + command_buffer_helper_(std::move(command_buffer_helper)), + shared_image_manager_(task_executor->shared_image_manager()), + mailbox_manager_(mailbox_manager), + sync_point_manager_(task_executor->sync_point_manager()) { + DETACH_FROM_SEQUENCE(gpu_sequence_checker_); + task_sequence_->ScheduleTask( + base::BindOnce(&SharedImageInterfaceInProcess::SetUpOnGpu, + base::Unretained(this), task_executor, image_factory, + memory_tracker), + {}); +} + +SharedImageInterfaceInProcess::~SharedImageInterfaceInProcess() { + base::WaitableEvent completion( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + + task_sequence_->ScheduleTask( + base::BindOnce(&SharedImageInterfaceInProcess::DestroyOnGpu, + base::Unretained(this), &completion), + {}); + completion.Wait(); +} + +void SharedImageInterfaceInProcess::SetUpOnGpu( + CommandBufferTaskExecutor* task_executor, + ImageFactory* image_factory, + MemoryTracker* memory_tracker) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + + context_state_ = task_executor->GetSharedContextState().get(); + create_factory_ = base::BindOnce( + [](CommandBufferTaskExecutor* task_executor, ImageFactory* image_factory, + MemoryTracker* memory_tracker, MailboxManager* mailbox_manager, + bool enable_wrapped_sk_image) { + auto shared_image_factory = std::make_unique<SharedImageFactory>( + task_executor->gpu_preferences(), + GpuDriverBugWorkarounds(task_executor->gpu_feature_info() + .enabled_gpu_driver_bug_workarounds), + task_executor->gpu_feature_info(), + task_executor->GetSharedContextState().get(), mailbox_manager, + task_executor->shared_image_manager(), image_factory, + memory_tracker, enable_wrapped_sk_image); + return shared_image_factory; + }, + task_executor, image_factory, memory_tracker, mailbox_manager_); + + // Make the SharedImageInterface use the same sequence as the command buffer, + // it's necessary for WebView because of the blocking behavior. + // TODO(piman): see if it's worth using a different sequence for non-WebView. + sync_point_client_state_ = sync_point_manager_->CreateSyncPointClientState( + CommandBufferNamespace::IN_PROCESS, command_buffer_id_, + task_sequence_->GetSequenceId()); +} + +void SharedImageInterfaceInProcess::DestroyOnGpu( + base::WaitableEvent* completion) { + bool have_context = MakeContextCurrent(); + if (shared_image_factory_) + shared_image_factory_->DestroyAllSharedImages(have_context); + + if (sync_point_client_state_) { + sync_point_client_state_->Destroy(); + sync_point_client_state_ = nullptr; + } + completion->Signal(); +} + +bool SharedImageInterfaceInProcess::MakeContextCurrent() { + if (!context_state_) + return false; + + if (context_state_->context_lost()) + return false; + + // |shared_image_factory_| never writes to the surface, so skip unnecessary + // MakeCurrent to improve performance. https://crbug.com/457431 + auto* context = context_state_->real_context(); + if (context->IsCurrent(nullptr) || + context->MakeCurrent(context_state_->surface())) + return true; + + context_state_->MarkContextLost(); + return false; +} + +void SharedImageInterfaceInProcess::LazyCreateSharedImageFactory() { + // This function is always called right after we call MakeContextCurrent(). + if (shared_image_factory_) + return; + + // We need WrappedSkImage to support creating a SharedImage with pixel data + // when GL is unavailable. This is used in various unit tests. + const bool enable_wrapped_sk_image = + command_buffer_helper_ && command_buffer_helper_->EnableWrappedSkImage(); + shared_image_factory_ = + std::move(create_factory_).Run(enable_wrapped_sk_image); +} + +Mailbox SharedImageInterfaceInProcess::CreateSharedImage( + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage) { + auto mailbox = Mailbox::GenerateForSharedImage(); + { + base::AutoLock lock(lock_); + // Note: we enqueue the task under the lock to guarantee monotonicity of + // the release ids as seen by the service. Unretained is safe because + // SharedImageInterfaceInProcess synchronizes with the GPU thread at + // destruction time, cancelling tasks, before |this| is destroyed. + ScheduleGpuTask( + base::BindOnce( + &SharedImageInterfaceInProcess::CreateSharedImageOnGpuThread, + base::Unretained(this), mailbox, format, size, color_space, usage, + MakeSyncToken(next_fence_sync_release_++)), + {}); + } + return mailbox; +} + +void SharedImageInterfaceInProcess::CreateSharedImageOnGpuThread( + const Mailbox& mailbox, + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + const SyncToken& sync_token) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + if (!MakeContextCurrent()) + return; + + LazyCreateSharedImageFactory(); + + if (!shared_image_factory_->CreateSharedImage(mailbox, format, size, + color_space, usage)) { + // Signal errors by losing the command buffer. + command_buffer_helper_->SetError(); + return; + } + mailbox_manager_->PushTextureUpdates(sync_token); + sync_point_client_state_->ReleaseFenceSync(sync_token.release_count()); +} + +Mailbox SharedImageInterfaceInProcess::CreateSharedImage( + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + base::span<const uint8_t> pixel_data) { + auto mailbox = Mailbox::GenerateForSharedImage(); + std::vector<uint8_t> pixel_data_copy(pixel_data.begin(), pixel_data.end()); + { + base::AutoLock lock(lock_); + // Note: we enqueue the task under the lock to guarantee monotonicity of + // the release ids as seen by the service. Unretained is safe because + // InProcessCommandBuffer synchronizes with the GPU thread at destruction + // time, cancelling tasks, before |this| is destroyed. + ScheduleGpuTask(base::BindOnce(&SharedImageInterfaceInProcess:: + CreateSharedImageWithDataOnGpuThread, + base::Unretained(this), mailbox, format, + size, color_space, usage, + MakeSyncToken(next_fence_sync_release_++), + std::move(pixel_data_copy)), + {}); + } + return mailbox; +} + +void SharedImageInterfaceInProcess::CreateSharedImageWithDataOnGpuThread( + const Mailbox& mailbox, + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + const SyncToken& sync_token, + std::vector<uint8_t> pixel_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + if (!MakeContextCurrent()) + return; + + LazyCreateSharedImageFactory(); + + if (!shared_image_factory_->CreateSharedImage( + mailbox, format, size, color_space, usage, pixel_data)) { + // Signal errors by losing the command buffer. + command_buffer_helper_->SetError(); + return; + } + mailbox_manager_->PushTextureUpdates(sync_token); + sync_point_client_state_->ReleaseFenceSync(sync_token.release_count()); +} + +Mailbox SharedImageInterfaceInProcess::CreateSharedImage( + gfx::GpuMemoryBuffer* gpu_memory_buffer, + GpuMemoryBufferManager* gpu_memory_buffer_manager, + const gfx::ColorSpace& color_space, + uint32_t usage) { + DCHECK(gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP || + gpu_memory_buffer->GetType() == gfx::ANDROID_HARDWARE_BUFFER || + gpu_memory_buffer_manager); + + // TODO(piman): DCHECK GMB format support. + DCHECK(IsImageSizeValidForGpuMemoryBufferFormat( + gpu_memory_buffer->GetSize(), gpu_memory_buffer->GetFormat())); + + auto mailbox = Mailbox::GenerateForSharedImage(); + gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle(); + bool requires_sync_token = handle.type == gfx::IO_SURFACE_BUFFER; + SyncToken sync_token; + { + base::AutoLock lock(lock_); + sync_token = MakeSyncToken(next_fence_sync_release_++); + // Note: we enqueue the task under the lock to guarantee monotonicity of + // the release ids as seen by the service. Unretained is safe because + // InProcessCommandBuffer synchronizes with the GPU thread at destruction + // time, cancelling tasks, before |this| is destroyed. + ScheduleGpuTask( + base::BindOnce( + &SharedImageInterfaceInProcess::CreateGMBSharedImageOnGpuThread, + base::Unretained(this), mailbox, std::move(handle), + gpu_memory_buffer->GetFormat(), gpu_memory_buffer->GetSize(), + color_space, usage, sync_token), + {}); + } + if (requires_sync_token) { + sync_token.SetVerifyFlush(); + gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer, + sync_token); + } + return mailbox; +} + +void SharedImageInterfaceInProcess::CreateGMBSharedImageOnGpuThread( + const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + const SyncToken& sync_token) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + if (!MakeContextCurrent()) + return; + + LazyCreateSharedImageFactory(); + + // TODO(piman): add support for SurfaceHandle (for backbuffers for ozone/drm). + SurfaceHandle surface_handle = kNullSurfaceHandle; + if (!shared_image_factory_->CreateSharedImage( + mailbox, kInProcessCommandBufferClientId, std::move(handle), format, + surface_handle, size, color_space, usage)) { + // Signal errors by losing the command buffer. + // Signal errors by losing the command buffer. + command_buffer_helper_->SetError(); + return; + } + mailbox_manager_->PushTextureUpdates(sync_token); + sync_point_client_state_->ReleaseFenceSync(sync_token.release_count()); +} + +SharedImageInterface::SwapChainMailboxes +SharedImageInterfaceInProcess::CreateSwapChain( + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage) { + NOTREACHED(); + return {}; +} + +void SharedImageInterfaceInProcess::PresentSwapChain( + const SyncToken& sync_token, + const Mailbox& mailbox) { + NOTREACHED(); +} + +#if defined(OS_FUCHSIA) +void SharedImageInterfaceInProcess::RegisterSysmemBufferCollection( + gfx::SysmemBufferCollectionId id, + zx::channel token) { + NOTREACHED(); +} +void SharedImageInterfaceInProcess::ReleaseSysmemBufferCollection( + gfx::SysmemBufferCollectionId id) { + NOTREACHED(); +} +#endif // defined(OS_FUCHSIA) + +void SharedImageInterfaceInProcess::UpdateSharedImage( + const SyncToken& sync_token, + const Mailbox& mailbox) { + UpdateSharedImage(sync_token, nullptr, mailbox); +} + +void SharedImageInterfaceInProcess::UpdateSharedImage( + const SyncToken& sync_token, + std::unique_ptr<gfx::GpuFence> acquire_fence, + const Mailbox& mailbox) { + DCHECK(!acquire_fence); + base::AutoLock lock(lock_); + // Note: we enqueue the task under the lock to guarantee monotonicity of + // the release ids as seen by the service. Unretained is safe because + // InProcessCommandBuffer synchronizes with the GPU thread at destruction + // time, cancelling tasks, before |this| is destroyed. + ScheduleGpuTask( + base::BindOnce( + &SharedImageInterfaceInProcess::UpdateSharedImageOnGpuThread, + base::Unretained(this), mailbox, + MakeSyncToken(next_fence_sync_release_++)), + {sync_token}); +} + +void SharedImageInterfaceInProcess::UpdateSharedImageOnGpuThread( + const Mailbox& mailbox, + const SyncToken& sync_token) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + if (!MakeContextCurrent()) + return; + + if (!shared_image_factory_ || + !shared_image_factory_->UpdateSharedImage(mailbox)) { + // Signal errors by losing the command buffer. + command_buffer_helper_->SetError(); + return; + } + mailbox_manager_->PushTextureUpdates(sync_token); + sync_point_client_state_->ReleaseFenceSync(sync_token.release_count()); +} + +void SharedImageInterfaceInProcess::DestroySharedImage( + const SyncToken& sync_token, + const Mailbox& mailbox) { + // Use sync token dependency to ensure that the destroy task does not run + // before sync token is released. + ScheduleGpuTask( + base::BindOnce( + &SharedImageInterfaceInProcess::DestroySharedImageOnGpuThread, + base::Unretained(this), mailbox), + {sync_token}); +} + +void SharedImageInterfaceInProcess::DestroySharedImageOnGpuThread( + const Mailbox& mailbox) { + DCHECK_CALLED_ON_VALID_SEQUENCE(gpu_sequence_checker_); + if (!MakeContextCurrent()) + return; + + if (!shared_image_factory_ || + !shared_image_factory_->DestroySharedImage(mailbox)) { + // Signal errors by losing the command buffer. + command_buffer_helper_->SetError(); + } +} + +SyncToken SharedImageInterfaceInProcess::GenUnverifiedSyncToken() { + base::AutoLock lock(lock_); + return MakeSyncToken(next_fence_sync_release_ - 1); +} + +SyncToken SharedImageInterfaceInProcess::GenVerifiedSyncToken() { + base::AutoLock lock(lock_); + SyncToken sync_token = MakeSyncToken(next_fence_sync_release_ - 1); + sync_token.SetVerifyFlush(); + return sync_token; +} + +void SharedImageInterfaceInProcess::Flush() { + // No need to flush in this implementation. +} + +scoped_refptr<gfx::NativePixmap> SharedImageInterfaceInProcess::GetNativePixmap( + const gpu::Mailbox& mailbox) { + DCHECK(shared_image_manager_->is_thread_safe()); + return shared_image_manager_->GetNativePixmap(mailbox); +} + +void SharedImageInterfaceInProcess::WrapTaskWithGpuUrl(base::OnceClosure task) { + if (command_buffer_helper_) { + command_buffer_helper_->WrapTaskWithGpuCheck(std::move(task)); + } else { + std::move(task).Run(); + } +} + +void SharedImageInterfaceInProcess::ScheduleGpuTask( + base::OnceClosure task, + std::vector<SyncToken> sync_token_fences) { + base::OnceClosure gpu_task = + base::BindOnce(&SharedImageInterfaceInProcess::WrapTaskWithGpuUrl, + base::Unretained(this), std::move(task)); + + task_sequence_->ScheduleTask(std::move(gpu_task), + std::move(sync_token_fences)); +} + +} // namespace gpu
diff --git a/gpu/ipc/shared_image_interface_in_process.h b/gpu/ipc/shared_image_interface_in_process.h new file mode 100644 index 0000000..e324a54 --- /dev/null +++ b/gpu/ipc/shared_image_interface_in_process.h
@@ -0,0 +1,220 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_IPC_SHARED_IMAGE_INTERFACE_IN_PROCESS_H_ +#define GPU_IPC_SHARED_IMAGE_INTERFACE_IN_PROCESS_H_ + +#include "build/build_config.h" +#include "gpu/command_buffer/client/shared_image_interface.h" +#include "gpu/command_buffer/common/command_buffer_id.h" +#include "gpu/ipc/in_process_command_buffer.h" + +namespace gpu { +class CommandBufferTaskExecutor; +class ImageFactory; +class MailboxManager; +class MemoryTracker; +class SyncPointClientState; +struct SyncToken; +class SharedContextState; +class SharedImageFactory; +class SharedImageManager; +class SingleTaskSequence; + +// This is an implementation of the SharedImageInterface to be used on viz +// compositor thread. This class also implements the corresponding parts +// happening on gpu thread. +// TODO(weiliangc): Currently this is implemented as backed by +// InProcessCommandBuffer. Add constructor for using with SkiaRenderer. +class GL_IN_PROCESS_CONTEXT_EXPORT SharedImageInterfaceInProcess + : public SharedImageInterface { + public: + using CommandBufferHelper = + InProcessCommandBuffer::SharedImageInterfaceHelper; + SharedImageInterfaceInProcess( + CommandBufferTaskExecutor* task_executor, + SingleTaskSequence* task_sequence, + CommandBufferId command_buffer_id, + MailboxManager* mailbox_manager, + ImageFactory* image_factory, + MemoryTracker* memory_tracker, + std::unique_ptr<CommandBufferHelper> command_buffer_helper); + ~SharedImageInterfaceInProcess() override; + + // The |SharedImageInterface| keeps ownership of the image until + // |DestroySharedImage| is called or the interface itself is destroyed (e.g. + // the GPU channel is lost). + Mailbox CreateSharedImage(viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage) override; + + // Same behavior as the above, except that this version takes |pixel_data| + // which is used to populate the SharedImage. |pixel_data| should have the + // same format which would be passed to glTexImage2D to populate a similarly + // specified texture. + Mailbox CreateSharedImage(viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + base::span<const uint8_t> pixel_data) override; + + // |usage| is a combination of |SharedImageUsage| bits that describes which + // API(s) the image will be used with. Format and size are derived from the + // GpuMemoryBuffer. |gpu_memory_buffer_manager| is the manager that created + // |gpu_memory_buffer|. If the |gpu_memory_buffer| was created on the client + // side (for NATIVE_PIXMAP or ANDROID_HARDWARE_BUFFER types only), without a + // GpuMemoryBufferManager, |gpu_memory_buffer_manager| can be nullptr. + // If valid, |color_space| will be applied to the shared + // image (possibly overwriting the one set on the GpuMemoryBuffer). + // The |SharedImageInterface| keeps ownership of the image until + // |DestroySharedImage| is called or the interface itself is destroyed (e.g. + // the GPU channel is lost). + Mailbox CreateSharedImage(gfx::GpuMemoryBuffer* gpu_memory_buffer, + GpuMemoryBufferManager* gpu_memory_buffer_manager, + const gfx::ColorSpace& color_space, + uint32_t usage) override; + + // Updates a shared image after its GpuMemoryBuffer (if any) was modified on + // the CPU or through external devices, after |sync_token| has been released. + void UpdateSharedImage(const SyncToken& sync_token, + const Mailbox& mailbox) override; + + // Updates a shared image after its GpuMemoryBuffer (if any) was modified on + // the CPU or through external devices, after |sync_token| has been released. + // If |acquire_fence| is not null, the fence is inserted in the GPU command + // stream and a server side wait is issued before any GPU command referring + // to this shared imaged is executed on the GPU. + void UpdateSharedImage(const SyncToken& sync_token, + std::unique_ptr<gfx::GpuFence> acquire_fence, + const Mailbox& mailbox) override; + + // Destroys the shared image, unregistering its mailbox, after |sync_token| + // has been released. After this call, the mailbox can't be used to reference + // the image any more, however if the image was imported into other APIs, + // those may keep a reference to the underlying data. + void DestroySharedImage(const SyncToken& sync_token, + const Mailbox& mailbox) override; + + // Creates a swap chain. Not reached in this implementation. + SwapChainMailboxes CreateSwapChain(viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage) override; + + // Swaps front and back buffer of a swap chain. Not reached in this + // implementation. + void PresentSwapChain(const SyncToken& sync_token, + const Mailbox& mailbox) override; + +#if defined(OS_FUCHSIA) + // Registers a sysmem buffer collection. Not reached in this implementation. + void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id, + zx::channel token) override; + + // Not reached in this implementation. + void ReleaseSysmemBufferCollection(gfx::SysmemBufferCollectionId id) override; +#endif // defined(OS_FUCHSIA) + + // Generates an unverified SyncToken that is released after all previous + // commands on this interface have executed on the service side. + SyncToken GenUnverifiedSyncToken() override; + + // Generates a verified SyncToken that is released after all previous + // commands on this interface have executed on the service side. + SyncToken GenVerifiedSyncToken() override; + + // Flush the SharedImageInterface, issuing any deferred IPCs. + void Flush() override; + + scoped_refptr<gfx::NativePixmap> GetNativePixmap( + const gpu::Mailbox& mailbox) override; + + private: + struct SharedImageFactoryInput; + + void SetUpOnGpu(CommandBufferTaskExecutor* task_executor, + ImageFactory* image_factory, + MemoryTracker* memory_tracker); + void DestroyOnGpu(base::WaitableEvent* completion); + + SyncToken MakeSyncToken(uint64_t release_id) { + return SyncToken(CommandBufferNamespace::IN_PROCESS, command_buffer_id_, + release_id); + } + + void ScheduleGpuTask(base::OnceClosure task, + std::vector<SyncToken> sync_token_fences); + + // Only called on the gpu thread. + bool MakeContextCurrent(); + void LazyCreateSharedImageFactory(); + void CreateSharedImageOnGpuThread(const Mailbox& mailbox, + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + const SyncToken& sync_token); + void CreateSharedImageWithDataOnGpuThread(const Mailbox& mailbox, + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + const SyncToken& sync_token, + std::vector<uint8_t> pixel_data); + + void CreateGMBSharedImageOnGpuThread(const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + uint32_t usage, + const SyncToken& sync_token); + void UpdateSharedImageOnGpuThread(const Mailbox& mailbox, + const SyncToken& sync_token); + void DestroySharedImageOnGpuThread(const Mailbox& mailbox); + void WrapTaskWithGpuUrl(base::OnceClosure task); + + // Used to schedule work on the gpu thread. This is a raw pointer for now + // since the ownership of SingleTaskSequence would be the same as the + // SharedImageInterfaceInProcess. + SingleTaskSequence* task_sequence_; + const CommandBufferId command_buffer_id_; + std::unique_ptr<CommandBufferHelper> command_buffer_helper_; + + base::OnceCallback<std::unique_ptr<SharedImageFactory>( + bool enable_wrapped_sk_image)> + create_factory_; + + // Sequence checker for tasks that run on the gpu "thread". + SEQUENCE_CHECKER(gpu_sequence_checker_); + + // Accessed on any thread. release_id_lock_ protects access to + // next_fence_sync_release_. + base::Lock lock_; + uint64_t next_fence_sync_release_ = 1; + + // Accessed on compositor thread. + // This is used to get NativePixmap, and is only used when SharedImageManager + // is thread safe. + SharedImageManager* shared_image_manager_; + + // Accessed on GPU thread. + // TODO(weiliangc): Check whether can be removed when !UsesSync(). + MailboxManager* mailbox_manager_; + // Used to check if context is lost at destruction time. + // TODO(weiliangc): SharedImageInterface should become active observer of + // whether context is lost. + SharedContextState* context_state_; + // Created and only used by this SharedImageInterface. + SyncPointManager* sync_point_manager_; + scoped_refptr<SyncPointClientState> sync_point_client_state_; + std::unique_ptr<SharedImageFactory> shared_image_factory_; + + DISALLOW_COPY_AND_ASSIGN(SharedImageInterfaceInProcess); +}; + +} // namespace gpu + +#endif // GPU_IPC_SHARED_IMAGE_INTERFACE_IN_PROCESS_H_
diff --git a/ios/build/bots/chromium.fyi/ios-device-goma-rbe-latest-clobber.json b/ios/build/bots/chromium.fyi/ios-device-goma-rbe-latest-clobber.json index ac165bde..5b1c7d9 100644 --- a/ios/build/bots/chromium.fyi/ios-device-goma-rbe-latest-clobber.json +++ b/ios/build/bots/chromium.fyi/ios-device-goma-rbe-latest-clobber.json
@@ -1,7 +1,7 @@ { "comments": [ "Goma RBE latest builder for iOS.", - "It is chromium.mac/ios-device.json + use_goma_canary, clobber." + "It is chromium.mac/ios-device.json + use_goma_latest, clobber." ], "xcode build version": "11a1027", "gn_args": [ @@ -12,7 +12,8 @@ "symbol_level=0", "target_cpu=\"arm64\"", "target_os=\"ios\"", - "use_goma=true" + "use_goma=true", + "ios_use_goma_rbe=true" ], "additional_compile_targets": [ "all"
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index 31e8882..b887399a 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -176,6 +176,9 @@ "media_content_type.cc", "media_content_type.h", "media_controller.h", + "media_error.cc", + "media_error.h", + "media_error_codes.h", "media_export.h", "media_log.cc", "media_log.h", @@ -529,6 +532,7 @@ "feedback_signal_accumulator_unittest.cc", "frame_rate_estimator_unittest.cc", "key_systems_unittest.cc", + "media_error_unittest.cc", "media_log_unittest.cc", "media_serializers_unittest.cc", "media_url_demuxer_unittest.cc",
diff --git a/media/base/media_error.cc b/media/base/media_error.cc new file mode 100644 index 0000000..64167ff --- /dev/null +++ b/media/base/media_error.cc
@@ -0,0 +1,68 @@ +// Copyright 2020 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 "media/base/media_error.h" +#include <memory> +#include "media/base/media_serializers.h" + +namespace media { + +MediaError::MediaError(ErrorCode code, + base::StringPiece message, + const base::Location& location) { + if (code == ErrorCode::kOk) { + DCHECK(message.empty()); + return; + } + + data_ = std::make_unique<MediaErrorInternal>(code, message); + AddFrame(location); +} + +// Copy Constructor +MediaError::MediaError(const MediaError& copy) { + if (copy.IsOk()) + return; + + data_ = std::make_unique<MediaErrorInternal>(copy.GetErrorCode(), + copy.GetErrorMessage()); + for (const base::Value& frame : copy.data_->frames) + data_->frames.push_back(frame.Clone()); + for (const MediaError& err : copy.data_->causes) + data_->causes.push_back(err); + data_->data = copy.data_->data.Clone(); +} + +// Allow move. +MediaError::MediaError(MediaError&&) = default; +MediaError& MediaError::operator=(MediaError&&) = default; + +MediaError::~MediaError() = default; + +MediaError::MediaErrorInternal::MediaErrorInternal(ErrorCode code, + base::StringPiece message) + : code(code), + message(message), + data(base::Value(base::Value::Type::DICTIONARY)) {} + +MediaError::MediaErrorInternal::~MediaErrorInternal() = default; + +MediaError&& MediaError::AddHere(const base::Location& location) && { + DCHECK(data_); + AddFrame(location); + return std::move(*this); +} + +MediaError&& MediaError::AddCause(MediaError&& cause) && { + DCHECK(data_ && cause.data_); + data_->causes.push_back(std::move(cause)); + return std::move(*this); +} + +void MediaError::AddFrame(const base::Location& location) { + DCHECK(data_); + data_->frames.push_back(MediaSerialize(location)); +} + +} // namespace media
diff --git a/media/base/media_error.h b/media/base/media_error.h new file mode 100644 index 0000000..a9e74ee --- /dev/null +++ b/media/base/media_error.h
@@ -0,0 +1,142 @@ +// Copyright 2020 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 MEDIA_BASE_MEDIA_ERROR_H_ +#define MEDIA_BASE_MEDIA_ERROR_H_ + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/location.h" +#include "base/strings/string_piece.h" +#include "base/values.h" +#include "media/base/media_error_codes.h" +#include "media/base/media_export.h" +#include "media/base/media_serializers_base.h" + +namespace media { + +// MediaError is meant to be a relatively small (sizeof(void*) bytes) object +// that can be returned as an error value from functions or passed to callbacks +// that want a report of status. MediaError allows attaching of arbitrary named +// data, other MediaErrors as causes, and stack frames, which can all be logged +// and reported throughout the media stack. The error code and message are +// immutable and can be used to give a stable numeric ID for any error +// generated by media code. +// There is also an OK state which can't hold any data and is only for +// successful returns. +class MEDIA_EXPORT MediaError { + public: + // Convenience function to return |kOk|. + // OK won't have a message, trace, or data associated with them, and DCHECK + // if they are added. + static MediaError Ok() { return MediaError(ErrorCode::kOk); } + + // Constructor to create a new MediaError from a numeric code & message. + // These are immutable; if you'd like to change them, then you likely should + // create a new MediaError. + // NOTE: This should never be given a location parameter when called - It is + // defaulted in order to grab the caller location. + MediaError(ErrorCode code, + base::StringPiece message = "", + const base::Location& location = base::Location::Current()); + + // Copy Constructor + MediaError(const MediaError& copy); + + // Allows move. + MediaError(MediaError&&); + MediaError& operator=(MediaError&&); + + // Needs an out of line destructor... + ~MediaError(); + + bool IsOk() const { return !data_; } + + // Getters for internal fields + base::StringPiece GetErrorMessage() const { + return data_ ? data_->message : ""; + } + ErrorCode GetErrorCode() const { + return data_ ? data_->code : ErrorCode::kOk; + } + + // Adds the current location to MediaError as it’s passed upwards. + // This does not need to be called at every location that touches it, but + // should be called for those locations where the path is ambiguous or + // critical. This can be especially helpful across IPC boundaries. This will + // fail on an OK status. + // NOTE: This should never be given a parameter when called - It is defaulted + // in order to grab the caller location. + MediaError&& AddHere( + const base::Location& location = base::Location::Current()) &&; + + // Add |cause| as the error that triggered this one. For example, + // DecoderStream might return kDecoderSelectionFailed with one or more causes + // that are the specific errors from the decoders that it tried. + MediaError&& AddCause(MediaError&& cause) &&; + void AddCause(MediaError&& cause) &; + + // Allows us to append any datatype which can be converted to + // an int/bool/string/base::Value. Any existing data associated with |key| + // will be overwritten by |value|. This will fail on an OK status. + template <typename T> + MediaError&& WithData(const char* key, const T& value) && { + DCHECK(data_); + data_->data.SetKey(key, MediaSerialize(value)); + return std::move(*this); + } + + template <typename T> + void WithData(const char* key, const T& value) & { + DCHECK(data_); + data_->data.SetKey(key, MediaSerialize(value)); + } + + private: + // Private helper to add the current stack frame to the error trace. + void AddFrame(const base::Location& location); + + // Keep the internal data in a unique ptr to minimize size of OK errors. + struct MediaErrorInternal { + MediaErrorInternal(ErrorCode code, base::StringPiece message); + ~MediaErrorInternal(); + + // The current error code + ErrorCode code = ErrorCode::kOk; + + // The current error message (Can be used for + // https://developer.mozilla.org/en-US/docs/Web/API/MediaError) + base::StringPiece message; + + // Stack frames + std::vector<base::Value> frames; + + // Causes + std::vector<MediaError> causes; + + // Data attached to the error + base::Value data; + }; + + // Allow self-serialization + friend struct internal::MediaSerializer<MediaError>; + + // A null internals is an implicit OK. + std::unique_ptr<MediaErrorInternal> data_; +}; + +// We need this two step macro to allow calling with no extra args - in a single +// step macro we would have no way of removing the trailing comma after the +// code. +#define MEDIA_ERROR(CODE_TRUNC, ...) \ + MEDIA_ERROR_INTERNAL(::media::ErrorCode::CODE_TRUNC, ##__VA_ARGS__) + +#define MEDIA_ERROR_INTERNAL(...) ::media::MediaError(__VA_ARGS__) + +} // namespace media + +#endif // MEDIA_BASE_MEDIA_ERROR_H_
diff --git a/media/base/media_error_codes.h b/media/base/media_error_codes.h new file mode 100644 index 0000000..4e0ecdff --- /dev/null +++ b/media/base/media_error_codes.h
@@ -0,0 +1,17 @@ +// Copyright 2020 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 MEDIA_BASE_MEDIA_ERROR_CODES_H_ +#define MEDIA_BASE_MEDIA_ERROR_CODES_H_ + +namespace media { + +enum class ErrorCode : uint32_t { + kOk = 0, + kCodeOnlyForTesting = std::numeric_limits<uint32_t>::max(), +}; + +} // namespace media + +#endif // MEDIA_BASE_MEDIA_ERROR_CODES_H_
diff --git a/media/base/media_error_unittest.cc b/media/base/media_error_unittest.cc new file mode 100644 index 0000000..4565e79 --- /dev/null +++ b/media/base/media_error_unittest.cc
@@ -0,0 +1,188 @@ +// Copyright 2020 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 <sstream> +#include <string> + +#include "base/json/json_writer.h" +#include "base/macros.h" +#include "media/base/media_error.h" +#include "media/base/media_serializers.h" +#include "media/base/test_helpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::HasSubstr; + +namespace media { + +class UselessThingToBeSerialized { + public: + explicit UselessThingToBeSerialized(const char* name) : name_(name) {} + const char* name_; +}; + +namespace internal { + +template <> +struct MediaSerializer<UselessThingToBeSerialized> { + static base::Value Serialize(const UselessThingToBeSerialized& t) { + return base::Value(t.name_); + } +}; + +} // namespace internal + +// Friend class of MediaLog for access to internal constants. +class MediaErrorTest : public testing::Test { + public: + MediaError DontFail() { return MediaError::Ok(); } + + MediaError FailEasily() { + return MEDIA_ERROR(kCodeOnlyForTesting, "Message"); + } + + MediaError FailRecursively(unsigned int count) { + if (!count) { + return FailEasily(); + } + return FailRecursively(count - 1).AddHere(); + } + + template <typename T> + MediaError FailWithData(const char* key, const T& t) { + return MediaError(ErrorCode::kCodeOnlyForTesting, "Message", FROM_HERE) + .WithData(key, t); + } + + MediaError FailWithCause() { + MediaError err = FailEasily(); + return FailEasily().AddCause(std::move(err)); + } + + MediaError DoSomethingGiveItBack(MediaError me) { + me.WithData("data", "Hey you! psst! Help me outta here! I'm trapped!"); + return me; + } +}; + +TEST_F(MediaErrorTest, StaticOKMethodGivesCorrectSerialization) { + MediaError ok = DontFail(); + base::Value actual = MediaSerialize(ok); + ASSERT_EQ(actual.GetString(), "Ok"); +} + +TEST_F(MediaErrorTest, SingleLayerError) { + MediaError failed = FailEasily(); + base::Value actual = MediaSerialize(failed); + ASSERT_EQ(actual.DictSize(), 5ul); + ASSERT_EQ(actual.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*actual.FindStringPath("error_message"), "Message"); + ASSERT_EQ(actual.FindListPath("stack")->GetList().size(), 1ul); + ASSERT_EQ(actual.FindListPath("causes")->GetList().size(), 0ul); + ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 0ul); + + const auto& stack = actual.FindListPath("stack")->GetList(); + ASSERT_EQ(stack[0].DictSize(), 2ul); // line and file + + // This is a bit fragile, since it's dependent on the file layout. + ASSERT_EQ(stack[0].FindIntPath("line").value_or(-1), 42); + ASSERT_THAT(*stack[0].FindStringPath("file"), + HasSubstr("media_error_unittest.cc")); +} + +TEST_F(MediaErrorTest, MultipleErrorLayer) { + MediaError failed = FailRecursively(3); + base::Value actual = MediaSerialize(failed); + ASSERT_EQ(actual.DictSize(), 5ul); + ASSERT_EQ(actual.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*actual.FindStringPath("error_message"), "Message"); + ASSERT_EQ(actual.FindListPath("stack")->GetList().size(), 4ul); + ASSERT_EQ(actual.FindListPath("causes")->GetList().size(), 0ul); + ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 0ul); + + const auto& stack = actual.FindListPath("stack")->GetList(); + ASSERT_EQ(stack[0].DictSize(), 2ul); // line and file +} + +TEST_F(MediaErrorTest, CanHaveData) { + MediaError failed = FailWithData("example", "data"); + base::Value actual = MediaSerialize(failed); + ASSERT_EQ(actual.DictSize(), 5ul); + ASSERT_EQ(actual.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*actual.FindStringPath("error_message"), "Message"); + ASSERT_EQ(actual.FindListPath("stack")->GetList().size(), 1ul); + ASSERT_EQ(actual.FindListPath("causes")->GetList().size(), 0ul); + ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 1ul); + + const auto& stack = actual.FindListPath("stack")->GetList(); + ASSERT_EQ(stack[0].DictSize(), 2ul); // line and file + + ASSERT_EQ(*actual.FindDictPath("data")->FindStringPath("example"), "data"); +} + +TEST_F(MediaErrorTest, CanUseCustomSerializer) { + MediaError failed = FailWithData("example", UselessThingToBeSerialized("F")); + base::Value actual = MediaSerialize(failed); + ASSERT_EQ(actual.DictSize(), 5ul); + ASSERT_EQ(actual.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*actual.FindStringPath("error_message"), "Message"); + ASSERT_EQ(actual.FindListPath("stack")->GetList().size(), 1ul); + ASSERT_EQ(actual.FindListPath("causes")->GetList().size(), 0ul); + ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 1ul); + + const auto& stack = actual.FindListPath("stack")->GetList(); + ASSERT_EQ(stack[0].DictSize(), 2ul); // line and file + + ASSERT_EQ(*actual.FindDictPath("data")->FindStringPath("example"), "F"); +} + +TEST_F(MediaErrorTest, CausedByHasVector) { + MediaError causal = FailWithCause(); + base::Value actual = MediaSerialize(causal); + ASSERT_EQ(actual.DictSize(), 5ul); + ASSERT_EQ(actual.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*actual.FindStringPath("error_message"), "Message"); + ASSERT_EQ(actual.FindListPath("stack")->GetList().size(), 1ul); + ASSERT_EQ(actual.FindListPath("causes")->GetList().size(), 1ul); + ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 0ul); + + base::Value& nested = actual.FindListPath("causes")->GetList()[0]; + ASSERT_EQ(nested.DictSize(), 5ul); + ASSERT_EQ(nested.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*nested.FindStringPath("error_message"), "Message"); + ASSERT_EQ(nested.FindListPath("stack")->GetList().size(), 1ul); + ASSERT_EQ(nested.FindListPath("causes")->GetList().size(), 0ul); + ASSERT_EQ(nested.FindDictPath("data")->DictSize(), 0ul); +} + +TEST_F(MediaErrorTest, CanCopyEasily) { + MediaError failed = FailEasily(); + MediaError withData = DoSomethingGiveItBack(failed); + + base::Value actual = MediaSerialize(failed); + ASSERT_EQ(actual.DictSize(), 5ul); + ASSERT_EQ(actual.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*actual.FindStringPath("error_message"), "Message"); + ASSERT_EQ(actual.FindListPath("stack")->GetList().size(), 1ul); + ASSERT_EQ(actual.FindListPath("causes")->GetList().size(), 0ul); + ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 0ul); + + actual = MediaSerialize(withData); + ASSERT_EQ(actual.DictSize(), 5ul); + ASSERT_EQ(actual.FindIntPath("error_code"), + static_cast<int>(ErrorCode::kCodeOnlyForTesting)); + ASSERT_EQ(*actual.FindStringPath("error_message"), "Message"); + ASSERT_EQ(actual.FindListPath("stack")->GetList().size(), 1ul); + ASSERT_EQ(actual.FindListPath("causes")->GetList().size(), 0ul); + ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 1ul); +} + +} // namespace media
diff --git a/media/base/media_serializers.h b/media/base/media_serializers.h index c3587beb..46c44f9 100644 --- a/media/base/media_serializers.h +++ b/media/base/media_serializers.h
@@ -7,9 +7,12 @@ #include <vector> +#include "base/location.h" #include "base/strings/stringprintf.h" #include "media/base/audio_decoder_config.h" #include "media/base/buffering_state.h" +#include "media/base/media_error.h" +#include "media/base/media_error_codes.h" #include "media/base/media_serializers_base.h" #include "media/base/video_decoder_config.h" #include "ui/gfx/geometry/size.h" @@ -344,6 +347,42 @@ } }; +// enum (simple) +template <> +struct MediaSerializer<media::ErrorCode> { + static inline base::Value Serialize(media::ErrorCode code) { + return base::Value(static_cast<int>(code)); + } +}; + +// Class (complex) +template <> +struct MediaSerializer<media::MediaError> { + static base::Value Serialize(const media::MediaError& err) { + if (err.IsOk()) + return base::Value("Ok"); + + base::Value result(base::Value::Type::DICTIONARY); + FIELD_SERIALIZE("error_code", err.GetErrorCode()); + FIELD_SERIALIZE("error_message", err.GetErrorMessage()); + FIELD_SERIALIZE("stack", err.data_->frames); + FIELD_SERIALIZE("data", err.data_->data); + FIELD_SERIALIZE("causes", err.data_->causes); + return result; + } +}; + +// Class (complex) +template <> +struct MediaSerializer<base::Location> { + static base::Value Serialize(const base::Location& value) { + base::Value result(base::Value::Type::DICTIONARY); + FIELD_SERIALIZE("file", value.file_name()); + FIELD_SERIALIZE("line", value.line_number()); + return result; + } +}; + #undef FIELD_SERIALIZE } // namespace internal
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 8744aa7..dc4c08f 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -612,6 +612,11 @@ const base::Feature kMediaLearningFramework{"MediaLearningFramework", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables the smoothness prediction experiment. Requires +// kMediaLearningFramework to be enabled also, else it does nothing. +const base::Feature kMediaLearningSmoothnessExperiment{ + "MediaLearningSmoothnessExperiment", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enable aggregate power measurement for media playback. const base::Feature kMediaPowerExperiment{"MediaPowerExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index ee44963d..7543de8 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -134,6 +134,7 @@ MEDIA_EXPORT extern const base::Feature kMediaInspectorLogging; MEDIA_EXPORT extern const base::Feature kMediaLearningExperiment; MEDIA_EXPORT extern const base::Feature kMediaLearningFramework; +MEDIA_EXPORT extern const base::Feature kMediaLearningSmoothnessExperiment; MEDIA_EXPORT extern const base::Feature kMediaPowerExperiment; MEDIA_EXPORT extern const base::Feature kMemoryPressureBasedSourceBufferGC; MEDIA_EXPORT extern const base::Feature kChromeosVideoDecoder;
diff --git a/media/blink/BUILD.gn b/media/blink/BUILD.gn index 16111731..a4e8c8f 100644 --- a/media/blink/BUILD.gn +++ b/media/blink/BUILD.gn
@@ -82,6 +82,7 @@ "//media", "//media:shared_memory_support", "//media/learning/common", + "//media/learning/mojo/public/cpp:cpp", "//media/mojo/mojom", "//net", "//services/network/public/cpp:cpp",
diff --git a/media/blink/learning_experiment_helper_unittest.cc b/media/blink/learning_experiment_helper_unittest.cc index 11cb0cd..6392602 100644 --- a/media/blink/learning_experiment_helper_unittest.cc +++ b/media/blink/learning_experiment_helper_unittest.cc
@@ -23,13 +23,14 @@ class MockLearningTaskController : public LearningTaskController { public: - MockLearningTaskController(const LearningTask& task) : task_(task) {} + explicit MockLearningTaskController(const LearningTask& task) : task_(task) {} ~MockLearningTaskController() override = default; - MOCK_METHOD3(BeginObservation, + MOCK_METHOD4(BeginObservation, void(base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_value)); + const base::Optional<TargetValue>& default_value, + const base::Optional<ukm::SourceId>& source_id)); MOCK_METHOD2(CompleteObservation, void(base::UnguessableToken id, const ObservationCompletion& completion)); @@ -81,7 +82,7 @@ }; TEST_F(LearningExperimentHelperTest, BeginComplete) { - EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _)); + EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _)); helper_->BeginObservation(dict_); TargetValue target(123); EXPECT_CALL(*controller_raw_, @@ -98,21 +99,21 @@ } TEST_F(LearningExperimentHelperTest, BeginCancel) { - EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _)); + EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _)); helper_->BeginObservation(dict_); EXPECT_CALL(*controller_raw_, CancelObservation(_)); helper_->CancelObservationIfNeeded(); } TEST_F(LearningExperimentHelperTest, CompleteWithoutBeginDoesNothing) { - EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _)).Times(0); + EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _)).Times(0); EXPECT_CALL(*controller_raw_, CompleteObservation(_, _)).Times(0); EXPECT_CALL(*controller_raw_, CancelObservation(_)).Times(0); helper_->CompleteObservationIfNeeded(TargetValue(123)); } TEST_F(LearningExperimentHelperTest, CancelWithoutBeginDoesNothing) { - EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _)).Times(0); + EXPECT_CALL(*controller_raw_, BeginObservation(_, _, _, _)).Times(0); EXPECT_CALL(*controller_raw_, CompleteObservation(_, _)).Times(0); EXPECT_CALL(*controller_raw_, CancelObservation(_)).Times(0); helper_->CancelObservationIfNeeded();
diff --git a/media/blink/smoothness_helper.cc b/media/blink/smoothness_helper.cc index 81b8ac1..ea4cabff 100644 --- a/media/blink/smoothness_helper.cc +++ b/media/blink/smoothness_helper.cc
@@ -12,7 +12,7 @@ namespace { static constexpr base::TimeDelta kSegmentSize = - base::TimeDelta::FromSeconds(60); + base::TimeDelta::FromSeconds(5); // Max proportion of dropped frames in a window before we call it "not smooth". static constexpr float kMaxDroppedFramesPerWindow = 0.2; @@ -67,14 +67,19 @@ int64_t segment_dropped_frames_; }; +SmoothnessHelper::SmoothnessHelper(const learning::FeatureVector& features) + : features_(features) {} + +SmoothnessHelper::~SmoothnessHelper() = default; + class SmoothnessHelperImpl : public SmoothnessHelper { public: SmoothnessHelperImpl( std::unique_ptr<LearningTaskController> consecutive_controller, const FeatureVector& features, Client* player) - : consecutive_bad_(std::move(consecutive_controller)), - features_(features), + : SmoothnessHelper(features), + consecutive_bad_(std::move(consecutive_controller)), player_(player) { monitor_ = std::make_unique<SmoothnessWindowMonitor>( player_, base::BindRepeating(&SmoothnessHelperImpl::OnWindow, @@ -95,7 +100,7 @@ // Once we get one full window, default to 0 for the consecutive windows // prediction task. if (!consecutive_bad_.is_started()) - consecutive_bad_.UpdateObservation(features_, TargetValue(0)); + consecutive_bad_.UpdateObservation(features(), TargetValue(0)); // If this is a bad window, extend the run of consecutive bad windows, and // update the target value if this is a new longest run. @@ -104,7 +109,7 @@ if (consecutive_bad_windows_ > max_consecutive_bad_windows_) { max_consecutive_bad_windows_ = consecutive_bad_windows_; consecutive_bad_.UpdateObservation( - features_, TargetValue(max_consecutive_bad_windows_)); + features(), TargetValue(max_consecutive_bad_windows_)); } } else { consecutive_bad_windows_ = 0; @@ -151,8 +156,6 @@ int consecutive_bad_windows_ = 0; int max_consecutive_bad_windows_ = 0; - FeatureVector features_; - // WebMediaPlayer which will tell us about the decoded / dropped frame counts. Client* player_;
diff --git a/media/blink/smoothness_helper.h b/media/blink/smoothness_helper.h index b4f302d..abdec26 100644 --- a/media/blink/smoothness_helper.h +++ b/media/blink/smoothness_helper.h
@@ -34,7 +34,10 @@ virtual unsigned DroppedFrameCount() const = 0; }; - virtual ~SmoothnessHelper() = default; + virtual ~SmoothnessHelper(); + + // Return the features that we were constructed with. + const learning::FeatureVector& features() const { return features_; } // |features| are the features that we'll use for any labelled examples that // we create. They should be features that could be captured at the time a @@ -48,6 +51,11 @@ // dropped frame ratio over all segments of a playback. A playback is not // recorded if it doesn't contain at least one full segment. static base::TimeDelta SegmentSizeForTesting(); + + protected: + SmoothnessHelper(const learning::FeatureVector& features); + + learning::FeatureVector features_; }; } // namespace media
diff --git a/media/blink/smoothness_helper_unittest.cc b/media/blink/smoothness_helper_unittest.cc index 4b1b730..2b1ccd6 100644 --- a/media/blink/smoothness_helper_unittest.cc +++ b/media/blink/smoothness_helper_unittest.cc
@@ -45,10 +45,11 @@ class SmoothnessHelperTest : public testing::Test { class MockLearningTaskController : public LearningTaskController { public: - MOCK_METHOD3(BeginObservation, + MOCK_METHOD4(BeginObservation, void(base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target)); + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id)); MOCK_METHOD2(CompleteObservation, void(base::UnguessableToken id, @@ -118,7 +119,7 @@ int total_frames = 0; // First segment has no dropped frames. Should record 0. - EXPECT_CALL(*consecutive_ltc_, BeginObservation(_, _, OPT_TARGET(0.0))) + EXPECT_CALL(*consecutive_ltc_, BeginObservation(_, _, OPT_TARGET(0.0), _)) .Times(1); SetFrameCounters(dropped_frames += 0, total_frames += 1000); FastForwardBy(segment_size_);
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index ecd6cd2..75710dd 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -52,6 +52,8 @@ #include "media/filters/chunk_demuxer.h" #include "media/filters/ffmpeg_demuxer.h" #include "media/filters/memory_data_source.h" +#include "media/learning/common/media_learning_tasks.h" +#include "media/learning/mojo/public/cpp/mojo_learning_task_controller.h" #include "media/media_buildflags.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/data_url.h" @@ -750,6 +752,9 @@ if (observer_) observer_->OnPlaying(); + // Try to create the smoothness helper, in case we were paused before. + UpdateSmoothnessHelper(); + watch_time_reporter_->SetAutoplayInitiated(client_->WasAutoplayInitiated()); // If we're seeking we'll trigger the watch time reporter upon seek completed; @@ -786,6 +791,8 @@ // No longer paused because it was hidden. paused_when_hidden_ = false; + UpdateSmoothnessHelper(); + // User initiated pause locks background videos. if (frame_->HasTransientUserActivation()) video_locked_when_paused_when_hidden_ = true; @@ -2221,6 +2228,9 @@ CreateVideoDecodeStatsReporter(); } + // Create or replace the smoothness helper now that we have a size. + UpdateSmoothnessHelper(); + client_->SizeChanged(); if (observer_) @@ -2244,6 +2254,9 @@ DCHECK(main_task_runner_->BelongsToCurrentThread()); if (power_status_helper_) power_status_helper_->SetAverageFrameRate(fps); + + last_reported_fps_ = fps; + UpdateSmoothnessHelper(); } void WebMediaPlayerImpl::OnAudioConfigChange(const AudioDecoderConfig& config) { @@ -3662,4 +3675,50 @@ current_frame_override_ = current_frame_override; } +void WebMediaPlayerImpl::UpdateSmoothnessHelper() { + // If the experiment flag is off, then do nothing. + if (!base::FeatureList::IsEnabled(kMediaLearningSmoothnessExperiment)) + return; + + // If we're paused, or if we can't get all the features, then clear any + // smoothness helper and stop. We'll try to create it later when we're + // playing and have all the features. + if (paused_ || !HasVideo() || pipeline_metadata_.natural_size.IsEmpty() || + !last_reported_fps_) { + smoothness_helper_.reset(); + return; + } + + // Fill in features. + // NOTE: this is a very bad way to do this, since it memorizes the order of + // features in the task. However, it'll do for now. + learning::FeatureVector features; + features.push_back( + learning::FeatureValue(pipeline_metadata_.video_decoder_config.codec())); + features.push_back(learning::FeatureValue( + pipeline_metadata_.video_decoder_config.profile())); + features.push_back( + learning::FeatureValue(pipeline_metadata_.natural_size.width())); + features.push_back(learning::FeatureValue(*last_reported_fps_)); + + // If we have a smoothness helper, and we're not changing the features, then + // do nothing. This prevents restarting the helper for no reason. + if (smoothness_helper_ && features == smoothness_helper_->features()) + return; + + // Create or restart the smoothness helper with |features|. + // Get the LearningTaskController for |task|. + learning::LearningTask task = learning::MediaLearningTasks::Get( + learning::MediaLearningTasks::Id::kConsecutiveBadWindows); + + mojo::Remote<media::learning::mojom::LearningTaskController> remote_ltc; + media_metrics_provider_->AcquireLearningTaskController( + task.name, remote_ltc.BindNewPipeAndPassReceiver()); + auto mojo_ltc = std::make_unique<learning::MojoLearningTaskController>( + task, std::move(remote_ltc)); + + smoothness_helper_ = + SmoothnessHelper::Create(std::move(mojo_ltc), features, this); +} + } // namespace media
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 7f5a2efe4..53c195f 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -40,6 +40,7 @@ #include "media/blink/media_blink_export.h" #include "media/blink/multibuffer_data_source.h" #include "media/blink/power_status_helper.h" +#include "media/blink/smoothness_helper.h" #include "media/blink/video_frame_compositor.h" #include "media/blink/webmediaplayer_params.h" #include "media/filters/pipeline_controller.h" @@ -93,7 +94,8 @@ public blink::WebMediaPlayerDelegate::Observer, public Pipeline::Client, public MediaObserverClient, - public blink::WebSurfaceLayerBridgeObserver { + public blink::WebSurfaceLayerBridgeObserver, + public SmoothnessHelper::Client { public: // Constructs a WebMediaPlayer implementation using Chromium's media stack. // |delegate| and |renderer_factory_selector| must not be null. @@ -629,6 +631,12 @@ void SetCurrentFrameOverrideForTesting( scoped_refptr<VideoFrame> current_frame_override); + // Create / recreate |smoothness_helper_|, with current features. Will take + // no action if we already have a smoothness helper with the same features + // that we want now. Will destroy the helper if we shouldn't be measuring + // smoothness right now. + void UpdateSmoothnessHelper(); + blink::WebLocalFrame* const frame_; // The playback state last reported to |delegate_|, to avoid setting duplicate @@ -1019,6 +1027,10 @@ std::unique_ptr<PowerStatusHelper> power_status_helper_; + // Created while playing, deleted otherwise. + std::unique_ptr<SmoothnessHelper> smoothness_helper_; + base::Optional<int> last_reported_fps_; + base::WeakPtr<WebMediaPlayerImpl> weak_this_; base::WeakPtrFactory<WebMediaPlayerImpl> weak_factory_{this};
diff --git a/media/learning/common/learning_task_controller.h b/media/learning/common/learning_task_controller.h index 8d5f1a9..64ba5a2c 100644 --- a/media/learning/common/learning_task_controller.h +++ b/media/learning/common/learning_task_controller.h
@@ -25,20 +25,15 @@ struct ObservationCompletion { ObservationCompletion() = default; /* implicit */ ObservationCompletion(const TargetValue& target, - WeightType w = 1., - ukm::SourceId id = ukm::kInvalidSourceId) - : target_value(target), weight(w), source_id(id) {} + WeightType w = 1.) + : target_value(target), weight(w) {} TargetValue target_value; WeightType weight; - // Optional, and ignored from the renderer. - ukm::SourceId source_id; - // Mostly for gmock matchers. bool operator==(const ObservationCompletion& rhs) const { - return target_value == rhs.target_value && weight == rhs.weight && - source_id == rhs.source_id; + return target_value == rhs.target_value && weight == rhs.weight; } }; @@ -73,8 +68,8 @@ virtual void BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target = - base::Optional<TargetValue>()) = 0; + const base::Optional<TargetValue>& default_target = base::nullopt, + const base::Optional<ukm::SourceId>& source_id = base::nullopt) = 0; // Complete an observation by sending a completion. virtual void CompleteObservation(base::UnguessableToken id,
diff --git a/media/learning/common/media_learning_tasks.cc b/media/learning/common/media_learning_tasks.cc index d11a57e..d695c58 100644 --- a/media/learning/common/media_learning_tasks.cc +++ b/media/learning/common/media_learning_tasks.cc
@@ -17,11 +17,45 @@ return task_; } +static const LearningTask& GetConsecutiveBadWindowsTask() { + static LearningTask task_; + if (!task_.feature_descriptions.size()) { + task_.name = "MediaLearningConsecutiveBadWindows"; + task_.model = LearningTask::Model::kExtraTrees; + + // Target is max number of consecutive bad windows. + task_.target_description = {"max_bad_windows", + LearningTask::Ordering::kNumeric}; + + // TODO: Be sure to update webmediaplayer_impl if you change these, since it + // memorizes them. + task_.feature_descriptions.push_back( + {"codec", LearningTask::Ordering::kUnordered}); + task_.feature_descriptions.push_back( + {"profile", LearningTask::Ordering::kUnordered}); + task_.feature_descriptions.push_back( + {"width", LearningTask::Ordering::kNumeric}); + task_.feature_descriptions.push_back( + {"fps", LearningTask::Ordering::kNumeric}); + + // Report via UKM, but allow up to 100 bad windows, since it'll auto-scale + // to two digits of precision. Might as well use all of it, even if 100 + // consecutive bad windows is unlikely. + task_.report_via_ukm = true; + task_.ukm_min_input_value = 0.0; + task_.ukm_max_input_value = 100.0; + } + + return task_; +} + // static const LearningTask& MediaLearningTasks::Get(Id id) { switch (id) { case Id::kWillPlay: return GetWillPlayTask(); + case Id::kConsecutiveBadWindows: + return GetConsecutiveBadWindowsTask(); } } @@ -29,6 +63,7 @@ void MediaLearningTasks::Register( base::RepeatingCallback<void(const LearningTask&)> cb) { cb.Run(Get(Id::kWillPlay)); + cb.Run(Get(Id::kConsecutiveBadWindows)); } } // namespace learning
diff --git a/media/learning/common/media_learning_tasks.h b/media/learning/common/media_learning_tasks.h index e5deb0f..798c05e 100644 --- a/media/learning/common/media_learning_tasks.h +++ b/media/learning/common/media_learning_tasks.h
@@ -21,6 +21,7 @@ // Ids for each LearningTask. enum class Id { kWillPlay, + kConsecutiveBadWindows, }; // Return the LearningTask for |id|.
diff --git a/media/learning/common/media_learning_tasks_unittest.cc b/media/learning/common/media_learning_tasks_unittest.cc index 727893d1..9f54b07 100644 --- a/media/learning/common/media_learning_tasks_unittest.cc +++ b/media/learning/common/media_learning_tasks_unittest.cc
@@ -24,13 +24,20 @@ EXPECT_EQ(task.name, "MediaLearningWillPlay"); } +TEST_F(MediaLearningTasksTest, ConsecutiveBadWindowsTask) { + LearningTask task = + MediaLearningTasks::Get(MediaLearningTasks::Id::kConsecutiveBadWindows); + // Make sure the name is correct, mostly to reduce cut-and-paste errors. + EXPECT_EQ(task.name, "MediaLearningConsecutiveBadWindows"); +} + TEST_F(MediaLearningTasksTest, EnumeratesAllTasks) { int count = 0; auto cb = base::BindRepeating( [](int* count, const LearningTask& task) { (*count)++; }, base::Unretained(&count)); MediaLearningTasks::Register(std::move(cb)); - EXPECT_EQ(count, 1); + EXPECT_EQ(count, 2); } } // namespace learning
diff --git a/media/learning/impl/learning_fuzzertest.cc b/media/learning/impl/learning_fuzzertest.cc index fd55555..8dc0554 100644 --- a/media/learning/impl/learning_fuzzertest.cc +++ b/media/learning/impl/learning_fuzzertest.cc
@@ -68,7 +68,7 @@ if (provider.ConsumeBool()) default_target = TargetValue(ConsumeDouble(&provider)); controller.BeginObservation(id, ConsumeFeatureVector(&provider), - default_target); + default_target, base::nullopt); controller.CompleteObservation( id, ObservationCompletion(TargetValue(ConsumeDouble(&provider)), ConsumeDouble(&provider)));
diff --git a/media/learning/impl/learning_session_impl.cc b/media/learning/impl/learning_session_impl.cc index f56a2df..39fe3da 100644 --- a/media/learning/impl/learning_session_impl.cc +++ b/media/learning/impl/learning_session_impl.cc
@@ -50,7 +50,8 @@ void BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target) override { + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id) override { if (!weak_session_) return; @@ -59,7 +60,7 @@ // doesn't support it. Since all client calls eventually come through us // anyway, it seems okay to handle it here. controller_->Post(FROM_HERE, &LearningTaskController::BeginObservation, id, - features, base::nullopt); + features, base::nullopt, source_id); } void CompleteObservation(base::UnguessableToken id,
diff --git a/media/learning/impl/learning_session_impl_unittest.cc b/media/learning/impl/learning_session_impl_unittest.cc index 3ab8089..c4b5fd9f 100644 --- a/media/learning/impl/learning_session_impl_unittest.cc +++ b/media/learning/impl/learning_session_impl_unittest.cc
@@ -43,10 +43,12 @@ void BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target) override { + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id) override { id_ = id; observation_features_ = features; default_target_ = default_target; + source_id_ = source_id; } void CompleteObservation(base::UnguessableToken id, @@ -86,6 +88,7 @@ FeatureVector predict_features_; PredictionCB predict_cb_; base::Optional<TargetValue> default_target_; + base::Optional<ukm::SourceId> source_id_; LabelledExample example_; // Most recently cancelled id. @@ -188,7 +191,8 @@ TargetValue(1234)); std::unique_ptr<LearningTaskController> ltc_0 = session_->GetController(task_0_.name); - ltc_0->BeginObservation(id, example_0.features); + ukm::SourceId source_id(123); + ltc_0->BeginObservation(id, example_0.features, base::nullopt, source_id); ltc_0->CompleteObservation( id, ObservationCompletion(example_0.target_value, example_0.weight)); @@ -203,6 +207,7 @@ task_environment_.RunUntilIdle(); EXPECT_EQ(task_controllers_[0]->example_, example_0); + EXPECT_EQ(task_controllers_[0]->source_id_, source_id); EXPECT_EQ(task_controllers_[1]->example_, example_1); }
diff --git a/media/learning/impl/learning_task_controller_helper.cc b/media/learning/impl/learning_task_controller_helper.cc index 6b05067..753dfb0 100644 --- a/media/learning/impl/learning_task_controller_helper.cc +++ b/media/learning/impl/learning_task_controller_helper.cc
@@ -24,10 +24,15 @@ LearningTaskControllerHelper::~LearningTaskControllerHelper() = default; -void LearningTaskControllerHelper::BeginObservation(base::UnguessableToken id, - FeatureVector features) { +void LearningTaskControllerHelper::BeginObservation( + base::UnguessableToken id, + FeatureVector features, + base::Optional<ukm::SourceId> source_id) { auto& pending_example = pending_examples_[id]; + if (source_id) + pending_example.source_id = *source_id; + // Start feature prediction, so that we capture the current values. if (!feature_provider_.is_null()) { feature_provider_.Post( @@ -50,7 +55,6 @@ iter->second.example.target_value = completion.target_value; iter->second.example.weight = completion.weight; iter->second.target_done = true; - iter->second.source_id = completion.source_id; ProcessExampleIfFinished(std::move(iter)); }
diff --git a/media/learning/impl/learning_task_controller_helper.h b/media/learning/impl/learning_task_controller_helper.h index 28318655..69e59a1 100644 --- a/media/learning/impl/learning_task_controller_helper.h +++ b/media/learning/impl/learning_task_controller_helper.h
@@ -47,7 +47,9 @@ virtual ~LearningTaskControllerHelper(); // See LearningTaskController::BeginObservation. - void BeginObservation(base::UnguessableToken id, FeatureVector features); + void BeginObservation(base::UnguessableToken id, + FeatureVector features, + base::Optional<ukm::SourceId> source_id); void CompleteObservation(base::UnguessableToken id, const ObservationCompletion& completion); void CancelObservation(base::UnguessableToken id);
diff --git a/media/learning/impl/learning_task_controller_helper_unittest.cc b/media/learning/impl/learning_task_controller_helper_unittest.cc index 003cc0c..1d07742 100644 --- a/media/learning/impl/learning_task_controller_helper_unittest.cc +++ b/media/learning/impl/learning_task_controller_helper_unittest.cc
@@ -108,11 +108,10 @@ // as they're done. CreateClient(false); ukm::SourceId source_id = 2; - helper_->BeginObservation(id_, example_.features); + helper_->BeginObservation(id_, example_.features, source_id); EXPECT_EQ(pending_example_count(), 1u); helper_->CompleteObservation( - id_, - ObservationCompletion(example_.target_value, example_.weight, source_id)); + id_, ObservationCompletion(example_.target_value, example_.weight)); EXPECT_TRUE(most_recent_example_); EXPECT_EQ(*most_recent_example_, example_); EXPECT_EQ(most_recent_example_->weight, example_.weight); @@ -123,7 +122,7 @@ TEST_F(LearningTaskControllerHelperTest, DropTargetValueWithoutFPWorks) { // Verify that we can drop an example without labelling it. CreateClient(false); - helper_->BeginObservation(id_, example_.features); + helper_->BeginObservation(id_, example_.features, base::nullopt); EXPECT_EQ(pending_example_count(), 1u); helper_->CancelObservation(id_); task_environment_.RunUntilIdle(); @@ -134,7 +133,7 @@ TEST_F(LearningTaskControllerHelperTest, AddTargetValueBeforeFP) { // Verify that an example is added if the target value arrives first. CreateClient(true); - helper_->BeginObservation(id_, example_.features); + helper_->BeginObservation(id_, example_.features, base::nullopt); EXPECT_EQ(pending_example_count(), 1u); task_environment_.RunUntilIdle(); // The feature provider should know about the example. @@ -159,7 +158,7 @@ TEST_F(LearningTaskControllerHelperTest, DropTargetValueBeforeFP) { // Verify that an example is correctly dropped before the FP adds features. CreateClient(true); - helper_->BeginObservation(id_, example_.features); + helper_->BeginObservation(id_, example_.features, base::nullopt); EXPECT_EQ(pending_example_count(), 1u); task_environment_.RunUntilIdle(); // The feature provider should know about the example. @@ -182,7 +181,7 @@ TEST_F(LearningTaskControllerHelperTest, AddTargetValueAfterFP) { // Verify that an example is added if the target value arrives second. CreateClient(true); - helper_->BeginObservation(id_, example_.features); + helper_->BeginObservation(id_, example_.features, base::nullopt); EXPECT_EQ(pending_example_count(), 1u); task_environment_.RunUntilIdle(); // The feature provider should know about the example. @@ -208,7 +207,7 @@ TEST_F(LearningTaskControllerHelperTest, DropTargetValueAfterFP) { // Verify that we can cancel the observationc after sending features. CreateClient(true); - helper_->BeginObservation(id_, example_.features); + helper_->BeginObservation(id_, example_.features, base::nullopt); EXPECT_EQ(pending_example_count(), 1u); task_environment_.RunUntilIdle(); // The feature provider should know about the example.
diff --git a/media/learning/impl/learning_task_controller_impl.cc b/media/learning/impl/learning_task_controller_impl.cc index 40bbd50e..1ec060c 100644 --- a/media/learning/impl/learning_task_controller_impl.cc +++ b/media/learning/impl/learning_task_controller_impl.cc
@@ -50,7 +50,8 @@ void LearningTaskControllerImpl::BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target) { + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id) { // TODO(liberato): Should we enforce that the right number of features are // present here? Right now, we allow it to be shorter, so that features from // a FeatureProvider may be omitted. Of course, they have to be at the end in @@ -65,7 +66,7 @@ // get here anyway. DCHECK(!default_target); - helper_->BeginObservation(id, features); + helper_->BeginObservation(id, features, source_id); } void LearningTaskControllerImpl::CompleteObservation(
diff --git a/media/learning/impl/learning_task_controller_impl.h b/media/learning/impl/learning_task_controller_impl.h index abc243cd..1453f1b7 100644 --- a/media/learning/impl/learning_task_controller_impl.h +++ b/media/learning/impl/learning_task_controller_impl.h
@@ -54,7 +54,8 @@ void BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target) override; + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id) override; void CompleteObservation(base::UnguessableToken id, const ObservationCompletion& completion) override; void CancelObservation(base::UnguessableToken id) override;
diff --git a/media/learning/impl/learning_task_controller_impl_unittest.cc b/media/learning/impl/learning_task_controller_impl_unittest.cc index 3b68cd2..38945699 100644 --- a/media/learning/impl/learning_task_controller_impl_unittest.cc +++ b/media/learning/impl/learning_task_controller_impl_unittest.cc
@@ -35,11 +35,13 @@ dist += info.observed; if (dist == predicted) num_correct_++; + most_recent_source_id_ = info.source_id; } public: int num_reported_ = 0; int num_correct_ = 0; + ukm::SourceId most_recent_source_id_; }; // Model that always predicts a constant. @@ -130,9 +132,11 @@ controller_->SetTrainerForTesting(std::move(fake_trainer)); } - void AddExample(const LabelledExample& example) { + void AddExample(const LabelledExample& example, + base::Optional<ukm::SourceId> source_id = base::nullopt) { base::UnguessableToken id = base::UnguessableToken::Create(); - controller_->BeginObservation(id, example.features, base::nullopt); + controller_->BeginObservation(id, example.features, base::nullopt, + source_id); controller_->CompleteObservation( id, ObservationCompletion(example.target_value, example.weight)); } @@ -285,5 +289,16 @@ VerifyPrediction(example.features, expected_histogram); } +TEST_F(LearningTaskControllerImplTest, + SourceIdIsProvidedToDistributionReporter) { + CreateController(); + LabelledExample example; + ukm::SourceId source_id(123); + // Add two examples, so that the second causes a prediction to be reported. + AddExample(example, source_id); + AddExample(example, source_id); + EXPECT_EQ(reporter_raw_->most_recent_source_id_, source_id); +} + } // namespace learning } // namespace media
diff --git a/media/learning/mojo/mojo_learning_task_controller_service.cc b/media/learning/mojo/mojo_learning_task_controller_service.cc index 22ab35ac..92dc1e17 100644 --- a/media/learning/mojo/mojo_learning_task_controller_service.cc +++ b/media/learning/mojo/mojo_learning_task_controller_service.cc
@@ -18,8 +18,9 @@ MojoLearningTaskControllerService::MojoLearningTaskControllerService( const LearningTask& task, + ukm::SourceId source_id, std::unique_ptr<::media::learning::LearningTaskController> impl) - : task_(task), impl_(std::move(impl)) {} + : task_(task), source_id_(source_id), impl_(std::move(impl)) {} MojoLearningTaskControllerService::~MojoLearningTaskControllerService() = default; @@ -39,7 +40,7 @@ // Since we own |impl_|, we don't need to keep track of in-flight // observations. We'll release |impl_| on destruction, which cancels them. - impl_->BeginObservation(id, features, default_target); + impl_->BeginObservation(id, features, default_target, source_id_); } void MojoLearningTaskControllerService::CompleteObservation(
diff --git a/media/learning/mojo/mojo_learning_task_controller_service.h b/media/learning/mojo/mojo_learning_task_controller_service.h index 3222681..eff098f 100644 --- a/media/learning/mojo/mojo_learning_task_controller_service.h +++ b/media/learning/mojo/mojo_learning_task_controller_service.h
@@ -22,8 +22,11 @@ : public mojom::LearningTaskController { public: // |impl| is the underlying controller that we'll send requests to. + // |source_id| will be used for all observations, since we don't trust the + // client to provide the right one. explicit MojoLearningTaskControllerService( const LearningTask& task, + ukm::SourceId source_id, std::unique_ptr<::media::learning::LearningTaskController> impl); ~MojoLearningTaskControllerService() override; @@ -44,6 +47,8 @@ protected: const LearningTask task_; + ukm::SourceId source_id_; + // Underlying controller to which we proxy calls. std::unique_ptr<::media::learning::LearningTaskController> impl_;
diff --git a/media/learning/mojo/mojo_learning_task_controller_service_unittest.cc b/media/learning/mojo/mojo_learning_task_controller_service_unittest.cc index 39d5b0d..971e6dc 100644 --- a/media/learning/mojo/mojo_learning_task_controller_service_unittest.cc +++ b/media/learning/mojo/mojo_learning_task_controller_service_unittest.cc
@@ -13,6 +13,11 @@ #include "media/learning/mojo/mojo_learning_task_controller_service.h" #include "testing/gtest/include/gtest/gtest.h" +namespace { +// Meaningless, but non-empty, source id. +ukm::SourceId kSourceId{123}; +} // namespace + namespace media { namespace learning { @@ -23,10 +28,12 @@ void BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target) override { + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id) override { begin_args_.id_ = id; begin_args_.features_ = features; - begin_args_.default_target_ = std::move(default_target); + begin_args_.default_target_ = default_target; + begin_args_.source_id_ = source_id; } void CompleteObservation(base::UnguessableToken id, @@ -60,6 +67,7 @@ base::UnguessableToken id_; FeatureVector features_; base::Optional<TargetValue> default_target_; + base::Optional<ukm::SourceId> source_id_; } begin_args_; struct { @@ -97,7 +105,7 @@ // Tell |learning_controller_| to forward to the fake learner impl. service_ = std::make_unique<MojoLearningTaskControllerService>( - task_, std::move(controller)); + task_, kSourceId, std::move(controller)); } LearningTask task_; @@ -118,6 +126,8 @@ EXPECT_EQ(id, controller_raw_->begin_args_.id_); EXPECT_EQ(features, controller_raw_->begin_args_.features_); EXPECT_FALSE(controller_raw_->begin_args_.default_target_); + EXPECT_TRUE(controller_raw_->begin_args_.source_id_); + EXPECT_EQ(*controller_raw_->begin_args_.source_id_, kSourceId); ObservationCompletion completion(TargetValue(1234)); service_->CompleteObservation(id, completion); @@ -148,6 +158,8 @@ EXPECT_EQ(id, controller_raw_->begin_args_.id_); EXPECT_EQ(features, controller_raw_->begin_args_.features_); EXPECT_EQ(default_target, controller_raw_->begin_args_.default_target_); + EXPECT_TRUE(controller_raw_->begin_args_.source_id_); + EXPECT_EQ(*controller_raw_->begin_args_.source_id_, kSourceId); } TEST_F(MojoLearningTaskControllerServiceTest, TooFewFeaturesIsIgnored) {
diff --git a/media/learning/mojo/public/cpp/BUILD.gn b/media/learning/mojo/public/cpp/BUILD.gn index c9070ef..2f70a90 100644 --- a/media/learning/mojo/public/cpp/BUILD.gn +++ b/media/learning/mojo/public/cpp/BUILD.gn
@@ -2,10 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("cpp") { +component("cpp") { visibility = [ "//media/learning/mojo:impl", "//media/learning/mojo/public/cpp:unit_tests", + "//media/blink", ] sources = [
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc b/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc index 8a1df7d..3d7b16cb 100644 --- a/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc +++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller.cc
@@ -11,7 +11,7 @@ MojoLearningTaskController::MojoLearningTaskController( const LearningTask& task, - mojo::PendingRemote<mojom::LearningTaskController> controller) + mojo::Remote<mojom::LearningTaskController> controller) : task_(task), controller_(std::move(controller)) {} MojoLearningTaskController::~MojoLearningTaskController() = default; @@ -19,9 +19,13 @@ void MojoLearningTaskController::BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target) { + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id) { // We don't need to keep track of in-flight observations, since the service - // side handles it for us. + // side handles it for us. Also note that |source_id| is ignored; the service + // has no reason to trust it. It will fill it in for us. DCHECK in case + // somebody actually tries to send us one, expecting it to be used. + DCHECK(!source_id); controller_->BeginObservation(id, features, default_target); }
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller.h b/media/learning/mojo/public/cpp/mojo_learning_task_controller.h index 9a32b044..efe5067 100644 --- a/media/learning/mojo/public/cpp/mojo_learning_task_controller.h +++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller.h
@@ -11,7 +11,6 @@ #include "base/macros.h" #include "media/learning/common/learning_task_controller.h" #include "media/learning/mojo/public/mojom/learning_task_controller.mojom.h" -#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" namespace media { @@ -25,14 +24,15 @@ // whatever |controller| uses. MojoLearningTaskController( const LearningTask& task, - mojo::PendingRemote<mojom::LearningTaskController> controller); + mojo::Remote<mojom::LearningTaskController> controller); ~MojoLearningTaskController() override; // LearningTaskController void BeginObservation( base::UnguessableToken id, const FeatureVector& features, - const base::Optional<TargetValue>& default_target) override; + const base::Optional<TargetValue>& default_target, + const base::Optional<ukm::SourceId>& source_id) override; void CompleteObservation(base::UnguessableToken id, const ObservationCompletion& completion) override; void CancelObservation(base::UnguessableToken id) override;
diff --git a/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc b/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc index 2b902f0d..559cde7 100644 --- a/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc +++ b/media/learning/mojo/public/cpp/mojo_learning_task_controller_unittest.cc
@@ -91,8 +91,10 @@ task_.name = "MyLearningTask"; // Tell |learning_controller_| to forward to the fake learner impl. - learning_controller_ = std::make_unique<MojoLearningTaskController>( - task_, learning_controller_receiver_.BindNewPipeAndPassRemote()); + mojo::Remote<media::learning::mojom::LearningTaskController> remote( + learning_controller_receiver_.BindNewPipeAndPassRemote()); + learning_controller_ = + std::make_unique<MojoLearningTaskController>(task_, std::move(remote)); } // Mojo stuff. @@ -113,7 +115,8 @@ TEST_F(MojoLearningTaskControllerTest, BeginWithoutDefaultTarget) { base::UnguessableToken id = base::UnguessableToken::Create(); FeatureVector features = {FeatureValue(123), FeatureValue(456)}; - learning_controller_->BeginObservation(id, features, base::nullopt); + learning_controller_->BeginObservation(id, features, base::nullopt, + base::nullopt); task_environment_.RunUntilIdle(); EXPECT_EQ(id, fake_learning_controller_.begin_args_.id_); EXPECT_EQ(features, fake_learning_controller_.begin_args_.features_); @@ -124,7 +127,8 @@ base::UnguessableToken id = base::UnguessableToken::Create(); TargetValue default_target(987); FeatureVector features = {FeatureValue(123), FeatureValue(456)}; - learning_controller_->BeginObservation(id, features, default_target); + learning_controller_->BeginObservation(id, features, default_target, + base::nullopt); task_environment_.RunUntilIdle(); EXPECT_EQ(id, fake_learning_controller_.begin_args_.id_); EXPECT_EQ(features, fake_learning_controller_.begin_args_.features_); @@ -136,7 +140,8 @@ // Test if we can update the default target to a non-nullopt. base::UnguessableToken id = base::UnguessableToken::Create(); FeatureVector features = {FeatureValue(123), FeatureValue(456)}; - learning_controller_->BeginObservation(id, features, base::nullopt); + learning_controller_->BeginObservation(id, features, base::nullopt, + base::nullopt); TargetValue default_target(987); learning_controller_->UpdateDefaultTarget(id, default_target); task_environment_.RunUntilIdle(); @@ -151,7 +156,8 @@ base::UnguessableToken id = base::UnguessableToken::Create(); FeatureVector features = {FeatureValue(123), FeatureValue(456)}; TargetValue default_target(987); - learning_controller_->BeginObservation(id, features, default_target); + learning_controller_->BeginObservation(id, features, default_target, + base::nullopt); learning_controller_->UpdateDefaultTarget(id, base::nullopt); task_environment_.RunUntilIdle(); EXPECT_EQ(id, fake_learning_controller_.update_default_args_.id_);
diff --git a/media/mojo/services/media_metrics_provider.cc b/media/mojo/services/media_metrics_provider.cc index 01e57a4..f6cd6be 100644 --- a/media/mojo/services/media_metrics_provider.cc +++ b/media/mojo/services/media_metrics_provider.cc
@@ -310,7 +310,7 @@ mojo::MakeSelfOwnedReceiver( std::make_unique<learning::MojoLearningTaskControllerService>( - controller->GetLearningTask(), std::move(controller)), + controller->GetLearningTask(), source_id_, std::move(controller)), std::move(receiver)); }
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index ac7254c..55caac3 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h
@@ -220,8 +220,7 @@ // The proxy requested authentication (for tunnel establishment). NET_ERROR(PROXY_AUTH_REQUESTED, -127) -// The SSL server attempted to use a weak ephemeral Diffie-Hellman key. -NET_ERROR(SSL_WEAK_SERVER_EPHEMERAL_DH_KEY, -129) +// Error -129 was removed (SSL_WEAK_SERVER_EPHEMERAL_DH_KEY). // Could not create a connection to the proxy server. An error occurred // either in resolving its name, or in connecting a socket to it.
diff --git a/net/ssl/openssl_ssl_util.cc b/net/ssl/openssl_ssl_util.cc index f518521..77fa36a 100644 --- a/net/ssl/openssl_ssl_util.cc +++ b/net/ssl/openssl_ssl_util.cc
@@ -101,8 +101,6 @@ return ERR_SSL_DECRYPT_ERROR_ALERT; case SSL_R_TLSV1_UNRECOGNIZED_NAME: return ERR_SSL_UNRECOGNIZED_NAME_ALERT; - case SSL_R_BAD_DH_P_LENGTH: - return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY; case SSL_R_SERVER_CERT_CHANGED: return ERR_SSL_SERVER_CERT_CHANGED; case SSL_R_WRONG_VERSION_ON_EARLY_DATA:
diff --git a/ppapi/tests/test_network_proxy.cc b/ppapi/tests/test_network_proxy.cc index de355730..24ec9f1 100644 --- a/ppapi/tests/test_network_proxy.cc +++ b/ppapi/tests/test_network_proxy.cc
@@ -33,12 +33,15 @@ // Assume no one configures a proxy for localhost. ASSERT_EQ("DIRECT", callback.output().AsString()); - callback.WaitForResult(pp::NetworkProxy::GetProxyForURL( - instance_, pp::Var("https://use.proxy.test/"), callback.GetCallback())); + callback.WaitForResult( + pp::NetworkProxy::GetProxyForURL(instance_, + pp::Var("http://www.google.com"), + callback.GetCallback())); CHECK_CALLBACK_BEHAVIOR(callback); ASSERT_EQ(PP_OK, callback.result()); output = callback.output(); - ASSERT_EQ("PROXY proxy.test:80", callback.output().AsString()); + // Don't know what the proxy might be, but it should be a valid result. + ASSERT_TRUE(output.is_string()); callback.WaitForResult( pp::NetworkProxy::GetProxyForURL(instance_,
diff --git a/printing/backend/cups_printer.cc b/printing/backend/cups_printer.cc index c7d1893..ce0d781 100644 --- a/printing/backend/cups_printer.cc +++ b/printing/backend/cups_printer.cc
@@ -16,7 +16,6 @@ namespace { -const char kCUPSDeviceUri[] = "device-uri"; const char kCUPSPrinterInfoOpt[] = "printer-info"; const char kCUPSPrinterStateOpt[] = "printer-state"; @@ -124,12 +123,6 @@ return make_and_model ? std::string(make_and_model) : std::string(); } -std::string CupsPrinter::GetUri() const { - const char* uri = cupsGetOption(kCUPSDeviceUri, destination_->num_options, - destination_->options); - return uri ? std::string(uri) : std::string(); -} - bool CupsPrinter::EnsureDestInfo() const { if (dest_info_) return true;
diff --git a/printing/backend/cups_printer.h b/printing/backend/cups_printer.h index 7efb68c..c1310ac 100644 --- a/printing/backend/cups_printer.h +++ b/printing/backend/cups_printer.h
@@ -77,8 +77,6 @@ std::string GetMakeAndModel() const; - std::string GetUri() const; - // Lazily initialize dest info as it can require a network call bool EnsureDestInfo() const;
diff --git a/printing/printing_context_chromeos.cc b/printing/printing_context_chromeos.cc index f976bea1..f7b1680 100644 --- a/printing/printing_context_chromeos.cc +++ b/printing/printing_context_chromeos.cc
@@ -356,15 +356,6 @@ SetPrintableArea(settings_.get(), media, true); cups_options_ = SettingsToCupsOptions(*settings_); send_user_info_ = settings_->send_user_info(); - if (send_user_info_) { - DCHECK(printer_); - std::string uri_string = printer_->GetUri(); - const base::StringPiece uri(uri_string); - if (!uri.starts_with("ipps:") && !uri.starts_with("https:") && - !uri.starts_with("usb:") && !uri.starts_with("ippusb:")) { - return OnError(); - } - } username_ = send_user_info_ ? settings_->username() : std::string(); return OK;
diff --git a/remoting/protocol/connection_unittest.cc b/remoting/protocol/connection_unittest.cc index 023c41ac..401e6d06 100644 --- a/remoting/protocol/connection_unittest.cc +++ b/remoting/protocol/connection_unittest.cc
@@ -236,7 +236,7 @@ } } - const int kMaxErrorHz = 50; + const int kMaxErrorHz = 100; int left_hz = (left * kAudioSampleRate / (num_samples - skipped_samples)); EXPECT_LE(kTestAudioSignalFrequencyLeftHz - kMaxErrorHz, left_hz); EXPECT_GE(kTestAudioSignalFrequencyLeftHz + kMaxErrorHz, left_hz);
diff --git a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java index 3ed6f98c..2bea0e1f 100644 --- a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java +++ b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
@@ -490,6 +490,15 @@ try { mTagHandler.connect(); + + if (!mPendingPushOperation.ndefWriteOptions.overwrite + && !mTagHandler.canAlwaysOverwrite()) { + Log.w(TAG, "Cannot overwrite the NFC tag due to existing data on it."); + pendingPushOperationCompleted(createError(NdefErrorType.NOT_ALLOWED, + "NDEFWriteOptions#overwrite does not allow overwrite.")); + return; + } + mTagHandler.write(NdefMessageUtils.toNdefMessage(mPendingPushOperation.ndefMessage)); pendingPushOperationCompleted(null); } catch (InvalidNdefMessageException e) { @@ -523,11 +532,9 @@ return; } - android.nfc.NdefMessage message = null; - try { mTagHandler.connect(); - message = mTagHandler.read(); + android.nfc.NdefMessage message = mTagHandler.read(); if (message == null) { // Tag is formatted to support NDEF but does not contain a message yet. // Let's create one with no records so that watchers can be notified.
diff --git a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcTagHandler.java b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcTagHandler.java index 0ec1c10..846651de 100644 --- a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcTagHandler.java +++ b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcTagHandler.java
@@ -56,6 +56,8 @@ throws IOException, TagLostException, FormatException, IllegalStateException; public NdefMessage read() throws IOException, TagLostException, FormatException, IllegalStateException; + public boolean canAlwaysOverwrite() + throws IOException, TagLostException, FormatException, IllegalStateException; } /** @@ -80,6 +82,13 @@ throws IOException, TagLostException, FormatException, IllegalStateException { return mNdef.getNdefMessage(); } + + @Override + public boolean canAlwaysOverwrite() + throws IOException, TagLostException, FormatException, IllegalStateException { + // Getting null means the tag is empty, overwrite is safe. + return mNdef.getNdefMessage() == null; + } } /** @@ -103,6 +112,11 @@ public NdefMessage read() throws FormatException { return NdefMessageUtils.emptyNdefMessage(); } + + @Override + public boolean canAlwaysOverwrite() { + return true; + } } protected NfcTagHandler(TagTechnology tech, TagTechnologyHandler handler, byte[] id) { @@ -183,4 +197,13 @@ } return false; } + + /** + * Returns false only if the tag is already NDEF formatted and contains some records. Otherwise + * true. + */ + public boolean canAlwaysOverwrite() + throws IOException, TagLostException, FormatException, IllegalStateException { + return mTechHandler.canAlwaysOverwrite(); + } }
diff --git a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java index c09719a..e689a9b1 100644 --- a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java +++ b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
@@ -1279,6 +1279,7 @@ private NdefWriteOptions createNdefWriteOptions() { NdefWriteOptions pushOptions = new NdefWriteOptions(); pushOptions.ignoreRead = false; + pushOptions.overwrite = true; return pushOptions; }
diff --git a/services/device/public/mojom/nfc.mojom b/services/device/public/mojom/nfc.mojom index 87485b4..f8724d94 100644 --- a/services/device/public/mojom/nfc.mojom +++ b/services/device/public/mojom/nfc.mojom
@@ -88,9 +88,15 @@ }; struct NDEFWriteOptions { - // If the property is true, the write operation will suspend active watchers - // until its completion. + // Only the case of |ignore_read| being |true| matters: while this push + // operation is pending, even a NFC tag comes in proximity range, do not read + // it for all active watchers. bool ignore_read; + + // Only the case of |overwrite| being |false| matters: the push operation will + // read the NFC tag regardless of |ignore_read| to determine if it has NDEF + // records on it, and if yes, do not execute write. + bool overwrite; }; struct NDEFScanOptions {
diff --git a/services/network/cross_origin_read_blocking.cc b/services/network/cross_origin_read_blocking.cc index 836509a..6d55dd0 100644 --- a/services/network/cross_origin_read_blocking.cc +++ b/services/network/cross_origin_read_blocking.cc
@@ -294,6 +294,12 @@ "application/vnd.spreadsheet-openxml", "application/vnd.wordprocessing-openxml", "text/csv", + // Block signed documents to protect (potentially sensitive) unencrypted + // body of the signed document. There should be no need to block + // encrypted documents (e.g. `multipart/encrypted` nor + // `application/pgp-encrypted`) and no need to block the signatures (e.g. + // `application/pgp-signature`). + "multipart/signed", // Block multipart responses because a protected type (e.g. JSON) can // become multipart if returned in a range request with multiple parts. // This is compatible with the web because the renderer can only see into
diff --git a/services/network/cross_origin_read_blocking_unittest.cc b/services/network/cross_origin_read_blocking_unittest.cc index cf9cfdcf..3eda3908 100644 --- a/services/network/cross_origin_read_blocking_unittest.cc +++ b/services/network/cross_origin_read_blocking_unittest.cc
@@ -2640,6 +2640,7 @@ {"application/x-gzip", MimeType::kNeverSniffed}, {"application/zip", MimeType::kNeverSniffed}, {"multipart/byteranges", MimeType::kNeverSniffed}, + {"multipart/signed", MimeType::kNeverSniffed}, {"text/csv", MimeType::kNeverSniffed}, {"text/event-stream", MimeType::kNeverSniffed}, };
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 3303c5ed..b0d400e 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -603,6 +603,9 @@ "test_target": "//chrome/installer/util:installer_util_unittests" }, { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/autofill.interactive_ui_tests.filter" + ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -7978,6 +7981,9 @@ "test_target": "//chrome/installer/util:installer_util_unittests" }, { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/autofill.interactive_ui_tests.filter" + ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -9294,6 +9300,9 @@ "test_target": "//chrome/installer/util:installer_util_unittests" }, { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/autofill.interactive_ui_tests.filter" + ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index 3f8b971..d5f51fd 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -141,6 +141,12 @@ ] } +source_set("interactive_ui_tests_filters") { + testonly = true + + data = [ "//testing/buildbot/filters/autofill.interactive_ui_tests.filter" ] +} + source_set("linux_ozone_views_unittests_filters") { data = [ "//testing/buildbot/filters/ozone-linux.x11_views_unittests.filter" ] }
diff --git a/testing/buildbot/filters/autofill.interactive_ui_tests.filter b/testing/buildbot/filters/autofill.interactive_ui_tests.filter new file mode 100644 index 0000000..588e299 --- /dev/null +++ b/testing/buildbot/filters/autofill.interactive_ui_tests.filter
@@ -0,0 +1,3 @@ +# TODO(crbug.com/967588): Allow Win7 interactive_ui_tests to disable autofill tests. +-All/AutofillDynamicFormInteractiveTest.* +-AutofillInteractiveTest.*
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index e14821f..7c613e9 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -795,11 +795,27 @@ 'shards': 6, }, }, + 'Win 7 Tests x64 (1)': { + # These tests are continually flaky on Win7 bots, crbug.com/967588 + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/autofill.interactive_ui_tests.filter', + ], + }, # temporary, https://crbug.com/818832 'Win10 Tests x64 (dbg)': { 'experiment_percentage': 100, }, + 'Win7 Tests (1)': { + # These tests are continually flaky on Win7 bots, crbug.com/967588 + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/autofill.interactive_ui_tests.filter', + ], + }, 'Win7 Tests (dbg)(1)': { + # These tests are continually flaky on Win7 bots, crbug.com/967588 + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/autofill.interactive_ui_tests.filter', + ], 'swarming': { 'shards': 4, },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 2001ad0c..f06ff91 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -422,10 +422,9 @@ ], "experiments": [ { - "name": "Enabled_WithNotification", + "name": "Enabled_NoNotification", "params": { - "update_notification_interval_days": "21", - "update_notification_state": "true" + "flow": "best_effort" }, "enable_features": [ "InlineUpdateFlow" @@ -2704,6 +2703,21 @@ ] } ], + "ExpandablePaymentHandler": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ScrollToExpandPaymentHandler" + ] + } + ] + } + ], "ExpectCTReporting": [ { "platforms": [ @@ -4313,6 +4327,21 @@ ] } ], + "OmniboxAssistantVoiceSearch": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "OmniboxAssistantVoiceSearch" + ] + } + ] + } + ], "OmniboxBundledExperimentV1": [ { "platforms": [
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 5329ab6..ad179bd 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -5338,6 +5338,21 @@ reload anchorClick + experimental type InstallabilityErrorArgument extends object + properties + # Argument name (e.g. name:'minimum-icon-size-in-pixels'). + string name + # Argument value (e.g. value:'64'). + string value + + # The installability error + experimental type InstallabilityError extends object + properties + # The error id (e.g. 'manifest-missing-suitable-icon'). + string errorId + # The list of error arguments (e.g. {name:'minimum-icon-size-in-pixels', value:'64'}). + array of InstallabilityErrorArgument errorArguments + # Deprecated, please use addScriptToEvaluateOnNewDocument instead. experimental deprecated command addScriptToEvaluateOnLoad parameters @@ -5446,7 +5461,8 @@ experimental command getInstallabilityErrors returns - array of string errors + deprecated array of string errors + experimental array of InstallabilityError installabilityErrors experimental command getManifestIcons returns
diff --git a/third_party/blink/renderer/bindings/core/v8/generated.gni b/third_party/blink/renderer/bindings/core/v8/generated.gni index 532519f..e5a1bbb 100644 --- a/third_party/blink/renderer/bindings/core/v8/generated.gni +++ b/third_party/blink/renderer/bindings/core/v8/generated.gni
@@ -40,6 +40,8 @@ "$bindings_core_v8_output_dir/double_or_string.h", "$bindings_core_v8_output_dir/double_or_string_or_string_sequence.cc", "$bindings_core_v8_output_dir/double_or_string_or_string_sequence.h", + "$bindings_core_v8_output_dir/element_or_document.cc", + "$bindings_core_v8_output_dir/element_or_document.h", "$bindings_core_v8_output_dir/event_listener_options_or_boolean.cc", "$bindings_core_v8_output_dir/event_listener_options_or_boolean.h", "$bindings_core_v8_output_dir/file_or_usv_string.cc",
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h index 2f4d94896..57f6585 100644 --- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h +++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
@@ -795,7 +795,7 @@ struct NativeValueTraits< T, typename std::enable_if_t<std::is_base_of<bindings::UnionBase, T>::value>> - : public NativeValueTraitsBase<T*> { + : public NativeValueTraitsBase<T> { static T NativeValue(v8::Isolate* isolate, v8::Local<v8::Value> value, ExceptionState& exception_state) {
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 8d286468c..8e4948f 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1195,92 +1195,6 @@ "frame/visual_viewport_test.cc", "fullscreen/scoped_allow_fullscreen_test.cc", "geometry/dom_matrix_test.cc", - "html/anchor_element_metrics_sender_test.cc", - "html/anchor_element_metrics_test.cc", - "html/canvas/canvas_async_blob_creator_test.cc", - "html/canvas/canvas_font_cache_test.cc", - "html/canvas/html_canvas_element_test.cc", - "html/canvas/image_data_test.cc", - "html/custom/custom_element_definition_test.cc", - "html/custom/custom_element_descriptor_test.cc", - "html/custom/custom_element_reaction_queue_test.cc", - "html/custom/custom_element_reaction_stack_test.cc", - "html/custom/custom_element_reaction_test_helpers.h", - "html/custom/custom_element_registry_test.cc", - "html/custom/custom_element_test.cc", - "html/custom/custom_element_test_helpers.cc", - "html/custom/custom_element_test_helpers.h", - "html/custom/custom_element_upgrade_sorter_test.cc", - "html/forms/email_input_type_test.cc", - "html/forms/external_date_time_chooser_test.cc", - "html/forms/external_popup_menu_test.cc", - "html/forms/file_input_type_test.cc", - "html/forms/form_controller_test.cc", - "html/forms/form_data_test.cc", - "html/forms/html_data_list_element_test.cc", - "html/forms/html_form_control_element_test.cc", - "html/forms/html_form_element_test.cc", - "html/forms/html_input_element_test.cc", - "html/forms/html_output_element_test.cc", - "html/forms/html_select_element_test.cc", - "html/forms/html_text_area_element_test.cc", - "html/forms/internal_popup_menu_test.cc", - "html/forms/option_list_test.cc", - "html/forms/password_input_type_test.cc", - "html/forms/step_range_test.cc", - "html/forms/text_control_element_test.cc", - "html/forms/type_ahead_test.cc", - "html/html_content_element_test.cc", - "html/html_dimension_test.cc", - "html/html_element_test.cc", - "html/html_embed_element_test.cc", - "html/html_frame_element_test.cc", - "html/html_iframe_element_test.cc", - "html/html_image_element_test.cc", - "html/html_link_element_sizes_attribute_test.cc", - "html/html_link_element_test.cc", - "html/html_meta_element_test.cc", - "html/html_object_element_test.cc", - "html/html_plugin_element_test.cc", - "html/html_slot_element_test.cc", - "html/html_table_row_element_test.cc", - "html/image_document_test.cc", - "html/imports/html_import_sheets_test.cc", - "html/lazy_load_frame_observer_test.cc", - "html/lazy_load_image_observer_test.cc", - "html/link_element_loading_test.cc", - "html/link_rel_attribute_test.cc", - "html/media/autoplay_uma_helper_test.cc", - "html/media/html_media_element_event_listeners_test.cc", - "html/media/html_media_element_test.cc", - "html/media/html_media_test_helper.cc", - "html/media/html_media_test_helper.h", - "html/media/html_video_element_persistent_test.cc", - "html/media/html_video_element_test.cc", - "html/media/media_custom_controls_fullscreen_detector_test.cc", - "html/media/video_auto_fullscreen_test.cc", - "html/media/video_filling_viewport_test.cc", - "html/media/video_wake_lock_test.cc", - "html/parser/atomic_html_token_test.cc", - "html/parser/compact_html_token_test.cc", - "html/parser/html_document_parser_loading_test.cc", - "html/parser/html_document_parser_test.cc", - "html/parser/html_entity_parser_test.cc", - "html/parser/html_parser_idioms_test.cc", - "html/parser/html_preload_scanner_document_test.cc", - "html/parser/html_preload_scanner_test.cc", - "html/parser/html_resource_preloader_test.cc", - "html/parser/html_srcset_parser_test.cc", - "html/parser/html_tokenizer_test.cc", - "html/parser/html_tree_builder_simulator_test.cc", - "html/parser/html_view_source_parser_test.cc", - "html/parser/text_resource_decoder_test.cc", - "html/portal/html_portal_element_test.cc", - "html/shadow/progress_shadow_element_test.cc", - "html/time_ranges_test.cc", - "html/track/text_track_list_test.cc", - "html/track/vtt/buffered_line_reader_test.cc", - "html/track/vtt/vtt_scanner_test.cc", "imagebitmap/image_bitmap_test.cc", "input/event_handler_test.cc", "input/fallback_cursor_event_manager_test.cc", @@ -1588,6 +1502,7 @@ "//third_party/blink/renderer/core/css:unit_tests", "//third_party/blink/renderer/core/editing:unit_tests", "//third_party/blink/renderer/core/fileapi:unit_tests", + "//third_party/blink/renderer/core/html:unit_tests", ] data_deps = [ ":unit_tests_data" ]
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc index f7c0484..3ff366de 100644 --- a/third_party/blink/renderer/core/css/media_values.cc +++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -20,7 +20,6 @@ #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" #include "third_party/blink/renderer/platform/graphics/color_space_gamut.h" namespace blink { @@ -139,13 +138,7 @@ } bool MediaValues::CalculateThreeDEnabled(LocalFrame* frame) { - DCHECK(frame); - DCHECK(frame->ContentLayoutObject()); - DCHECK(frame->ContentLayoutObject()->Compositor()); - bool three_d_enabled = false; - if (LayoutView* view = frame->ContentLayoutObject()) - three_d_enabled = view->Compositor()->HasAcceleratedCompositing(); - return three_d_enabled; + return frame->GetPage()->GetSettings().GetAcceleratedCompositingEnabled(); } bool MediaValues::CalculateInImmersiveMode(LocalFrame* frame) {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 2829f85..2bba91c 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -226,6 +226,7 @@ #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h" #include "third_party/blink/renderer/core/inspector/main_thread_debugger.h" +#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h" #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h" #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h" #include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h" @@ -6839,6 +6840,20 @@ return *intersection_observer_controller_; } +ElementIntersectionObserverData* +Document::DocumentExplicitRootIntersectionObserverData() const { + return document_explicit_root_intersection_observer_data_.Get(); +} + +ElementIntersectionObserverData& +Document::EnsureDocumentExplicitRootIntersectionObserverData() { + if (!document_explicit_root_intersection_observer_data_) { + document_explicit_root_intersection_observer_data_ = + MakeGarbageCollected<ElementIntersectionObserverData>(); + } + return *document_explicit_root_intersection_observer_data_; +} + ResizeObserverController& Document::EnsureResizeObserverController() { if (!resize_observer_controller_) { resize_observer_controller_ = @@ -7824,6 +7839,7 @@ visitor->Trace(elem_sheet_); visitor->Trace(node_iterators_); visitor->Trace(ranges_); + visitor->Trace(document_explicit_root_intersection_observer_data_); visitor->Trace(style_engine_); visitor->Trace(form_controller_); visitor->Trace(visited_link_state_);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 8a2f0b2..2e17781 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -98,6 +98,7 @@ class ChromeClient; class Comment; class ComputedAccessibleNode; +class ElementIntersectionObserverData; class WindowAgent; class WindowAgentFactory; class ComputedStyle; @@ -954,6 +955,14 @@ IntersectionObserverController* GetIntersectionObserverController(); IntersectionObserverController& EnsureIntersectionObserverController(); + // This is used to track IntersectionObservers for which this document is the + // explicit root. The IntersectionObserverController tracks *all* observers + // associated with this document; usually that's what you want. + ElementIntersectionObserverData* + DocumentExplicitRootIntersectionObserverData() const; + ElementIntersectionObserverData& + EnsureDocumentExplicitRootIntersectionObserverData(); + ResizeObserverController* GetResizeObserverController() const { return resize_observer_controller_; } @@ -1886,6 +1895,9 @@ MutationObserverOptions mutation_observer_types_; + Member<ElementIntersectionObserverData> + document_explicit_root_intersection_observer_data_; + Member<StyleEngine> style_engine_; Member<StyleSheetList> style_sheet_list_;
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index 67441a59..f62bf44c 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -202,9 +202,6 @@ pre_dispatch_event_handler_result) == kContinueDispatching) { if (DispatchEventAtCapturing() == kContinueDispatching) { - // TODO(crbug/882574): Remove these. - CHECK(event_->HasEventPath()); - CHECK(!event_->GetEventPath().IsEmpty()); if (DispatchEventAtTarget() == kContinueDispatching) DispatchEventAtBubbling(); }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index d9a6a9d6..6280a7f 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -242,8 +242,6 @@ bool GetIntrinsicSizingInfo(IntrinsicSizingInfo&) const override; bool HasIntrinsicSizingInfo() const override; - void UpdateAcceleratedCompositingSettings(); - void UpdateCountersAfterStyleChange(); void Dispose() override;
diff --git a/third_party/blink/renderer/core/html/BUILD.gn b/third_party/blink/renderer/core/html/BUILD.gn index 2c5aa64c..cd6d44da 100644 --- a/third_party/blink/renderer/core/html/BUILD.gn +++ b/third_party/blink/renderer/core/html/BUILD.gn
@@ -602,3 +602,94 @@ testonly = true data_deps = [ ":form_controls_pickers_js" ] } + +blink_core_tests("unit_tests") { + sources = [ + "anchor_element_metrics_sender_test.cc", + "anchor_element_metrics_test.cc", + "canvas/canvas_async_blob_creator_test.cc", + "canvas/canvas_font_cache_test.cc", + "canvas/html_canvas_element_test.cc", + "canvas/image_data_test.cc", + "custom/custom_element_definition_test.cc", + "custom/custom_element_descriptor_test.cc", + "custom/custom_element_reaction_queue_test.cc", + "custom/custom_element_reaction_stack_test.cc", + "custom/custom_element_reaction_test_helpers.h", + "custom/custom_element_registry_test.cc", + "custom/custom_element_test.cc", + "custom/custom_element_test_helpers.cc", + "custom/custom_element_test_helpers.h", + "custom/custom_element_upgrade_sorter_test.cc", + "forms/email_input_type_test.cc", + "forms/external_date_time_chooser_test.cc", + "forms/external_popup_menu_test.cc", + "forms/file_input_type_test.cc", + "forms/form_controller_test.cc", + "forms/form_data_test.cc", + "forms/html_data_list_element_test.cc", + "forms/html_form_control_element_test.cc", + "forms/html_form_element_test.cc", + "forms/html_input_element_test.cc", + "forms/html_output_element_test.cc", + "forms/html_select_element_test.cc", + "forms/html_text_area_element_test.cc", + "forms/internal_popup_menu_test.cc", + "forms/option_list_test.cc", + "forms/password_input_type_test.cc", + "forms/step_range_test.cc", + "forms/text_control_element_test.cc", + "forms/type_ahead_test.cc", + "html_content_element_test.cc", + "html_dimension_test.cc", + "html_element_test.cc", + "html_embed_element_test.cc", + "html_frame_element_test.cc", + "html_iframe_element_test.cc", + "html_image_element_test.cc", + "html_link_element_sizes_attribute_test.cc", + "html_link_element_test.cc", + "html_meta_element_test.cc", + "html_object_element_test.cc", + "html_plugin_element_test.cc", + "html_slot_element_test.cc", + "html_table_row_element_test.cc", + "image_document_test.cc", + "imports/html_import_sheets_test.cc", + "lazy_load_frame_observer_test.cc", + "lazy_load_image_observer_test.cc", + "link_element_loading_test.cc", + "link_rel_attribute_test.cc", + "media/autoplay_uma_helper_test.cc", + "media/html_media_element_event_listeners_test.cc", + "media/html_media_element_test.cc", + "media/html_media_test_helper.cc", + "media/html_media_test_helper.h", + "media/html_video_element_persistent_test.cc", + "media/html_video_element_test.cc", + "media/media_custom_controls_fullscreen_detector_test.cc", + "media/video_auto_fullscreen_test.cc", + "media/video_filling_viewport_test.cc", + "media/video_wake_lock_test.cc", + "parser/atomic_html_token_test.cc", + "parser/compact_html_token_test.cc", + "parser/html_document_parser_loading_test.cc", + "parser/html_document_parser_test.cc", + "parser/html_entity_parser_test.cc", + "parser/html_parser_idioms_test.cc", + "parser/html_preload_scanner_document_test.cc", + "parser/html_preload_scanner_test.cc", + "parser/html_resource_preloader_test.cc", + "parser/html_srcset_parser_test.cc", + "parser/html_tokenizer_test.cc", + "parser/html_tree_builder_simulator_test.cc", + "parser/html_view_source_parser_test.cc", + "parser/text_resource_decoder_test.cc", + "portal/html_portal_element_test.cc", + "shadow/progress_shadow_element_test.cc", + "time_ranges_test.cc", + "track/text_track_list_test.cc", + "track/vtt/buffered_line_reader_test.cc", + "track/vtt/vtt_scanner_test.cc", + ] +}
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index c8a6482..f8d653d 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -72,7 +72,6 @@ #include "third_party/blink/renderer/core/layout/layout_html_canvas.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/page/chrome_client.h" -#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_timing.h" #include "third_party/blink/renderer/core/probe/core_probes.h" @@ -601,7 +600,7 @@ if (layout_object->IsCanvas()) { if (old_size != Size()) { ToLayoutHTMLCanvas(layout_object)->CanvasSizeChanged(); - if (GetLayoutBox() && GetLayoutBox()->HasAcceleratedCompositing()) + if (GetDocument().GetSettings()->GetAcceleratedCompositingEnabled()) GetLayoutBox()->ContentChanged(kCanvasChanged); } if (had_resource_provider) @@ -616,7 +615,8 @@ DCHECK(context_); if (!context_->IsComposited()) return true; - if (GetLayoutBox() && GetLayoutBox()->HasAcceleratedCompositing()) + auto* settings = GetDocument().GetSettings(); + if (settings && settings->GetAcceleratedCompositingEnabled()) return false; return true; @@ -1049,7 +1049,8 @@ // The following is necessary for handling the special case of canvases in // the dev tools overlay, which run in a process that supports accelerated // 2d canvas but in a special compositing context that does not. - if (GetLayoutBox() && !GetLayoutBox()->HasAcceleratedCompositing()) + auto* settings = GetDocument().GetSettings(); + if (settings && !settings->GetAcceleratedCompositingEnabled()) return false; // Avoid creating |contextProvider| until we're sure we want to try use it,
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc index 4e48437..7c0eac3 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
@@ -188,29 +188,29 @@ root_to_document_transform = transform_state.AccumulatedTransform(); } -// If root_element is non-null, it is treated as the explicit root of an +// If root_node is non-null, it is treated as the explicit root of an // IntersectionObserver; if it is valid, its LayoutObject is returned. // -// If root_element is null, returns the object to be used as the implicit root +// If root_node is null, returns the object to be used as the implicit root // for a given target. // // https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-root const LayoutObject* IntersectionGeometry::GetRootLayoutObjectForTarget( - const Element* root_element, + const Node* root_node, LayoutObject* target, bool check_containing_block_chain) { - if (!root_element) + if (!root_node) return target ? LocalRootView(*target) : nullptr; - if (!root_element->isConnected()) + if (!root_node->isConnected()) return nullptr; LayoutObject* root = nullptr; if (RuntimeEnabledFeatures:: IntersectionObserverDocumentScrollingElementRootEnabled() && - root_element == root_element->GetDocument().scrollingElement()) { - root = root_element->GetDocument().GetLayoutView(); + root_node->IsDocumentNode()) { + root = To<Document>(root_node)->GetLayoutView(); } else { - root = root_element->GetLayoutObject(); + root = root_node->GetLayoutObject(); if (target && check_containing_block_chain && !IsContainingBlockChainDescendant(target, root)) { root = nullptr; @@ -219,7 +219,7 @@ return root; } -IntersectionGeometry::IntersectionGeometry(const Element* root_element, +IntersectionGeometry::IntersectionGeometry(const Node* root_node, const Element& target_element, const Vector<Length>& root_margin, const Vector<float>& thresholds, @@ -230,13 +230,13 @@ threshold_index_(0) { if (cached_rects) cached_rects->valid = false; - if (!root_element) + if (!root_node) flags_ |= kRootIsImplicit; LayoutObject* target = GetTargetLayoutObject(target_element); if (!target) return; - const LayoutObject* root = GetRootLayoutObjectForTarget( - root_element, target, !ShouldUseCachedRects()); + const LayoutObject* root = + GetRootLayoutObjectForTarget(root_node, target, !ShouldUseCachedRects()); if (!root) return; RootGeometry root_geometry(root, root_margin); @@ -244,7 +244,7 @@ } IntersectionGeometry::IntersectionGeometry(const RootGeometry& root_geometry, - const Element& explicit_root, + const Node& explicit_root, const Element& target_element, const Vector<float>& thresholds, unsigned flags,
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h index 8e9232b2..35e33f4 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_geometry.h
@@ -17,8 +17,9 @@ class Element; class LayoutObject; +class Node; -// Computes the intersection between an ancestor (root) element and a +// Computes the intersection between an ancestor (root) node and a // descendant (target) element, with overflow and CSS clipping applied. // Optionally also checks whether the target is occluded or has visual // effects applied. @@ -67,11 +68,11 @@ }; static const LayoutObject* GetRootLayoutObjectForTarget( - const Element* root_element, + const Node* root_node, LayoutObject* target, bool check_containing_block_chain); - IntersectionGeometry(const Element* root, + IntersectionGeometry(const Node* root, const Element& target, const Vector<Length>& root_margin, const Vector<float>& thresholds, @@ -79,7 +80,7 @@ CachedRects* cached_rects = nullptr); IntersectionGeometry(const RootGeometry& root_geometry, - const Element& explicit_root, + const Node& explicit_root, const Element& target, const Vector<float>& thresholds, unsigned flags,
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc index de486b65..27cc687 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
@@ -160,7 +160,12 @@ const IntersectionObserverInit* observer_init, IntersectionObserverDelegate& delegate, ExceptionState& exception_state) { - Element* root = observer_init->root(); + Node* root = nullptr; + if (observer_init->root().IsElement()) { + root = observer_init->root().GetAsElement(); + } else if (observer_init->root().IsDocument()) { + root = observer_init->root().GetAsDocument(); + } DOMHighResTimeStamp delay = 0; bool track_visibility = false; @@ -231,7 +236,7 @@ IntersectionObserver::IntersectionObserver( IntersectionObserverDelegate& delegate, - Element* root, + Node* root, const Vector<Length>& root_margin, const Vector<float>& thresholds, ThresholdInterpretation semantics, @@ -277,7 +282,14 @@ break; } if (root) { - root->EnsureIntersectionObserverData().AddObserver(*this); + if (root->IsDocumentNode()) { + To<Document>(root) + ->EnsureDocumentExplicitRootIntersectionObserverData() + .AddObserver(*this); + } else { + DCHECK(root->IsElementNode()); + To<Element>(root)->EnsureIntersectionObserverData().AddObserver(*this); + } root->GetDocument() .EnsureIntersectionObserverController() .AddTrackedObserver(*this, track_visibility);
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.h b/third_party/blink/renderer/core/intersection_observer/intersection_observer.h index 7f1b008..dcad8727 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.h
@@ -24,6 +24,7 @@ class IntersectionObserverDelegate; class IntersectionObserverEntry; class IntersectionObserverInit; +class Node; class ScriptState; class V8IntersectionObserverCallback; @@ -98,7 +99,7 @@ static void ResumeSuspendedObservers(); explicit IntersectionObserver(IntersectionObserverDelegate&, - Element*, + Node*, const Vector<Length>& root_margin, const Vector<float>& thresholds, ThresholdInterpretation semantics, @@ -114,14 +115,14 @@ ExceptionState& = ASSERT_NO_EXCEPTION); // API attributes. - Element* root() const { return root_.Get(); } + Node* root() const { return root_.Get(); } String rootMargin() const; const Vector<float>& thresholds() const { return thresholds_; } DOMHighResTimeStamp delay() const { return delay_; } bool trackVisibility() const { return track_visibility_; } bool trackFractionOfRoot() const { return track_fraction_of_root_; } - // An observer can either track intersections with an explicit root Element, + // An observer can either track intersections with an explicit root Node, // or with the the top-level frame's viewport (the "implicit root"). When // tracking the implicit root, root_ will be null, but because root_ is a // weak pointer, we cannot surmise that this observer tracks the implicit @@ -147,7 +148,7 @@ DeliveryBehavior GetDeliveryBehavior() const; void Deliver(); - // Returns false if this observer has an explicit root element which has been + // Returns false if this observer has an explicit root node which has been // deleted; true otherwise. bool RootIsValid() const; bool CanUseCachedRects() const { return can_use_cached_rects_; } @@ -166,7 +167,7 @@ void ProcessCustomWeakness(const WeakCallbackInfo&); const Member<IntersectionObserverDelegate> delegate_; - UntracedMember<Element> root_; + UntracedMember<Node> root_; HeapLinkedHashSet<WeakMember<IntersectionObservation>> observations_; Vector<float> thresholds_; DOMHighResTimeStamp delay_;
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl b/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl index 599d74c..ccb34d8 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.idl
@@ -10,8 +10,8 @@ Exposed=Window, ActiveScriptWrappable ] interface IntersectionObserver { - [CallWith=ScriptState, RaisesException, MeasureAs=IntersectionObserver_Constructor] constructor(IntersectionObserverCallback callback, optional IntersectionObserverInit options = {}); - readonly attribute Element? root; + [CallWith=ScriptState, RaisesException, MeasureAs=IntersectionObserver_Constructor] constructor(IntersectionObserverCallback callback, optional IntersectionObserverInit options); + readonly attribute Node? root; readonly attribute DOMString rootMargin; // https://github.com/WICG/IntersectionObserver/issues/114 readonly attribute FrozenArray<double> thresholds;
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h b/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h index 06de2d2..7393989 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h
@@ -54,6 +54,7 @@ const char* NameInHeapSnapshot() const override { return "IntersectionObserverController"; } + unsigned GetTrackedObserverCountForTesting() const { return explicit_root_observers_.size(); } @@ -72,7 +73,7 @@ // IntersectionObservers for which this is the execution context of the // callback, and with unsent notifications. HeapHashSet<Member<IntersectionObserver>> pending_intersection_observers_; - // This is 'true' if any tracked element is the target of an observer for + // This is 'true' if any tracked node is the target of an observer for // which observer->trackVisibility() is true. bool needs_occlusion_tracking_; };
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl b/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl index aec7427..e83f13d 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_init.idl
@@ -5,7 +5,7 @@ // https://wicg.github.io/IntersectionObserver/#intersection-observer-init dictionary IntersectionObserverInit { - Element? root = null; + (Element or Document)? root = null; DOMString rootMargin = "0px"; (double or sequence<double>) threshold = 0; [RuntimeEnabled=IntersectionObserverV2] DOMHighResTimeStamp delay = 0;
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc index 23d0d4c..36ef56c 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
@@ -13,6 +13,7 @@ #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/exported/web_view_impl.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" +#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h" #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h" #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h" @@ -132,7 +133,7 @@ Element* root = GetDocument().getElementById("root"); ASSERT_TRUE(root); IntersectionObserverInit* observer_init = IntersectionObserverInit::Create(); - observer_init->setRoot(root); + observer_init->setRoot(ElementOrDocument::FromElement(root)); DummyExceptionStateForTesting exception_state; TestIntersectionObserverDelegate* observer_delegate = MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument()); @@ -159,27 +160,32 @@ EXPECT_FALSE(observer_delegate->LastEntry()->isIntersecting()); } -TEST_F(IntersectionObserverTest, ScrollingElementRootClips) { +TEST_F(IntersectionObserverTest, DocumentRootClips) { ScopedIntersectionObserverDocumentScrollingElementRootForTest scope(true); WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); + SimRequest iframe_resource("https://example.com/iframe.html", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML( + <iframe src="iframe.html" style="width:200px; height:100px"></iframe> + )HTML"); + iframe_resource.Complete(R"HTML( <div id='target'>Hello, world!</div> <div id='spacer' style='height:2000px'></div> )HTML"); - Element* root = GetDocument().scrollingElement(); - ASSERT_TRUE(root); + Document* iframe_document = To<WebLocalFrameImpl>(MainFrame().FirstChild()) + ->GetFrame() + ->GetDocument(); IntersectionObserverInit* observer_init = IntersectionObserverInit::Create(); - observer_init->setRoot(root); + observer_init->setRoot(ElementOrDocument::FromDocument(iframe_document)); DummyExceptionStateForTesting exception_state; TestIntersectionObserverDelegate* observer_delegate = MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument()); IntersectionObserver* observer = IntersectionObserver::Create( observer_init, *observer_delegate, exception_state); ASSERT_FALSE(exception_state.HadException()); - Element* target = GetDocument().getElementById("target"); + Element* target = iframe_document->getElementById("target"); ASSERT_TRUE(target); observer->observe(target, exception_state); @@ -190,8 +196,8 @@ EXPECT_EQ(observer_delegate->EntryCount(), 1); EXPECT_TRUE(observer_delegate->LastEntry()->isIntersecting()); - GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 1000), - kProgrammaticScroll); + iframe_document->View()->LayoutViewport()->SetScrollOffset( + ScrollOffset(0, 1000), kProgrammaticScroll); Compositor().BeginFrame(); test::RunPendingTasks(); EXPECT_EQ(observer_delegate->CallCount(), 2); @@ -530,7 +536,7 @@ Persistent<Element> target = GetDocument().getElementById("target1"); Persistent<IntersectionObserverInit> observer_init = IntersectionObserverInit::Create(); - observer_init->setRoot(root); + observer_init->setRoot(ElementOrDocument::FromElement(root)); Persistent<TestIntersectionObserverDelegate> observer_delegate = MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument()); Persistent<IntersectionObserver> observer = @@ -679,7 +685,7 @@ Element* target2 = GetDocument().getElementById("target2"); IntersectionObserverInit* observer_init = IntersectionObserverInit::Create(); - observer_init->setRoot(root); + observer_init->setRoot(ElementOrDocument::FromElement(root)); DummyExceptionStateForTesting exception_state; TestIntersectionObserverDelegate* observer_delegate = MakeGarbageCollected<TestIntersectionObserverDelegate>(GetDocument());
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index 7f0e82e..558bfab 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -1682,6 +1682,24 @@ return false; } +LayoutUnit LayoutBlock::EmptyLineBaseline( + LineDirectionMode line_direction) const { + if (!HasLineIfEmpty()) + return LayoutUnit(-1); + const SimpleFontData* font_data = FirstLineStyle()->GetFont().PrimaryFont(); + if (!font_data) + return LayoutUnit(-1); + const auto& font_metrics = font_data->GetFontMetrics(); + const LayoutUnit line_height = + LineHeight(true, line_direction, kPositionOfInteriorLineBoxes); + const LayoutUnit border_padding = line_direction == kHorizontalLine + ? BorderTop() + PaddingTop() + : BorderRight() + PaddingRight(); + return LayoutUnit((font_metrics.Ascent() + + (line_height - font_metrics.Height()) / 2 + border_padding) + .ToInt()); +} + LayoutUnit LayoutBlock::LineHeight(bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { @@ -1849,18 +1867,8 @@ } } } - const SimpleFontData* font_data = FirstLineStyle()->GetFont().PrimaryFont(); - if (font_data && !have_normal_flow_child && HasLineIfEmpty()) { - const FontMetrics& font_metrics = font_data->GetFontMetrics(); - return LayoutUnit( - (font_metrics.Ascent() + - (LineHeight(true, line_direction, kPositionOfInteriorLineBoxes) - - font_metrics.Height()) / - 2 + - (line_direction == kHorizontalLine ? BorderTop() + PaddingTop() - : BorderRight() + PaddingRight())) - .ToInt()); - } + if (!have_normal_flow_child) + return EmptyLineBaseline(line_direction); return LayoutUnit(-1); }
diff --git a/third_party/blink/renderer/core/layout/layout_block.h b/third_party/blink/renderer/core/layout/layout_block.h index e8214ab5..e2b23cc 100644 --- a/third_party/blink/renderer/core/layout/layout_block.h +++ b/third_party/blink/renderer/core/layout/layout_block.h
@@ -486,6 +486,8 @@ hit_test_action == kHitTestChildBlockBackground; } + LayoutUnit EmptyLineBaseline(LineDirectionMode line_direction) const; + private: LayoutObjectChildList* VirtualChildren() final { return Children(); } const LayoutObjectChildList* VirtualChildren() const final {
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index 4f0611af..1cb9d247 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -2541,23 +2541,7 @@ return LastLineBox()->LogicalTop() + font_data->GetFontMetrics().Ascent(LastRootBox()->BaselineType()); } - if (!HasLineIfEmpty()) - return LayoutUnit(-1); - - const SimpleFontData* font_data = FirstLineStyle()->GetFont().PrimaryFont(); - DCHECK(font_data); - if (!font_data) - return LayoutUnit(-1); - - const FontMetrics& font_metrics = font_data->GetFontMetrics(); - return LayoutUnit( - (font_metrics.Ascent() + - (LineHeight(true, line_direction, kPositionOfInteriorLineBoxes) - - font_metrics.Height()) / - 2 + - (line_direction == kHorizontalLine ? BorderTop() + PaddingTop() - : BorderRight() + PaddingRight())) - .ToInt()); + return EmptyLineBaseline(line_direction); } void LayoutBlockFlow::RemoveFloatingObjectsFromDescendants() {
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index f53a7f9..b89f688 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -85,10 +85,6 @@ Layer()->ContentChanged(change_type); } -bool LayoutBoxModelObject::HasAcceleratedCompositing() const { - return View()->Compositor()->HasAcceleratedCompositing(); -} - LayoutBoxModelObject::LayoutBoxModelObject(ContainerNode* node) : LayoutObject(node) {}
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.h b/third_party/blink/renderer/core/layout/layout_box_model_object.h index 40b2a33..068165d3 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.h +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -415,7 +415,6 @@ LayoutGeometryMap&) const override; void ContentChanged(ContentChangeType); - bool HasAcceleratedCompositing() const; // Returns true if the background is painted opaque in the given rect. // The query rect is given in local coordinate system.
diff --git a/third_party/blink/renderer/core/layout/layout_text_control.h b/third_party/blink/renderer/core/layout/layout_text_control.h index 4c6b2bfb..9953f56f 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control.h +++ b/third_party/blink/renderer/core/layout/layout_text_control.h
@@ -125,9 +125,6 @@ LayoutUnit InlineBlockBaseline(LineDirectionMode direction) const override { return LayoutBlock::InlineBlockBaseline(direction); } - bool ShouldIgnoreOverflowPropertyForInlineBlockBaseline() const override { - return true; - } }; } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc index 3cac751..5e42e41a 100644 --- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc +++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -66,10 +66,7 @@ namespace blink { PaintLayerCompositor::PaintLayerCompositor(LayoutView& layout_view) - : layout_view_(layout_view), - has_accelerated_compositing_(layout_view.GetDocument() - .GetSettings() - ->GetAcceleratedCompositingEnabled()) {} + : layout_view_(layout_view) {} PaintLayerCompositor::~PaintLayerCompositor() { DCHECK_EQ(root_layer_attachment_, kRootLayerUnattached); @@ -135,7 +132,9 @@ bool PaintLayerCompositor::RootShouldAlwaysComposite() const { // If compositing is disabled for the WebView, then nothing composites. - if (!has_accelerated_compositing_) + if (!layout_view_.GetDocument() + .GetSettings() + ->GetAcceleratedCompositingEnabled()) return false; // Local roots composite always, when compositing is enabled globally. if (layout_view_.GetFrame()->IsLocalRoot()) @@ -150,12 +149,6 @@ } void PaintLayerCompositor::UpdateAcceleratedCompositingSettings() { - // AcceleratedCompositing setting does not change after initialization. - DCHECK_EQ(has_accelerated_compositing_, - layout_view_.GetDocument() - .GetSettings() - ->GetAcceleratedCompositingEnabled()); - root_should_always_composite_dirty_ = true; if (root_layer_attachment_ != kRootLayerUnattached) RootLayer()->SetNeedsCompositingInputsUpdate(); @@ -321,7 +314,9 @@ void PaintLayerCompositor::UpdateWithoutAcceleratedCompositing( CompositingUpdateType update_type) { - DCHECK(!HasAcceleratedCompositing()); + DCHECK(!layout_view_.GetDocument() + .GetSettings() + ->GetAcceleratedCompositingEnabled()); if (update_type >= kCompositingUpdateAfterCompositingInputChange) { CompositingInputsUpdater(RootLayer(), GetCompositingInputsRoot()).Update(); @@ -379,7 +374,9 @@ CompositingUpdateType update_type = pending_update_type_; pending_update_type_ = kCompositingUpdateNone; - if (!HasAcceleratedCompositing()) { + if (!layout_view_.GetDocument() + .GetSettings() + ->GetAcceleratedCompositingEnabled()) { UpdateWithoutAcceleratedCompositing(update_type); Lifecycle().AdvanceTo( std::min(DocumentLifecycle::kCompositingClean, target_state)); @@ -712,7 +709,9 @@ const bool has_compositor_animation = CompositingReasonFinder::CompositingReasonsForAnimation( *layer->GetLayoutObject().Style()) != CompositingReason::kNone; - return has_accelerated_compositing_ && + return layout_view_.GetDocument() + .GetSettings() + ->GetAcceleratedCompositingEnabled() && (has_compositor_animation || !layer->SubtreeIsInvisible()) && layer->IsSelfPaintingLayer() && !layer->GetLayoutObject().IsLayoutFlowThread() &&
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h index b54493b..9ef33cc 100644 --- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h +++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h
@@ -95,11 +95,6 @@ // to the native view/window system. void SetCompositingModeEnabled(bool); - // Returns true if the accelerated compositing is enabled - bool HasAcceleratedCompositing() const { - return has_accelerated_compositing_; - } - bool PreferCompositingToLCDTextEnabled() const; bool RootShouldAlwaysComposite() const; @@ -198,7 +193,6 @@ GraphicsLayer* GetXrImmersiveDomOverlayLayer() const; LayoutView& layout_view_; - const bool has_accelerated_compositing_ = true; bool compositing_ = false;
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 50e827e..61bf788 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -412,7 +412,7 @@ ComputedStyle::kIncludeIndependentTransformProperties); MakeMatrixRenderable( *transform, - Compositor() ? Compositor()->HasAcceleratedCompositing() : false); + box->GetDocument().GetSettings()->GetAcceleratedCompositingEnabled()); } }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 2c226f36..e2ed59df 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -862,8 +862,11 @@ if (GetNode()->nodeName() == "TIME") return ax::mojom::Role::kTime; - if (IsEmbeddedObject()) - return ax::mojom::Role::kEmbeddedObject; + if (IsA<HTMLPlugInElement>(GetNode())) { + if (IsA<HTMLEmbedElement>(GetNode())) + return ax::mojom::Role::kEmbeddedObject; + return ax::mojom::Role::kPluginObject; + } if (IsA<HTMLHRElement>(*GetNode())) return ax::mojom::Role::kSplitter; @@ -1106,10 +1109,6 @@ return false; } -bool AXNodeObject::IsEmbeddedObject() const { - return IsA<HTMLPlugInElement>(GetNode()); -} - bool AXNodeObject::IsFieldset() const { return IsA<HTMLFieldSetElement>(GetNode()); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h index c66c112..67c649c 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -98,7 +98,6 @@ bool IsMultiline() const override; bool IsEditable() const override { return IsNativeTextControl(); } bool ComputeIsEditableRoot() const override; - bool IsEmbeddedObject() const final; bool IsFieldset() const final; bool IsHeading() const final; bool IsHovered() const final;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index ec0766f4..87acf5f 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -380,6 +380,7 @@ {ax::mojom::Role::kNote, "Note"}, {ax::mojom::Role::kPane, "Pane"}, {ax::mojom::Role::kParagraph, "Paragraph"}, + {ax::mojom::Role::kPluginObject, "PluginObject"}, {ax::mojom::Role::kPopUpButton, "PopUpButton"}, {ax::mojom::Role::kPre, "Pre"}, {ax::mojom::Role::kPresentational, "Presentational"}, @@ -3573,6 +3574,7 @@ case ax::mojom::Role::kNavigation: case ax::mojom::Role::kNote: case ax::mojom::Role::kPane: + case ax::mojom::Role::kPluginObject: case ax::mojom::Role::kProgressIndicator: case ax::mojom::Role::kRadioGroup: case ax::mojom::Role::kRootWebArea:
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 39ba8dfd..a72eee5 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -409,7 +409,6 @@ } virtual bool IsControl() const { return false; } virtual bool IsDefault() const { return false; } - virtual bool IsEmbeddedObject() const { return false; } virtual bool IsFieldset() const { return false; } virtual bool IsHeading() const { return false; } virtual bool IsImage() const { return false; }
diff --git a/third_party/blink/renderer/modules/nfc/ndef_write_options.idl b/third_party/blink/renderer/modules/nfc/ndef_write_options.idl index 473dec8..81fe17b1 100644 --- a/third_party/blink/renderer/modules/nfc/ndef_write_options.idl +++ b/third_party/blink/renderer/modules/nfc/ndef_write_options.idl
@@ -6,5 +6,6 @@ dictionary NDEFWriteOptions { boolean ignoreRead = true; + boolean overwrite = true; AbortSignal? signal; };
diff --git a/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc b/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc index f40d00a..538930d 100644 --- a/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc +++ b/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
@@ -57,9 +57,10 @@ const blink::NDEFWriteOptions* write_options) { // https://w3c.github.io/web-nfc/#the-ndefwriteoptions-dictionary // Default values for NDEFWriteOptions dictionary are: - // ignoreRead = true + // ignoreRead = true, overwrite = true NDEFWriteOptionsPtr write_options_ptr = NDEFWriteOptions::New(); write_options_ptr->ignore_read = write_options->ignoreRead(); + write_options_ptr->overwrite = write_options->overwrite(); return write_options_ptr; }
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc index cab1ff58..63d08f1 100644 --- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc +++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
@@ -284,37 +284,10 @@ video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::DECODE_END_TIME, current_time); - // RTP_TIMESTAMP, PROCESSING_TIME, and CAPTURE_BEGIN_TIME are all exposed - // through the JavaScript callback mechanism video.requestAnimationFrame(). video_frame->metadata()->SetDouble( media::VideoFrameMetadata::RTP_TIMESTAMP, static_cast<double>(incoming_frame.timestamp())); - if (incoming_frame.processing_time()) { - video_frame->metadata()->SetTimeDelta( - media::VideoFrameMetadata::PROCESSING_TIME, - base::TimeDelta::FromMicroseconds( - incoming_frame.processing_time()->Elapsed().us())); - } - - // Set capture time to arrival of last packet. - if (!incoming_frame.packet_infos().empty()) { - int64_t last_packet_arrival_ms = - std::max_element( - incoming_frame.packet_infos().cbegin(), - incoming_frame.packet_infos().cend(), - [](const webrtc::RtpPacketInfo& a, const webrtc::RtpPacketInfo& b) { - return a.receive_time_ms() < b.receive_time_ms(); - }) - ->receive_time_ms(); - const base::TimeTicks capture_time = - base::TimeTicks() + - base::TimeDelta::FromMilliseconds(last_packet_arrival_ms) + time_diff_; - - video_frame->metadata()->SetTimeTicks( - media::VideoFrameMetadata::CAPTURE_BEGIN_TIME, capture_time); - } - PostCrossThreadTask( *io_task_runner_, FROM_HERE, CrossThreadBindOnce(&RemoteVideoSourceDelegate::DoRenderFrameOnIOThread,
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc index 02185a2..8b96314 100644 --- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
@@ -24,22 +24,12 @@ #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" #include "third_party/blink/renderer/platform/webrtc/track_observer.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" -#include "third_party/webrtc/api/rtp_packet_infos.h" #include "third_party/webrtc/api/video/color_space.h" #include "third_party/webrtc/api/video/i420_buffer.h" #include "ui/gfx/color_space.h" namespace blink { -namespace { -// On Linux the clock in WebRTC and Chromium are more or less the same. -// On Windows they are not the same and the accuracy of the measured time -// difference is in the range [-1, 1] ms. Since this is compensated for both -// here and in MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate we need -// to use the worst case difference between these two measurements. -float kChromiumWebRtcMaxTimeDiffMs = 2.0f; -} // namespace - ACTION_P(RunClosure, closure) { closure.Run(); } @@ -65,9 +55,7 @@ blink::MockWebRtcVideoTrack::Create("test", webrtc_video_source_)), remote_source_(nullptr), number_of_successful_track_starts_(0), - number_of_failed_track_starts_(0), - time_diff_(base::TimeTicks::Now() - base::TimeTicks() - - base::TimeDelta::FromMicroseconds(rtc::TimeMicros())) {} + number_of_failed_track_starts_(0) {} void SetUp() override { scoped_refptr<base::SingleThreadTaskRunner> main_thread = @@ -151,8 +139,6 @@ return web_source_; } - const base::TimeDelta& time_diff() const { return time_diff_; } - private: void OnTrackStarted(blink::WebPlatformMediaStreamSource* source, blink::mojom::MediaStreamRequestResult result, @@ -173,8 +159,6 @@ blink::WebMediaStreamSource web_source_; int number_of_successful_track_starts_; int number_of_failed_track_starts_; - // WebRTC Chromium timestamp diff - const base::TimeDelta time_diff_; }; TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) { @@ -280,137 +264,6 @@ track->RemoveSink(&sink); } -TEST_F(MediaStreamRemoteVideoSourceTest, - PopulateRequestAnimationFrameMetadata) { - std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack()); - blink::MockMediaStreamVideoSink sink; - track->AddSink(&sink, sink.GetDeliverFrameCB(), false); - - base::RunLoop run_loop; - EXPECT_CALL(sink, OnVideoFrame()) - .WillOnce(RunClosure(run_loop.QuitClosure())); - rtc::scoped_refptr<webrtc::I420Buffer> buffer( - new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240)); - - uint32_t kSsrc = 0; - const std::vector<uint32_t> kCsrcs; - uint32_t kRtpTimestamp = 123456; - float kProcessingTime = 0.014; - - const webrtc::Timestamp kProcessingFinish = - webrtc::Timestamp::ms(rtc::TimeMillis()); - const webrtc::Timestamp kProcessingStart = - kProcessingFinish - webrtc::TimeDelta::ms(1.0e3 * kProcessingTime); - - webrtc::RtpPacketInfos::vector_type packet_infos; - for (int i = 0; i < 4; ++i) { - packet_infos.emplace_back(kSsrc, kCsrcs, kRtpTimestamp, absl::nullopt, - absl::nullopt, kProcessingStart.ms() - 100 + i); - } - // Capture time should be the same as the last arrival time. - base::TimeTicks kExpectedCaptureTime = - base::TimeTicks() + - base::TimeDelta::FromMilliseconds(kProcessingStart.ms() - 100 + 3) + - time_diff(); - - webrtc::VideoFrame input_frame = - webrtc::VideoFrame::Builder() - .set_video_frame_buffer(buffer) - .set_timestamp_rtp(kRtpTimestamp) - .set_packet_infos(webrtc::RtpPacketInfos(packet_infos)) - .build(); - - input_frame.set_processing_time({kProcessingStart, kProcessingFinish}); - source()->SinkInterfaceForTesting()->OnFrame(input_frame); - run_loop.Run(); - - EXPECT_EQ(1, sink.number_of_frames()); - scoped_refptr<media::VideoFrame> output_frame = sink.last_frame(); - EXPECT_TRUE(output_frame); - - base::TimeDelta elapsed; - EXPECT_TRUE(output_frame->metadata()->GetTimeDelta( - media::VideoFrameMetadata::PROCESSING_TIME, &elapsed)); - EXPECT_FLOAT_EQ(elapsed.InSecondsF(), kProcessingTime); - - base::TimeTicks capture_time; - EXPECT_TRUE(output_frame->metadata()->GetTimeTicks( - media::VideoFrameMetadata::CAPTURE_BEGIN_TIME, &capture_time)); - EXPECT_NEAR((capture_time - kExpectedCaptureTime).InMillisecondsF(), 0.0f, - kChromiumWebRtcMaxTimeDiffMs); - - double rtp_timestamp; - EXPECT_TRUE(output_frame->metadata()->GetDouble( - media::VideoFrameMetadata::RTP_TIMESTAMP, &rtp_timestamp)); - EXPECT_EQ(static_cast<uint32_t>(rtp_timestamp), kRtpTimestamp); - - track->RemoveSink(&sink); -} - -TEST_F(MediaStreamRemoteVideoSourceTest, ReferenceTimeEqualsTimestampUs) { - std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack()); - blink::MockMediaStreamVideoSink sink; - track->AddSink(&sink, sink.GetDeliverFrameCB(), false); - - base::RunLoop run_loop; - EXPECT_CALL(sink, OnVideoFrame()) - .WillOnce(RunClosure(run_loop.QuitClosure())); - rtc::scoped_refptr<webrtc::I420Buffer> buffer( - new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240)); - - int64_t kTimestampUs = rtc::TimeMicros(); - webrtc::VideoFrame input_frame = webrtc::VideoFrame::Builder() - .set_video_frame_buffer(buffer) - .set_timestamp_us(kTimestampUs) - .build(); - - source()->SinkInterfaceForTesting()->OnFrame(input_frame); - run_loop.Run(); - - EXPECT_EQ(1, sink.number_of_frames()); - scoped_refptr<media::VideoFrame> output_frame = sink.last_frame(); - EXPECT_TRUE(output_frame); - - base::TimeTicks reference_time; - EXPECT_TRUE(output_frame->metadata()->GetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, &reference_time)); - EXPECT_NEAR((reference_time - - (base::TimeTicks() + - base::TimeDelta::FromMicroseconds(kTimestampUs) + time_diff())) - .InMillisecondsF(), - 0.0f, kChromiumWebRtcMaxTimeDiffMs); - track->RemoveSink(&sink); -} - -// This is a special case that is used to signal "render immediately". -TEST_F(MediaStreamRemoteVideoSourceTest, NoTimestampUsMeansNoReferenceTime) { - std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack()); - blink::MockMediaStreamVideoSink sink; - track->AddSink(&sink, sink.GetDeliverFrameCB(), false); - - base::RunLoop run_loop; - EXPECT_CALL(sink, OnVideoFrame()) - .WillOnce(RunClosure(run_loop.QuitClosure())); - rtc::scoped_refptr<webrtc::I420Buffer> buffer( - new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240)); - - webrtc::VideoFrame input_frame = - webrtc::VideoFrame::Builder().set_video_frame_buffer(buffer).build(); - - source()->SinkInterfaceForTesting()->OnFrame(input_frame); - run_loop.Run(); - - EXPECT_EQ(1, sink.number_of_frames()); - scoped_refptr<media::VideoFrame> output_frame = sink.last_frame(); - EXPECT_TRUE(output_frame); - - base::TimeTicks reference_time; - EXPECT_FALSE(output_frame->metadata()->GetTimeTicks( - media::VideoFrameMetadata::REFERENCE_TIME, &reference_time)); - - track->RemoveSink(&sink); -} - class TestEncodedVideoFrame : public webrtc::RecordableEncodedFrame { public: rtc::scoped_refptr<const webrtc::EncodedImageBufferInterface> encoded_buffer()
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc index 9d21f454..0ec885d 100644 --- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc +++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
@@ -93,7 +93,7 @@ if (!task_runner) return RejectPromiseImmediately(exception_state); } else { - task_runner = GetTaskRunnerFor(WebSchedulingPriority::kDefaultPriority); + task_runner = GetTaskRunnerFor(WebSchedulingPriority::kUserVisiblePriority); } // TODO(shaseley): We need to figure out the behavior we want for delay. For
diff --git a/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl b/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl index 854de5b..c3a3011 100644 --- a/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl +++ b/third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.idl
@@ -5,11 +5,9 @@ // Experimental Scheduling API Proposal: // https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit# enum TaskPriority { - "immediate", - "high", - "default", - "low", - "idle" + "user-blocking", + "user-visible", + "background" }; dictionary SchedulerPostTaskOptions {
diff --git a/third_party/blink/renderer/modules/scheduler/task_controller.idl b/third_party/blink/renderer/modules/scheduler/task_controller.idl index f2e27e3..e125038 100644 --- a/third_party/blink/renderer/modules/scheduler/task_controller.idl +++ b/third_party/blink/renderer/modules/scheduler/task_controller.idl
@@ -9,7 +9,7 @@ ImplementedAs=DOMTaskController, RuntimeEnabled=WebScheduler ] interface TaskController : AbortController { - [CallWith=Document] constructor(optional TaskPriority priority = "default"); + [CallWith=Document] constructor(optional TaskPriority priority = "user-visible"); void setPriority(TaskPriority priority); };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 01a058bf..138b01b 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -736,7 +736,7 @@ WebFeature feature = WebFeature::kOffscreenCanvasTransferToImageBitmapWebGL; UseCounter::Count(ExecutionContext::From(script_state), feature); return MakeGarbageCollected<ImageBitmap>( - GetDrawingBuffer()->TransferToStaticBitmapImage(nullptr)); + GetDrawingBuffer()->TransferToStaticBitmapImage()); } void WebGLRenderingContextBase::commit() { @@ -1263,10 +1263,8 @@ void WebGLRenderingContextBase::SetupFlags() { DCHECK(GetDrawingBuffer()); if (canvas()) { - if (Page* p = canvas()->GetDocument().GetPage()) { - synthesized_errors_to_console_ = - p->GetSettings().GetWebGLErrorsToConsoleEnabled(); - } + synthesized_errors_to_console_ = + canvas()->GetDocument().GetSettings()->GetWebGLErrorsToConsoleEnabled(); } is_depth_stencil_supported_ = @@ -1370,9 +1368,9 @@ if (!marked_canvas_dirty_) { marked_canvas_dirty_ = true; LayoutBox* layout_box = canvas()->GetLayoutBox(); - if (layout_box && layout_box->HasAcceleratedCompositing()) { + auto* settings = canvas()->GetDocument().GetSettings(); + if (layout_box && settings->GetAcceleratedCompositingEnabled()) layout_box->ContentChanged(change_type); - } IntSize canvas_size = ClampedCanvasSize(); DidDraw(SkIRect::MakeXYWH(0, 0, canvas_size.Width(), canvas_size.Height())); }
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc index 18924c3..df52155 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc +++ b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
@@ -503,8 +503,6 @@ frame_transport_->FramePreImage(webgl_context->ContextGL()); - std::unique_ptr<viz::SingleReleaseCallback> image_release_callback; - if (frame_transport_->DrawingIntoSharedBuffer()) { // Image is written to shared buffer already. Just submit with a // placeholder. @@ -512,13 +510,12 @@ DVLOG(3) << __FUNCTION__ << ": FrameSubmit for SharedBuffer mode"; frame_transport_->FrameSubmit(immersive_presentation_provider_.get(), webgl_context->ContextGL(), webgl_context, - std::move(image_ref), - std::move(image_release_callback), frame_id_); + std::move(image_ref), frame_id_); return; } scoped_refptr<StaticBitmapImage> image_ref = - layer->TransferToStaticBitmapImage(&image_release_callback); + layer->TransferToStaticBitmapImage(); if (!image_ref) return; @@ -532,8 +529,7 @@ frame_transport_->FrameSubmit(immersive_presentation_provider_.get(), webgl_context->ContextGL(), webgl_context, - std::move(image_ref), - std::move(image_release_callback), frame_id_); + std::move(image_ref), frame_id_); // Reset our frame id, since anything we'd want to do (resizing/etc) can // no-longer happen to this frame.
diff --git a/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc b/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc index 064dc8f..3f32909e 100644 --- a/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc +++ b/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
@@ -296,10 +296,9 @@ viewports_dirty_ = true; } -scoped_refptr<StaticBitmapImage> XRWebGLLayer::TransferToStaticBitmapImage( - std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { +scoped_refptr<StaticBitmapImage> XRWebGLLayer::TransferToStaticBitmapImage() { if (drawing_buffer_) { - return drawing_buffer_->TransferToStaticBitmapImage(out_release_callback); + return drawing_buffer_->TransferToStaticBitmapImage(); } return nullptr; }
diff --git a/third_party/blink/renderer/modules/xr/xr_webgl_layer.h b/third_party/blink/renderer/modules/xr/xr_webgl_layer.h index 24765b0..95d27ea 100644 --- a/third_party/blink/renderer/modules/xr/xr_webgl_layer.h +++ b/third_party/blink/renderer/modules/xr/xr_webgl_layer.h
@@ -74,8 +74,7 @@ // mailbox holder and its size respectively. void HandleBackgroundImage(const gpu::MailboxHolder&, const IntSize&) {} - scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage( - std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback); + scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(); void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index e01b73d..474cd52 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1116,6 +1116,7 @@ "graphics/subtree_paint_property_update_reason.h", "graphics/surface_layer_bridge.cc", "graphics/surface_layer_bridge.h", + "graphics/texture_holder.cc", "graphics/texture_holder.h", "graphics/touch_action.h", "graphics/unaccelerated_static_bitmap_image.cc",
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc index 9e2843f..d8b8868 100644 --- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc +++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -27,48 +27,22 @@ namespace blink { scoped_refptr<AcceleratedStaticBitmapImage> -AcceleratedStaticBitmapImage::CreateFromWebGLContextImage( - const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token, - unsigned texture_id, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& - context_provider_wrapper, - IntSize mailbox_size, - bool is_origin_top_left) { - return base::AdoptRef(new AcceleratedStaticBitmapImage( - mailbox, sync_token, texture_id, std::move(context_provider_wrapper), - mailbox_size, is_origin_top_left)); -} - -scoped_refptr<AcceleratedStaticBitmapImage> AcceleratedStaticBitmapImage::CreateFromCanvasMailbox( const gpu::Mailbox& mailbox, const gpu::SyncToken& sync_token, GLuint shared_image_texture_id, const SkImageInfo& sk_image_info, GLenum texture_target, - base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper, - PlatformThreadId context_thread_id, bool is_origin_top_left, + base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper, + base::PlatformThreadRef context_thread_ref, + scoped_refptr<base::SingleThreadTaskRunner> context_task_runner, std::unique_ptr<viz::SingleReleaseCallback> release_callback) { return base::AdoptRef(new AcceleratedStaticBitmapImage( mailbox, sync_token, shared_image_texture_id, sk_image_info, - texture_target, std::move(context_provider_wrapper), context_thread_id, - is_origin_top_left, std::move(release_callback))); -} - -AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage( - const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token, - unsigned texture_id, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& - context_provider_wrapper, - IntSize mailbox_size, - bool is_origin_top_left) - : paint_image_content_id_(cc::PaintImage::GetNextContentId()) { - mailbox_texture_holder_ = std::make_unique<MailboxTextureHolder>( - mailbox, sync_token, texture_id, std::move(context_provider_wrapper), - mailbox_size, is_origin_top_left); + texture_target, is_origin_top_left, std::move(context_provider_wrapper), + context_thread_ref, std::move(context_task_runner), + std::move(release_callback))); } AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage( @@ -77,17 +51,20 @@ GLuint shared_image_texture_id, const SkImageInfo& sk_image_info, GLenum texture_target, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& - context_provider_wrapper, - PlatformThreadId context_thread_id, bool is_origin_top_left, + base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper, + base::PlatformThreadRef context_thread_ref, + scoped_refptr<base::SingleThreadTaskRunner> context_task_runner, std::unique_ptr<viz::SingleReleaseCallback> release_callback) : mailbox_ref_(base::MakeRefCounted<TextureHolder::MailboxRef>( + sync_token, + context_thread_ref, + std::move(context_task_runner), std::move(release_callback))), paint_image_content_id_(cc::PaintImage::GetNextContentId()) { mailbox_texture_holder_ = std::make_unique<MailboxTextureHolder>( - mailbox, sync_token, std::move(context_provider_wrapper), mailbox_ref_, - context_thread_id, sk_image_info, texture_target, is_origin_top_left); + mailbox, context_provider_wrapper, mailbox_ref_, sk_image_info, + texture_target, is_origin_top_left); if (shared_image_texture_id) { skia_texture_holder_ = std::make_unique<SkiaTextureHolder>( mailbox_texture_holder_.get(), shared_image_texture_id);
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h index 3909e75c..5c8958a 100644 --- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h +++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
@@ -30,23 +30,10 @@ public: ~AcceleratedStaticBitmapImage() override; - // Can specify the GrContext that created the texture backing. Ideally all - // callers would use this option. - // The |mailbox| is a name for the texture backing, allowing other contexts to - // use the same backing. - static scoped_refptr<AcceleratedStaticBitmapImage> - CreateFromWebGLContextImage( - const gpu::Mailbox&, - const gpu::SyncToken&, - unsigned texture_id, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&, - IntSize mailbox_size, - bool is_origin_top_left); - - // Creates an image wrapping a shared image mailbox. |release_callback| is a - // callback to be invoked when this mailbox/texture can be safely destroyed. - // It can be invoked on any thread. Note that it is assumed that the mailbox - // can only be used for read operations, no writes are allowed. + // Creates an image wrapping a shared image mailbox. + // + // |sync_token| is the token that must be waited on before reading the + // contents of this mailbox. // // |shared_image_texture_id| is an optional texture bound to the shared image // mailbox imported into the provided context. If provided the caller must @@ -54,18 +41,35 @@ // and has a read lock on the shared image until the |release_callback| is // invoked. // - // If the image is created on a different thread than |context_thread_id| then - // the provided sync_token must be verified and no |shared_image_texture_id| - // should be provided. + // |sk_image_info| provides the metadata associated with the backing. + // + // |texture_target| is the target that the texture should be bound to if the + // backing is used with GL. + // + // |is_origin_top_left| indicates whether the origin in texture space + // corresponds to the top-left content pixel. + // + // |context_provider| is the context that the mailbox was created with. + // |context_thread_ref| and |context_task_runner| refer to the thread the + // context is bound to. If the image is created on a different thread than + // |context_thread_ref| then the provided sync_token must be verified and no + // |shared_image_texture_id| should be provided. + // + // |release_callback| is a callback to be invoked when this mailbox can be + // safely destroyed. It is guaranteed to be invoked on the context thread. + // + // Note that it is assumed that the mailbox can only be used for read + // operations, no writes are allowed. static scoped_refptr<AcceleratedStaticBitmapImage> CreateFromCanvasMailbox( const gpu::Mailbox&, const gpu::SyncToken&, GLuint shared_image_texture_id, const SkImageInfo& sk_image_info, GLenum texture_target, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>, - PlatformThreadId context_thread_id, bool is_origin_top_left, + base::WeakPtr<WebGraphicsContext3DProviderWrapper>, + base::PlatformThreadRef context_thread_ref, + scoped_refptr<base::SingleThreadTaskRunner> context_task_runner, std::unique_ptr<viz::SingleReleaseCallback> release_callback); bool CurrentFrameKnownToBeOpaque() override; @@ -98,20 +102,27 @@ const IntRect& source_sub_rectangle) override; bool HasMailbox() const final { return !!mailbox_texture_holder_; } - // To be called on sender thread before performing a transfer + + // To be called on sender thread before performing a transfer to a different + // thread. void Transfer() final; void EnsureMailbox(MailboxSyncMode, GLenum filter) final; + // Provides the mailbox backing for this image. The caller must wait on the + // sync token from GetSyncToken before accessing this mailbox. const gpu::Mailbox& GetMailbox() const final { - static const gpu::Mailbox mailbox; - return mailbox_texture_holder_ ? mailbox_texture_holder_->GetMailbox() - : mailbox; + return mailbox_texture_holder_->GetMailbox(); } const gpu::SyncToken& GetSyncToken() const final { - static const gpu::SyncToken sync_token; - return mailbox_texture_holder_ ? mailbox_texture_holder_->GetSyncToken() - : sync_token; + return mailbox_texture_holder_->GetSyncToken(); + } + + // Updates the sync token that must be waited on before recycling or deleting + // the mailbox for this image. This must be set by callers using the mailbox + // externally to this class. + void UpdateSyncToken(const gpu::SyncToken& sync_token) final { + mailbox_texture_holder_->UpdateSyncToken(sync_token); } bool IsOriginTopLeft() const final { return texture_holder()->IsOriginTopLeft(); @@ -123,19 +134,13 @@ AcceleratedStaticBitmapImage( const gpu::Mailbox&, const gpu::SyncToken&, - unsigned texture_id, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&, - IntSize mailbox_size, - bool is_origin_top_left); - AcceleratedStaticBitmapImage( - const gpu::Mailbox&, - const gpu::SyncToken&, GLuint shared_image_texture_id, const SkImageInfo& sk_image_info, GLenum texture_target, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&, - PlatformThreadId context_thread_id, bool is_origin_top_left, + base::WeakPtr<WebGraphicsContext3DProviderWrapper>, + base::PlatformThreadRef context_thread_ref, + scoped_refptr<base::SingleThreadTaskRunner> context_task_runner, std::unique_ptr<viz::SingleReleaseCallback> release_callback); void CreateImageFromMailboxIfNeeded();
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc index cdc6fa8..30b1312f 100644 --- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc +++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h" +#include "base/test/null_task_runner.h" #include "base/test/task_environment.h" #include "components/viz/test/test_gles2_interface.h" #include "testing/gmock/include/gmock/gmock.h" @@ -47,9 +48,14 @@ scoped_refptr<StaticBitmapImage> CreateBitmap() { auto mailbox = gpu::Mailbox::GenerateForSharedImage(); - return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage( - mailbox, GenTestSyncToken(100), 0, - SharedGpuContext::ContextProviderWrapper(), IntSize(100, 100), true); + auto release_callback = viz::SingleReleaseCallback::Create( + base::BindOnce([](const gpu::SyncToken&, bool) {})); + return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox( + mailbox, GenTestSyncToken(100), 0, SkImageInfo::MakeN32Premul(100, 100), + GL_TEXTURE_2D, true, SharedGpuContext::ContextProviderWrapper(), + base::PlatformThread::CurrentRef(), + base::MakeRefCounted<base::NullTaskRunner>(), + std::move(release_callback)); } class AcceleratedStaticBitmapImageTest : public Test {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index 031ddc5..b8db348 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -48,7 +48,8 @@ CanvasResource::CanvasResource(base::WeakPtr<CanvasResourceProvider> provider, SkFilterQuality filter_quality, const CanvasColorParams& color_params) - : owning_thread_id_(base::PlatformThread::CurrentId()), + : owning_thread_ref_(base::PlatformThread::CurrentRef()), + owning_thread_task_runner_(Thread::Current()->GetTaskRunner()), provider_(std::move(provider)), filter_quality_(filter_quality), color_params_(color_params) {} @@ -60,7 +61,7 @@ } void CanvasResource::OnDestroy() { - if (owning_thread_id_ != base::PlatformThread::CurrentId()) { + if (is_cross_thread()) { // Destroyed on wrong thread. This can happen when the thread of origin was // torn down, in which case the GPU context owning any underlying resources // no longer exists. @@ -337,8 +338,7 @@ BufferFormat(ColorParams().TransferableResourceFormat()), context_provider_wrapper_->ContextProvider() ->GetCapabilities()) - : GL_TEXTURE_2D), - owning_thread_task_runner_(Thread::Current()->GetTaskRunner()) { + : GL_TEXTURE_2D) { if (!context_provider_wrapper_) return; @@ -484,15 +484,7 @@ bool has_read_ref_on_texture, const gpu::SyncToken& sync_token, bool is_lost) { - if (resource->is_cross_thread()) { - auto& task_runner = *resource->owning_thread_task_runner_; - PostCrossThreadTask( - task_runner, FROM_HERE, - CrossThreadBindOnce(&CanvasResourceSharedImage::OnBitmapImageDestroyed, - std::move(resource), has_read_ref_on_texture, - sync_token, is_lost)); - return; - } + DCHECK(!resource->is_cross_thread()); if (has_read_ref_on_texture) { DCHECK_GT(resource->owning_thread_data().bitmap_image_read_refs, 0u); @@ -574,8 +566,8 @@ gpu::SyncToken token = is_cross_thread() ? sync_token() : gpu::SyncToken(); image = AcceleratedStaticBitmapImage::CreateFromCanvasMailbox( mailbox(), token, texture_id_for_image, image_info, texture_target_, - context_provider_wrapper_, owning_thread_id_, is_origin_top_left_, - std::move(release_callback)); + is_origin_top_left_, context_provider_wrapper_, owning_thread_ref_, + owning_thread_task_runner_, std::move(release_callback)); DCHECK(image); return image; @@ -708,8 +700,9 @@ return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox( mailbox_, GetSyncToken(), /*shared_image_texture_id=*/0u, - CreateSkImageInfo(), texture_target_, context_provider_wrapper_, - owning_thread_id_, is_origin_top_left_, std::move(release_callback)); + CreateSkImageInfo(), texture_target_, is_origin_top_left_, + context_provider_wrapper_, owning_thread_ref_, owning_thread_task_runner_, + std::move(release_callback)); } void ExternalCanvasResource::TearDown() { @@ -793,7 +786,7 @@ // It's safe to share the front buffer texture id if we're on the same thread // since the |release_callback| ensures this resource will be alive. GLuint shared_texture_id = 0u; - if (base::PlatformThread::CurrentId() == owning_thread_id_) + if (!is_cross_thread()) shared_texture_id = front_buffer_texture_id_; // The |release_callback| keeps a ref on this resource to ensure the backing @@ -806,8 +799,10 @@ return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox( front_buffer_mailbox_, sync_token_, shared_texture_id, image_info, - GL_TEXTURE_2D, context_provider_wrapper_, owning_thread_id_, - /*is_origin_top_left=*/true, std::move(release_callback)); + GL_TEXTURE_2D, + /*is_origin_top_left=*/true, context_provider_wrapper_, + owning_thread_ref_, owning_thread_task_runner_, + std::move(release_callback)); } void CanvasResourceSwapChain::Abandon() { @@ -854,7 +849,7 @@ } void CanvasResourceSwapChain::PresentSwapChain() { - DCHECK_EQ(base::PlatformThread::CurrentId(), owning_thread_id_); + DCHECK(!is_cross_thread()); DCHECK(context_provider_wrapper_); TRACE_EVENT0("blink", "CanvasResourceSwapChain::PresentSwapChain");
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h index 2c00261..3e821bc 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -148,6 +148,10 @@ SkImageInfo CreateSkImageInfo() const; + bool is_cross_thread() const { + return base::PlatformThread::CurrentRef() != owning_thread_ref_; + } + protected: CanvasResource(base::WeakPtr<CanvasResourceProvider>, SkFilterQuality, @@ -194,7 +198,8 @@ CanvasResourceProvider* Provider() { return provider_.get(); } base::WeakPtr<CanvasResourceProvider> WeakProvider() { return provider_; } - const base::PlatformThreadId owning_thread_id_; + const base::PlatformThreadRef owning_thread_ref_; + const scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_; protected: // Returns the texture target for the resource. @@ -294,9 +299,6 @@ GLenum TextureTarget() const override { return texture_target_; } void WillDraw(); - bool is_cross_thread() const { - return base::PlatformThread::CurrentId() != owning_thread_id_; - } bool has_read_access() const { return owning_thread_data().bitmap_image_read_refs > 0u; } @@ -350,11 +352,11 @@ uint32_t shared_image_usage_flags); OwningThreadData& owning_thread_data() { - DCHECK_EQ(base::PlatformThread::CurrentId(), owning_thread_id_); + DCHECK(!is_cross_thread()); return owning_thread_data_; } const OwningThreadData& owning_thread_data() const { - DCHECK_EQ(base::PlatformThread::CurrentId(), owning_thread_id_); + DCHECK(!is_cross_thread()); return owning_thread_data_; } @@ -387,7 +389,6 @@ const bool is_accelerated_; const bool is_overlay_candidate_; const GLenum texture_target_; - const scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_; OwningThreadData owning_thread_data_; };
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 0ad96592..d8e258f 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -52,6 +52,7 @@ #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource.h" #include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h" +#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h" @@ -190,7 +191,8 @@ opengl_flip_y_extension_( ContextProvider()->GetCapabilities().mesa_framebuffer_flip_y), initial_gpu_(gpu_preference), - current_active_gpu_(gpu_preference) { + current_active_gpu_(gpu_preference), + weak_factory_(this) { // Used by browser tests to detect the use of a DrawingBuffer. TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation", TRACE_EVENT_SCOPE_GLOBAL); @@ -390,9 +392,9 @@ // This holds a ref on the DrawingBuffer that will keep it alive until the // mailbox is released (and while the release callback is running). It also // owns the SharedBitmap. - auto func = WTF::Bind(&DrawingBuffer::MailboxReleasedSoftware, - scoped_refptr<DrawingBuffer>(this), - WTF::Passed(std::move(registered))); + auto func = base::BindOnce(&DrawingBuffer::MailboxReleasedSoftware, + weak_factory_.GetWeakPtr(), + WTF::Passed(std::move(registered))); *out_release_callback = viz::SingleReleaseCallback::Create(std::move(func)); ResetBuffersToAutoClear(); @@ -501,9 +503,8 @@ // This holds a ref on the DrawingBuffer that will keep it alive until the // mailbox is released (and while the release callback is running). - auto func = - WTF::Bind(&DrawingBuffer::MailboxReleasedGpu, - scoped_refptr<DrawingBuffer>(this), color_buffer_for_mailbox); + auto func = base::BindOnce(&DrawingBuffer::NotifyMailboxReleasedGpu, + color_buffer_for_mailbox); *out_release_callback = viz::SingleReleaseCallback::Create(std::move(func)); } @@ -515,18 +516,29 @@ return true; } +// static +void DrawingBuffer::NotifyMailboxReleasedGpu( + scoped_refptr<ColorBuffer> color_buffer, + const gpu::SyncToken& sync_token, + bool lost_resource) { + DCHECK(color_buffer->owning_thread_ref == base::PlatformThread::CurrentRef()); + + // Update the SyncToken to ensure that we will wait for it even if we + // immediately destroy this buffer. + color_buffer->receive_sync_token = sync_token; + if (color_buffer->drawing_buffer) { + color_buffer->drawing_buffer->MailboxReleasedGpu(color_buffer, + lost_resource); + } +} + void DrawingBuffer::MailboxReleasedGpu(scoped_refptr<ColorBuffer> color_buffer, - const gpu::SyncToken& sync_token, bool lost_resource) { // If the mailbox has been returned by the compositor then it is no // longer being presented, and so is no longer the front buffer. if (color_buffer == front_color_buffer_) front_color_buffer_ = nullptr; - // Update the SyncToken to ensure that we will wait for it even if we - // immediately destroy this buffer. - color_buffer->receive_sync_token = sync_token; - if (destruction_in_progress_ || color_buffer->size != size_ || gl_->GetGraphicsResetStatusKHR() != GL_NO_ERROR || lost_resource || is_hidden_) { @@ -558,8 +570,7 @@ recycled_bitmaps_.push_back(std::move(registered)); } -scoped_refptr<StaticBitmapImage> DrawingBuffer::TransferToStaticBitmapImage( - std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { +scoped_refptr<StaticBitmapImage> DrawingBuffer::TransferToStaticBitmapImage() { ScopedStateRestorer scoped_state_restorer(this); viz::TransferableResource transferable_resource; @@ -580,35 +591,10 @@ SkImage::MakeFromBitmap(black_bitmap)); } + DCHECK(release_callback); DCHECK_EQ(size_.Width(), transferable_resource.size.width()); DCHECK_EQ(size_.Height(), transferable_resource.size.height()); - // Make our own textureId that is a reference on the same texture backing - // being used as the front buffer (which was returned from - // PrepareTransferableResourceInternal()). We do not need to wait on the sync - // token in |transferable_resource| since the mailbox was produced on the same - // |m_gl| context that we are using here. Similarly, the |release_callback| - // will run on the same context so we don't need to send a sync token for this - // consume action back to it. - // TODO(danakj): Instead of using PrepareTransferableResourceInternal(), we - // could just use the actual texture id and avoid needing to produce/consume a - // mailbox. - GLuint texture_id = gl_->CreateAndTexStorage2DSharedImageCHROMIUM( - transferable_resource.mailbox_holder.mailbox.name); - - if (out_release_callback) { - // Allow the consumer to release the resource when done using it, so it can - // be recycled. - *out_release_callback = std::move(release_callback); - } else { - // Return the mailbox but report that the resource is lost to prevent trying - // to use the backing for future frames. We keep it alive with our own - // reference to the backing via our |textureId|. - gpu::SyncToken sync_token; - gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); - release_callback->Run(sync_token, true /* lost_resource */); - } - // We reuse the same mailbox name from above since our texture id was consumed // from it. const auto& sk_image_mailbox = transferable_resource.mailbox_holder.mailbox; @@ -620,12 +606,18 @@ const auto& sk_image_sync_token = transferable_resource.mailbox_holder.sync_token; + const SkImageInfo sk_image_info = + SkImageInfo::MakeN32Premul(size_.Width(), size_.Height()); + // TODO(xidachen): Create a small pool of recycled textures from // ImageBitmapRenderingContext's transferFromImageBitmap, and try to use them // in DrawingBuffer. - return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage( - sk_image_mailbox, sk_image_sync_token, texture_id, - context_provider_->GetWeakPtr(), size_, opengl_flip_y_extension_); + return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox( + sk_image_mailbox, sk_image_sync_token, /* shared_image_texture_id = */ 0, + sk_image_info, transferable_resource.mailbox_holder.texture_target, + /* is_origin_top_left = */ opengl_flip_y_extension_, + context_provider_->GetWeakPtr(), base::PlatformThread::CurrentRef(), + Thread::Current()->GetTaskRunner(), std::move(release_callback)); } scoped_refptr<DrawingBuffer::ColorBuffer> @@ -675,18 +667,29 @@ } DrawingBuffer::ColorBuffer::ColorBuffer( - DrawingBuffer* drawing_buffer, + base::WeakPtr<DrawingBuffer> drawing_buffer, const IntSize& size, GLuint texture_id, std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer, gpu::Mailbox mailbox) - : drawing_buffer(drawing_buffer), + : owning_thread_ref(base::PlatformThread::CurrentRef()), + drawing_buffer(std::move(drawing_buffer)), size(size), texture_id(texture_id), gpu_memory_buffer(std::move(gpu_memory_buffer)), mailbox(mailbox) {} DrawingBuffer::ColorBuffer::~ColorBuffer() { + if (base::PlatformThread::CurrentRef() != owning_thread_ref || + !drawing_buffer) { + // If the context has been destroyed no cleanup is necessary since all + // resources below are automatically destroyed. Note that if a ColorBuffer + // is being destroyed on a different thread, it implies that the owning + // thread was destroyed which means the associated context was also + // destroyed. + return; + } + gpu::gles2::GLES2Interface* gl = drawing_buffer->gl_; gpu::SharedImageInterface* sii = drawing_buffer->ContextProvider()->SharedImageInterface(); @@ -1628,8 +1631,9 @@ // Import frontbuffer of swap chain into GL. texture_id = gl_->CreateAndTexStorage2DSharedImageCHROMIUM( front_buffer_mailbox.name); - front_color_buffer_ = base::AdoptRef( - new ColorBuffer(this, size, texture_id, nullptr, front_buffer_mailbox)); + front_color_buffer_ = base::MakeRefCounted<ColorBuffer>( + weak_factory_.GetWeakPtr(), size, texture_id, nullptr, + front_buffer_mailbox); } // Import the backbuffer of swap chain or allocated SharedImage into GL. texture_id = @@ -1656,9 +1660,9 @@ gl_->DeleteFramebuffers(1, &fbo); } - return base::AdoptRef(new ColorBuffer(this, size, texture_id, - std::move(gpu_memory_buffer), - back_buffer_mailbox)); + return base::MakeRefCounted<ColorBuffer>( + weak_factory_.GetWeakPtr(), size, texture_id, + std::move(gpu_memory_buffer), back_buffer_mailbox); } void DrawingBuffer::AttachColorBufferToReadFramebuffer() {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h index 3e22699..d330796 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -228,10 +228,7 @@ // contents of the front buffer. This is done without any pixel copies. The // texture in the ImageBitmap is from the active ContextProvider on the // DrawingBuffer. - // If out_release_callback is null, the image is discarded. If it is non-null - // the image must be recycled or discarded by calling *out_release_callback. - scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage( - std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback); + scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(); bool CopyToPlatformTexture(gpu::gles2::GLES2Interface*, GLenum dst_target, @@ -356,18 +353,22 @@ bool pixel_pack_buffer_binding_dirty_ = false; }; - struct ColorBuffer : public RefCounted<ColorBuffer> { - ColorBuffer(DrawingBuffer*, + struct ColorBuffer : public base::RefCountedThreadSafe<ColorBuffer> { + ColorBuffer(base::WeakPtr<DrawingBuffer> drawing_buffer, const IntSize&, GLuint texture_id, std::unique_ptr<gfx::GpuMemoryBuffer>, gpu::Mailbox mailbox); ~ColorBuffer(); + // The thread on which the ColorBuffer is created and the DrawingBuffer is + // bound to. + const base::PlatformThreadRef owning_thread_ref; + // The owning DrawingBuffer. Note that DrawingBuffer is explicitly destroyed // by the beginDestruction method, which will eventually drain all of its // ColorBuffers. - scoped_refptr<DrawingBuffer> drawing_buffer; + base::WeakPtr<DrawingBuffer> drawing_buffer; const IntSize size; const GLuint texture_id = 0; std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; @@ -430,8 +431,10 @@ // Callbacks for mailboxes given to the compositor from // FinishPrepareTransferableResource{Gpu,Software}. + static void NotifyMailboxReleasedGpu(scoped_refptr<ColorBuffer>, + const gpu::SyncToken&, + bool lost_resource); void MailboxReleasedGpu(scoped_refptr<ColorBuffer>, - const gpu::SyncToken&, bool lost_resource); void MailboxReleasedSoftware(RegisteredBitmap, const gpu::SyncToken&, @@ -630,6 +633,8 @@ const gl::GpuPreference initial_gpu_; gl::GpuPreference current_active_gpu_; + base::WeakPtrFactory<DrawingBuffer> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(DrawingBuffer); };
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc index 19d15ce..537c1af 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc
@@ -203,9 +203,8 @@ drawing_buffer_->BeginDestruction(); } -TEST_F(DrawingBufferTest, VerifyDestructionCompleteAfterAllResourceReleased) { - bool live = true; - drawing_buffer_->live_ = &live; +TEST_F(DrawingBufferTest, VerifySharedImagesReleasedAfterReleaseCallback) { + auto* sii = drawing_buffer_->SharedImageInterfaceForTests(); viz::TransferableResource resource1; std::unique_ptr<viz::SingleReleaseCallback> release_callback1; @@ -231,67 +230,20 @@ EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3, &release_callback3)); - EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - release_callback1->Run(gpu::SyncToken(), false /* lostResource */); - - drawing_buffer_->BeginDestruction(); - ASSERT_EQ(live, true); - - DrawingBufferForTests* raw_pointer = drawing_buffer_.get(); - drawing_buffer_ = nullptr; - ASSERT_EQ(live, true); - - EXPECT_FALSE(raw_pointer->MarkContentsChanged()); - release_callback2->Run(gpu::SyncToken(), false /* lostResource */); - ASSERT_EQ(live, true); - - EXPECT_FALSE(raw_pointer->MarkContentsChanged()); - release_callback3->Run(gpu::SyncToken(), false /* lostResource */); - ASSERT_EQ(live, false); -} - -TEST_F(DrawingBufferTest, verifyDrawingBufferStaysAliveIfResourcesAreLost) { - bool live = true; - drawing_buffer_->live_ = &live; - - viz::TransferableResource resource1; - std::unique_ptr<viz::SingleReleaseCallback> release_callback1; - viz::TransferableResource resource2; - std::unique_ptr<viz::SingleReleaseCallback> release_callback2; - viz::TransferableResource resource3; - std::unique_ptr<viz::SingleReleaseCallback> release_callback3; - - EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource1, - &release_callback1)); - VerifyStateWasRestored(); - EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource2, - &release_callback2)); - VerifyStateWasRestored(); - EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3, - &release_callback3)); - VerifyStateWasRestored(); + EXPECT_EQ(sii->shared_image_count(), 4u); EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); release_callback1->Run(gpu::SyncToken(), true /* lostResource */); - EXPECT_EQ(live, true); + EXPECT_EQ(sii->shared_image_count(), 3u); + + release_callback2->Run(gpu::SyncToken(), true /* lostResource */); + EXPECT_EQ(sii->shared_image_count(), 2u); + + // The resource is not marked lost so it's recycled after the callback. + release_callback3->Run(gpu::SyncToken(), false /* lostResource */); + EXPECT_EQ(sii->shared_image_count(), 2u); drawing_buffer_->BeginDestruction(); - EXPECT_EQ(live, true); - - EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - release_callback2->Run(gpu::SyncToken(), false /* lostResource */); - EXPECT_EQ(live, true); - - DrawingBufferForTests* raw_ptr = drawing_buffer_.get(); - drawing_buffer_ = nullptr; - EXPECT_EQ(live, true); - - EXPECT_FALSE(raw_ptr->MarkContentsChanged()); - release_callback3->Run(gpu::SyncToken(), true /* lostResource */); - EXPECT_EQ(live, false); } TEST_F(DrawingBufferTest, VerifyOnlyOneRecycledResourceMustBeKept) {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc index 63b92488..8e66f9b 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -18,9 +18,7 @@ XRFrameTransport::XRFrameTransport() : submit_frame_client_receiver_(this) {} -XRFrameTransport::~XRFrameTransport() { - CallPreviousFrameCallback(); -} +XRFrameTransport::~XRFrameTransport() = default; void XRFrameTransport::PresentChange() { frame_copier_ = nullptr; @@ -79,13 +77,6 @@ } } -void XRFrameTransport::CallPreviousFrameCallback() { - if (previous_image_release_callback_) { - previous_image_release_callback_->Run(gpu::SyncToken(), false); - previous_image_release_callback_ = nullptr; - } -} - void XRFrameTransport::FrameSubmitMissing( device::mojom::blink::XRPresentationProvider* vr_presentation_provider, gpu::gles2::GLES2Interface* gl, @@ -101,7 +92,6 @@ gpu::gles2::GLES2Interface* gl, DrawingBuffer::Client* drawing_buffer_client, scoped_refptr<Image> image_ref, - std::unique_ptr<viz::SingleReleaseCallback> release_callback, int16_t vr_frame_id) { DCHECK(transport_options_); @@ -114,8 +104,6 @@ // without waiting. if (transport_options_->wait_for_transfer_notification) WaitForPreviousTransfer(); - CallPreviousFrameCallback(); - previous_image_release_callback_ = std::move(release_callback); if (!frame_copier_ || !last_transfer_succeeded_) { frame_copier_ = std::make_unique<GpuMemoryBufferImageCopy>(gl); } @@ -173,8 +161,6 @@ if (transport_options_->wait_for_transfer_notification) WaitForPreviousTransfer(); previous_image_ = std::move(image_ref); - CallPreviousFrameCallback(); - previous_image_release_callback_ = std::move(release_callback); // Create mailbox and sync token for transfer. TRACE_EVENT_BEGIN0("gpu", "XRFrameTransport::GetMailbox");
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h index f0fa052..4a094aa 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h +++ b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
@@ -52,7 +52,6 @@ gpu::gles2::GLES2Interface*, DrawingBuffer::Client*, scoped_refptr<Image> image_ref, - std::unique_ptr<viz::SingleReleaseCallback>, int16_t vr_frame_id); void FrameSubmitMissing(device::mojom::blink::XRPresentationProvider*, @@ -65,7 +64,6 @@ void WaitForPreviousTransfer(); base::TimeDelta WaitForPreviousRenderToFinish(); base::TimeDelta WaitForGpuFenceReceived(); - void CallPreviousFrameCallback(); // XRPresentationClient void OnSubmitFrameTransferred(bool success) override; @@ -78,7 +76,6 @@ // Used to keep the image alive until the next frame if using // waitForPreviousTransferToFinish. scoped_refptr<Image> previous_image_; - std::unique_ptr<viz::SingleReleaseCallback> previous_image_release_callback_; bool waiting_for_previous_frame_transfer_ = false; bool last_transfer_succeeded_ = false;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc index f466089..9578314 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h" #include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h" +#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h" #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -25,16 +26,27 @@ // some of the common bits into a base class? XRWebGLDrawingBuffer::ColorBuffer::ColorBuffer( - XRWebGLDrawingBuffer* drawing_buffer, + base::WeakPtr<XRWebGLDrawingBuffer> drawing_buffer, const IntSize& size, const gpu::Mailbox& mailbox, GLuint texture_id) - : drawing_buffer(drawing_buffer), + : owning_thread_ref(base::PlatformThread::CurrentRef()), + drawing_buffer(std::move(drawing_buffer)), size(size), texture_id(texture_id), mailbox(mailbox) {} XRWebGLDrawingBuffer::ColorBuffer::~ColorBuffer() { + if (base::PlatformThread::CurrentRef() != owning_thread_ref || + !drawing_buffer) { + // If the context has been destroyed no cleanup is necessary since all + // resources below are automatically destroyed. Note that if a ColorBuffer + // is being destroyed on a different thread, it implies that the owning + // thread was destroyed which means the associated context was also + // destroyed. + return; + } + gpu::gles2::GLES2Interface* gl = drawing_buffer->ContextGL(); if (receive_sync_token.HasData()) gl->WaitSyncTokenCHROMIUM(receive_sync_token.GetConstData()); @@ -105,68 +117,6 @@ return xr_drawing_buffer; } -void XRWebGLDrawingBuffer::MirrorClient::OnMirrorImageAvailable( - scoped_refptr<StaticBitmapImage> image, - std::unique_ptr<viz::SingleReleaseCallback> callback) { - // Replace the next image if we have one already. - if (next_image_ && next_release_callback_) { - next_release_callback_->Run(gpu::SyncToken(), false); - } - - // Set our new image. - next_image_ = image; - next_release_callback_ = std::move(callback); -} - -void XRWebGLDrawingBuffer::MirrorClient::BeginDestruction() { - // Call all callbacks we have to clean up associated resources. For - // next_release_callback_, we report the previous image as "not lost", meaning - // we can reuse the texture/image. For previous_release_callback_ - // and current_release_callback_, we report the image as lost, because we - // don't know if the consumer is still using them, so they should not be - // reused. - if (previous_release_callback_) { - previous_release_callback_->Run(gpu::SyncToken(), true); - previous_release_callback_ = nullptr; - } - - if (current_release_callback_) { - current_release_callback_->Run(gpu::SyncToken(), true); - current_release_callback_ = nullptr; - } - - if (next_release_callback_) { - next_release_callback_->Run(gpu::SyncToken(), false); - next_release_callback_ = nullptr; - } - - next_image_ = nullptr; -} - -scoped_refptr<StaticBitmapImage> -XRWebGLDrawingBuffer::MirrorClient::GetLastImage() { - if (!next_image_) - return nullptr; - - scoped_refptr<StaticBitmapImage> ret = next_image_; - next_image_ = nullptr; - DCHECK(!previous_release_callback_); - previous_release_callback_ = std::move(current_release_callback_); - DCHECK(!current_release_callback_); - current_release_callback_ = std::move(next_release_callback_); - return ret; -} - -void XRWebGLDrawingBuffer::MirrorClient::CallLastReleaseCallback() { - if (previous_release_callback_) - previous_release_callback_->Run(gpu::SyncToken(), false); - previous_release_callback_ = nullptr; -} - -XRWebGLDrawingBuffer::MirrorClient::~MirrorClient() { - BeginDestruction(); -} - XRWebGLDrawingBuffer::XRWebGLDrawingBuffer(DrawingBuffer* drawing_buffer, GLuint framebuffer, bool discard_framebuffer_supported, @@ -178,11 +128,10 @@ discard_framebuffer_supported_(discard_framebuffer_supported), depth_(want_depth_buffer), stencil_(want_stencil_buffer), - alpha_(want_alpha_channel) {} + alpha_(want_alpha_channel), + weak_factory_(this) {} void XRWebGLDrawingBuffer::BeginDestruction() { - mirror_client_ = nullptr; - if (back_color_buffer_) { gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL(); gl->EndSharedImageAccessDirectCHROMIUM(back_color_buffer_->texture_id); @@ -242,18 +191,6 @@ return drawing_buffer_->ContextGL(); } -void XRWebGLDrawingBuffer::SetMirrorClient(scoped_refptr<MirrorClient> client) { - mirror_client_ = client; - if (mirror_client_) { - // Immediately send a black 1x1 image to the mirror client to ensure that - // it has content to show. - sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(1, 1); - mirror_client_->OnMirrorImageAvailable( - UnacceleratedStaticBitmapImage::Create(surface->makeImageSnapshot()), - nullptr); - } -} - bool XRWebGLDrawingBuffer::ContextLost() { return drawing_buffer_->destroyed(); } @@ -523,7 +460,8 @@ DrawingBuffer::Client* client = drawing_buffer_->client(); client->DrawingBufferClientRestoreTexture2DBinding(); - return base::AdoptRef(new ColorBuffer(this, size_, mailbox, texture_id)); + return base::MakeRefCounted<ColorBuffer>(weak_factory_.GetWeakPtr(), size_, + mailbox, texture_id); } scoped_refptr<XRWebGLDrawingBuffer::ColorBuffer> @@ -626,8 +564,7 @@ } scoped_refptr<StaticBitmapImage> -XRWebGLDrawingBuffer::TransferToStaticBitmapImage( - std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) { +XRWebGLDrawingBuffer::TransferToStaticBitmapImage() { gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL(); scoped_refptr<ColorBuffer> buffer; bool success = false; @@ -661,47 +598,45 @@ // This holds a ref on the XRWebGLDrawingBuffer that will keep it alive // until the mailbox is released (and while the callback is running). auto func = - WTF::Bind(mirror_client_ ? &XRWebGLDrawingBuffer::MailboxReleasedToMirror - : &XRWebGLDrawingBuffer::MailboxReleased, - scoped_refptr<XRWebGLDrawingBuffer>(this), buffer); + base::BindOnce(&XRWebGLDrawingBuffer::NotifyMailboxReleased, buffer); std::unique_ptr<viz::SingleReleaseCallback> release_callback = viz::SingleReleaseCallback::Create(std::move(func)); + const SkImageInfo sk_image_info = + SkImageInfo::MakeN32Premul(size_.Width(), size_.Height()); - // Make our own textureId that is a reference on the same shared image being - // used as the front buffer. We do not need a - // Begin/EndSharedImageAccessDirectCHROMIUM as the texture id is just for - // lifetime, not actual access. We do not need to wait on the sync token - // since the GL context has already waited on it. Similarly, the release - // callback will run on the same context so we don't need to send a sync token - // for this consume action back to it. - GLuint texture_id = - gl->CreateAndTexStorage2DSharedImageCHROMIUM(buffer->mailbox.name); + return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox( + buffer->mailbox, buffer->produce_sync_token, + /* shared_image_texture_id = */ 0, sk_image_info, GL_TEXTURE_2D, + /* is_origin_top_left = */ false, + drawing_buffer_->ContextProviderWeakPtr(), + base::PlatformThread::CurrentRef(), Thread::Current()->GetTaskRunner(), + std::move(release_callback)); +} - if (out_release_callback) { - *out_release_callback = std::move(release_callback); - } else { - release_callback->Run(gpu::SyncToken(), true /* lost_resource */); +// static +void XRWebGLDrawingBuffer::NotifyMailboxReleased( + scoped_refptr<ColorBuffer> color_buffer, + const gpu::SyncToken& sync_token, + bool lost_resource) { + DCHECK(color_buffer->owning_thread_ref == base::PlatformThread::CurrentRef()); + + // Update the SyncToken to ensure that we will wait for it even if we + // immediately destroy this buffer. + color_buffer->receive_sync_token = sync_token; + if (color_buffer->drawing_buffer) { + color_buffer->drawing_buffer->MailboxReleased(color_buffer, lost_resource); } - - return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage( - buffer->mailbox, buffer->produce_sync_token, texture_id, - drawing_buffer_->ContextProviderWeakPtr(), size_, false); } void XRWebGLDrawingBuffer::MailboxReleased( scoped_refptr<ColorBuffer> color_buffer, - const gpu::SyncToken& sync_token, bool lost_resource) { // If the mailbox has been returned by the compositor then it is no // longer being presented, and so is no longer the front buffer. if (color_buffer == front_color_buffer_) front_color_buffer_ = nullptr; - // Update the SyncToken to ensure that we will wait for it even if we - // immediately destroy this buffer. - color_buffer->receive_sync_token = sync_token; - if (drawing_buffer_->destroyed() || color_buffer->size != size_ || lost_resource) { return; @@ -714,35 +649,4 @@ recycled_color_buffer_queue_.push_front(color_buffer); } -void XRWebGLDrawingBuffer::MailboxReleasedToMirror( - scoped_refptr<ColorBuffer> color_buffer, - const gpu::SyncToken& sync_token, - bool lost_resource) { - if (!mirror_client_ || lost_resource) { - MailboxReleased(std::move(color_buffer), sync_token, lost_resource); - return; - } - - gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL(); - color_buffer->receive_sync_token = sync_token; - - auto func = - WTF::Bind(&XRWebGLDrawingBuffer::MailboxReleased, - scoped_refptr<XRWebGLDrawingBuffer>(this), color_buffer); - - std::unique_ptr<viz::SingleReleaseCallback> release_callback = - viz::SingleReleaseCallback::Create(std::move(func)); - - GLuint texture_id = - gl->CreateAndTexStorage2DSharedImageCHROMIUM(color_buffer->mailbox.name); - - scoped_refptr<StaticBitmapImage> image = - AcceleratedStaticBitmapImage::CreateFromWebGLContextImage( - color_buffer->mailbox, color_buffer->produce_sync_token, texture_id, - drawing_buffer_->ContextProviderWeakPtr(), color_buffer->size, false); - - mirror_client_->OnMirrorImageAvailable(std::move(image), - std::move(release_callback)); -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h index 44649d8..26f28d0c 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h +++ b/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
@@ -43,28 +43,7 @@ void Resize(const IntSize&); - scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage( - std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback); - - class PLATFORM_EXPORT MirrorClient : public RefCounted<MirrorClient> { - public: - void OnMirrorImageAvailable(scoped_refptr<StaticBitmapImage>, - std::unique_ptr<viz::SingleReleaseCallback>); - - void BeginDestruction(); - scoped_refptr<StaticBitmapImage> GetLastImage(); - void CallLastReleaseCallback(); - - ~MirrorClient(); - - private: - scoped_refptr<StaticBitmapImage> next_image_; - std::unique_ptr<viz::SingleReleaseCallback> next_release_callback_; - std::unique_ptr<viz::SingleReleaseCallback> current_release_callback_; - std::unique_ptr<viz::SingleReleaseCallback> previous_release_callback_; - }; - - void SetMirrorClient(scoped_refptr<MirrorClient> mirror_client); + scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(); void UseSharedBuffer(const gpu::MailboxHolder&); void DoneWithSharedBuffer(); @@ -75,17 +54,22 @@ void BeginDestruction(); private: - struct PLATFORM_EXPORT ColorBuffer : public RefCounted<ColorBuffer> { - ColorBuffer(XRWebGLDrawingBuffer*, + struct PLATFORM_EXPORT ColorBuffer + : public base::RefCountedThreadSafe<ColorBuffer> { + ColorBuffer(base::WeakPtr<XRWebGLDrawingBuffer>, const IntSize&, const gpu::Mailbox& mailbox, GLuint texture_id); ~ColorBuffer(); + // The thread on which the ColorBuffer is created and the DrawingBuffer is + // bound to. + const base::PlatformThreadRef owning_thread_ref; + // The owning XRWebGLDrawingBuffer. Note that DrawingBuffer is explicitly // destroyed by the BeginDestruction method, which will eventually drain all // of its ColorBuffers. - scoped_refptr<XRWebGLDrawingBuffer> drawing_buffer; + base::WeakPtr<XRWebGLDrawingBuffer> drawing_buffer; const IntSize size; // The id of the texture that imports the shared image into the @@ -126,12 +110,10 @@ void ClearBoundFramebuffer(); - void MailboxReleased(scoped_refptr<ColorBuffer>, - const gpu::SyncToken&, - bool lost_resource); - void MailboxReleasedToMirror(scoped_refptr<ColorBuffer>, - const gpu::SyncToken&, - bool lost_resource); + static void NotifyMailboxReleased(scoped_refptr<ColorBuffer>, + const gpu::SyncToken&, + bool lost_resource); + void MailboxReleased(scoped_refptr<ColorBuffer>, bool lost_resource); // Reference to the DrawingBuffer that owns the GL context for this object. scoped_refptr<DrawingBuffer> drawing_buffer_; @@ -174,7 +156,7 @@ int max_texture_size_ = 0; int sample_count_ = 0; - scoped_refptr<MirrorClient> mirror_client_; + base::WeakPtrFactory<XRWebGLDrawingBuffer> weak_factory_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc b/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc index 6e0c7398..a263542 100644 --- a/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc +++ b/third_party/blink/renderer/platform/graphics/gpu_memory_buffer_image_copy.cc
@@ -101,6 +101,10 @@ gl_->EndSharedImageAccessDirectCHROMIUM(source_texture_id); gl_->DeleteTextures(1, &source_texture_id); + gpu::SyncToken copy_done_sync_token; + gl_->GenSyncTokenCHROMIUM(copy_done_sync_token.GetData()); + static_image->UpdateSyncToken(copy_done_sync_token); + // Cleanup the draw framebuffer, associated image and texture. gl_->BindTexture(target, dest_texture_id); gl_->ReleaseTexImage2DCHROMIUM(target, image_id);
diff --git a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc index 17aa70c1..a9a52b3 100644 --- a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc +++ b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
@@ -14,55 +14,10 @@ namespace blink { -namespace { - -void ReleaseTexture( - bool is_converted_from_skia_texture, - unsigned texture_id, - std::unique_ptr<gpu::Mailbox> mailbox, - base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider, - std::unique_ptr<gpu::SyncToken> sync_token) { - if (!is_converted_from_skia_texture && texture_id && context_provider) { - context_provider->ContextProvider()->ContextGL()->WaitSyncTokenCHROMIUM( - sync_token->GetData()); - context_provider->ContextProvider()->ContextGL()->DeleteTextures( - 1, &texture_id); - } -} - -} // namespace - MailboxTextureHolder::MailboxTextureHolder( const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token, - unsigned texture_id_to_delete_after_mailbox_consumed, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& - context_provider_wrapper, - IntSize mailbox_size, - bool is_origin_top_left) - : TextureHolder(std::move(context_provider_wrapper), - base::MakeRefCounted<MailboxRef>(nullptr), - is_origin_top_left), - mailbox_(mailbox), - texture_id_(texture_id_to_delete_after_mailbox_consumed), - is_converted_from_skia_texture_(false), - thread_id_(0), - sk_image_info_(SkImageInfo::MakeN32Premul(mailbox_size.Width(), - mailbox_size.Height())), - texture_target_(GL_TEXTURE_2D) { - DCHECK(mailbox_.IsSharedImage()); - - mailbox_ref()->set_sync_token(sync_token); - InitCommon(); -} - -MailboxTextureHolder::MailboxTextureHolder( - const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& - context_provider_wrapper, + base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper, scoped_refptr<MailboxRef> mailbox_ref, - PlatformThreadId context_thread_id, const SkImageInfo& sk_image_info, GLenum texture_target, bool is_origin_top_left) @@ -70,16 +25,9 @@ std::move(mailbox_ref), is_origin_top_left), mailbox_(mailbox), - texture_id_(0), - is_converted_from_skia_texture_(false), - thread_id_(context_thread_id), sk_image_info_(sk_image_info), texture_target_(texture_target) { - DCHECK(thread_id_); - DCHECK(!IsCrossThread() || sync_token.verified_flush()); DCHECK(mailbox_.IsSharedImage()); - - this->mailbox_ref()->set_sync_token(sync_token); } void MailboxTextureHolder::Sync(MailboxSyncMode mode) { @@ -133,12 +81,6 @@ } } -void MailboxTextureHolder::InitCommon() { - DCHECK(!thread_id_); - thread_id_ = base::PlatformThread::CurrentId(); - texture_thread_task_runner_ = Thread::Current()->GetTaskRunner(); -} - bool MailboxTextureHolder::IsValid() const { if (IsCrossThread()) { // If context is is from another thread, validity cannot be verified. @@ -149,29 +91,9 @@ } bool MailboxTextureHolder::IsCrossThread() const { - return thread_id_ != base::PlatformThread::CurrentId(); + return mailbox_ref()->is_cross_thread(); } -MailboxTextureHolder::~MailboxTextureHolder() { - std::unique_ptr<gpu::SyncToken> passed_sync_token( - new gpu::SyncToken(mailbox_ref()->sync_token())); - std::unique_ptr<gpu::Mailbox> passed_mailbox(new gpu::Mailbox(mailbox_)); - - if (texture_thread_task_runner_ && IsCrossThread()) { - PostCrossThreadTask( - *texture_thread_task_runner_, FROM_HERE, - CrossThreadBindOnce(&ReleaseTexture, is_converted_from_skia_texture_, - texture_id_, WTF::Passed(std::move(passed_mailbox)), - WTF::Passed(ContextProviderWrapper()), - WTF::Passed(std::move(passed_sync_token)))); - } else { - ReleaseTexture(is_converted_from_skia_texture_, texture_id_, - std::move(passed_mailbox), ContextProviderWrapper(), - std::move(passed_sync_token)); - } - - texture_id_ = 0u; // invalidate the texture. - texture_thread_task_runner_ = nullptr; -} +MailboxTextureHolder::~MailboxTextureHolder() = default; } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h index 45e1902..452965d9 100644 --- a/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h +++ b/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
@@ -40,35 +40,18 @@ GLenum texture_target() const { return texture_target_; } void Sync(MailboxSyncMode); - // In WebGL's commit or transferToImageBitmap calls, it will call the - // DrawingBuffer::transferToStaticBitmapImage function, which produces the - // input parameters for this method. - MailboxTextureHolder(const gpu::Mailbox&, - const gpu::SyncToken&, - unsigned texture_id_to_delete_after_mailbox_consumed, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&, - IntSize mailbox_size, - bool is_origin_top_left); // This function may be used when the MailboxTextureHolder is created on a // different thread. The caller must provide a verified sync token if it is // created cross-thread. MailboxTextureHolder(const gpu::Mailbox&, - const gpu::SyncToken&, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&, + base::WeakPtr<WebGraphicsContext3DProviderWrapper>, scoped_refptr<MailboxRef> mailbox_ref, - PlatformThreadId context_thread_id, const SkImageInfo& sk_image_info, GLenum texture_target, bool is_origin_top_left); private: - void InitCommon(); - gpu::Mailbox mailbox_; - unsigned texture_id_; - bool is_converted_from_skia_texture_; - scoped_refptr<base::SingleThreadTaskRunner> texture_thread_task_runner_; - base::PlatformThreadId thread_id_; bool did_issue_ordering_barrier_ = false; SkImageInfo sk_image_info_; GLenum texture_target_;
diff --git a/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc b/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc index 8b7181e..531f2b37 100644 --- a/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc +++ b/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
@@ -17,11 +17,6 @@ namespace blink { namespace { -bool IsSkImageOriginTopLeft(sk_sp<SkImage> image) { - GrSurfaceOrigin origin; - image->getBackendTexture(false, &origin); - return origin == kTopLeft_GrSurfaceOrigin; -} struct ReleaseContext { scoped_refptr<TextureHolder::MailboxRef> mailbox_ref; @@ -46,15 +41,6 @@ } // namespace SkiaTextureHolder::SkiaTextureHolder( - sk_sp<SkImage> image, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& - context_provider_wrapper) - : TextureHolder(std::move(context_provider_wrapper), - base::MakeRefCounted<MailboxRef>(nullptr), - IsSkImageOriginTopLeft(image)), - image_(std::move(image)) {} - -SkiaTextureHolder::SkiaTextureHolder( const MailboxTextureHolder* mailbox_texture_holder, GLuint shared_image_texture_id) : TextureHolder(SharedGpuContext::ContextProviderWrapper(),
diff --git a/third_party/blink/renderer/platform/graphics/skia_texture_holder.h b/third_party/blink/renderer/platform/graphics/skia_texture_holder.h index 4aa25299..75de7d9 100644 --- a/third_party/blink/renderer/platform/graphics/skia_texture_holder.h +++ b/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
@@ -32,11 +32,6 @@ const sk_sp<SkImage>& GetSkImage() const { return image_; } - // When creating a AcceleratedStaticBitmap from a texture-backed SkImage, this - // function will be called to create a TextureHolder object. - SkiaTextureHolder(sk_sp<SkImage>, - base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&); - // This function consumes the mailbox in the input parameter and turn it into // a texture-backed SkImage. // |shared_image_texture_id| is an optional texture bound to the
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.h b/third_party/blink/renderer/platform/graphics/static_bitmap_image.h index 7f55e36..cd29634 100644 --- a/third_party/blink/renderer/platform/graphics/static_bitmap_image.h +++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
@@ -89,6 +89,7 @@ return mailbox; } virtual const gpu::SyncToken& GetSyncToken() const; + virtual void UpdateSyncToken(const gpu::SyncToken&) {} virtual bool IsPremultiplied() const { return true; } // Methods have exactly the same implementation for all sub-classes
diff --git a/third_party/blink/renderer/platform/graphics/texture_holder.cc b/third_party/blink/renderer/platform/graphics/texture_holder.cc new file mode 100644 index 0000000..48ca1ca --- /dev/null +++ b/third_party/blink/renderer/platform/graphics/texture_holder.cc
@@ -0,0 +1,39 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/platform/graphics/texture_holder.h" + +namespace blink { + +namespace { +void ReleaseCallbackOnContextThread( + std::unique_ptr<viz::SingleReleaseCallback> callback, + const gpu::SyncToken sync_token) { + callback->Run(sync_token, /* is_lost = */ false); +} +} // namespace + +TextureHolder::MailboxRef::MailboxRef( + const gpu::SyncToken& sync_token, + base::PlatformThreadRef context_thread_ref, + scoped_refptr<base::SingleThreadTaskRunner> context_task_runner, + std::unique_ptr<viz::SingleReleaseCallback> release_callback) + : sync_token_(sync_token), + context_thread_ref_(context_thread_ref), + context_task_runner_(std::move(context_task_runner)), + release_callback_(std::move(release_callback)) { + DCHECK(!is_cross_thread() || sync_token_.verified_flush()); +} + +TextureHolder::MailboxRef::~MailboxRef() { + if (context_thread_ref_ == base::PlatformThread::CurrentRef()) { + ReleaseCallbackOnContextThread(std::move(release_callback_), sync_token_); + } else { + context_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&ReleaseCallbackOnContextThread, + std::move(release_callback_), sync_token_)); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/texture_holder.h b/third_party/blink/renderer/platform/graphics/texture_holder.h index a1ba07e2..5a79d5b4 100644 --- a/third_party/blink/renderer/platform/graphics/texture_holder.h +++ b/third_party/blink/renderer/platform/graphics/texture_holder.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_TEXTURE_HOLDER_H_ #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "components/viz/common/resources/single_release_callback.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/sync_token.h" @@ -24,19 +25,22 @@ public: class MailboxRef : public ThreadSafeRefCounted<MailboxRef> { public: - explicit MailboxRef( - std::unique_ptr<viz::SingleReleaseCallback> release_callback) - : release_callback_(std::move(release_callback)) {} - ~MailboxRef() { - if (release_callback_) - release_callback_->Run(sync_token_, false /* resource_lost */); - } + MailboxRef(const gpu::SyncToken& sync_token, + base::PlatformThreadRef context_thread_ref, + scoped_refptr<base::SingleThreadTaskRunner> context_task_runner, + std::unique_ptr<viz::SingleReleaseCallback> release_callback); + ~MailboxRef(); + bool is_cross_thread() const { + return base::PlatformThread::CurrentRef() != context_thread_ref_; + } void set_sync_token(gpu::SyncToken token) { sync_token_ = token; } const gpu::SyncToken& sync_token() const { return sync_token_; } private: gpu::SyncToken sync_token_; + const base::PlatformThreadRef context_thread_ref_; + const scoped_refptr<base::SingleThreadTaskRunner> context_task_runner_; std::unique_ptr<viz::SingleReleaseCallback> release_callback_; };
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index 4efe837..4ccedb3 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -958,16 +958,12 @@ // and add a range of new priorities less than low. if (task_queue->web_scheduling_priority()) { switch (task_queue->web_scheduling_priority().value()) { - case WebSchedulingPriority::kImmediatePriority: - return TaskQueue::QueuePriority::kHighestPriority; - case WebSchedulingPriority::kHighPriority: + case WebSchedulingPriority::kUserBlockingPriority: return TaskQueue::QueuePriority::kHighPriority; - case WebSchedulingPriority::kDefaultPriority: + case WebSchedulingPriority::kUserVisiblePriority: return TaskQueue::QueuePriority::kNormalPriority; - case WebSchedulingPriority::kLowPriority: + case WebSchedulingPriority::kBackgroundPriority: return TaskQueue::QueuePriority::kLowPriority; - case WebSchedulingPriority::kIdlePriority: - return TaskQueue::QueuePriority::kBestEffortPriority; } }
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc index 43efd83..176171f8 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -2314,11 +2314,9 @@ // Helper for posting tasks to a WebSchedulingTaskQueue. |task_descriptor| is // a string with space delimited task identifiers. The first letter of each // task identifier specifies the task queue priority: - // - 'I': Immediate - // - 'H': High - // - 'D': Default - // - 'L': Low - // - 'E': Idle + // - 'U': UserBlocking + // - 'V': UserVisible + // - 'B': Background void PostWebSchedulingTestTasks(Vector<String>* run_order, const String& task_descriptor) { std::istringstream stream(task_descriptor.Utf8()); @@ -2327,20 +2325,14 @@ stream >> task; WebSchedulingPriority priority; switch (task[0]) { - case 'I': - priority = WebSchedulingPriority::kImmediatePriority; + case 'U': + priority = WebSchedulingPriority::kUserBlockingPriority; break; - case 'H': - priority = WebSchedulingPriority::kHighPriority; + case 'V': + priority = WebSchedulingPriority::kUserVisiblePriority; break; - case 'D': - priority = WebSchedulingPriority::kDefaultPriority; - break; - case 'L': - priority = WebSchedulingPriority::kLowPriority; - break; - case 'E': - priority = WebSchedulingPriority::kIdlePriority; + case 'B': + priority = WebSchedulingPriority::kBackgroundPriority; break; default: EXPECT_FALSE(true); @@ -2361,23 +2353,23 @@ TEST_F(WebSchedulingTaskQueueTest, TasksRunInPriorityOrder) { Vector<String> run_order; - PostWebSchedulingTestTasks(&run_order, "E1 E2 L1 L2 D1 D2 H1 H2 I1 I2"); + PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2"); base::RunLoop().RunUntilIdle(); - EXPECT_THAT(run_order, testing::ElementsAre("I1", "I2", "H1", "H2", "D1", - "D2", "L1", "L2", "E1", "E2")); + EXPECT_THAT(run_order, + testing::ElementsAre("U1", "U2", "V1", "V2", "B1", "B2")); } TEST_F(WebSchedulingTaskQueueTest, DynamicTaskPriorityOrder) { Vector<String> run_order; - PostWebSchedulingTestTasks(&run_order, "E1 E2 D1 D2 I1 I2"); - task_queues_[static_cast<int>(WebSchedulingPriority::kImmediatePriority)] - ->SetPriority(WebSchedulingPriority::kLowPriority); + PostWebSchedulingTestTasks(&run_order, "B1 B2 V1 V2 U1 U2"); + task_queues_[static_cast<int>(WebSchedulingPriority::kUserBlockingPriority)] + ->SetPriority(WebSchedulingPriority::kBackgroundPriority); base::RunLoop().RunUntilIdle(); EXPECT_THAT(run_order, - testing::ElementsAre("D1", "D2", "I1", "I2", "E1", "E2")); + testing::ElementsAre("V1", "V2", "B1", "B2", "U1", "U2")); } } // namespace frame_scheduler_impl_unittest
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc index 18f4199..99e7a2f 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -260,38 +260,24 @@ TEST_F(FrameTaskQueueControllerTest, AddWebSchedulingTaskQueues) { scoped_refptr<MainThreadTaskQueue> task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - QueueTraits(), WebSchedulingPriority::kImmediatePriority); + QueueTraits(), WebSchedulingPriority::kUserBlockingPriority); EXPECT_EQ(1u, frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); - EXPECT_EQ(WebSchedulingPriority::kImmediatePriority, + EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority, task_queue->web_scheduling_priority().value()); task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - QueueTraits(), WebSchedulingPriority::kHighPriority); + QueueTraits(), WebSchedulingPriority::kUserVisiblePriority); EXPECT_EQ(2u, frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); - EXPECT_EQ(WebSchedulingPriority::kHighPriority, + EXPECT_EQ(WebSchedulingPriority::kUserVisiblePriority, task_queue->web_scheduling_priority().value()); task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - QueueTraits(), WebSchedulingPriority::kDefaultPriority); + QueueTraits(), WebSchedulingPriority::kBackgroundPriority); EXPECT_EQ(3u, frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); - EXPECT_EQ(WebSchedulingPriority::kDefaultPriority, - task_queue->web_scheduling_priority().value()); - - task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - QueueTraits(), WebSchedulingPriority::kLowPriority); - EXPECT_EQ(4u, - frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); - EXPECT_EQ(WebSchedulingPriority::kLowPriority, - task_queue->web_scheduling_priority().value()); - - task_queue = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - QueueTraits(), WebSchedulingPriority::kIdlePriority); - EXPECT_EQ(5u, - frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); - EXPECT_EQ(WebSchedulingPriority::kIdlePriority, + EXPECT_EQ(WebSchedulingPriority::kBackgroundPriority, task_queue->web_scheduling_priority().value()); } @@ -299,18 +285,18 @@ AddMultipleSamePriorityWebSchedulingTaskQueues) { scoped_refptr<MainThreadTaskQueue> task_queue1 = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - QueueTraits(), WebSchedulingPriority::kImmediatePriority); + QueueTraits(), WebSchedulingPriority::kUserBlockingPriority); EXPECT_EQ(1u, frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); - EXPECT_EQ(WebSchedulingPriority::kImmediatePriority, + EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority, task_queue1->web_scheduling_priority().value()); scoped_refptr<MainThreadTaskQueue> task_queue2 = frame_task_queue_controller_->NewWebSchedulingTaskQueue( - QueueTraits(), WebSchedulingPriority::kImmediatePriority); + QueueTraits(), WebSchedulingPriority::kUserBlockingPriority); EXPECT_EQ(2u, frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size()); - EXPECT_EQ(WebSchedulingPriority::kImmediatePriority, + EXPECT_EQ(WebSchedulingPriority::kUserBlockingPriority, task_queue2->web_scheduling_priority().value()); EXPECT_NE(task_queue1.get(), task_queue2.get());
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc b/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc index c3c9844..d680bb7 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc
@@ -8,45 +8,33 @@ namespace { -const AtomicString& ImmediatePriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, immediate_priority, ("immediate")); - return immediate_priority; +const AtomicString& UserBlockingPriorityKeyword() { + DEFINE_STATIC_LOCAL(const AtomicString, user_blocking_priority, + ("user-blocking")); + return user_blocking_priority; } -const AtomicString& HighPriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, high_priority, ("high")); - return high_priority; +const AtomicString& UserVisiblePriorityKeyword() { + DEFINE_STATIC_LOCAL(const AtomicString, user_visible_priority, + ("user-visible")); + return user_visible_priority; } -const AtomicString& DefaultPriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, default_priority, ("default")); - return default_priority; -} - -const AtomicString& LowPriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, low_priority, ("low")); - return low_priority; -} - -const AtomicString& IdlePriorityKeyword() { - DEFINE_STATIC_LOCAL(const AtomicString, idle_priority, ("idle")); - return idle_priority; +const AtomicString& BackgroundPriorityKeyword() { + DEFINE_STATIC_LOCAL(const AtomicString, background_priority, ("background")); + return background_priority; } } // namespace AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) { switch (priority) { - case WebSchedulingPriority::kImmediatePriority: - return ImmediatePriorityKeyword(); - case WebSchedulingPriority::kHighPriority: - return HighPriorityKeyword(); - case WebSchedulingPriority::kDefaultPriority: - return DefaultPriorityKeyword(); - case WebSchedulingPriority::kLowPriority: - return LowPriorityKeyword(); - case WebSchedulingPriority::kIdlePriority: - return IdlePriorityKeyword(); + case WebSchedulingPriority::kUserBlockingPriority: + return UserBlockingPriorityKeyword(); + case WebSchedulingPriority::kUserVisiblePriority: + return UserVisiblePriorityKeyword(); + case WebSchedulingPriority::kBackgroundPriority: + return BackgroundPriorityKeyword(); } NOTREACHED(); @@ -55,19 +43,14 @@ WebSchedulingPriority WebSchedulingPriorityFromString( const AtomicString& priority) { - if (priority == ImmediatePriorityKeyword()) - return WebSchedulingPriority::kImmediatePriority; - if (priority == HighPriorityKeyword()) - return WebSchedulingPriority::kHighPriority; - if (priority == DefaultPriorityKeyword()) - return WebSchedulingPriority::kDefaultPriority; - if (priority == LowPriorityKeyword()) - return WebSchedulingPriority::kLowPriority; - if (priority == IdlePriorityKeyword()) - return WebSchedulingPriority::kIdlePriority; - + if (priority == UserBlockingPriorityKeyword()) + return WebSchedulingPriority::kUserBlockingPriority; + if (priority == UserVisiblePriorityKeyword()) + return WebSchedulingPriority::kUserVisiblePriority; + if (priority == BackgroundPriorityKeyword()) + return WebSchedulingPriority::kBackgroundPriority; NOTREACHED(); - return WebSchedulingPriority::kDefaultPriority; + return WebSchedulingPriority::kUserVisiblePriority; } } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h b/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h index fde66f5..049ecb25 100644 --- a/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h +++ b/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h
@@ -13,13 +13,11 @@ // Priorities for the experimental scheduling API (see // https://github.com/WICG/main-thread-scheduling). enum class WebSchedulingPriority { - kImmediatePriority = 0, - kHighPriority = 1, - kDefaultPriority = 2, - kLowPriority = 3, - kIdlePriority = 4, + kUserBlockingPriority = 0, + kUserVisiblePriority = 1, + kBackgroundPriority = 2, - kLastPriority = kIdlePriority + kLastPriority = kBackgroundPriority }; PLATFORM_EXPORT AtomicString
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 34262e4..1eb799c 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2799,6 +2799,7 @@ crbug.com/641245 external/wpt/css/motion/offset-path-ray-contain-005.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac10.11 ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-animation.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-canvas-parent.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-canvas-sibling.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-parent-with-border-radius.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json index 12ff71b..5eed2a3 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -255206,6 +255206,12 @@ {} ] ], + "html/semantics/document-metadata/the-style-element/style_load_event.html": [ + [ + "html/semantics/document-metadata/the-style-element/style_load_event.html", + {} + ] + ], "html/semantics/document-metadata/the-style-element/style_media.html": [ [ "html/semantics/document-metadata/the-style-element/style_media.html", @@ -347151,7 +347157,7 @@ "testharness" ], "IndexedDB/idb-binary-key-detached.htm": [ - "26afcfb1cd03c2cfb3e4fcc4a9ce382144225f24", + "5a2e1f79f42e5d816870a1f948519317f0fd00fe", "testharness" ], "IndexedDB/idb-binary-key-roundtrip.htm": [ @@ -347179,7 +347185,7 @@ "testharness" ], "IndexedDB/idbcursor-advance-exception-order.html": [ - "13f7fdae5a57a716a13ed808fcd3613034f71e2d", + "1e05c9074d6b1e5c86c46cc1f91bdbd0ecb26ad9", "testharness" ], "IndexedDB/idbcursor-advance-invalid.htm": [ @@ -347907,7 +347913,7 @@ "testharness" ], "IndexedDB/idbkeyrange-includes.htm": [ - "aea588051aeaab63c3855a778b22d1a6932d78ff", + "9a408e888a42d2f79eaf2ed2f30311fbaa596625", "testharness" ], "IndexedDB/idbkeyrange.htm": [ @@ -350427,7 +350433,7 @@ "testharness" ], "bluetooth/idl/idl-BluetoothUUID.html": [ - "2adf35a419ff9687511884e4294ec72dbb22d347", + "14463127e06b422a2830042bb887e5108e200753", "testharness" ], "bluetooth/idl/idl-NavigatorBluetooth.html": [ @@ -351703,7 +351709,7 @@ "support" ], "common/test-setting-immutable-prototype.js": [ - "92e61c07424166f4fd514ac0cd6d50f1c68b0020", + "de619b1d76663d0f41f13b720609bd4cc28747c2", "support" ], "common/test-setting-immutable-prototype.js.headers": [ @@ -352719,7 +352725,7 @@ "testharness" ], "content-security-policy/generic/eval-typecheck-callout-order.tentative.html": [ - "7b3c12e396445ff72480a1e9c7cc77550f93f75c", + "0be7cf29a284d5f2471c7ada0b5cd643b6f0fb6a", "testharness" ], "content-security-policy/generic/eval-typecheck-callout-order.tentative.html.headers": [ @@ -436027,7 +436033,7 @@ "testharness" ], "css/cssom/CSSStyleSheet.html": [ - "90cfb02751fa540ae29d12357deb41c3671a7567", + "d38efc280232c182db8c301714083a0e3d002413", "testharness" ], "css/cssom/HTMLLinkElement-disabled-001.tentative-expected.txt": [ @@ -436415,7 +436421,7 @@ "testharness" ], "css/cssom/medialist-interfaces-002.html": [ - "9820015f5e02642ea4c544184811f9f243ee83c5", + "210ace1393a12c34323983dddf9b11467cb38d94", "testharness" ], "css/cssom/medialist-interfaces-003.html": [ @@ -445811,7 +445817,7 @@ "support" ], "custom-elements/historical.html": [ - "70981ce59c41dd352bccf1b70a1cb7c8cecf30ec", + "5a961b13ad7f44f64b3df6dafeeb9321e8bf6762", "testharness" ], "custom-elements/htmlconstructor/newtarget-expected.txt": [ @@ -451019,7 +451025,7 @@ "testharness" ], "encoding/textdecoder-fatal.any.js": [ - "5884f11ec3cf145e2d405e30e3ce346abfc97c1b", + "ba8aa5d06c3e2dfea532c70f30bb0841f6966a72", "testharness" ], "encoding/textdecoder-ignorebom.any.js": [ @@ -453559,7 +453565,7 @@ "testharness" ], "fetch/api/headers/headers-record.html": [ - "85dfadd269d2c7460865dc5d1b16ae1b9834a5a8", + "34acc3b1c557ce7bc1841ad3d785fb1f732f299f", "testharness" ], "fetch/api/headers/headers-structure.html": [ @@ -456347,7 +456353,7 @@ "support" ], "generic-sensor/SensorErrorEvent-constructor.https.html": [ - "6e2d1684f57af55a6ca02a982d037250ab4c372a", + "2d68dec56d9a9d6982e5ba729e3a201625f368df", "testharness" ], "generic-sensor/generic-sensor-feature-policy-test.sub.js": [ @@ -458195,7 +458201,7 @@ "testharness" ], "html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub-expected.txt": [ - "9f8ff14c7a7032e1879bffae58e241cea28a4336", + "50084aab9553c49abee24a25e464d5b0b60d1c1a", "support" ], "html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub.html": [ @@ -458203,7 +458209,7 @@ "testharness" ], "html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub-expected.txt": [ - "8e4eb1b79bdeaa06d036297482035da5e98148f6", + "81ed8f9245e63deae8e01dce0e768ca78a1027ea", "support" ], "html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub.html": [ @@ -458211,7 +458217,7 @@ "testharness" ], "html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub-expected.txt": [ - "191c6d77793154768c9865d0de96c98d48baa12e", + "057e0979b0b8af9c4a885567aca075b592f63125", "support" ], "html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub.html": [ @@ -458227,7 +458233,7 @@ "testharness" ], "html/browsers/history/the-location-interface/location-prototype-setting-same-origin-expected.txt": [ - "7b13efac9d1f1bc6aafdee9139a0fda1f0e898b7", + "24572f16ea63549e448e072a84e4fdf1099d6910", "support" ], "html/browsers/history/the-location-interface/location-prototype-setting-same-origin.html": [ @@ -458623,7 +458629,7 @@ "testharness" ], "html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt": [ - "c37433813ae49f401d0487f6bbd9d76c5fd9b3b8", + "2a42279b8de244630e428d8586b60617f1401df0", "support" ], "html/browsers/origin/cross-origin-objects/cross-origin-objects-on-new-window.html": [ @@ -458631,7 +458637,7 @@ "testharness" ], "html/browsers/origin/cross-origin-objects/cross-origin-objects.html": [ - "20f1dfb70839a5aa3fb365e4ecf9ba0f60addc1d", + "2c92d5e51ad8078cec4f6e5e76035a52df93a245", "testharness" ], "html/browsers/origin/cross-origin-objects/frame-with-then.html": [ @@ -459207,7 +459213,7 @@ "testharness" ], "html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin-domain.sub-expected.txt": [ - "9f8ff14c7a7032e1879bffae58e241cea28a4336", + "50084aab9553c49abee24a25e464d5b0b60d1c1a", "support" ], "html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin-domain.sub.html": [ @@ -459215,7 +459221,7 @@ "testharness" ], "html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin.sub-expected.txt": [ - "8e4eb1b79bdeaa06d036297482035da5e98148f6", + "81ed8f9245e63deae8e01dce0e768ca78a1027ea", "support" ], "html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin.sub.html": [ @@ -459223,7 +459229,7 @@ "testharness" ], "html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-goes-cross-origin-domain.sub-expected.txt": [ - "191c6d77793154768c9865d0de96c98d48baa12e", + "057e0979b0b8af9c4a885567aca075b592f63125", "support" ], "html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-goes-cross-origin-domain.sub.html": [ @@ -459707,7 +459713,7 @@ "support" ], "html/cross-origin-embedder-policy/require-corp.https.html": [ - "49b2eb123b519dc96314b1db31cc4d6797efae92", + "8747d29e9343cdfae1d534a39947783ad26ef29c", "testharness" ], "html/cross-origin-embedder-policy/require-corp.https.html.headers": [ @@ -465115,7 +465121,7 @@ "support" ], "html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html": [ - "e3e0778c97a2a04ded5a151d31b1dc4f82334187", + "095931ad785553a9b64d79d96eacebcb021e3171", "testharness" ], "html/infrastructure/common-dom-interfaces/collections/htmlformcontrolscollection.html": [ @@ -467638,6 +467644,10 @@ "ef8ac89c4663e970366401bcaa501b774e410c67", "testharness" ], + "html/semantics/document-metadata/the-style-element/style_load_event.html": [ + "911a088c2ab37e0a457c28aa75b477d1af6561df", + "testharness" + ], "html/semantics/document-metadata/the-style-element/style_media.html": [ "5bd189a2635dae4b17348023d70e29614eed7e50", "testharness" @@ -468799,7 +468809,7 @@ "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html": [ - "63c3018aa9969e819ca8e0109141534467a4bfeb", + "cb28f6591ce9614d6a1aa3e0ea7b753d6cb713df", "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-cue-negative-duration.html": [ @@ -483139,7 +483149,7 @@ "testharness" ], "mediacapture-record/BlobEvent-constructor.html": [ - "3bcf4296e68aea1a7b167e570c0dcec148cc95e4", + "66dc3404d78020108edc823292bff9b83cda42a6", "testharness" ], "mediacapture-record/META.yml": [ @@ -483427,7 +483437,7 @@ "testharness" ], "mediacapture-streams/MediaStreamTrackEvent-constructor.https.html": [ - "8f5a543d8fbed8b046deab4672729a112842faba", + "4946cd71d8125f678af69c87042cc61ddb5b57a5", "testharness" ], "mediacapture-streams/OWNERS": [ @@ -483487,11 +483497,11 @@ "testharness" ], "mediasession/positionstate.html": [ - "2eab2986d4583c1a289b7876010193c8d3d44b3f", + "9033a7be5ce5909e0de9d73e8e6aa02c84387e4d", "testharness" ], "mediasession/setactionhandler.html": [ - "6e1bb26c67a828ae847734070024b404138e7932", + "8f1330f82899e513f1183452490aa0f25b1a6f74", "testharness" ], "mimesniff/META.yml": [ @@ -512891,7 +512901,7 @@ "support" ], "service-workers/service-worker/resources/interfaces-worker.sub.js": [ - "ac79ddc005688affe9acc67b83f43ef304f81c81", + "44bd0870b9561eff46eaf1e56aa27912ce0c11a7", "support" ], "service-workers/service-worker/resources/invalid-blobtype-iframe.https.html": [ @@ -523635,7 +523645,7 @@ "support" ], "tools/wptrunner/wptrunner/process.py": [ - "26e11ddfc8758e95d7f5048596ab8cae4f4bb546", + "8a2b894cb74d4ec091931bf417c92d5bea071cae", "support" ], "tools/wptrunner/wptrunner/products.py": [ @@ -527923,7 +527933,7 @@ "testharness" ], "url/failure.html": [ - "bebdb3dcc4df6ba11a16a1b2a2b450fb610c0f76", + "ac16edf8c743af2650b2b78f570c84f2bc75ecda", "testharness" ], "url/historical.any-expected.txt": [ @@ -527963,11 +527973,11 @@ "support" ], "url/toascii.window-expected.txt": [ - "0425c863532011dc0579c8289a01fdf6bcca5d6d", + "9b87a9be9d998ce07a81975b619f411b2331a0b1", "support" ], "url/toascii.window.js": [ - "b28c664479a26aafddef076ce73ab448418d91fc", + "cdc488ec28526f530031b66b63b3c23ff7dad430", "testharness" ], "url/url-constructor.html": [ @@ -529083,7 +529093,7 @@ "testharness" ], "web-animations/interfaces/Animatable/animate.html": [ - "95d7db7bb3ba36fc9a0914ebe0d2c8e910e29cf1", + "4d17d2dd00ece70673cdd9ca52a77d540c3eac43", "testharness" ], "web-animations/interfaces/Animatable/getAnimations-expected.txt": [ @@ -529171,7 +529181,7 @@ "testharness" ], "web-animations/interfaces/AnimationEffect/updateTiming.html": [ - "746f0d74f19272b0cb4a63b27102642b5eaba459", + "f4f672ab1aac76905e3258144fbf022201df0f53", "testharness" ], "web-animations/interfaces/AnimationPlaybackEvent/constructor.html": [ @@ -529239,11 +529249,11 @@ "testharness" ], "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html": [ - "8233dc07c5de8d17619489e0d759c75c4d2a059f", + "e78e13d69aa5e8004c4ec49de2bc98b6bfb6a54a", "testharness" ], "web-animations/interfaces/KeyframeEffect/setKeyframes.html": [ - "675a705891fa6c75c233179e59cc73cc516ff48c", + "a5c81a29bd9d975c93e652edb614f6dbb1570e3b", "testharness" ], "web-animations/interfaces/KeyframeEffect/style-change-events-expected.txt": [ @@ -529595,7 +529605,7 @@ "support" ], "web-nfc/NDEFMessage_constructor.https.html": [ - "4e53828c310976b5b37657f84a89f03c48e7bc59", + "5d6b557e3ccf73d078e9dc0eda63ca31a28551b8", "testharness" ], "web-nfc/NDEFReader-document-hidden-manual.https-expected.txt": [ @@ -529623,11 +529633,11 @@ "testharness" ], "web-nfc/NDEFReadingEvent_constructor.https.html": [ - "5427b75ae2b6d0fa6c45b24af51b02a8737ffd0b", + "122070f50ed7c4fdb15947cbec68e2a62eea9a06", "testharness" ], "web-nfc/NDEFRecord_constructor.https.html": [ - "a2ea09fa681aff85e0cf69d217a89e9a79a8d96b", + "bf4697f8b17ca97de735dc0851a2f48766b1a6b6", "testharness" ], "web-nfc/NDEFWriter-document-hidden-manual.https-expected.txt": [ @@ -532411,7 +532421,7 @@ "testharness" ], "webmessaging/with-options/null-transfer.html": [ - "72bebd1e38e8c5538ebaf24fe608048bed61d18d", + "2ea09eb7ab4ada86bd4624e222fbdebc026d95e8", "testharness" ], "webmessaging/with-options/one-arg.html": [ @@ -532507,7 +532517,7 @@ "testharness" ], "webmessaging/with-ports/023.html": [ - "da6a5c49a448c2ce502fe09a0693ce15abb6e00d", + "e2569a8463f51f0691f572de7024cd93936adb20", "testharness" ], "webmessaging/with-ports/024.html": [ @@ -532691,11 +532701,11 @@ "support" ], "webrtc-identity/RTCPeerConnection-constructor-expected.txt": [ - "dc884ad040f8b716c034908d9cde69678f2c3c93", + "9bece81541bb54d05a135ed8d904ecc1d9980e1c", "support" ], "webrtc-identity/RTCPeerConnection-constructor.html": [ - "8498e6b35c9ff820c86773dd874930c5b012229e", + "e7b7016338d8b8865b95098a0ec6f7eb2b65c4fb", "testharness" ], "webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https-expected.txt": [ @@ -534695,11 +534705,11 @@ "support" ], "webstorage/event_constructor.html": [ - "fe7fca77a93c7adec48dc31e7926331e427b969b", + "e0bb3f374f4326267e509b4605a7f573a13a627b", "testharness" ], "webstorage/event_initstorageevent.html": [ - "2fe893143614ca6d44becd027f6befba82e18ad1", + "b06a01617a832d51941bc5b351bfc1a6a9f07a59", "testharness" ], "webstorage/event_local_key.html": [ @@ -535119,7 +535129,7 @@ "support" ], "webvtt/api/VTTCue/constructor-exceptions.html": [ - "4d051fb3e981811961c3491297955542acbe445d", + "843cab098456c963912cbe255b23b2f9bef14f67", "testharness" ], "webvtt/api/VTTCue/constructor-expected.txt": [
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idb-binary-key-detached.htm b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-binary-key-detached.htm index 26afcfb..5a2e1f79 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/idb-binary-key-detached.htm +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-binary-key-detached.htm
@@ -23,7 +23,7 @@ worker.postMessage('', [buffer]); assert_equals(array.byteLength, 0); - assert_throws(new TypeError, () => { store.put('', buffer); }); + assert_throws_js(TypeError, () => { store.put('', buffer); }); t.done(); }, 'Detached ArrayBuffer' @@ -43,7 +43,7 @@ worker.postMessage('', [array.buffer]); assert_equals(array.length, 0); - assert_throws(new TypeError, () => { store.put('', array); }); + assert_throws_js(TypeError, () => { store.put('', array); }); t.done(); }, 'Detached TypedArray'
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idbcursor-advance-exception-order.html b/third_party/blink/web_tests/external/wpt/IndexedDB/idbcursor-advance-exception-order.html index 13f7fdae..1e05c907 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/idbcursor-advance-exception-order.html +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idbcursor-advance-exception-order.html
@@ -23,7 +23,7 @@ const cursor = r.result; setTimeout(t.step_func(() => { - assert_throws(new TypeError, () => { cursor.advance(0); }, + assert_throws_js(TypeError, () => { cursor.advance(0); }, '"zero" check (TypeError) should precede ' + '"not active" check (TransactionInactiveError)'); t.done();
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idbkeyrange-includes.htm b/third_party/blink/web_tests/external/wpt/IndexedDB/idbkeyrange-includes.htm index aea5880..9a408e8 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/idbkeyrange-includes.htm +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idbkeyrange-includes.htm
@@ -8,7 +8,7 @@ test(function() { var range = IDBKeyRange.bound(12, 34); - assert_throws(new TypeError, function() { range.includes(); }, + assert_throws_js(TypeError, function() { range.includes(); }, 'throws if key is not specified'); assert_throws('DataError', function() { range.includes(undefined); },
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/idl/idl-BluetoothUUID.html b/third_party/blink/web_tests/external/wpt/bluetooth/idl/idl-BluetoothUUID.html index 2adf35a..1446312 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/idl/idl-BluetoothUUID.html +++ b/third_party/blink/web_tests/external/wpt/bluetooth/idl/idl-BluetoothUUID.html
@@ -142,16 +142,16 @@ let func = () => {}; // cannonicalUUID - assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(object)); + assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(object)); // [] converts to '', which converts to 0 before the range check. assert_equals(BluetoothUUID.canonicalUUID(array), base_uuid); - assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(func)); - assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(undefined)); + assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(func)); + assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(undefined)); assert_equals(BluetoothUUID.canonicalUUID(null), base_uuid); assert_equals(BluetoothUUID.canonicalUUID(false), base_uuid); assert_equals( BluetoothUUID.canonicalUUID(true), BluetoothUUID.canonicalUUID(1)); - assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(NaN)); + assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(NaN)); // getService assert_throws(TypeError(), () => BluetoothUUID.getService(object));
diff --git a/third_party/blink/web_tests/external/wpt/common/test-setting-immutable-prototype.js b/third_party/blink/web_tests/external/wpt/common/test-setting-immutable-prototype.js index 92e61c0..de619b1d 100644 --- a/third_party/blink/web_tests/external/wpt/common/test-setting-immutable-prototype.js +++ b/third_party/blink/web_tests/external/wpt/common/test-setting-immutable-prototype.js
@@ -1,7 +1,7 @@ self.testSettingImmutablePrototypeToNewValueOnly = (prefix, target, newValue, newValueString, { isSameOriginDomain }) => { test(() => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { Object.setPrototypeOf(target, newValue); }); }, `${prefix}: setting the prototype to ${newValueString} via Object.setPrototypeOf should throw a TypeError`);
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/generic/eval-typecheck-callout-order.tentative.html b/third_party/blink/web_tests/external/wpt/content-security-policy/generic/eval-typecheck-callout-order.tentative.html index 7b3c12e..0be7cf2 100644 --- a/third_party/blink/web_tests/external/wpt/content-security-policy/generic/eval-typecheck-callout-order.tentative.html +++ b/third_party/blink/web_tests/external/wpt/content-security-policy/generic/eval-typecheck-callout-order.tentative.html
@@ -10,7 +10,7 @@ <script nonce='abc'> test(function() { - assert_throws(new EvalError, function() { + assert_throws_js(EvalError, function() { eval("0"); }, "eval of a string should reach host callout"); }, "eval of a string should be checked by CSP");
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet.html b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet.html index 90cfb02..d38efc2 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom/CSSStyleSheet.html
@@ -45,7 +45,7 @@ }, 'insertRule with #bar selector'); test(function() { - assert_throws(new TypeError, function() { styleSheet.insertRule() }); + assert_throws_js(TypeError, function() { styleSheet.insertRule() }); }, 'insertRule with no argument throws'); test(function() { @@ -65,7 +65,7 @@ }, 'deleteRule(1)'); test(function() { - assert_throws(new TypeError, function() { styleSheet.deleteRule() }); + assert_throws_js(TypeError, function() { styleSheet.deleteRule() }); }, 'deleteRule with no argument throws'); test(function() {
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/medialist-interfaces-002.html b/third_party/blink/web_tests/external/wpt/css/cssom/medialist-interfaces-002.html index 9820015..210ace1 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom/medialist-interfaces-002.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom/medialist-interfaces-002.html
@@ -36,7 +36,7 @@ // MediaList.deleteMedium called without argument throws error. test(function() { media_list = setup(); - assert_throws(new TypeError, function() { media_list.deleteMedium(); }); + assert_throws_js(TypeError, function() { media_list.deleteMedium(); }); }, "deleteMedium_called_without_argument"); // MediaList.deleteMedium removes correct medium and updates corresponding properties.
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/historical.html b/third_party/blink/web_tests/external/wpt/custom-elements/historical.html index 70981ce..5a961b1 100644 --- a/third_party/blink/web_tests/external/wpt/custom-elements/historical.html +++ b/third_party/blink/web_tests/external/wpt/custom-elements/historical.html
@@ -17,7 +17,7 @@ assert_false(element.hasAttribute('is')) } catch (e) { // If v1 is supported, then converting string to dictionary should throw. - assert_throws(new TypeError, function() { throw e }) + assert_throws_js(TypeError, function() { throw e }) } }, 'document.createElement(localName, "string") should not work') @@ -29,7 +29,7 @@ assert_false(element.hasAttribute('is')) } catch (e) { // If v1 is supported, then converting string to dictionary should throw. - assert_throws(new TypeError, function() { throw e }) + assert_throws_js(TypeError, function() { throw e }) } }, 'document.createElementNS(namespace, qualifiedName, "string") should not work') </script>
diff --git a/third_party/blink/web_tests/external/wpt/encoding/textdecoder-fatal.any.js b/third_party/blink/web_tests/external/wpt/encoding/textdecoder-fatal.any.js index 5884f11..ba8aa5d 100644 --- a/third_party/blink/web_tests/external/wpt/encoding/textdecoder-fatal.any.js +++ b/third_party/blink/web_tests/external/wpt/encoding/textdecoder-fatal.any.js
@@ -71,7 +71,7 @@ assert_equals(decoder.decode(new DataView(bytes.buffer, 0, 3)), '♥', 'decode() should decode full sequence'); - assert_throws(new TypeError, + assert_throws_js(TypeError, () => decoder.decode(new DataView(bytes.buffer, 0, 2)), 'decode() should throw on incomplete sequence'); assert_equals(decoder.decode(new DataView(bytes.buffer, 0, 3)),
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/headers/headers-record.html b/third_party/blink/web_tests/external/wpt/fetch/api/headers/headers-record.html index 85dfadd..34acc3b1 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/headers/headers-record.html +++ b/third_party/blink/web_tests/external/wpt/fetch/api/headers/headers-record.html
@@ -35,7 +35,7 @@ }, "Passing undefined to Headers constructor"); test(function() { - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { var h = new Headers(null); }); }, "Passing null to Headers constructor"); @@ -126,7 +126,7 @@ this.add_cleanup(clearLog); var record = { a: "b", "\uFFFF": "d" }; var proxy = new Proxy(record, loggingHandler); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { var h = new Headers(proxy); }); @@ -151,7 +151,7 @@ this.add_cleanup(clearLog); var record = { a: "\uFFFF", c: "d" } var proxy = new Proxy(record, loggingHandler); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { var h = new Headers(proxy); });
diff --git a/third_party/blink/web_tests/external/wpt/fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html b/third_party/blink/web_tests/external/wpt/fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html index 917e549..255ff1da 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html +++ b/third_party/blink/web_tests/external/wpt/fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html
@@ -63,6 +63,7 @@ "application/x-protobuf", "application/zip", "multipart/byteranges", + "multipart/signed", "text/csv", "text/event-stream", ]
diff --git a/third_party/blink/web_tests/external/wpt/generic-sensor/SensorErrorEvent-constructor.https.html b/third_party/blink/web_tests/external/wpt/generic-sensor/SensorErrorEvent-constructor.https.html index 6e2d168..2d68dec 100644 --- a/third_party/blink/web_tests/external/wpt/generic-sensor/SensorErrorEvent-constructor.https.html +++ b/third_party/blink/web_tests/external/wpt/generic-sensor/SensorErrorEvent-constructor.https.html
@@ -6,7 +6,7 @@ <script> test(() => { assert_equals(SensorErrorEvent.length, 2); - assert_throws(new TypeError, () => new SensorErrorEvent('error')); + assert_throws_js(TypeError, () => new SensorErrorEvent('error')); }, 'SensorErrorEvent constructor without init dict'); test(() => {
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub-expected.txt index 9f8ff14..50084aa 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin-domain.sub-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. PASS Cross-origin via document.domain: the prototype is null -FAIL Cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Cross-origin via document.domain: setting the prototype to an empty object via __proto__ should throw a "SecurityError" DOMException FAIL Cross-origin via document.domain: setting the prototype to an empty object via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Cross-origin via document.domain: the prototype must still be null
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub-expected.txt index 8e4eb1b7..81ed8f92 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-cross-origin.sub-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. PASS Cross-origin: the prototype is null -FAIL Cross-origin: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Cross-origin: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Cross-origin: setting the prototype to an empty object via __proto__ should throw a "SecurityError" DOMException FAIL Cross-origin: setting the prototype to an empty object via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Cross-origin: the prototype must still be null
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub-expected.txt index 191c6d77..057e097 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-goes-cross-origin-domain.sub-expected.txt
@@ -1,18 +1,18 @@ This is a testharness.js-based test. PASS Same-origin (for now): the prototype is accessible PASS Became cross-origin via document.domain: the prototype is now null -FAIL Became cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Became cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Became cross-origin via document.domain: setting the prototype to an empty object via __proto__ should throw a "SecurityError" DOMException FAIL Became cross-origin via document.domain: setting the prototype to an empty object via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Became cross-origin via document.domain: the prototype must still be null FAIL Became cross-origin via document.domain: setting the prototype to null via Object.setPrototypeOf should not throw Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Became cross-origin via document.domain: setting the prototype to null via __proto__ should throw a "SecurityError" since it ends up in CrossOriginGetOwnProperty FAIL Became cross-origin via document.domain: setting the prototype to null via Reflect.setPrototypeOf should return true Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. -FAIL Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via __proto__ should throw a "SecurityError" DOMException FAIL Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-expected.txt index 7b13efa..24572f1 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. PASS Same-origin prerequisite check: the original prototype is accessible -FAIL Same-origin: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Same-origin: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); }" did not throw FAIL Same-origin: setting the prototype to an empty object via __proto__ should throw a TypeError assert_throws: function "function() {
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt index c374338..2a42279 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt
@@ -12,15 +12,15 @@ PASS [[GetPrototypeOf]] should return null (cross-origin) PASS [[GetPrototypeOf]] should return null (same-origin + document.domain) PASS [[GetPrototypeOf]] should return null (cross-site) -FAIL [[SetPrototypeOf]] should return false (cross-origin) assert_throws: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[SetPrototypeOf]] should return false (same-origin + document.domain) assert_throws: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[SetPrototypeOf]] should return false (cross-site) assert_throws: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") +FAIL [[SetPrototypeOf]] should return false (cross-origin) assert_throws_js: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[SetPrototypeOf]] should return false (same-origin + document.domain) assert_throws_js: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[SetPrototypeOf]] should return false (cross-site) assert_throws_js: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS [[IsExtensible]] should return true for cross-origin objects (cross-origin) PASS [[IsExtensible]] should return true for cross-origin objects (same-origin + document.domain) PASS [[IsExtensible]] should return true for cross-origin objects (cross-site) -FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-origin) assert_throws: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[PreventExtensions]] should throw for cross-origin objects (same-origin + document.domain) assert_throws: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-site) assert_throws: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") +FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-origin) assert_throws_js: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[PreventExtensions]] should throw for cross-origin objects (same-origin + document.domain) assert_throws_js: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-site) assert_throws_js: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") FAIL [[GetOwnProperty]] - Properties on cross-origin objects should be reported |own| (cross-origin) Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. FAIL [[GetOwnProperty]] - Properties on cross-origin objects should be reported |own| (same-origin + document.domain) Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. FAIL [[GetOwnProperty]] - Properties on cross-origin objects should be reported |own| (cross-site) Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame.
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html b/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html index 20f1dfb..2c92d5e5 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html +++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
@@ -341,8 +341,8 @@ if (Object.setPrototypeOf) setters.push(function(p) { Object.setPrototypeOf(this, p); }); setters.forEach(function(protoSetter) { - assert_throws(new TypeError, function() { protoSetter.call(win, new Object()); }, "proto setter |call| on cross-origin Window"); - assert_throws(new TypeError, function() { protoSetter.call(win.location, new Object()); }, "proto setter |call| on cross-origin Location"); + assert_throws_js(TypeError, function() { protoSetter.call(win, new Object()); }, "proto setter |call| on cross-origin Window"); + assert_throws_js(TypeError, function() { protoSetter.call(win.location, new Object()); }, "proto setter |call| on cross-origin Location"); }); // Hack to avoid "duplicate test name" harness issues. setters.forEach(function(protoSetter) { @@ -375,9 +375,9 @@ * [[PreventExtensions]] */ addTest(function(win) { - assert_throws(new TypeError, function() { Object.preventExtensions(win) }, + assert_throws_js(TypeError, function() { Object.preventExtensions(win) }, "preventExtensions on cross-origin Window should throw"); - assert_throws(new TypeError, function() { Object.preventExtensions(win.location) }, + assert_throws_js(TypeError, function() { Object.preventExtensions(win.location) }, "preventExtensions on cross-origin Location should throw"); }, "[[PreventExtensions]] should throw for cross-origin objects");
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin-domain.sub-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin-domain.sub-expected.txt index 9f8ff14..50084aa 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin-domain.sub-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin-domain.sub-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. PASS Cross-origin via document.domain: the prototype is null -FAIL Cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Cross-origin via document.domain: setting the prototype to an empty object via __proto__ should throw a "SecurityError" DOMException FAIL Cross-origin via document.domain: setting the prototype to an empty object via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Cross-origin via document.domain: the prototype must still be null
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin.sub-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin.sub-expected.txt index 8e4eb1b7..81ed8f92 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin.sub-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-cross-origin.sub-expected.txt
@@ -1,8 +1,8 @@ This is a testharness.js-based test. PASS Cross-origin: the prototype is null -FAIL Cross-origin: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Cross-origin: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Cross-origin: setting the prototype to an empty object via __proto__ should throw a "SecurityError" DOMException FAIL Cross-origin: setting the prototype to an empty object via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Cross-origin: the prototype must still be null
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-goes-cross-origin-domain.sub-expected.txt b/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-goes-cross-origin-domain.sub-expected.txt index 191c6d77..057e097 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-goes-cross-origin-domain.sub-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-windowproxy-exotic-object/windowproxy-prototype-setting-goes-cross-origin-domain.sub-expected.txt
@@ -1,18 +1,18 @@ This is a testharness.js-based test. PASS Same-origin (for now): the prototype is accessible PASS Became cross-origin via document.domain: the prototype is now null -FAIL Became cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Became cross-origin via document.domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Became cross-origin via document.domain: setting the prototype to an empty object via __proto__ should throw a "SecurityError" DOMException FAIL Became cross-origin via document.domain: setting the prototype to an empty object via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Became cross-origin via document.domain: the prototype must still be null FAIL Became cross-origin via document.domain: setting the prototype to null via Object.setPrototypeOf should not throw Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. PASS Became cross-origin via document.domain: setting the prototype to null via __proto__ should throw a "SecurityError" since it ends up in CrossOriginGetOwnProperty FAIL Became cross-origin via document.domain: setting the prototype to null via Reflect.setPrototypeOf should return true Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. -FAIL Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via Object.setPrototypeOf should throw a TypeError assert_throws: function "() => { +FAIL Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { Object.setPrototypeOf(target, newValue); - }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") + }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via __proto__ should throw a "SecurityError" DOMException FAIL Became cross-origin via document.domain: setting the prototype to the original value from before going cross-origin via Reflect.setPrototypeOf should return false Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html b/third_party/blink/web_tests/external/wpt/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html index e3e0778c9..095931a 100644 --- a/third_party/blink/web_tests/external/wpt/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html +++ b/third_party/blink/web_tests/external/wpt/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html
@@ -160,7 +160,7 @@ test(function() { assert_equals(document.all.namedItem.length, 1); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { document.all.namedItem(); }); }, "namedItem method with no argument");
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html index 63c3018..cb28f65 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html
@@ -52,7 +52,7 @@ // to the new value; if the new value is the string "auto", // then it must be interpreted as the special value auto. assert_equals(textCue.line, "auto"); - assert_throws(new TypeError, function() { textCue.line = "gazonk"; }); + assert_throws_js(TypeError, function() { textCue.line = "gazonk"; }); assert_equals(textCue.line, "auto"); textCue.line = 42; assert_equals(textCue.line, 42);
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/document-scrolling-element-root.html b/third_party/blink/web_tests/external/wpt/intersection-observer/document-scrolling-element-root.html index 9996299..443ff2e 100644 --- a/third_party/blink/web_tests/external/wpt/intersection-observer/document-scrolling-element-root.html +++ b/third_party/blink/web_tests/external/wpt/intersection-observer/document-scrolling-element-root.html
@@ -28,18 +28,16 @@ runTestCycle(function() { assert_true(!!iframe, "iframe exists"); - root = iframe.contentDocument.scrollingElement; - assert_true(!!root, "Root element exists."); target = iframe.contentDocument.getElementById("target"); assert_true(!!target, "Target element exists."); var observer = new IntersectionObserver(function(changes) { entries = entries.concat(changes) - }, { root: root }); + }, { root: iframe.contentDocument }); observer.observe(target); entries = entries.concat(observer.takeRecords()); assert_equals(entries.length, 0, "No initial notifications."); runTestCycle(step0, "First rAF."); - }, "Observer with explicit root which is the document's scrolling element."); + }, "Observer with explicit root which is the document."); }; function step0() {
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-record/BlobEvent-constructor.html b/third_party/blink/web_tests/external/wpt/mediacapture-record/BlobEvent-constructor.html index 3bcf4296..66dc3404 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-record/BlobEvent-constructor.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-record/BlobEvent-constructor.html
@@ -6,25 +6,25 @@ <script> test(function() { assert_equals(BlobEvent.length, 2); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new BlobEvent("type"); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new BlobEvent("type", null); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new BlobEvent("type", undefined); }); }, "The BlobEventInit dictionary is required"); test(function() { - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new BlobEvent("type", {}); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new BlobEvent("type", { data: null }); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new BlobEvent("type", { data: undefined }); }); }, "The BlobEventInit dictionary's data member is required.");
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrackEvent-constructor.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrackEvent-constructor.https.html index 8f5a543..4946cd71 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrackEvent-constructor.https.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrackEvent-constructor.https.html
@@ -6,25 +6,25 @@ <script> test(function() { assert_equals(MediaStreamTrackEvent.length, 2); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new MediaStreamTrackEvent("type"); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new MediaStreamTrackEvent("type", null); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new MediaStreamTrackEvent("type", undefined); }); }, "The eventInitDict argument is required"); test(function() { - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new MediaStreamTrackEvent("type", {}); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new MediaStreamTrackEvent("type", { track: null }); }); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new MediaStreamTrackEvent("type", { track: undefined }); }); }, "The eventInitDict's track member is required.");
diff --git a/third_party/blink/web_tests/external/wpt/mediasession/positionstate.html b/third_party/blink/web_tests/external/wpt/mediasession/positionstate.html index 2eab2986..9033a7be 100644 --- a/third_party/blink/web_tests/external/wpt/mediasession/positionstate.html +++ b/third_party/blink/web_tests/external/wpt/mediasession/positionstate.html
@@ -42,8 +42,8 @@ }, 'Test setPositionState with zero duration'); test(() => { - assert_throws( - new TypeError, + assert_throws_js( + TypeError, _ => { window.navigator.mediaSession.setPositionState({ duration: 60.9, @@ -54,8 +54,8 @@ }, 'Test setPositionState throws a TypeError if playback rate is negative'); test(() => { - assert_throws( - new TypeError, + assert_throws_js( + TypeError, _ => { window.navigator.mediaSession.setPositionState({ duration: -1 @@ -64,8 +64,8 @@ }, 'Test setPositionState throws a TypeError if duration is negative'); test(() => { - assert_throws( - new TypeError, + assert_throws_js( + TypeError, _ => { window.navigator.mediaSession.setPositionState({ duration: 10, @@ -75,8 +75,8 @@ }, 'Test setPositionState throws a TypeError if position is negative'); test(() => { - assert_throws( - new TypeError, + assert_throws_js( + TypeError, _ => { window.navigator.mediaSession.setPositionState({ duration: 10, @@ -86,8 +86,8 @@ }, 'Test setPositionState throws a TypeError if duration is less than position'); test(() => { - assert_throws( - new TypeError, + assert_throws_js( + TypeError, _ => { window.navigator.mediaSession.setPositionState({ duration: 60.9, @@ -98,8 +98,8 @@ }, 'Test setPositionState throws a TypeError if playback rate is zero'); test(() => { - assert_throws( - new TypeError, + assert_throws_js( + TypeError, _ => { window.navigator.mediaSession.setPositionState({ position: 10.1,
diff --git a/third_party/blink/web_tests/external/wpt/mediasession/setactionhandler.html b/third_party/blink/web_tests/external/wpt/mediasession/setactionhandler.html index 6e1bb26..8f1330f 100644 --- a/third_party/blink/web_tests/external/wpt/mediasession/setactionhandler.html +++ b/third_party/blink/web_tests/external/wpt/mediasession/setactionhandler.html
@@ -16,8 +16,8 @@ }, "Test that setActionHandler() can be executed for supported actions"); test(function(t) { - assert_throws( - new TypeError, + assert_throws_js( + TypeError, _ => { window.navigator.mediaSession.setActionHandler("invalid", null); }); }, "Test that setActionHandler() throws exception for unsupported actions");
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js index ac79ddc..44bd087 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js
@@ -51,13 +51,13 @@ assert_equals( new ExtendableEvent('ExtendableEvent').type, 'ExtendableEvent', 'Type of ExtendableEvent should be ExtendableEvent'); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new FetchEvent('FetchEvent'); }, 'FetchEvent constructor with one argument throws'); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new FetchEvent('FetchEvent', {}); }, 'FetchEvent constructor with empty init dict throws'); - assert_throws(new TypeError, function() { + assert_throws_js(TypeError, function() { new FetchEvent('FetchEvent', {request: null}); }, 'FetchEvent constructor with null request member throws'); assert_equals(
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/process.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/process.py index 26e11ddf..8a2b894 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/process.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/process.py
@@ -7,5 +7,5 @@ """Encode all the environment values as the appropriate type for each Python version This assumes that all the data is or can be represented as UTF8""" - env_type = six.ensure_binary if sys.version_info[0] < 3 else six.ensure_string + env_type = six.ensure_binary if sys.version_info[0] < 3 else six.ensure_str return {env_type(key): env_type(value) for key, value in six.iteritems(env)}
diff --git a/third_party/blink/web_tests/external/wpt/url/failure.html b/third_party/blink/web_tests/external/wpt/url/failure.html index bebdb3dc..ac16edf 100644 --- a/third_party/blink/web_tests/external/wpt/url/failure.html +++ b/third_party/blink/web_tests/external/wpt/url/failure.html
@@ -25,7 +25,7 @@ self.test(() => { const url = new URL("about:blank") - assert_throws(new TypeError, () => url.href = test.input) + assert_throws_js(TypeError, () => url.href = test.input) }, "URL's href: " + name) self.test(() => { @@ -34,11 +34,11 @@ }, "XHR: " + name) self.test(() => { - assert_throws(new TypeError, () => self.navigator.sendBeacon(test.input)) + assert_throws_js(TypeError, () => self.navigator.sendBeacon(test.input)) }, "sendBeacon(): " + name) self.test(() => { - assert_throws(new TypeError, () => self[0].location = test.input) + assert_throws_js(self[0].TypeError, () => self[0].location = test.input) }, "Location's href: " + name) self.test(() => {
diff --git a/third_party/blink/web_tests/external/wpt/url/toascii.window-expected.txt b/third_party/blink/web_tests/external/wpt/url/toascii.window-expected.txt index 0425c86..9b87a9be 100644 --- a/third_party/blink/web_tests/external/wpt/url/toascii.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/url/toascii.window-expected.txt
@@ -100,7 +100,7 @@ FAIL x..β (using <area>) Failed to construct 'URL': Invalid URL FAIL x..β (using <area>.host) assert_equals: expected "x..xn--nxa" but got "" FAIL x..β (using <area>.hostname) assert_equals: expected "x..xn--nxa" but got "" -FAIL xn--a (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw +FAIL xn--a (using URL) assert_throws_js: function "() => makeURL("url", hostTest.input)" did not throw FAIL xn--a (using URL.host) assert_equals: expected "x" but got "xn--a" FAIL xn--a (using URL.hostname) assert_equals: expected "x" but got "xn--a" FAIL xn--a (using <a>) assert_equals: expected "" but got "xn--a" @@ -109,7 +109,7 @@ FAIL xn--a (using <area>) assert_equals: expected "" but got "xn--a" FAIL xn--a (using <area>.host) assert_equals: expected "x" but got "xn--a" FAIL xn--a (using <area>.hostname) assert_equals: expected "x" but got "xn--a" -FAIL xn--a.xn--nxa (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw +FAIL xn--a.xn--nxa (using URL) assert_throws_js: function "() => makeURL("url", hostTest.input)" did not throw FAIL xn--a.xn--nxa (using URL.host) assert_equals: expected "x" but got "xn--a.xn--nxa" FAIL xn--a.xn--nxa (using URL.hostname) assert_equals: expected "x" but got "xn--a.xn--nxa" FAIL xn--a.xn--nxa (using <a>) assert_equals: expected "" but got "xn--a.xn--nxa" @@ -172,7 +172,7 @@ FAIL .example (using <area>) assert_equals: expected "https://.example/x" but got "https://%E2%80%8D.example/x" FAIL .example (using <area>.host) assert_equals: expected "x" but got "" FAIL .example (using <area>.hostname) assert_equals: expected "x" but got "" -FAIL xn--1ug.example (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw +FAIL xn--1ug.example (using URL) assert_throws_js: function "() => makeURL("url", hostTest.input)" did not throw FAIL xn--1ug.example (using URL.host) assert_equals: expected "x" but got "xn--1ug.example" FAIL xn--1ug.example (using URL.hostname) assert_equals: expected "x" but got "xn--1ug.example" FAIL xn--1ug.example (using <a>) assert_equals: expected "" but got "xn--1ug.example" @@ -190,7 +190,7 @@ FAIL يa (using <area>) assert_equals: expected "https://يa/x" but got "https://%D9%8Aa/x" FAIL يa (using <area>.host) assert_equals: expected "x" but got "" FAIL يa (using <area>.hostname) assert_equals: expected "x" but got "" -FAIL xn--a-yoc (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw +FAIL xn--a-yoc (using URL) assert_throws_js: function "() => makeURL("url", hostTest.input)" did not throw FAIL xn--a-yoc (using URL.host) assert_equals: expected "x" but got "xn--a-yoc" FAIL xn--a-yoc (using URL.hostname) assert_equals: expected "x" but got "xn--a-yoc" FAIL xn--a-yoc (using <a>) assert_equals: expected "" but got "xn--a-yoc" @@ -226,7 +226,7 @@ FAIL �.com (using <area>) assert_equals: expected "https://\ufffd.com/x" but got "https://%EF%BF%BD.com/x" FAIL �.com (using <area>.host) assert_equals: expected "x" but got "" FAIL �.com (using <area>.hostname) assert_equals: expected "x" but got "" -FAIL xn--zn7c.com (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw +FAIL xn--zn7c.com (using URL) assert_throws_js: function "() => makeURL("url", hostTest.input)" did not throw FAIL xn--zn7c.com (using URL.host) assert_equals: expected "x" but got "xn--zn7c.com" FAIL xn--zn7c.com (using URL.hostname) assert_equals: expected "x" but got "xn--zn7c.com" FAIL xn--zn7c.com (using <a>) assert_equals: expected "" but got "xn--zn7c.com"
diff --git a/third_party/blink/web_tests/external/wpt/url/toascii.window.js b/third_party/blink/web_tests/external/wpt/url/toascii.window.js index b28c664..cdc488ec 100644 --- a/third_party/blink/web_tests/external/wpt/url/toascii.window.js +++ b/third_party/blink/web_tests/external/wpt/url/toascii.window.js
@@ -28,7 +28,7 @@ assert_equals(url.href, "https://" + hostTest.output + "/x") } else { if(type === "url") { - assert_throws(new TypeError, () => makeURL("url", hostTest.input)) + assert_throws_js(TypeError, () => makeURL("url", hostTest.input)) } else { const url = makeURL(type, hostTest.input) assert_equals(url.host, "")
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/animate.html b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/animate.html index 95d7db7b..4d17d2d 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/animate.html +++ b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/Animatable/animate.html
@@ -81,7 +81,7 @@ for (const subtest of gInvalidKeyframesTests) { test(t => { const div = createDiv(t); - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { div.animate(subtest.input, 2000); }); }, `Element.animate() does not accept ${subtest.desc}`); @@ -108,7 +108,7 @@ for (const invalid of gBadDelayValues) { test(t => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { createDiv(t).animate(null, { delay: invalid }); }); }, `Element.animate() does not accept invalid delay value: ${invalid}`); @@ -127,7 +127,7 @@ continue; } test(t => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { createDiv(t).animate(null, invalid); }); }, 'Element.animate() does not accept invalid duration value: ' @@ -136,7 +136,7 @@ for (const invalid of gBadDurationValues) { test(t => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { createDiv(t).animate(null, { duration: invalid }); }); }, 'Element.animate() does not accept invalid duration value: ' @@ -146,7 +146,7 @@ for (const invalidEasing of gInvalidEasings) { test(t => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { createDiv(t).animate({ easing: invalidEasing }, 2000); }); }, `Element.animate() does not accept invalid easing: '${invalidEasing}'`); @@ -154,7 +154,7 @@ for (const invalid of gBadIterationStartValues) { test(t => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { createDiv(t).animate(null, { iterationStart: invalid }); }); }, 'Element.animate() does not accept invalid iterationStart value: ' + @@ -163,7 +163,7 @@ for (const invalid of gBadIterationsValues) { test(t => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { createDiv(t).animate(null, { iterations: invalid }); }); }, 'Element.animate() does not accept invalid iterations value: ' +
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming.html b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming.html index 746f0d7..f4f672a 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming.html +++ b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming.html
@@ -258,7 +258,7 @@ for (const invalid of gBadDurationValues) { test(t => { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { createDiv(t).animate(null, { duration: invalid }); }); }, 'Throws when setting invalid duration: '
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html index 8233dc07..e78e13d 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html +++ b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html
@@ -37,7 +37,7 @@ test(() => { for (const invalidEasing of gInvalidEasings) { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { new KeyframeEffect(target, { easing: invalidEasing }); }, `TypeError is thrown for easing '${invalidEasing}'`); } @@ -46,7 +46,7 @@ test(() => { for (const invalidEasing of gInvalidEasings) { - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { new KeyframeEffect(target, [{ easing: invalidEasing }]); }, `TypeError is thrown for easing '${invalidEasing}'`); }
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html index 675a7058..a5c81a29 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html +++ b/third_party/blink/web_tests/external/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes.html
@@ -34,7 +34,7 @@ for (const subtest of gInvalidKeyframesTests) { test(t => { const effect = new KeyframeEffect(target, {}); - assert_throws(new TypeError, () => { + assert_throws_js(TypeError, () => { effect.setKeyframes(subtest.input); }); }, `KeyframeEffect constructor throws with ${subtest.desc}`);
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFMessage_constructor.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFMessage_constructor.https.html index 4e53828c..5d6b557 100644 --- a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFMessage_constructor.https.html +++ b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFMessage_constructor.https.html
@@ -8,21 +8,21 @@ test(() => { assert_equals(NDEFMessage.length, 1); - assert_throws(new TypeError, () => new NDEFMessage()); + assert_throws_js(TypeError, () => new NDEFMessage()); }, 'NDEFMessage constructor without init dict'); test(() => { - assert_throws(new TypeError, () => new NDEFMessage(null), + assert_throws_js(TypeError, () => new NDEFMessage(null), 'NDEFMessageInit#records is a required field.'); }, 'NDEFMessage constructor with null init dict'); test(() => { - assert_throws(new TypeError, () => new NDEFMessage({dummy_key: 'dummy_value'}), + assert_throws_js(TypeError, () => new NDEFMessage({dummy_key: 'dummy_value'}), 'NDEFMessageInit#records is a required field.'); }, 'NDEFMessage constructor without NDEFMessageInit#records field'); test(() => { - assert_throws(new TypeError, () => new NDEFMessage({records: []}), + assert_throws_js(TypeError, () => new NDEFMessage({records: []}), 'NDEFMessageInit#records should not be empty.'); }, 'NDEFMessage constructor with NDEFMessageInit#records being empty');
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReadingEvent_constructor.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReadingEvent_constructor.https.html index 5427b75..122070f 100644 --- a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReadingEvent_constructor.https.html +++ b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFReadingEvent_constructor.https.html
@@ -8,11 +8,11 @@ test(() => { assert_equals(NDEFReadingEvent.length, 2); - assert_throws(new TypeError, () => new NDEFReadingEvent('message')); + assert_throws_js(TypeError, () => new NDEFReadingEvent('message')); }, 'NDEFReadingEvent constructor without init dict'); test(() => { - assert_throws(new TypeError, () => new NDEFReadingEvent('type', + assert_throws_js(TypeError, () => new NDEFReadingEvent('type', {serialNumber: '', message: null}), 'NDEFMessageInit#records is a required field.'); }, 'NDEFReadingEvent constructor failed to construct its NDEFMessage');
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFRecord_constructor.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFRecord_constructor.https.html index a2ea09f..bf4697f8 100644 --- a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFRecord_constructor.https.html +++ b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFRecord_constructor.https.html
@@ -8,42 +8,42 @@ test(() => { assert_equals(NDEFRecord.length, 1); - assert_throws(new TypeError, () => new NDEFRecord()); + assert_throws_js(TypeError, () => new NDEFRecord()); }, 'NDEFRecord constructor without init dict'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord(null), + assert_throws_js(TypeError, () => new NDEFRecord(null), 'NDEFRecordInit#recordType is a required field.'); }, 'NDEFRecord constructor with null init dict'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord({id: test_record_id, data: test_text_data}), + assert_throws_js(TypeError, () => new NDEFRecord({id: test_record_id, data: test_text_data}), 'NDEFRecordInit#recordType is a required field.'); }, 'NDEFRecord constructor without NDEFRecordInit#recordType field'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('empty', test_text_data, test_record_id)), 'id does not apply for empty record type.'); }, 'NDEFRecord constructor with empty record type and id'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('empty', test_text_data, test_record_id, 'text/plain')), 'mediaType does not apply for empty record type.'); - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('text', test_text_data, test_record_id, 'text/plain')), 'mediaType does not apply for text record type.'); - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('url', test_url_data, test_record_id, 'text/plain')), 'mediaType does not apply for url record type.'); - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('absolute-url', test_url_data, test_record_id, 'text/plain')), 'mediaType does not apply for absolute-url record type.'); - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('unknown', test_buffer_data, test_record_id, 'application/octet-stream')), 'mediaType does not apply for unknown record type.'); - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('foo.example.com:bar', test_buffer_data, test_record_id, 'application/octet-stream')), 'mediaType does not apply for external record type.'); }, 'NDEFRecord constructor should only accept mediaType for mime record type'); @@ -207,7 +207,7 @@ }, 'NDEFRecord constructor with absolute-url record type'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createMimeRecord("A string is not a BufferSource")), 'Only BufferSource is allowed to be the record data.'); @@ -250,7 +250,7 @@ }, 'NDEFRecord constructor with mime record type and json data'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createUnknownRecord("A string is not a BufferSource")), 'Only BufferSource is allowed to be the record data.'); @@ -280,7 +280,7 @@ }, 'NDEFRecord constructor with unknown record type'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord( + assert_throws_js(TypeError, () => new NDEFRecord( createRecord('foo.eXamPle.com:bAr*-', "A string is not a BufferSource or NDEFMessageInit")), 'Only BufferSource and NDEFMessageInit are allowed to be the record data.'); @@ -331,15 +331,15 @@ }, 'NDEFRecord constructor with external record type'); test(() => { - assert_throws(new TypeError, () => new NDEFRecord(createRecord('EMptY')), + assert_throws_js(TypeError, () => new NDEFRecord(createRecord('EMptY')), 'Unknown record type.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord('TeXt', test_text_data)), + assert_throws_js(TypeError, () => new NDEFRecord(createRecord('TeXt', test_text_data)), 'Unknown record type.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord('uRL', test_url_data)), + assert_throws_js(TypeError, () => new NDEFRecord(createRecord('uRL', test_url_data)), 'Unknown record type.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord('Mime', test_buffer_data)), + assert_throws_js(TypeError, () => new NDEFRecord(createRecord('Mime', test_buffer_data)), 'Unknown record type.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord('sMart-PosTER', test_url_data)), + assert_throws_js(TypeError, () => new NDEFRecord(createRecord('sMart-PosTER', test_url_data)), 'Unknown record type.'); }, 'NDEFRecord constructor with record type string being treated as case sensitive'); @@ -352,21 +352,21 @@ const record = new NDEFRecord(createRecord( [...Array(251)].map(_ => 'a').join('') + ':xyz', test_buffer_data)); // Exceeding 255, Throws. - assert_throws(new TypeError, () => new NDEFRecord(createRecord( + assert_throws_js(TypeError, () => new NDEFRecord(createRecord( [...Array(252)].map(_ => 'a').join('') + ':xyz', test_buffer_data)), 'The external type should not be longer than 255.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord( + assert_throws_js(TypeError, () => new NDEFRecord(createRecord( 'xyz', test_buffer_data)), 'The external type must have a \':\'.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord( + assert_throws_js(TypeError, () => new NDEFRecord(createRecord( ':xyz', test_buffer_data)), 'The domain should not be empty.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord( + assert_throws_js(TypeError, () => new NDEFRecord(createRecord( 'example.com:', test_buffer_data)), 'The type should not be empty.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord( + assert_throws_js(TypeError, () => new NDEFRecord(createRecord( 'example.com:xyz[', test_buffer_data)), 'The type should not contain \'[\'.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord( + assert_throws_js(TypeError, () => new NDEFRecord(createRecord( 'example.com:xyz~', test_buffer_data)), 'The type should not contain \'~\'.'); - assert_throws(new TypeError, () => new NDEFRecord(createRecord( + assert_throws_js(TypeError, () => new NDEFRecord(createRecord( 'example.com:xyz/', test_buffer_data)), 'The type should not contain \'/\'.'); }, 'NDEFRecord constructor with invalid external record type');
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/with-options/null-transfer.html b/third_party/blink/web_tests/external/wpt/webmessaging/with-options/null-transfer.html index 72bebd1..2ea09eb 100644 --- a/third_party/blink/web_tests/external/wpt/webmessaging/with-options/null-transfer.html +++ b/third_party/blink/web_tests/external/wpt/webmessaging/with-options/null-transfer.html
@@ -5,6 +5,6 @@ <div id=log></div> <script> test(function(t) { - assert_throws(new TypeError, () => postMessage('', {transfer: null})); + assert_throws_js(TypeError, () => postMessage('', {transfer: null})); }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/023.html b/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/023.html index da6a5c4..e2569a8 100644 --- a/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/023.html +++ b/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/023.html
@@ -5,7 +5,7 @@ <div id=log></div> <script> test(function(t) { - assert_throws(new TypeError, () => postMessage('', '*', null)); + assert_throws_js(TypeError, () => postMessage('', '*', null)); }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor-expected.txt index dc884ad0..9bece81 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor-expected.txt
@@ -1,4 +1,4 @@ This is a testharness.js-based test. -FAIL RTCPeerConnection constructor throws if the given peerIdentity getter throws assert_throws: function "() => new RTCPeerConnection({ peerIdentity: toStringThrows })" did not throw +FAIL RTCPeerConnection constructor throws if the given peerIdentity getter throws assert_throws_js: function "() => new RTCPeerConnection({ peerIdentity: toStringThrows })" did not throw Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor.html b/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor.html index 8498e6b..e7b70163 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor.html +++ b/third_party/blink/web_tests/external/wpt/webrtc-identity/RTCPeerConnection-constructor.html
@@ -6,6 +6,6 @@ <script> test(() => { const toStringThrows = { toString: function() { throw new Error; } }; - assert_throws(new Error, () => new RTCPeerConnection({ peerIdentity: toStringThrows })); + assert_throws_js(Error, () => new RTCPeerConnection({ peerIdentity: toStringThrows })); }, "RTCPeerConnection constructor throws if the given peerIdentity getter throws"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webstorage/event_constructor.html b/third_party/blink/web_tests/external/wpt/webstorage/event_constructor.html index fe7fca7..e0bb3f3 100644 --- a/third_party/blink/web_tests/external/wpt/webstorage/event_constructor.html +++ b/third_party/blink/web_tests/external/wpt/webstorage/event_constructor.html
@@ -8,7 +8,7 @@ <body> <script> test(function() { - assert_throws(new TypeError, () => new StorageEvent()); + assert_throws_js(TypeError, () => new StorageEvent()); // should be redundant, but .length can be wrong with custom bindings assert_equals(StorageEvent.length, 1, 'StorageEvent.length'); }, 'constructor with no arguments');
diff --git a/third_party/blink/web_tests/external/wpt/webstorage/event_initstorageevent.html b/third_party/blink/web_tests/external/wpt/webstorage/event_initstorageevent.html index 2fe8931..b06a016 100644 --- a/third_party/blink/web_tests/external/wpt/webstorage/event_initstorageevent.html +++ b/third_party/blink/web_tests/external/wpt/webstorage/event_initstorageevent.html
@@ -9,7 +9,7 @@ <script> test(() => { const event = new StorageEvent('storage'); - assert_throws(new TypeError, () => event.initStorageEvent()); + assert_throws_js(TypeError, () => event.initStorageEvent()); // should be redundant, but .length can be wrong with custom bindings assert_equals(event.initStorageEvent.length, 1, 'event.initStorageEvent.length'); }, 'initStorageEvent with 0 arguments');
diff --git a/third_party/blink/web_tests/external/wpt/webvtt/api/VTTCue/constructor-exceptions.html b/third_party/blink/web_tests/external/wpt/webvtt/api/VTTCue/constructor-exceptions.html index 4d051fb3..843cab09 100644 --- a/third_party/blink/web_tests/external/wpt/webvtt/api/VTTCue/constructor-exceptions.html +++ b/third_party/blink/web_tests/external/wpt/webvtt/api/VTTCue/constructor-exceptions.html
@@ -5,14 +5,14 @@ <div id=log></div> <script> test(function() { - assert_throws(new TypeError, function() { new VTTCue(NaN, 0, 'foo'); }); - assert_throws(new TypeError, function() { new VTTCue(Infinity, 0, 'foo'); }); - assert_throws(new TypeError, function() { new VTTCue('tomorrow', 0, 'foo'); }); + assert_throws_js(TypeError, function() { new VTTCue(NaN, 0, 'foo'); }); + assert_throws_js(TypeError, function() { new VTTCue(Infinity, 0, 'foo'); }); + assert_throws_js(TypeError, function() { new VTTCue('tomorrow', 0, 'foo'); }); }, document.title+', non-finite start time'); test(function() { - assert_throws(new TypeError, function() { new VTTCue(0, NaN, 'foo'); }); - assert_throws(new TypeError, function() { new VTTCue(0, Infinity, 'foo'); }); - assert_throws(new TypeError, function() { new VTTCue(0, 'tomorrow', 'foo'); }); + assert_throws_js(TypeError, function() { new VTTCue(0, NaN, 'foo'); }); + assert_throws_js(TypeError, function() { new VTTCue(0, Infinity, 'foo'); }); + assert_throws_js(TypeError, function() { new VTTCue(0, 'tomorrow', 'foo'); }); }, document.title+', non-finite end time'); test(function() { var start = { valueOf: function() { return 42; } };
diff --git a/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-options-type.html b/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-options-type.html index b7c96b15..74523f4 100644 --- a/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-options-type.html +++ b/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-options-type.html
@@ -25,23 +25,22 @@ }, 'Test worker construction with the "module" worker type.'); test(() => { - try { - new Worker('resources/post-message-on-load-worker.js', { type: '' }); - assert_unreached( - 'Worker construction with an empty type should throw an exception'); - } catch (e) { - assert_equals(e.name, 'TypeError'); - } + assert_throws( + new TypeError(), + () => { + new Worker('resources/post-message-on-load-worker.js', { type: '' }); + }, + 'Worker construction with an empty type should throw an exception'); }, 'Test worker construction with an empty worker type.'); test(() => { - try { - new Worker('resources/post-message-on-load-worker.js', { type: 'unknown' }); - assert_unreached( - 'Worker construction with an unknown type should throw an exception'); - } catch (e) { - assert_equals(e.name, 'TypeError'); - } + assert_throws( + new TypeError(), + () => { + new Worker('resources/post-message-on-load-worker.js', + { type: 'unknown' }); + }, + 'Worker construction with an unknown type should throw an exception'); }, 'Test worker construction with an unknown worker type.'); </script>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt index 8b80809..f612371 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/failure-expected.txt
@@ -2,316 +2,316 @@ Found 313 tests; 142 PASS, 171 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL's constructor's base argument: file://example:1/ should throw -FAIL URL's href: file://example:1/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example:1/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example:1/ should throw PASS sendBeacon(): file://example:1/ should throw -FAIL Location's href: file://example:1/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:1/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example:1/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:1/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example:1/ should throw PASS URL's constructor's base argument: file://example:test/ should throw -FAIL URL's href: file://example:test/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example:test/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example:test/ should throw PASS sendBeacon(): file://example:test/ should throw -FAIL Location's href: file://example:test/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:test/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example:test/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:test/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example:test/ should throw PASS URL's constructor's base argument: file://example%/ should throw -FAIL URL's href: file://example%/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example%/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example%/ should throw PASS sendBeacon(): file://example%/ should throw -FAIL Location's href: file://example%/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example%/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example%/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example%/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example%/ should throw PASS URL's constructor's base argument: file://[example]/ should throw -FAIL URL's href: file://[example]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://[example]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://[example]/ should throw PASS sendBeacon(): file://[example]/ should throw -FAIL Location's href: file://[example]/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://[example]/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://[example]/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://[example]/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://[example]/ should throw PASS URL's constructor's base argument: http://user:pass@/ should throw -FAIL URL's href: http://user:pass@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://user:pass@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://user:pass@/ should throw PASS sendBeacon(): http://user:pass@/ should throw -FAIL Location's href: http://user:pass@/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user:pass@/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://user:pass@/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user:pass@/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://user:pass@/ should throw PASS URL's constructor's base argument: http://foo:-80/ should throw -FAIL URL's href: http://foo:-80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://foo:-80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://foo:-80/ should throw PASS sendBeacon(): http://foo:-80/ should throw -FAIL Location's href: http://foo:-80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://foo:-80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://foo:-80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://foo:-80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://foo:-80/ should throw PASS URL's constructor's base argument: http:/:@/www.example.com should throw -FAIL URL's href: http:/:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/:@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://user@/www.example.com should throw -FAIL URL's href: http://user@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://user@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://user@/www.example.com should throw PASS sendBeacon(): http://user@/www.example.com should throw -FAIL Location's href: http://user@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://user@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://user@/www.example.com should throw PASS URL's constructor's base argument: http:@/www.example.com should throw -FAIL URL's href: http:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/@/www.example.com should throw -FAIL URL's href: http:/@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://@/www.example.com should throw -FAIL URL's href: http://@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://@/www.example.com should throw PASS sendBeacon(): http://@/www.example.com should throw -FAIL Location's href: http://@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://@/www.example.com should throw PASS URL's constructor's base argument: https:@/www.example.com should throw -FAIL URL's href: https:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https:@/www.example.com should throw PASS sendBeacon(): https:@/www.example.com should throw -FAIL Location's href: https:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https:@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https:@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https:@/www.example.com should throw PASS URL's constructor's base argument: http:a:b@/www.example.com should throw -FAIL URL's href: http:a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:a:b@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:a:b@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/a:b@/www.example.com should throw -FAIL URL's href: http:/a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/a:b@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://a:b@/www.example.com should throw -FAIL URL's href: http://a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://a:b@/www.example.com should throw PASS sendBeacon(): http://a:b@/www.example.com should throw -FAIL Location's href: http://a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://a:b@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://a:b@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://a:b@/www.example.com should throw PASS URL's constructor's base argument: http::@/www.example.com should throw -FAIL URL's href: http::@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http::@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http::@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http::@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http::@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http::@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http::@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http::@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:@:www.example.com should throw -FAIL URL's href: http:@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:@:www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/@:www.example.com should throw -FAIL URL's href: http:/@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/@:www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://@:www.example.com should throw -FAIL URL's href: http://@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://@:www.example.com should throw PASS sendBeacon(): http://@:www.example.com should throw -FAIL Location's href: http://@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@:www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@:www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://@:www.example.com should throw PASS URL's constructor's base argument: https://� should throw -FAIL URL's href: https://� should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://� should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://� should throw PASS sendBeacon(): https://� should throw -FAIL Location's href: https://� should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://�' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://� should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://�' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://� should throw PASS URL's constructor's base argument: https://%EF%BF%BD should throw -FAIL URL's href: https://%EF%BF%BD should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://%EF%BF%BD should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://%EF%BF%BD should throw PASS sendBeacon(): https://%EF%BF%BD should throw -FAIL Location's href: https://%EF%BF%BD should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://%EF%BF%BD' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://%EF%BF%BD should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://%EF%BF%BD' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://%EF%BF%BD should throw FAIL URL's constructor's base argument: https://x x:12 should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: https://x x:12 should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://x x:12 should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: https://x x:12 should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): https://x x:12 should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: https://x x:12 should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): https://x x:12 should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: https://x x:12 should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): https://x x:12 should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://[www.google.com]/ should throw -FAIL URL's href: http://[www.google.com]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://[www.google.com]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://[www.google.com]/ should throw PASS sendBeacon(): http://[www.google.com]/ should throw -FAIL Location's href: http://[www.google.com]/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[www.google.com]/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://[www.google.com]/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[www.google.com]/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://[www.google.com]/ should throw FAIL URL's constructor's base argument: sc://\0/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://\0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://\0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://\0/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://\0/ should throw -FAIL Location's href: sc://\0/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://\0/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://\0/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc:// / should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc:// / should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc:// / should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc:// / should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc:// / should throw -FAIL Location's href: sc:// / should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc:// / should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc:// / should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://@/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://@/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://@/ should throw -FAIL Location's href: sc://@/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://@/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://@/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://te@s:t@/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://te@s:t@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://te@s:t@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://te@s:t@/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://te@s:t@/ should throw -FAIL Location's href: sc://te@s:t@/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://te@s:t@/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://te@s:t@/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://:/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://:/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://:/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://:/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://:/ should throw -FAIL Location's href: sc://:/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://:/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://:/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://:12/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://:12/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://:12/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://:12/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://:12/ should throw -FAIL Location's href: sc://:12/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://:12/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://:12/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://[/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://[/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://[/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://[/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://[/ should throw -FAIL Location's href: sc://[/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://[/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://[/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://\/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://\/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://\/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://\/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://\/ should throw -FAIL Location's href: sc://\/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://\/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://\/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://]/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://]/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://]/ should throw -FAIL Location's href: sc://]/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://]/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://]/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: ftp://example.com%80/ should throw -FAIL URL's href: ftp://example.com%80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: ftp://example.com%80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: ftp://example.com%80/ should throw PASS sendBeacon(): ftp://example.com%80/ should throw -FAIL Location's href: ftp://example.com%80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: ftp://example.com%80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): ftp://example.com%80/ should throw PASS URL's constructor's base argument: ftp://example.com%A0/ should throw -FAIL URL's href: ftp://example.com%A0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: ftp://example.com%A0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: ftp://example.com%A0/ should throw PASS sendBeacon(): ftp://example.com%A0/ should throw -FAIL Location's href: ftp://example.com%A0/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%A0/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: ftp://example.com%A0/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%A0/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): ftp://example.com%A0/ should throw PASS URL's constructor's base argument: https://example.com%80/ should throw -FAIL URL's href: https://example.com%80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://example.com%80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://example.com%80/ should throw PASS sendBeacon(): https://example.com%80/ should throw -FAIL Location's href: https://example.com%80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://example.com%80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://example.com%80/ should throw PASS URL's constructor's base argument: https://example.com%A0/ should throw -FAIL URL's href: https://example.com%A0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://example.com%A0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://example.com%A0/ should throw PASS sendBeacon(): https://example.com%A0/ should throw -FAIL Location's href: https://example.com%A0/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%A0/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://example.com%A0/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%A0/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://example.com%A0/ should throw PASS URL's constructor's base argument: https://0x100000000/test should throw -FAIL URL's href: https://0x100000000/test should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://0x100000000/test should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://0x100000000/test should throw PASS sendBeacon(): https://0x100000000/test should throw -FAIL Location's href: https://0x100000000/test should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://0x100000000/test' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://0x100000000/test should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://0x100000000/test' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://0x100000000/test should throw PASS URL's constructor's base argument: https://256.0.0.1/test should throw -FAIL URL's href: https://256.0.0.1/test should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://256.0.0.1/test should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://256.0.0.1/test should throw PASS sendBeacon(): https://256.0.0.1/test should throw -FAIL Location's href: https://256.0.0.1/test should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://256.0.0.1/test' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://256.0.0.1/test should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://256.0.0.1/test' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://256.0.0.1/test should throw PASS URL's constructor's base argument: https://[0::0::0] should throw -FAIL URL's href: https://[0::0::0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0::0::0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0::0::0] should throw PASS sendBeacon(): https://[0::0::0] should throw -FAIL Location's href: https://[0::0::0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0::0::0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0::0::0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0::0::0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0::0::0] should throw PASS URL's constructor's base argument: https://[0:.0] should throw -FAIL URL's href: https://[0:.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:.0] should throw PASS sendBeacon(): https://[0:.0] should throw -FAIL Location's href: https://[0:.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:.0] should throw PASS URL's constructor's base argument: https://[0:0:] should throw -FAIL URL's href: https://[0:0:] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:0:] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:0:] should throw PASS sendBeacon(): https://[0:0:] should throw -FAIL Location's href: https://[0:0:] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:0:]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:0:] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:0:]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:0:] should throw PASS URL's constructor's base argument: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw -FAIL URL's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw PASS sendBeacon(): https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw -FAIL Location's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1:2:3:4:5:6:7.0.0.0.1]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1:2:3:4:5:6:7.0.0.0.1]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw PASS URL's constructor's base argument: https://[0:1.00.0.0.0] should throw -FAIL URL's href: https://[0:1.00.0.0.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.00.0.0.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.00.0.0.0] should throw PASS sendBeacon(): https://[0:1.00.0.0.0] should throw -FAIL Location's href: https://[0:1.00.0.0.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.00.0.0.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.00.0.0.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.00.0.0.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.00.0.0.0] should throw PASS URL's constructor's base argument: https://[0:1.290.0.0.0] should throw -FAIL URL's href: https://[0:1.290.0.0.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.290.0.0.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.290.0.0.0] should throw PASS sendBeacon(): https://[0:1.290.0.0.0] should throw -FAIL Location's href: https://[0:1.290.0.0.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.290.0.0.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.290.0.0.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.290.0.0.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.290.0.0.0] should throw PASS URL's constructor's base argument: https://[0:1.23.23] should throw -FAIL URL's href: https://[0:1.23.23] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.23.23] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.23.23] should throw PASS sendBeacon(): https://[0:1.23.23] should throw -FAIL Location's href: https://[0:1.23.23] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.23.23]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.23.23] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.23.23]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.23.23] should throw PASS URL's constructor's base argument: http://? should throw -FAIL URL's href: http://? should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://? should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://? should throw PASS sendBeacon(): http://? should throw -FAIL Location's href: http://? should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://?' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://? should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://?' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://? should throw PASS URL's constructor's base argument: http://# should throw -FAIL URL's href: http://# should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://# should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://# should throw PASS sendBeacon(): http://# should throw -FAIL Location's href: http://# should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://#' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://# should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://#' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://# should throw FAIL URL's constructor's base argument: non-special://[:80/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: non-special://[:80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: non-special://[:80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: non-special://[:80/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): non-special://[:80/ should throw -FAIL Location's href: non-special://[:80/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: non-special://[:80/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): non-special://[:80/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://[::127.0.0.0.1] should throw -FAIL URL's href: http://[::127.0.0.0.1] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://[::127.0.0.0.1] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://[::127.0.0.0.1] should throw PASS sendBeacon(): http://[::127.0.0.0.1] should throw -FAIL Location's href: http://[::127.0.0.0.1] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[::127.0.0.0.1]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://[::127.0.0.0.1] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[::127.0.0.0.1]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://[::127.0.0.0.1] should throw PASS URL's constructor's base argument: a should throw -FAIL URL's href: a should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: a/ should throw -FAIL URL's href: a/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a/ should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a/ should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: a// should throw -FAIL URL's href: a// should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a// should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a// should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a// should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a// should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a// should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a// should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a// should throw assert_throws: function "() => self.open(test.input).close()" did not throw Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt index 8b80809..f612371 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/failure-expected.txt
@@ -2,316 +2,316 @@ Found 313 tests; 142 PASS, 171 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL's constructor's base argument: file://example:1/ should throw -FAIL URL's href: file://example:1/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example:1/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example:1/ should throw PASS sendBeacon(): file://example:1/ should throw -FAIL Location's href: file://example:1/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:1/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example:1/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:1/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example:1/ should throw PASS URL's constructor's base argument: file://example:test/ should throw -FAIL URL's href: file://example:test/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example:test/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example:test/ should throw PASS sendBeacon(): file://example:test/ should throw -FAIL Location's href: file://example:test/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:test/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example:test/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:test/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example:test/ should throw PASS URL's constructor's base argument: file://example%/ should throw -FAIL URL's href: file://example%/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example%/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example%/ should throw PASS sendBeacon(): file://example%/ should throw -FAIL Location's href: file://example%/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example%/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example%/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example%/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example%/ should throw PASS URL's constructor's base argument: file://[example]/ should throw -FAIL URL's href: file://[example]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://[example]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://[example]/ should throw PASS sendBeacon(): file://[example]/ should throw -FAIL Location's href: file://[example]/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://[example]/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://[example]/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://[example]/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://[example]/ should throw PASS URL's constructor's base argument: http://user:pass@/ should throw -FAIL URL's href: http://user:pass@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://user:pass@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://user:pass@/ should throw PASS sendBeacon(): http://user:pass@/ should throw -FAIL Location's href: http://user:pass@/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user:pass@/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://user:pass@/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user:pass@/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://user:pass@/ should throw PASS URL's constructor's base argument: http://foo:-80/ should throw -FAIL URL's href: http://foo:-80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://foo:-80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://foo:-80/ should throw PASS sendBeacon(): http://foo:-80/ should throw -FAIL Location's href: http://foo:-80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://foo:-80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://foo:-80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://foo:-80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://foo:-80/ should throw PASS URL's constructor's base argument: http:/:@/www.example.com should throw -FAIL URL's href: http:/:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/:@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://user@/www.example.com should throw -FAIL URL's href: http://user@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://user@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://user@/www.example.com should throw PASS sendBeacon(): http://user@/www.example.com should throw -FAIL Location's href: http://user@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://user@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://user@/www.example.com should throw PASS URL's constructor's base argument: http:@/www.example.com should throw -FAIL URL's href: http:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/@/www.example.com should throw -FAIL URL's href: http:/@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://@/www.example.com should throw -FAIL URL's href: http://@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://@/www.example.com should throw PASS sendBeacon(): http://@/www.example.com should throw -FAIL Location's href: http://@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://@/www.example.com should throw PASS URL's constructor's base argument: https:@/www.example.com should throw -FAIL URL's href: https:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https:@/www.example.com should throw PASS sendBeacon(): https:@/www.example.com should throw -FAIL Location's href: https:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https:@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https:@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https:@/www.example.com should throw PASS URL's constructor's base argument: http:a:b@/www.example.com should throw -FAIL URL's href: http:a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:a:b@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:a:b@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/a:b@/www.example.com should throw -FAIL URL's href: http:/a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/a:b@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://a:b@/www.example.com should throw -FAIL URL's href: http://a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://a:b@/www.example.com should throw PASS sendBeacon(): http://a:b@/www.example.com should throw -FAIL Location's href: http://a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://a:b@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://a:b@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://a:b@/www.example.com should throw PASS URL's constructor's base argument: http::@/www.example.com should throw -FAIL URL's href: http::@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http::@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http::@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http::@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http::@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http::@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http::@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http::@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:@:www.example.com should throw -FAIL URL's href: http:@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:@:www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/@:www.example.com should throw -FAIL URL's href: http:/@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/@:www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://@:www.example.com should throw -FAIL URL's href: http://@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://@:www.example.com should throw PASS sendBeacon(): http://@:www.example.com should throw -FAIL Location's href: http://@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@:www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@:www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://@:www.example.com should throw PASS URL's constructor's base argument: https://� should throw -FAIL URL's href: https://� should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://� should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://� should throw PASS sendBeacon(): https://� should throw -FAIL Location's href: https://� should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://�' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://� should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://�' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://� should throw PASS URL's constructor's base argument: https://%EF%BF%BD should throw -FAIL URL's href: https://%EF%BF%BD should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://%EF%BF%BD should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://%EF%BF%BD should throw PASS sendBeacon(): https://%EF%BF%BD should throw -FAIL Location's href: https://%EF%BF%BD should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://%EF%BF%BD' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://%EF%BF%BD should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://%EF%BF%BD' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://%EF%BF%BD should throw FAIL URL's constructor's base argument: https://x x:12 should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: https://x x:12 should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://x x:12 should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: https://x x:12 should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): https://x x:12 should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: https://x x:12 should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): https://x x:12 should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: https://x x:12 should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): https://x x:12 should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://[www.google.com]/ should throw -FAIL URL's href: http://[www.google.com]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://[www.google.com]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://[www.google.com]/ should throw PASS sendBeacon(): http://[www.google.com]/ should throw -FAIL Location's href: http://[www.google.com]/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[www.google.com]/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://[www.google.com]/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[www.google.com]/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://[www.google.com]/ should throw FAIL URL's constructor's base argument: sc://\0/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://\0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://\0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://\0/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://\0/ should throw -FAIL Location's href: sc://\0/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://\0/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://\0/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc:// / should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc:// / should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc:// / should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc:// / should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc:// / should throw -FAIL Location's href: sc:// / should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc:// / should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc:// / should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://@/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://@/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://@/ should throw -FAIL Location's href: sc://@/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://@/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://@/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://te@s:t@/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://te@s:t@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://te@s:t@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://te@s:t@/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://te@s:t@/ should throw -FAIL Location's href: sc://te@s:t@/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://te@s:t@/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://te@s:t@/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://:/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://:/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://:/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://:/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://:/ should throw -FAIL Location's href: sc://:/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://:/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://:/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://:12/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://:12/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://:12/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://:12/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://:12/ should throw -FAIL Location's href: sc://:12/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://:12/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://:12/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://[/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://[/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://[/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://[/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://[/ should throw -FAIL Location's href: sc://[/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://[/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://[/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://\/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://\/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://\/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://\/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://\/ should throw -FAIL Location's href: sc://\/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://\/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://\/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://]/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://]/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://]/ should throw -FAIL Location's href: sc://]/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://]/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://]/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: ftp://example.com%80/ should throw -FAIL URL's href: ftp://example.com%80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: ftp://example.com%80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: ftp://example.com%80/ should throw PASS sendBeacon(): ftp://example.com%80/ should throw -FAIL Location's href: ftp://example.com%80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: ftp://example.com%80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): ftp://example.com%80/ should throw PASS URL's constructor's base argument: ftp://example.com%A0/ should throw -FAIL URL's href: ftp://example.com%A0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: ftp://example.com%A0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: ftp://example.com%A0/ should throw PASS sendBeacon(): ftp://example.com%A0/ should throw -FAIL Location's href: ftp://example.com%A0/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%A0/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: ftp://example.com%A0/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%A0/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): ftp://example.com%A0/ should throw PASS URL's constructor's base argument: https://example.com%80/ should throw -FAIL URL's href: https://example.com%80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://example.com%80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://example.com%80/ should throw PASS sendBeacon(): https://example.com%80/ should throw -FAIL Location's href: https://example.com%80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://example.com%80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://example.com%80/ should throw PASS URL's constructor's base argument: https://example.com%A0/ should throw -FAIL URL's href: https://example.com%A0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://example.com%A0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://example.com%A0/ should throw PASS sendBeacon(): https://example.com%A0/ should throw -FAIL Location's href: https://example.com%A0/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%A0/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://example.com%A0/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%A0/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://example.com%A0/ should throw PASS URL's constructor's base argument: https://0x100000000/test should throw -FAIL URL's href: https://0x100000000/test should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://0x100000000/test should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://0x100000000/test should throw PASS sendBeacon(): https://0x100000000/test should throw -FAIL Location's href: https://0x100000000/test should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://0x100000000/test' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://0x100000000/test should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://0x100000000/test' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://0x100000000/test should throw PASS URL's constructor's base argument: https://256.0.0.1/test should throw -FAIL URL's href: https://256.0.0.1/test should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://256.0.0.1/test should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://256.0.0.1/test should throw PASS sendBeacon(): https://256.0.0.1/test should throw -FAIL Location's href: https://256.0.0.1/test should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://256.0.0.1/test' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://256.0.0.1/test should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://256.0.0.1/test' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://256.0.0.1/test should throw PASS URL's constructor's base argument: https://[0::0::0] should throw -FAIL URL's href: https://[0::0::0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0::0::0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0::0::0] should throw PASS sendBeacon(): https://[0::0::0] should throw -FAIL Location's href: https://[0::0::0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0::0::0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0::0::0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0::0::0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0::0::0] should throw PASS URL's constructor's base argument: https://[0:.0] should throw -FAIL URL's href: https://[0:.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:.0] should throw PASS sendBeacon(): https://[0:.0] should throw -FAIL Location's href: https://[0:.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:.0] should throw PASS URL's constructor's base argument: https://[0:0:] should throw -FAIL URL's href: https://[0:0:] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:0:] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:0:] should throw PASS sendBeacon(): https://[0:0:] should throw -FAIL Location's href: https://[0:0:] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:0:]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:0:] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:0:]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:0:] should throw PASS URL's constructor's base argument: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw -FAIL URL's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw PASS sendBeacon(): https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw -FAIL Location's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1:2:3:4:5:6:7.0.0.0.1]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1:2:3:4:5:6:7.0.0.0.1]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw PASS URL's constructor's base argument: https://[0:1.00.0.0.0] should throw -FAIL URL's href: https://[0:1.00.0.0.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.00.0.0.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.00.0.0.0] should throw PASS sendBeacon(): https://[0:1.00.0.0.0] should throw -FAIL Location's href: https://[0:1.00.0.0.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.00.0.0.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.00.0.0.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.00.0.0.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.00.0.0.0] should throw PASS URL's constructor's base argument: https://[0:1.290.0.0.0] should throw -FAIL URL's href: https://[0:1.290.0.0.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.290.0.0.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.290.0.0.0] should throw PASS sendBeacon(): https://[0:1.290.0.0.0] should throw -FAIL Location's href: https://[0:1.290.0.0.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.290.0.0.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.290.0.0.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.290.0.0.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.290.0.0.0] should throw PASS URL's constructor's base argument: https://[0:1.23.23] should throw -FAIL URL's href: https://[0:1.23.23] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.23.23] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.23.23] should throw PASS sendBeacon(): https://[0:1.23.23] should throw -FAIL Location's href: https://[0:1.23.23] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.23.23]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.23.23] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.23.23]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.23.23] should throw PASS URL's constructor's base argument: http://? should throw -FAIL URL's href: http://? should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://? should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://? should throw PASS sendBeacon(): http://? should throw -FAIL Location's href: http://? should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://?' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://? should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://?' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://? should throw PASS URL's constructor's base argument: http://# should throw -FAIL URL's href: http://# should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://# should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://# should throw PASS sendBeacon(): http://# should throw -FAIL Location's href: http://# should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://#' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://# should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://#' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://# should throw FAIL URL's constructor's base argument: non-special://[:80/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: non-special://[:80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: non-special://[:80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: non-special://[:80/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): non-special://[:80/ should throw -FAIL Location's href: non-special://[:80/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: non-special://[:80/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): non-special://[:80/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://[::127.0.0.0.1] should throw -FAIL URL's href: http://[::127.0.0.0.1] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://[::127.0.0.0.1] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://[::127.0.0.0.1] should throw PASS sendBeacon(): http://[::127.0.0.0.1] should throw -FAIL Location's href: http://[::127.0.0.0.1] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[::127.0.0.0.1]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://[::127.0.0.0.1] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[::127.0.0.0.1]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://[::127.0.0.0.1] should throw PASS URL's constructor's base argument: a should throw -FAIL URL's href: a should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: a/ should throw -FAIL URL's href: a/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a/ should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a/ should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: a// should throw -FAIL URL's href: a// should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a// should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a// should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a// should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a// should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a// should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a// should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a// should throw assert_throws: function "() => self.open(test.input).close()" did not throw Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt index 6c297e1..f4d7101 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/failure-expected.txt
@@ -2,316 +2,316 @@ Found 313 tests; 143 PASS, 170 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS URL's constructor's base argument: file://example:1/ should throw -FAIL URL's href: file://example:1/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example:1/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example:1/ should throw PASS sendBeacon(): file://example:1/ should throw -FAIL Location's href: file://example:1/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:1/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example:1/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:1/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example:1/ should throw PASS URL's constructor's base argument: file://example:test/ should throw -FAIL URL's href: file://example:test/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example:test/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example:test/ should throw PASS sendBeacon(): file://example:test/ should throw -FAIL Location's href: file://example:test/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:test/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example:test/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example:test/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example:test/ should throw PASS URL's constructor's base argument: file://example%/ should throw -FAIL URL's href: file://example%/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://example%/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://example%/ should throw PASS sendBeacon(): file://example%/ should throw -FAIL Location's href: file://example%/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example%/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://example%/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://example%/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://example%/ should throw PASS URL's constructor's base argument: file://[example]/ should throw -FAIL URL's href: file://[example]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: file://[example]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: file://[example]/ should throw PASS sendBeacon(): file://[example]/ should throw -FAIL Location's href: file://[example]/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://[example]/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: file://[example]/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'file://[example]/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): file://[example]/ should throw PASS URL's constructor's base argument: http://user:pass@/ should throw -FAIL URL's href: http://user:pass@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://user:pass@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://user:pass@/ should throw PASS sendBeacon(): http://user:pass@/ should throw -FAIL Location's href: http://user:pass@/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user:pass@/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://user:pass@/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user:pass@/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://user:pass@/ should throw PASS URL's constructor's base argument: http://foo:-80/ should throw -FAIL URL's href: http://foo:-80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://foo:-80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://foo:-80/ should throw PASS sendBeacon(): http://foo:-80/ should throw -FAIL Location's href: http://foo:-80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://foo:-80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://foo:-80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://foo:-80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://foo:-80/ should throw PASS URL's constructor's base argument: http:/:@/www.example.com should throw -FAIL URL's href: http:/:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/:@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://user@/www.example.com should throw -FAIL URL's href: http://user@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://user@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://user@/www.example.com should throw PASS sendBeacon(): http://user@/www.example.com should throw -FAIL Location's href: http://user@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://user@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://user@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://user@/www.example.com should throw PASS URL's constructor's base argument: http:@/www.example.com should throw -FAIL URL's href: http:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/@/www.example.com should throw -FAIL URL's href: http:/@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://@/www.example.com should throw -FAIL URL's href: http://@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://@/www.example.com should throw PASS sendBeacon(): http://@/www.example.com should throw -FAIL Location's href: http://@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://@/www.example.com should throw PASS URL's constructor's base argument: https:@/www.example.com should throw -FAIL URL's href: https:@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https:@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https:@/www.example.com should throw PASS sendBeacon(): https:@/www.example.com should throw -FAIL Location's href: https:@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https:@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https:@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https:@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https:@/www.example.com should throw PASS URL's constructor's base argument: http:a:b@/www.example.com should throw -FAIL URL's href: http:a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): http:a:b@/www.example.com should throw -FAIL Location's href: http:a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: http:a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" threw object "TypeError: Cannot read property 'close' of null" that is not a DOMException SyntaxError: property "code" is equal to undefined, expected 12 PASS URL's constructor's base argument: http:/a:b@/www.example.com should throw -FAIL URL's href: http:/a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/a:b@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/a:b@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/a:b@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://a:b@/www.example.com should throw -FAIL URL's href: http://a:b@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://a:b@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://a:b@/www.example.com should throw PASS sendBeacon(): http://a:b@/www.example.com should throw -FAIL Location's href: http://a:b@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://a:b@/www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://a:b@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://a:b@/www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://a:b@/www.example.com should throw PASS URL's constructor's base argument: http::@/www.example.com should throw -FAIL URL's href: http::@/www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http::@/www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http::@/www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http::@/www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http::@/www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http::@/www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http::@/www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http::@/www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:@:www.example.com should throw -FAIL URL's href: http:@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:@:www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http:/@:www.example.com should throw -FAIL URL's href: http:/@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http:/@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: http:/@:www.example.com should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): http:/@:www.example.com should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: http:/@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): http:/@:www.example.com should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: http:/@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): http:/@:www.example.com should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://@:www.example.com should throw -FAIL URL's href: http://@:www.example.com should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://@:www.example.com should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://@:www.example.com should throw PASS sendBeacon(): http://@:www.example.com should throw -FAIL Location's href: http://@:www.example.com should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@:www.example.com' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://@:www.example.com should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://@:www.example.com' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://@:www.example.com should throw PASS URL's constructor's base argument: https://� should throw -FAIL URL's href: https://� should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://� should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://� should throw PASS sendBeacon(): https://� should throw -FAIL Location's href: https://� should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://�' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://� should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://�' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://� should throw PASS URL's constructor's base argument: https://%EF%BF%BD should throw -FAIL URL's href: https://%EF%BF%BD should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://%EF%BF%BD should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://%EF%BF%BD should throw PASS sendBeacon(): https://%EF%BF%BD should throw -FAIL Location's href: https://%EF%BF%BD should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://%EF%BF%BD' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://%EF%BF%BD should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://%EF%BF%BD' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://%EF%BF%BD should throw FAIL URL's constructor's base argument: https://x x:12 should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: https://x x:12 should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://x x:12 should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: https://x x:12 should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): https://x x:12 should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: https://x x:12 should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): https://x x:12 should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: https://x x:12 should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): https://x x:12 should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://[www.google.com]/ should throw -FAIL URL's href: http://[www.google.com]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://[www.google.com]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://[www.google.com]/ should throw PASS sendBeacon(): http://[www.google.com]/ should throw -FAIL Location's href: http://[www.google.com]/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[www.google.com]/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://[www.google.com]/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[www.google.com]/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://[www.google.com]/ should throw FAIL URL's constructor's base argument: sc://\0/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://\0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://\0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://\0/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://\0/ should throw -FAIL Location's href: sc://\0/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://\0/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://\0/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc:// / should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc:// / should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc:// / should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc:// / should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc:// / should throw -FAIL Location's href: sc:// / should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc:// / should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc:// / should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://@/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://@/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://@/ should throw -FAIL Location's href: sc://@/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://@/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://@/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://te@s:t@/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://te@s:t@/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://te@s:t@/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://te@s:t@/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://te@s:t@/ should throw -FAIL Location's href: sc://te@s:t@/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://te@s:t@/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://te@s:t@/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://:/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://:/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://:/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://:/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://:/ should throw -FAIL Location's href: sc://:/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://:/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://:/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://:12/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://:12/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://:12/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://:12/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://:12/ should throw -FAIL Location's href: sc://:12/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://:12/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://:12/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://[/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://[/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://[/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://[/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://[/ should throw -FAIL Location's href: sc://[/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://[/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://[/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://\/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://\/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://\/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://\/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://\/ should throw -FAIL Location's href: sc://\/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://\/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://\/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw FAIL URL's constructor's base argument: sc://]/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: sc://]/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: sc://]/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: sc://]/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): sc://]/ should throw -FAIL Location's href: sc://]/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: sc://]/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): sc://]/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: ftp://example.com%80/ should throw -FAIL URL's href: ftp://example.com%80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: ftp://example.com%80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: ftp://example.com%80/ should throw PASS sendBeacon(): ftp://example.com%80/ should throw -FAIL Location's href: ftp://example.com%80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: ftp://example.com%80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): ftp://example.com%80/ should throw PASS URL's constructor's base argument: ftp://example.com%A0/ should throw -FAIL URL's href: ftp://example.com%A0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: ftp://example.com%A0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: ftp://example.com%A0/ should throw PASS sendBeacon(): ftp://example.com%A0/ should throw -FAIL Location's href: ftp://example.com%A0/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%A0/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: ftp://example.com%A0/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'ftp://example.com%A0/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): ftp://example.com%A0/ should throw PASS URL's constructor's base argument: https://example.com%80/ should throw -FAIL URL's href: https://example.com%80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://example.com%80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://example.com%80/ should throw PASS sendBeacon(): https://example.com%80/ should throw -FAIL Location's href: https://example.com%80/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%80/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://example.com%80/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%80/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://example.com%80/ should throw PASS URL's constructor's base argument: https://example.com%A0/ should throw -FAIL URL's href: https://example.com%A0/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://example.com%A0/ should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://example.com%A0/ should throw PASS sendBeacon(): https://example.com%A0/ should throw -FAIL Location's href: https://example.com%A0/ should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%A0/' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://example.com%A0/ should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://example.com%A0/' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://example.com%A0/ should throw PASS URL's constructor's base argument: https://0x100000000/test should throw -FAIL URL's href: https://0x100000000/test should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://0x100000000/test should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://0x100000000/test should throw PASS sendBeacon(): https://0x100000000/test should throw -FAIL Location's href: https://0x100000000/test should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://0x100000000/test' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://0x100000000/test should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://0x100000000/test' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://0x100000000/test should throw PASS URL's constructor's base argument: https://256.0.0.1/test should throw -FAIL URL's href: https://256.0.0.1/test should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://256.0.0.1/test should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://256.0.0.1/test should throw PASS sendBeacon(): https://256.0.0.1/test should throw -FAIL Location's href: https://256.0.0.1/test should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://256.0.0.1/test' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://256.0.0.1/test should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://256.0.0.1/test' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://256.0.0.1/test should throw PASS URL's constructor's base argument: https://[0::0::0] should throw -FAIL URL's href: https://[0::0::0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0::0::0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0::0::0] should throw PASS sendBeacon(): https://[0::0::0] should throw -FAIL Location's href: https://[0::0::0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0::0::0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0::0::0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0::0::0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0::0::0] should throw PASS URL's constructor's base argument: https://[0:.0] should throw -FAIL URL's href: https://[0:.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:.0] should throw PASS sendBeacon(): https://[0:.0] should throw -FAIL Location's href: https://[0:.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:.0] should throw PASS URL's constructor's base argument: https://[0:0:] should throw -FAIL URL's href: https://[0:0:] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:0:] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:0:] should throw PASS sendBeacon(): https://[0:0:] should throw -FAIL Location's href: https://[0:0:] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:0:]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:0:] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:0:]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:0:] should throw PASS URL's constructor's base argument: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw -FAIL URL's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw PASS sendBeacon(): https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw -FAIL Location's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1:2:3:4:5:6:7.0.0.0.1]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1:2:3:4:5:6:7.0.0.0.1]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1:2:3:4:5:6:7.0.0.0.1] should throw PASS URL's constructor's base argument: https://[0:1.00.0.0.0] should throw -FAIL URL's href: https://[0:1.00.0.0.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.00.0.0.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.00.0.0.0] should throw PASS sendBeacon(): https://[0:1.00.0.0.0] should throw -FAIL Location's href: https://[0:1.00.0.0.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.00.0.0.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.00.0.0.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.00.0.0.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.00.0.0.0] should throw PASS URL's constructor's base argument: https://[0:1.290.0.0.0] should throw -FAIL URL's href: https://[0:1.290.0.0.0] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.290.0.0.0] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.290.0.0.0] should throw PASS sendBeacon(): https://[0:1.290.0.0.0] should throw -FAIL Location's href: https://[0:1.290.0.0.0] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.290.0.0.0]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.290.0.0.0] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.290.0.0.0]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.290.0.0.0] should throw PASS URL's constructor's base argument: https://[0:1.23.23] should throw -FAIL URL's href: https://[0:1.23.23] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: https://[0:1.23.23] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: https://[0:1.23.23] should throw PASS sendBeacon(): https://[0:1.23.23] should throw -FAIL Location's href: https://[0:1.23.23] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.23.23]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: https://[0:1.23.23] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'https://[0:1.23.23]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): https://[0:1.23.23] should throw PASS URL's constructor's base argument: http://? should throw -FAIL URL's href: http://? should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://? should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://? should throw PASS sendBeacon(): http://? should throw -FAIL Location's href: http://? should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://?' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://? should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://?' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://? should throw PASS URL's constructor's base argument: http://# should throw -FAIL URL's href: http://# should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://# should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://# should throw PASS sendBeacon(): http://# should throw -FAIL Location's href: http://# should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://#' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://# should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://#' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://# should throw FAIL URL's constructor's base argument: non-special://[:80/ should throw assert_throws: function "() => new URL("about:blank", test.input)" did not throw -FAIL URL's href: non-special://[:80/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: non-special://[:80/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: non-special://[:80/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw PASS sendBeacon(): non-special://[:80/ should throw -FAIL Location's href: non-special://[:80/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL Location's href: non-special://[:80/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): non-special://[:80/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: http://[::127.0.0.0.1] should throw -FAIL URL's href: http://[::127.0.0.0.1] should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: http://[::127.0.0.0.1] should throw assert_throws_js: function "() => url.href = test.input" did not throw PASS XHR: http://[::127.0.0.0.1] should throw PASS sendBeacon(): http://[::127.0.0.0.1] should throw -FAIL Location's href: http://[::127.0.0.0.1] should throw assert_throws: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[::127.0.0.0.1]' is not a valid URL." ("SyntaxError") expected object "TypeError" ("TypeError") +FAIL Location's href: http://[::127.0.0.0.1] should throw assert_throws_js: function "() => self[0].location = test.input" threw object "SyntaxError: Failed to set the 'href' property on 'Location': 'http://[::127.0.0.0.1]' is not a valid URL." ("SyntaxError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS window.open(): http://[::127.0.0.0.1] should throw PASS URL's constructor's base argument: a should throw -FAIL URL's href: a should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: a/ should throw -FAIL URL's href: a/ should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a/ should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a/ should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a/ should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a/ should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a/ should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a/ should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a/ should throw assert_throws: function "() => self.open(test.input).close()" did not throw PASS URL's constructor's base argument: a// should throw -FAIL URL's href: a// should throw assert_throws: function "() => url.href = test.input" did not throw +FAIL URL's href: a// should throw assert_throws_js: function "() => url.href = test.input" did not throw FAIL XHR: a// should throw assert_throws: function "() => client.open("GET", test.input)" did not throw -FAIL sendBeacon(): a// should throw assert_throws: function "() => self.navigator.sendBeacon(test.input)" did not throw -FAIL Location's href: a// should throw assert_throws: function "() => self[0].location = test.input" did not throw +FAIL sendBeacon(): a// should throw assert_throws_js: function "() => self.navigator.sendBeacon(test.input)" did not throw +FAIL Location's href: a// should throw assert_throws_js: function "() => self[0].location = test.input" did not throw FAIL window.open(): a// should throw assert_throws: function "() => self.open(test.input).close()" did not throw Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/not-site-per-process/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub-expected.txt b/third_party/blink/web_tests/virtual/not-site-per-process/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub-expected.txt new file mode 100644 index 0000000..333dd07 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-site-per-process/external/wpt/html/browsers/history/the-location-interface/location-prototype-setting-same-origin-domain.sub-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +PASS Same-origin-domain prerequisite check: the original prototype is accessible +FAIL Same-origin-domain: setting the prototype to an empty object via Object.setPrototypeOf should throw a TypeError assert_throws_js: function "() => { + Object.setPrototypeOf(target, newValue); + }" did not throw +FAIL Same-origin-domain: setting the prototype to an empty object via __proto__ should throw a TypeError assert_throws: function "function() { + target.__proto__ = newValue; + }" did not throw +FAIL Same-origin-domain: setting the prototype to an empty object via Reflect.setPrototypeOf should return false assert_false: expected false got true +FAIL Same-origin-domain: the prototype must still be its original value assert_equals: expected object "[object Location]" but got object "[object Object]" +PASS Same-origin-domain: setting the prototype to its original value via Object.setPrototypeOf should not throw +PASS Same-origin-domain: setting the prototype to its original value via __proto__ should not throw +PASS Same-origin-domain: setting the prototype to its original value via Reflect.setPrototypeOf should return true +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt b/third_party/blink/web_tests/virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt index c374338..2a42279 100644 --- a/third_party/blink/web_tests/virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt +++ b/third_party/blink/web_tests/virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-expected.txt
@@ -12,15 +12,15 @@ PASS [[GetPrototypeOf]] should return null (cross-origin) PASS [[GetPrototypeOf]] should return null (same-origin + document.domain) PASS [[GetPrototypeOf]] should return null (cross-site) -FAIL [[SetPrototypeOf]] should return false (cross-origin) assert_throws: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[SetPrototypeOf]] should return false (same-origin + document.domain) assert_throws: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[SetPrototypeOf]] should return false (cross-site) assert_throws: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") +FAIL [[SetPrototypeOf]] should return false (cross-origin) assert_throws_js: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[SetPrototypeOf]] should return false (same-origin + document.domain) assert_throws_js: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[SetPrototypeOf]] should return false (cross-site) assert_throws_js: proto setter |call| on cross-origin Window function "function() { protoSetter.call(win, new Object()); }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") PASS [[IsExtensible]] should return true for cross-origin objects (cross-origin) PASS [[IsExtensible]] should return true for cross-origin objects (same-origin + document.domain) PASS [[IsExtensible]] should return true for cross-origin objects (cross-site) -FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-origin) assert_throws: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[PreventExtensions]] should throw for cross-origin objects (same-origin + document.domain) assert_throws: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") -FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-site) assert_throws: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected object "TypeError" ("TypeError") +FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-origin) assert_throws_js: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[PreventExtensions]] should throw for cross-origin objects (same-origin + document.domain) assert_throws_js: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") +FAIL [[PreventExtensions]] should throw for cross-origin objects (cross-site) assert_throws_js: preventExtensions on cross-origin Window should throw function "function() { Object.preventExtensions(win) }" threw object "SecurityError: Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") FAIL [[GetOwnProperty]] - Properties on cross-origin objects should be reported |own| (cross-origin) Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. FAIL [[GetOwnProperty]] - Properties on cross-origin objects should be reported |own| (same-origin + document.domain) Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame. FAIL [[GetOwnProperty]] - Properties on cross-origin objects should be reported |own| (cross-site) Blocked a frame with origin "http://web-platform.test:8001" from accessing a cross-origin frame.
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/change_delayed_task_priority.html b/third_party/blink/web_tests/wpt_internal/scheduler/change_delayed_task_priority.html index 62d6b17..dc5517d 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/change_delayed_task_priority.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/change_delayed_task_priority.html
@@ -14,12 +14,12 @@ async_test(t => { let now = performance.now(); - let tc = new TaskController('low'); + let tc = new TaskController('background'); scheduler.postTask(t.step_func(() => { assert_equals(++taskCount, 1); - tc.setPriority('immediate'); - }), { priority: 'immediate', delay: 10 }); + tc.setPriority('user-blocking'); + }), { priority: 'user-blocking', delay: 10 }); scheduler.postTask(t.step_func_done(() => { assert_equals(++taskCount, 2); @@ -28,6 +28,6 @@ assert_greater_than_equal(elapsed, 20); }), { signal: tc.signal, delay: 20 }); -}, 'Tests delay when moving a delayed task'); +}, "Tests delay when changing a delayed task's priority"); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/change_task_priority.html b/third_party/blink/web_tests/wpt_internal/scheduler/change_task_priority.html index 1507ff930b4..d35a5531 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/change_task_priority.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/change_task_priority.html
@@ -13,19 +13,19 @@ let task_controllers = []; for (let i = 0; i < 5; i++) { - let tc = new TaskController('idle'); + let tc = new TaskController('background'); scheduler.postTask(() => { result += i.toString(); }, { signal: tc.signal }); task_controllers.push(tc); } - task_controllers[2].setPriority('high'); - assert_equals(task_controllers[2].signal.priority, 'high'); + task_controllers[2].setPriority('user-blocking'); + assert_equals(task_controllers[2].signal.priority, 'user-blocking'); scheduler.postTask(t.step_func_done(() => { assert_equals('20134', result); - }), { priority: 'idle' }); + }), { priority: 'background' }); }, 'Test modifying TaskController priority');
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/post_delayed_task.html b/third_party/blink/web_tests/wpt_internal/scheduler/post_delayed_task.html index c704aa2..824d201 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/post_delayed_task.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/post_delayed_task.html
@@ -13,7 +13,7 @@ scheduler.postTask(t.step_func_done(() => { let elapsed = performance.now() - now; assert_greater_than_equal(elapsed, 10); - }), { priority: 'immediate', delay: 10 }); + }), { priority: 'user-blocking', delay: 10 }); }, 'Tests basic scheduler.postTask with a delay'); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/post_task_then_detach.html b/third_party/blink/web_tests/wpt_internal/scheduler/post_task_then_detach.html index da1e39e..4bcdb01 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/post_task_then_detach.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/post_task_then_detach.html
@@ -13,7 +13,7 @@ async_test(t => { // Give the task time to run if it hadn't been detached. - scheduler.postTask(t.step_func_done(() => {}), { priority: "idle" }); + scheduler.postTask(t.step_func_done(() => {}), { priority: "background" }); }, 'Test scheduler.postTask() from an iframe that is removed before the task runs'); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/post_task_with_signal_and_priority.html b/third_party/blink/web_tests/wpt_internal/scheduler/post_task_with_signal_and_priority.html index 27c5129..525d56f 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/post_task_with_signal_and_priority.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/post_task_with_signal_and_priority.html
@@ -10,11 +10,11 @@ async_test(t => { var result = "fail"; - let tc = new TaskController("low"); - scheduler.postTask(() => { result = "pass"; }, { priority : "high", signal: tc.signal }); + let tc = new TaskController("background"); + scheduler.postTask(() => { result = "pass"; }, { priority : "user-blocking", signal: tc.signal }); - // Since the above task should be run at high priority, it should execute - // before this default priority task. + // Since the above task should be run at user-blocking priority, it should execute + // before this user-visible priority task. scheduler.postTask(t.step_func_done(() => { assert_equals(result, "pass"); }));
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/post_task_without_signals.html b/third_party/blink/web_tests/wpt_internal/scheduler/post_task_without_signals.html index 8c6d1d1..644e22b59 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/post_task_without_signals.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/post_task_without_signals.html
@@ -11,7 +11,7 @@ async_test(t => { function* priorityGenerator() { let priorities = [ - "immediate", "high", "default", "low", "idle" + "user-blocking", "user-visible", "background" ]; for (let i = 0; i < priorities.length; i++) yield priorities[i];
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/task_arguments.html b/third_party/blink/web_tests/wpt_internal/scheduler/task_arguments.html index 323429e..2782315a 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/task_arguments.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/task_arguments.html
@@ -12,7 +12,7 @@ scheduler.postTask(t.step_func_done((arg1, arg2) => { assert_equals(arg1, 'foo'); assert_equals(arg2, 10); - }), { priority: 'default' }, 'foo', 10); + }), { priority: 'user-visible' }, 'foo', 10); }, 'Test scheduler.postTask correctly passes arguments'); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort.html b/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort.html index cb004cc..6c32dfd 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort.html
@@ -13,7 +13,7 @@ let task_controllers = []; for (let i = 0; i < 5; i++) { - let tc = new TaskController("default"); + let tc = new TaskController(); let task = scheduler.postTask(() => { result += i.toString(); }, { signal: tc.signal }); @@ -34,7 +34,7 @@ assert_equals(result, '0134'); })); - let final_task_tc = new TaskController("default"); + let final_task_tc = new TaskController(); // Check that canceling running, completed, or canceled tasks is a no-op. scheduler.postTask(t.step_func_done(() => { final_task_tc.abort();
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort_with_custom_priority.html b/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort_with_custom_priority.html index 556beaf1..6a26dba4 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort_with_custom_priority.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_abort_with_custom_priority.html
@@ -10,19 +10,19 @@ async_test(t => { let result = 0; - let tc = new TaskController("default"); + let tc = new TaskController(); scheduler.postTask(() => {}, { signal: tc.signal }).then( () => { assert_unreached('This task should have been aborted'); }, () => { result++; }); - scheduler.postTask(() => {}, { priority: "idle", signal: tc.signal }).then( + scheduler.postTask(() => {}, { priority: "background", signal: tc.signal }).then( () => { assert_unreached('This task should have been aborted'); }, () => { result++; }); tc.abort(); scheduler.postTask(t.step_func_done(() => { assert_equals(result, 2); - }), { priority: "idle" }); + }), { priority: "background" }); }, 'Test that when scheduler.postTask() is given both a signal and priority. the signal abort is honored');
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_setPriority.html b/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_setPriority.html index 7499058..0610cfa6 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_setPriority.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/task_controller_setPriority.html
@@ -10,7 +10,7 @@ async_test(t => { let result = ''; - let tc = new TaskController("default"); + let tc = new TaskController("user-visible"); for (let i = 0; i < 5; i++) { let task = scheduler.postTask(() => { @@ -18,15 +18,14 @@ }, { signal: tc.signal }); } - scheduler.postTask(() => { result += "5"; }, { priority : "high" }); - scheduler.postTask(() => { result += "6"; }, { priority : "default" }); - scheduler.postTask(() => { result += "7"; }, { priority : "low" }); + scheduler.postTask(() => { result += "5"; }, { priority : "user-blocking" }); + scheduler.postTask(() => { result += "6"; }, { priority : "user-visible" }); - tc.setPriority("idle"); + tc.setPriority("background"); scheduler.postTask(t.step_func_done(() => { - assert_equals(result, '56701234'); - }), { priority: "idle" }); + assert_equals(result, '5601234'); + }), { priority: "background" }); }, 'Test that TaskController.setPriority() changes the priority of all associated tasks');
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/task_order.html b/third_party/blink/web_tests/wpt_internal/scheduler/task_order.html index 3e50805..c7d7536 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/task_order.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/task_order.html
@@ -23,20 +23,16 @@ // Post tasks in reverse priority order and expect they are run from highest // to lowest priority. - scheduleReportTask('E1', 'idle'); - scheduleReportTask('E2', 'idle'); - scheduleReportTask('L1', 'low'); - scheduleReportTask('L2', 'low'); - scheduleReportTask('D1', 'default'); - scheduleReportTask('D2', 'default'); - scheduleReportTask('H1', 'high'); - scheduleReportTask('H2', 'high'); - scheduleReportTask('I1', 'immediate'); - scheduleReportTask('I2', 'immediate'); + scheduleReportTask('B1', 'background'); + scheduleReportTask('B2', 'background'); + scheduleReportTask('UV1', 'user-visible'); + scheduleReportTask('UV2', 'user-visible'); + scheduleReportTask('UB1', 'user-blocking'); + scheduleReportTask('UB2', 'user-blocking'); scheduler.postTask(t.step_func_done(() => { - assert_equals(result, 'I1 I2 H1 H2 D1 D2 L1 L2 E1 E2'); - }), { priority: 'idle' }); + assert_equals(result, 'UB1 UB2 UV1 UV2 B1 B2'); + }), { priority: 'background' }); }, 'Test scheduler.postTask task run in priority order'); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_after_accessing_result.html b/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_after_accessing_result.html index d642071..1b1c3f4c 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_after_accessing_result.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_after_accessing_result.html
@@ -10,7 +10,7 @@ async_test(t => { (function() { - let tc = new TaskController("default"); + let tc = new TaskController(); let task_promise = scheduler.postTask(() => 1234, { signal: tc.signal }); task_promise.then(t.step_func((res) => { assert_true(false, 'task promise should not be fulfilled when the task is canceled.');
diff --git a/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_before_accessing_result.html b/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_before_accessing_result.html index e95b8510..952f823 100644 --- a/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_before_accessing_result.html +++ b/third_party/blink/web_tests/wpt_internal/scheduler/task_result_cancel_before_accessing_result.html
@@ -10,7 +10,7 @@ async_test(t => { (function() { - let tc = new TaskController("default"); + let tc = new TaskController(); let task_promise = scheduler.postTask(() => 1234, { signal: tc.signal }); tc.abort(); task_promise.then(t.step_func((res) => {
diff --git a/third_party/chromevox/BUILD.gn b/third_party/chromevox/BUILD.gn index d74f722..bfbe4b3 100644 --- a/third_party/chromevox/BUILD.gn +++ b/third_party/chromevox/BUILD.gn
@@ -8,16 +8,10 @@ chromevox_out_dir = "$root_out_dir/resources/chromeos/accessibility/chromevox" group("chromevox_third_party_resources") { - deps = [ - ":chromevox_third_party_background_resources", - ] + deps = [ ":chromevox_third_party_background_resources" ] } copy("chromevox_third_party_background_resources") { - sources = [ - "third_party/sre/sre_browser.js", - ] - outputs = [ - "$chromevox_out_dir/background/{{source_file_part}}", - ] + sources = [ "third_party/sre/sre_browser.js" ] + outputs = [ "$chromevox_out_dir/background/{{source_file_part}}" ] }
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js index 07968149..bffabd5 100644 --- a/third_party/closure_compiler/externs/automation.js +++ b/third_party/closure_compiler/externs/automation.js
@@ -223,6 +223,7 @@ NOTE: 'note', PANE: 'pane', PARAGRAPH: 'paragraph', + PLUGIN_OBJECT: 'pluginObject', POP_UP_BUTTON: 'popUpButton', PRE: 'pre', PRESENTATIONAL: 'presentational',
diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c index a39e627..58744b8b 100644 --- a/third_party/zlib/deflate.c +++ b/third_party/zlib/deflate.c
@@ -318,6 +318,10 @@ s->w_size + window_padding, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + /* Avoid use of uninitialized value, see: + * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11360 + */ + memset(s->prev, 0, s->w_size * sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */
diff --git a/third_party/zlib/patches/0003-uninitializedjump.patch b/third_party/zlib/patches/0003-uninitializedjump.patch new file mode 100644 index 0000000..ab6f6ad7 --- /dev/null +++ b/third_party/zlib/patches/0003-uninitializedjump.patch
@@ -0,0 +1,15 @@ +diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c +index a39e62787862..c6053fd1c7ea 100644 +--- a/third_party/zlib/deflate.c ++++ b/third_party/zlib/deflate.c +@@ -318,6 +318,10 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + s->w_size + window_padding, + 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); ++ /* Avoid use of uninitialized value, see: ++ * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11360 ++ */ ++ memset(s->prev, 0, s->w_size * sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */
diff --git a/tools/cfi/blacklist.txt b/tools/cfi/blacklist.txt index 8ece972..aa732c9 100644 --- a/tools/cfi/blacklist.txt +++ b/tools/cfi/blacklist.txt
@@ -173,8 +173,8 @@ src:*media/cdm/* src:*third_party/swiftshader/* src:*base/native_library_unittest.cc -src:*chrome/browser/ui/libgtkui/app_indicator_icon.cc -src:*chrome/browser/ui/libgtkui/unity_service.cc +src:*chrome/browser/ui/gtk/app_indicator_icon.cc +src:*chrome/browser/ui/gtk/unity_service.cc src:*components/cronet/native/* src:*third_party/breakpad/breakpad/src/client/linux/handler/exception_handler_unittest.cc
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 1b6ce1f..70c327b 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -37413,6 +37413,7 @@ <int value="-882434910" label="EnableAggregatedMlSearchRanking:enabled"/> <int value="-881447505" label="ash-disable-shelf-model-synchronization"/> <int value="-881054479" label="WebAssemblyStreaming:disabled"/> + <int value="-880201293" label="OmniboxAssistantVoiceSearch:disabled"/> <int value="-879055117" label="ClipboardContentSetting:enabled"/> <int value="-879031960" label="FetchKeepaliveTimeoutSetting:disabled"/> <int value="-876148583" label="ArcBootCompletedBroadcast:disabled"/> @@ -39788,6 +39789,7 @@ <int value="2097048479" label="disable-auto-hiding-toolbar-threshold"/> <int value="2098714203" label="enable-generic-sensors"/> <int value="2098907258" label="UseSurfaceLayerForVideo:disabled"/> + <int value="2099945365" label="OmniboxAssistantVoiceSearch:enabled"/> <int value="2101151142" label="disable-direct-write"/> <int value="2104340988" label="CrostiniUsername:disabled"/> <int value="2104788328" label="use-winrt-midi-api"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 9412c2f8..1cf2c49 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -5296,7 +5296,7 @@ <histogram name="Apps.AppList.AnswerCardSearchProvider.SearchAnswerLoadingTime" units="ms" expires_after="2020-07-06"> - <owner>jennyz@chriomium.org</owner> + <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> The time between sending an answer card request and receiving the @@ -5307,7 +5307,7 @@ <histogram name="Apps.AppList.AnswerCardSearchProvider.SearchAnswerNavigationTime" units="ms" expires_after="2020-05-03"> - <owner>jennyz@chriomium.org</owner> + <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> The time between sending an answer card request and receiving the @@ -5412,19 +5412,6 @@ </summary> </histogram> -<histogram name="Apps.AppList.DriveQuickAccessProvider.ResultPresence" - enum="AppListDriveQuickAccessResultPresence" expires_after="2020-06-01"> - <owner>tby@chromium.org</owner> - <owner>wrong@chromium.org</owner> - <owner>jiameng@chromium.org</owner> - <summary> - Emitted when the launcher updates the displayed zero-state search results. - Records whether a) a Drive QuickAccess result was displayed, b) a DQA result - was present in the candidate results list but wasn't one of the top 5 so was - not displayed, or c) no DQA results were in the results list. - </summary> -</histogram> - <histogram name="Apps.AppList.DriveQuickAccessProvider.TimeFromFetchToZeroStateStart" units="ms" expires_after="2020-07-06"> @@ -5450,7 +5437,7 @@ <histogram name="Apps.AppList.LauncherSearchProvider.QueryTime" units="ms" expires_after="2019-12-31"> - <owner>jennyz@chriomium.org</owner> + <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> The time between sending a non-empty query and receiving results back from @@ -5460,7 +5447,7 @@ <histogram name="Apps.AppList.OmniboxProvider.QueryTime" units="ms" expires_after="2020-05-03"> - <owner>jennyz@chriomium.org</owner> + <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> The time between sending an non-empty query and receiving search results @@ -5471,7 +5458,7 @@ <histogram name="Apps.AppList.OmniboxProvider.ZeroStateLatency" units="ms" expires_after="2020-07-06"> - <owner>jennyz@chriomium.org</owner> + <owner>jennyz@chromium.org</owner> <owner>newcomer@chromium.org</owner> <summary> The time between sending an empty query and receiving zero state @@ -5800,6 +5787,19 @@ </summary> </histogram> +<histogram name="Apps.AppListDriveQuickAccessProvider.ResultPresence" + enum="AppListDriveQuickAccessResultPresence" expires_after="2020-06-01"> + <owner>tby@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>jiameng@chromium.org</owner> + <summary> + Emitted when the launcher updates the displayed zero-state search results. + Records whether a) a Drive QuickAccess result was displayed, b) a DQA result + was present in the candidate results list but wasn't one of the top 5 so was + not displayed, or c) no DQA results were in the results list. + </summary> +</histogram> + <histogram name="Apps.AppListFolder.ShowHide.AnimationSmoothness" units="%" expires_after="2020-05-24"> <owner>wutao@chromium.org</owner> @@ -6945,7 +6945,7 @@ <histogram base="true" name="Arc.CpuRestrictionDisabled" units="ms" expires_after="2020-03-09"> - <owner>wvk@google.org</owner> + <owner>wvk@google.com</owner> <owner>khmel@google.com</owner> <summary> Records the time that throttling was disabled due to a particular throttle @@ -8267,8 +8267,8 @@ <!-- Name completed by histogram suffixes name="HotseatTransitionType" --> - <owner>anasalazar@chromium.com</owner> - <owner>newcomer@chromium.com</owner> + <owner>anasalazar@chromium.org</owner> + <owner>newcomer@chromium.org</owner> <summary> Tracks the animation smoothness for the transitions of the hotseat to and from the shown state. @@ -13539,7 +13539,7 @@ <histogram name="Autofill.SubmittedValuePatterns" enum="AutofillValuePatterns" expires_after="M88"> <owner>kolos@chromium.org</owner> - <owner>jsaul@google</owner> + <owner>jsaul@google.com</owner> <summary> Metric to measure if a submitted form contains any recognizable value patterns (e.g., Unified Payment Interface Virtual Payment address (UPI @@ -20216,7 +20216,7 @@ <!-- Name completed by histogram_suffixes name="TabSwitchInputLatency" --> <owner>ejoe@google.com</owner> - <owner>jonross@chromium.com</owner> + <owner>jonross@chromium.org</owner> <summary> The time between input event timestamp for tab switch and when the TabStripModel begins processing the switch. @@ -20250,7 +20250,7 @@ <!-- Name completed by histogram_suffixes name="TabSwitchingType" --> <owner>fdoray@chromium.org</owner> - <owner>jonross@chromium.com</owner> + <owner>jonross@chromium.org</owner> <summary> The time between a tab switch input event timestamp and when the tab is hidden, if no frame is presented in the meantime. @@ -20262,7 +20262,7 @@ <!-- Name completed by histogram_suffixes name="TabSwitchingType" --> <owner>ejoe@google.com</owner> - <owner>jonross@chromium.com</owner> + <owner>jonross@chromium.org</owner> <summary> The time between the input event timestamp and the frame presentation time on a tab switch. @@ -22085,8 +22085,8 @@ <obsolete> Deprecated as of 12/2017. </obsolete> - <owner>aseren@yandex-team.ru</owner> <owner>gab@chromium.org</owner> + <owner>aseren@yandex-team.ru</owner> <summary> The error code of remote process termination on Windows in case when remote process hung. This histogram has been replaced by @@ -22096,15 +22096,15 @@ <histogram name="Chrome.ProcessSingleton.RemoteHungProcessTerminateReason" enum="RemoteHungProcessTerminateReason" expires_after="M77"> - <owner>aseren@yandex-team.ru</owner> <owner>gab@chromium.org</owner> + <owner>aseren@yandex-team.ru</owner> <summary>The reason of remote hang processes termination.</summary> </histogram> <histogram name="Chrome.ProcessSingleton.RemoteProcessInteractionResult" enum="RemoteProcessInteractionResult" expires_after="M81"> - <owner>aseren@yandex-team.ru</owner> <owner>gab@chromium.org</owner> + <owner>aseren@yandex-team.ru</owner> <summary> Used to send the result of interaction with remote process as histograms in case when remote process influences on start. @@ -22113,8 +22113,8 @@ <histogram name="Chrome.ProcessSingleton.TerminateProcessErrorCode.Posix" enum="PopularOSErrno" expires_after="M77"> - <owner>aseren@yandex-team.ru</owner> <owner>gab@chromium.org</owner> + <owner>aseren@yandex-team.ru</owner> <summary> The error code of remote process termination on Posix in case when remote process hung. @@ -22123,8 +22123,8 @@ <histogram name="Chrome.ProcessSingleton.TerminateProcessErrorCode.Windows" enum="WinGetLastError" expires_after="M81"> - <owner>aseren@yandex-team.ru</owner> <owner>gab@chromium.org</owner> + <owner>aseren@yandex-team.ru</owner> <summary> The error code of remote process termination on Windows in case when remote process hung. @@ -22133,8 +22133,8 @@ <histogram name="Chrome.ProcessSingleton.TerminateProcessTime" units="ms" expires_after="2020-03-08"> - <owner>aseren@yandex-team.ru</owner> <owner>gab@chromium.org</owner> + <owner>aseren@yandex-team.ru</owner> <summary> Time it takes from TerminateProcess call to the moment when we stop waiting for remote process switches to signal state. @@ -22143,8 +22143,8 @@ <histogram name="Chrome.ProcessSingleton.TerminationWaitErrorCode.Windows" enum="WinGetLastError" expires_after="M81"> - <owner>aseren@yandex-team.ru</owner> <owner>gab@chromium.org</owner> + <owner>aseren@yandex-team.ru</owner> <summary> The error code of wating for remote process termination on Windows. </summary> @@ -22810,7 +22810,7 @@ <histogram name="ChromeOS.SAML.SamlChallengeKeyHandlerResult" enum="SamlChallengeKeyHandlerResult" expires_after="2020-06-01"> <owner>miersh@google.com</owner> - <owner>pmarko@chromium.com</owner> + <owner>pmarko@chromium.org</owner> <summary> Tracks results of calculating response for a challenge from Verified Access server for remove attestation during SAML authentication. @@ -30158,7 +30158,7 @@ <histogram name="Cryptohome.InstallAttributesUsage" enum="InstallAttributesUsageEvent" expires_after="2020-07-13"> <owner>vsavu@google.com</owner> - <owner>igorcov@chromium.com</owner> + <owner>igorcov@chromium.org</owner> <summary> Records the result of using the install_attributes.pb cache. This is logged at each device boot. @@ -30168,7 +30168,7 @@ <histogram name="Cryptohome.InstallAttributesValidation" enum="InstallAttributesValidationEvent" expires_after="2020-07-13"> <owner>vsavu@google.com</owner> - <owner>igorcov@chromium.com</owner> + <owner>igorcov@chromium.org</owner> <summary> Records the result of validating install_attributes.pb. This is logged at each device boot. @@ -39583,8 +39583,8 @@ <histogram name="Download.QuarantineService.ConnectionError" enum="BooleanConnectionError" expires_after="M80"> - <owner>alewoolf@microsoft.com</owner> <owner>pmonette@chromium.org</owner> + <owner>alewoolf@microsoft.com</owner> <summary> Whether a connection error has happened for the QuarantineService. </summary> @@ -41172,7 +41172,7 @@ <histogram name="EasyUnlock.StartupTimeFromSuspend" units="ms" expires_after="2020-12-15"> - <owner>hansberry@chromium.com</owner> + <owner>hansberry@chromium.org</owner> <owner>better-together-dev@google.com</owner> <summary> The time it takes after resuming from a suspended state (ie. opening the @@ -61087,8 +61087,8 @@ <histogram name="InputMethod.CompositionWithImm32BasedIme" enum="Boolean" expires_after="M78"> - <owner>siliu@microsoft.com</owner> <owner>lanwei@chromium.org</owner> + <owner>siliu@microsoft.com</owner> <summary> Whether the composition is composed by IMM32-based input method processor when TSF is disabled on Windows. Recorded when user starts new composition. @@ -79415,7 +79415,7 @@ <histogram name="Navigation.MainFrame.FrameCount" units="frames" expires_after="2020-08-01"> <owner>michaelpg@chromium.org</owner> - <owner>yilkal@chormium.org</owner> + <owner>yilkal@chromium.org</owner> <summary> The number of frames that are present in a WebContents. Recorded once when the main frame finishes loading. @@ -79425,7 +79425,7 @@ <histogram name="Navigation.MainFrame.MaxFrameCount" units="frames" expires_after="2020-08-01"> <owner>michaelpg@chromium.org</owner> - <owner>yilkal@chormium.org</owner> + <owner>yilkal@chromium.org</owner> <summary> The maximum number of loaded frames that are present in a WebContents. Recorded once when the main frame is moving away from current page. This can @@ -89166,8 +89166,8 @@ <obsolete> Removed 10/2017. </obsolete> - <owner>maksim.sisov@intel.com</owner> <owner>mmenke@chromium.org</owner> + <owner>maksim.sisov@intel.com</owner> <summary> Records how many times expected content size equals/less/more than size of read body/buffer or content size is unkown. Recorded for each resource load. @@ -90421,9 +90421,9 @@ <obsolete> Removed September 2016. </obsolete> - <owner>sigbjorn@opera.com</owner> <owner>agl@chromium.org</owner> <owner>rsleevi@chromium.org</owner> + <owner>sigbjorn@opera.com</owner> <summary> Bit strength of the key exchange for DHE. Recorded for each SSL/TLS connection in the socket pool where Connect() succeeds. @@ -90434,9 +90434,9 @@ expires_after="never"> <!-- expires-never: Used to keep track of the TLS ecosystem. --> - <owner>sigbjorn@opera.com</owner> <owner>agl@chromium.org</owner> <owner>rsleevi@chromium.org</owner> + <owner>sigbjorn@opera.com</owner> <summary> The curve used for key exchange for ECDHE. Recorded for each SSL/TLS connection in the socket pool where Connect() succeeds. @@ -90448,9 +90448,9 @@ <obsolete> Removed May 2016. </obsolete> - <owner>sigbjorn@opera.com</owner> <owner>agl@chromium.org</owner> <owner>rsleevi@chromium.org</owner> + <owner>sigbjorn@opera.com</owner> <summary> Bit strength of the key exchange for RSA. Recorded for each SSL/TLS connection in the socket pool where Connect() succeeds. See |SSL_SESSION|'s @@ -102391,7 +102391,7 @@ enum="IosLocationAuthorizationStatus" expires_after="M86"> <owner>mpearson@chromium.org</owner> <owner>jdonnelly@chromium.org</owner> - <owner>stkhapugin@chromium.com</owner> + <owner>stkhapugin@chromium.org</owner> <summary> For iOS, whether the application is authorized to use location services when the user enters a search query into the Omnibox. @@ -144672,7 +144672,7 @@ <histogram name="Signin.UserRequestedWipeDataOnSignout" enum="BooleanRequested" expires_after="M82"> - <owner>triploblastic@google.org</owner> + <owner>triploblastic@google.com</owner> <owner>bsazonov@chromium.org</owner> <summary>User requested to wipe local device data on signout.</summary> </histogram> @@ -169689,7 +169689,7 @@ </histogram> <histogram name="WebFont.FontDisplayValue" enum="FontDisplayValue" - expires_after="2020-03-01"> + expires_after="2021-01-20"> <owner>kenjibaheux@chromium.org</owner> <owner>ksakamoto@chromium.org</owner> <summary>
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc index be52001..a6ba9de 100644 --- a/ui/accessibility/ax_enum_util.cc +++ b/ui/accessibility/ax_enum_util.cc
@@ -537,6 +537,8 @@ return "pane"; case ax::mojom::Role::kParagraph: return "paragraph"; + case ax::mojom::Role::kPluginObject: + return "pluginObject"; case ax::mojom::Role::kPopUpButton: return "popUpButton"; case ax::mojom::Role::kPre: @@ -915,6 +917,8 @@ return ax::mojom::Role::kPane; if (0 == strcmp(role, "paragraph")) return ax::mojom::Role::kParagraph; + if (0 == strcmp(role, "pluginObject")) + return ax::mojom::Role::kPluginObject; if (0 == strcmp(role, "popUpButton")) return ax::mojom::Role::kPopUpButton; if (0 == strcmp(role, "pre"))
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom index 3a4b82f4..5c185bd 100644 --- a/ui/accessibility/ax_enums.mojom +++ b/ui/accessibility/ax_enums.mojom
@@ -253,6 +253,7 @@ kNote, kPane, kParagraph, + kPluginObject, kPopUpButton, kPre, kPresentational,
diff --git a/ui/accessibility/extensions/chromevoxclassic/cvox2/background/automation_predicate.js b/ui/accessibility/extensions/chromevoxclassic/cvox2/background/automation_predicate.js index 96cc5a6..312d926c 100644 --- a/ui/accessibility/extensions/chromevoxclassic/cvox2/background/automation_predicate.js +++ b/ui/accessibility/extensions/chromevoxclassic/cvox2/background/automation_predicate.js
@@ -221,7 +221,8 @@ AutomationPredicate.structuralContainer = function(node) { return node.role == RoleType.ROOT_WEB_AREA || node.role == RoleType.EMBEDDED_OBJECT || node.role == RoleType.IFRAME || - node.role == RoleType.IFRAME_PRESENTATIONAL; + node.role == RoleType.IFRAME_PRESENTATIONAL || + node.role == RoleType.PLUGIN_OBJECT; }; /**
diff --git a/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js b/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js index 9cc61cf..0b2ac9b 100644 --- a/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js +++ b/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js
@@ -205,7 +205,8 @@ var node = evt.target; // Discard focus events on embeddedObject and client nodes. - if (node.role == RoleType.EMBEDDED_OBJECT || node.role == RoleType.CLIENT) + if (node.role == RoleType.EMBEDDED_OBJECT || node.role == RoleType.CLIENT || + node.role == RoleType.PLUGIN_OBJECT) return; this.createTextEditHandlerIfNeeded_(evt.target);
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index a3b5738..8fd00b97 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -2609,6 +2609,8 @@ return ATK_ROLE_PANEL; case ax::mojom::Role::kParagraph: return ATK_ROLE_PARAGRAPH; + case ax::mojom::Role::kPluginObject: + return ATK_ROLE_EMBEDDED; case ax::mojom::Role::kPopUpButton: { std::string html_tag = GetData().GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm index 7f9ec08..9d14dc8 100644 --- a/ui/accessibility/platform/ax_platform_node_mac.mm +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -167,6 +167,7 @@ {ax::mojom::Role::kNone, NSAccessibilityGroupRole}, {ax::mojom::Role::kNote, NSAccessibilityGroupRole}, {ax::mojom::Role::kParagraph, NSAccessibilityGroupRole}, + {ax::mojom::Role::kPluginObject, NSAccessibilityGroupRole}, {ax::mojom::Role::kPopUpButton, NSAccessibilityPopUpButtonRole}, {ax::mojom::Role::kPre, NSAccessibilityGroupRole}, {ax::mojom::Role::kPresentational, NSAccessibilityGroupRole},
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index 7a977599..e4ee6c0 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -4751,11 +4751,7 @@ return ROLE_SYSTEM_DOCUMENT; case ax::mojom::Role::kEmbeddedObject: - if (GetDelegate()->GetChildCount()) { - return ROLE_SYSTEM_GROUPING; - } else { - return ROLE_SYSTEM_CLIENT; - } + return ROLE_SYSTEM_CLIENT; case ax::mojom::Role::kFigcaption: return ROLE_SYSTEM_GROUPING; @@ -4909,6 +4905,12 @@ case ax::mojom::Role::kParagraph: return ROLE_SYSTEM_GROUPING; + case ax::mojom::Role::kPluginObject: + if (GetDelegate()->GetChildCount()) + return ROLE_SYSTEM_GROUPING; + else + return ROLE_SYSTEM_CLIENT; + case ax::mojom::Role::kPopUpButton: { std::string html_tag = GetData().GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag); @@ -5295,9 +5297,7 @@ ia2_role = IA2_ROLE_FOOTNOTE; break; case ax::mojom::Role::kEmbeddedObject: - if (!GetDelegate()->GetChildCount()) { - ia2_role = IA2_ROLE_EMBEDDED_OBJECT; - } + ia2_role = IA2_ROLE_EMBEDDED_OBJECT; break; case ax::mojom::Role::kFigcaption: ia2_role = IA2_ROLE_CAPTION; @@ -5352,6 +5352,10 @@ case ax::mojom::Role::kParagraph: ia2_role = IA2_ROLE_PARAGRAPH; break; + case ax::mojom::Role::kPluginObject: + if (!GetDelegate()->GetChildCount()) + ia2_role = IA2_ROLE_EMBEDDED_OBJECT; + break; case ax::mojom::Role::kPre: ia2_role = IA2_ROLE_PARAGRAPH; break; @@ -5579,11 +5583,7 @@ return L"document"; case ax::mojom::Role::kEmbeddedObject: - if (GetDelegate()->GetChildCount()) { - return L"group"; - } else { - return L"document"; - } + return L"region"; case ax::mojom::Role::kEmphasis: return L"emphasis"; @@ -5743,6 +5743,12 @@ case ax::mojom::Role::kParagraph: return L"group"; + case ax::mojom::Role::kPluginObject: + if (GetDelegate()->GetChildCount()) + return L"group"; + else + return L"document"; + case ax::mojom::Role::kPopUpButton: { std::string html_tag = GetData().GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag); @@ -6245,11 +6251,7 @@ return UIA_DocumentControlTypeId; case ax::mojom::Role::kEmbeddedObject: - if (GetDelegate()->GetChildCount()) { - return UIA_GroupControlTypeId; - } else { - return UIA_DocumentControlTypeId; - } + return UIA_PaneControlTypeId; case ax::mojom::Role::kEmphasis: return UIA_TextControlTypeId; @@ -6406,6 +6408,12 @@ case ax::mojom::Role::kParagraph: return UIA_GroupControlTypeId; + case ax::mojom::Role::kPluginObject: + if (GetDelegate()->GetChildCount()) + return UIA_GroupControlTypeId; + else + return UIA_DocumentControlTypeId; + case ax::mojom::Role::kPopUpButton: { std::string html_tag = GetData().GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
diff --git a/ui/base/glib/scoped_gobject.h b/ui/base/glib/scoped_gobject.h index 119fb1b..24ef91ec 100644 --- a/ui/base/glib/scoped_gobject.h +++ b/ui/base/glib/scoped_gobject.h
@@ -47,7 +47,7 @@ g_object_ref_sink(obj_); } - // This function is necessary so that libgtkui can overload it in + // This function is necessary so that gtk can overload it in // the case of T = GtkStyleContext. void Unref() { if (obj_)
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index b5d04ab..50dc513 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -215,10 +215,6 @@ // the combined opacity of the parent. float GetCombinedOpacity() const; - // Returns the target color temperature if animator is running, or the current - // temperature otherwise. - float GetTargetTemperature() const; - // Blur pixels by 3 * this amount in anything below the layer and visible // through the layer. float background_blur() const { return background_blur_sigma_; }
diff --git a/ui/gfx/animation/BUILD.gn b/ui/gfx/animation/BUILD.gn index 52f5744..4d0782a 100644 --- a/ui/gfx/animation/BUILD.gn +++ b/ui/gfx/animation/BUILD.gn
@@ -51,6 +51,14 @@ sources += [ "animation_win.cc" ] } + if (is_desktop_linux) { + sources += [ + "animation_linux.cc", + "animation_settings_provider_linux.cc", + "animation_settings_provider_linux.h", + ] + } + if (!is_android) { sources += [ "throb_animation.cc",
diff --git a/ui/gfx/animation/animation.cc b/ui/gfx/animation/animation.cc index 4295c88d..b216afb5 100644 --- a/ui/gfx/animation/animation.cc +++ b/ui/gfx/animation/animation.cc
@@ -112,17 +112,18 @@ RichAnimationRenderMode::FORCE_ENABLED; } -#if !defined(OS_WIN) && (!defined(OS_MACOSX) || defined(OS_IOS)) +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_IOS) || \ + defined(OS_FUCHSIA) // static bool Animation::ShouldRenderRichAnimationImpl() { - // Defined in platform specific file for Windows and OSX. return true; + // Defined in platform specific file for Windows and OSX and Linux. } // static bool Animation::ScrollAnimationsEnabledBySystem() { - // Defined in platform specific files for Windows and OSX. return true; + // Defined in platform specific files for Windows and OSX and Linux. } #if !defined(OS_ANDROID) @@ -136,7 +137,8 @@ prefers_reduced_motion_ = false; } #endif // !defined(OS_ANDROID) -#endif // !defined(OS_WIN) && (!defined(OS_MACOSX) || defined(OS_IOS)) +#endif // defined(OS_ANDROID) || defined(OS_CHROMEOS) || defined(OS_IOS) || + // defined(OS_FUCHSIA) // static bool Animation::PrefersReducedMotion() {
diff --git a/ui/gfx/animation/animation_linux.cc b/ui/gfx/animation/animation_linux.cc new file mode 100644 index 0000000..0bcce53 --- /dev/null +++ b/ui/gfx/animation/animation_linux.cc
@@ -0,0 +1,37 @@ +// Copyright 2020 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 "ui/gfx/animation/animation.h" + +#include "ui/gfx/animation/animation_settings_provider_linux.h" + +namespace gfx { + +namespace { + +// GTK only has a global setting for whether animations should be enabled. So +// use it for all of the specific settings that Chrome needs. +bool AnimationsEnabled() { + auto* provider = AnimationSettingsProviderLinux::GetInstance(); + return !provider || provider->AnimationsEnabled(); +} + +} // namespace + +// static +bool Animation::ShouldRenderRichAnimationImpl() { + return AnimationsEnabled(); +} + +// static +bool Animation::ScrollAnimationsEnabledBySystem() { + return AnimationsEnabled(); +} + +// static +void Animation::UpdatePrefersReducedMotion() { + prefers_reduced_motion_ = !AnimationsEnabled(); +} + +} // namespace gfx
diff --git a/ui/gfx/animation/animation_settings_provider_linux.cc b/ui/gfx/animation/animation_settings_provider_linux.cc new file mode 100644 index 0000000..a2e1359 --- /dev/null +++ b/ui/gfx/animation/animation_settings_provider_linux.cc
@@ -0,0 +1,30 @@ +// Copyright 2020 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 "ui/gfx/animation/animation_settings_provider_linux.h" + +#include "base/logging.h" + +namespace gfx { + +// static +AnimationSettingsProviderLinux* AnimationSettingsProviderLinux::instance_ = + nullptr; + +// static +AnimationSettingsProviderLinux* AnimationSettingsProviderLinux::GetInstance() { + return instance_; +} + +AnimationSettingsProviderLinux::AnimationSettingsProviderLinux() { + DCHECK(!instance_); + instance_ = this; +} + +AnimationSettingsProviderLinux::~AnimationSettingsProviderLinux() { + DCHECK_EQ(instance_, this); + instance_ = nullptr; +} + +} // namespace gfx
diff --git a/ui/gfx/animation/animation_settings_provider_linux.h b/ui/gfx/animation/animation_settings_provider_linux.h new file mode 100644 index 0000000..9ddfe82 --- /dev/null +++ b/ui/gfx/animation/animation_settings_provider_linux.h
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_ANIMATION_ANIMATION_SETTINGS_PROVIDER_LINUX_H_ +#define UI_GFX_ANIMATION_ANIMATION_SETTINGS_PROVIDER_LINUX_H_ + +#include "base/macros.h" +#include "ui/gfx/animation/animation_export.h" + +namespace gfx { + +class ANIMATION_EXPORT AnimationSettingsProviderLinux { + public: + virtual ~AnimationSettingsProviderLinux(); + + // Indicates if animations are enabled by the toolkit. + virtual bool AnimationsEnabled() const = 0; + + static AnimationSettingsProviderLinux* GetInstance(); + + protected: + AnimationSettingsProviderLinux(); + + private: + static AnimationSettingsProviderLinux* instance_; + + DISALLOW_COPY_AND_ASSIGN(AnimationSettingsProviderLinux); +}; + +} // namespace gfx + +#endif // UI_GFX_ANIMATION_ANIMATION_SETTINGS_PROVIDER_LINUX_H_
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc index dddce3e..de7320f 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view.cc +++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -91,6 +91,8 @@ : Widget::InitParams::WindowOpacity::kOpaque; bubble_params.accept_events = bubble->accept_events(); bubble_params.remove_standard_frame = true; + bubble_params.layer_type = bubble->GetLayerType(); + // Use a window default shadow if the bubble doesn't provides its own. if (bubble->GetShadow() == BubbleBorder::NO_ASSETS) bubble_params.shadow_type = Widget::InitParams::ShadowType::kDefault; @@ -340,6 +342,10 @@ Widget::InitParams* params, Widget* widget) const {} +ui::LayerType BubbleDialogDelegateView::GetLayerType() const { + return ui::LAYER_TEXTURED; +} + void BubbleDialogDelegateView::UseCompactMargins() { set_margins(gfx::Insets(6)); }
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h index d63281d9..ea8d72f 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view.h +++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -137,6 +137,9 @@ virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params, Widget* widget) const; + // The layer type of the bubble widget. + virtual ui::LayerType GetLayerType() const; + // Sets the content margins to a default picked for smaller bubbles. void UseCompactMargins();
diff --git a/ui/views/linux_ui/linux_ui.h b/ui/views/linux_ui/linux_ui.h index 3c224db0..e3ca11fe 100644 --- a/ui/views/linux_ui/linux_ui.h +++ b/ui/views/linux_ui/linux_ui.h
@@ -14,6 +14,7 @@ #include "ui/base/cursor/cursor_theme_manager_linux.h" #include "ui/base/ime/linux/linux_input_method_context_factory.h" #include "ui/base/ime/linux/text_edit_key_bindings_delegate_auralinux.h" +#include "ui/gfx/animation/animation_settings_provider_linux.h" #include "ui/gfx/skia_font_delegate.h" #include "ui/shell_dialogs/shell_dialog_linux.h" #include "ui/views/buildflags.h" @@ -58,7 +59,8 @@ public gfx::SkiaFontDelegate, public ui::ShellDialogLinux, public ui::TextEditKeyBindingsDelegateAuraLinux, - public ui::CursorThemeManagerLinux { + public ui::CursorThemeManagerLinux, + public gfx::AnimationSettingsProviderLinux { public: using UseSystemThemeCallback = base::RepeatingCallback<bool(aura::Window* window)>;
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn index 6cc11fe..eee92b0 100644 --- a/weblayer/BUILD.gn +++ b/weblayer/BUILD.gn
@@ -119,6 +119,8 @@ "browser/navigation_impl.h", "browser/profile_impl.cc", "browser/profile_impl.h", + "browser/session_service.cc", + "browser/session_service.h", "browser/ssl_error_controller_client.cc", "browser/ssl_error_controller_client.h", "browser/ssl_error_handler.cc", @@ -199,6 +201,7 @@ "//components/autofill/content/browser", "//components/autofill/content/renderer", "//components/autofill/core/browser", + "//components/base32", "//components/crash/content/app", "//components/crash/content/browser", "//components/embedder_support", @@ -207,6 +210,7 @@ "//components/security_interstitials/content:security_interstitial_page", "//components/security_interstitials/content/renderer:security_interstitial_page_controller", "//components/security_interstitials/core", + "//components/sessions", "//components/spellcheck:buildflags", "//components/ssl_errors", "//components/startup_metric_utils/browser",
diff --git a/weblayer/browser/DEPS b/weblayer/browser/DEPS index bb81182d..c23e946 100644 --- a/weblayer/browser/DEPS +++ b/weblayer/browser/DEPS
@@ -4,6 +4,7 @@ "+components/autofill/content/browser", "+components/autofill/core/browser", "+components/autofill/core/common", + "+components/base32", "+components/crash/content/browser", "+components/download/public/common", "+components/embedder_support", @@ -12,6 +13,7 @@ "+components/user_prefs", "+components/safe_browsing/core/common", "+components/security_interstitials", + "+components/sessions", "+components/spellcheck/browser", "+components/ssl_errors", "+components/startup_metric_utils",
diff --git a/weblayer/browser/browser_impl.cc b/weblayer/browser/browser_impl.cc index 0058bad..154067bd 100644 --- a/weblayer/browser/browser_impl.cc +++ b/weblayer/browser/browser_impl.cc
@@ -6,8 +6,13 @@ #include <algorithm> +#include "base/path_service.h" +#include "components/base32/base32.h" +#include "content/public/browser/browser_context.h" #include "weblayer/browser/profile_impl.h" +#include "weblayer/browser/session_service.h" #include "weblayer/browser/tab_impl.h" +#include "weblayer/common/weblayer_paths.h" #include "weblayer/public/browser_observer.h" #if defined(OS_ANDROID) @@ -19,19 +24,27 @@ namespace weblayer { -std::unique_ptr<Browser> Browser::Create(Profile* profile) { - return std::make_unique<BrowserImpl>(static_cast<ProfileImpl*>(profile)); +std::unique_ptr<Browser> Browser::Create(Profile* profile, + const std::string& persistence_id) { + return std::make_unique<BrowserImpl>(static_cast<ProfileImpl*>(profile), + persistence_id); } #if defined(OS_ANDROID) BrowserImpl::BrowserImpl(ProfileImpl* profile, + const std::string& persistence_id, const base::android::JavaParamRef<jobject>& java_impl) - : BrowserImpl(profile) { + : BrowserImpl(profile, persistence_id) { java_impl_ = java_impl; } #endif -BrowserImpl::BrowserImpl(ProfileImpl* profile) : profile_(profile) {} +BrowserImpl::BrowserImpl(ProfileImpl* profile, + const std::string& persistence_id) + : profile_(profile), persistence_id_(persistence_id) { + if (!persistence_id.empty()) + CreateSessionServiceAndRestore(); +} BrowserImpl::~BrowserImpl() { while (!tabs_.empty()) { @@ -153,6 +166,10 @@ return tabs_; } +void BrowserImpl::PrepareForShutdown() { + session_service_.reset(); +} + void BrowserImpl::AddObserver(BrowserObserver* observer) { browser_observers_.AddObserver(observer); } @@ -161,13 +178,30 @@ browser_observers_.RemoveObserver(observer); } +base::FilePath BrowserImpl::GetSessionServiceDataPath() { + base::FilePath base_path; + if (profile_->GetBrowserContext()->IsOffTheRecord()) { + CHECK(base::PathService::Get(DIR_USER_DATA, &base_path)); + base_path = base_path.AppendASCII("Incognito Restore Data"); + } else { + base_path = profile_->data_path().AppendASCII("Restore Data"); + } + const std::string encoded_name = base32::Base32Encode(persistence_id_); + return base_path.AppendASCII("State" + encoded_name); +} + +void BrowserImpl::CreateSessionServiceAndRestore() { + session_service_ = + std::make_unique<SessionService>(GetSessionServiceDataPath(), this); +} + #if defined(OS_ANDROID) static jlong JNI_BrowserImpl_CreateBrowser( JNIEnv* env, jlong profile, const base::android::JavaParamRef<jobject>& java_impl) { - return reinterpret_cast<intptr_t>( - new BrowserImpl(reinterpret_cast<ProfileImpl*>(profile), java_impl)); + return reinterpret_cast<intptr_t>(new BrowserImpl( + reinterpret_cast<ProfileImpl*>(profile), std::string(), java_impl)); } static void JNI_BrowserImpl_DeleteBrowser(JNIEnv* env, jlong browser) {
diff --git a/weblayer/browser/browser_impl.h b/weblayer/browser/browser_impl.h index 4a614f9e..84cdc4e 100644 --- a/weblayer/browser/browser_impl.h +++ b/weblayer/browser/browser_impl.h
@@ -5,6 +5,7 @@ #ifndef WEBLAYER_BROWSER_BROWSER_IMPL_H_ #define WEBLAYER_BROWSER_BROWSER_IMPL_H_ +#include <memory> #include <vector> #include "base/observer_list.h" @@ -15,22 +16,30 @@ #include "base/android/scoped_java_ref.h" #endif +namespace base { +class FilePath; +} + namespace weblayer { class ProfileImpl; +class SessionService; class TabImpl; class BrowserImpl : public Browser { public: #if defined(OS_ANDROID) BrowserImpl(ProfileImpl* profile, + const std::string& persistence_id, const base::android::JavaParamRef<jobject>& java_impl); #endif - explicit BrowserImpl(ProfileImpl* profile); + BrowserImpl(ProfileImpl* profile, const std::string& persistence_id); ~BrowserImpl() override; BrowserImpl(const BrowserImpl&) = delete; BrowserImpl& operator=(const BrowserImpl&) = delete; + SessionService* session_service() { return session_service_.get(); } + ProfileImpl* profile() { return profile_; } #if defined(OS_ANDROID) @@ -57,10 +66,16 @@ void SetActiveTab(Tab* tab) override; Tab* GetActiveTab() override; const std::vector<Tab*>& GetTabs() override; + void PrepareForShutdown() override; void AddObserver(BrowserObserver* observer) override; void RemoveObserver(BrowserObserver* observer) override; private: + void CreateSessionServiceAndRestore(); + + // Returns the path used by |session_service_|. + base::FilePath GetSessionServiceDataPath(); + #if defined(OS_ANDROID) base::android::ScopedJavaGlobalRef<jobject> java_impl_; #endif @@ -69,6 +84,7 @@ std::vector<Tab*> tabs_; TabImpl* active_tab_ = nullptr; const std::string persistence_id_; + std::unique_ptr<SessionService> session_service_; }; } // namespace weblayer
diff --git a/weblayer/browser/profile_impl.h b/weblayer/browser/profile_impl.h index 5882d17f..7a9888c 100644 --- a/weblayer/browser/profile_impl.h +++ b/weblayer/browser/profile_impl.h
@@ -38,6 +38,9 @@ content::BrowserContext* GetBrowserContext(); + // Path data is stored at, empty if off-the-record. + const base::FilePath& data_path() const { return data_path_; } + // Profile implementation: void ClearBrowsingData(const std::vector<BrowsingDataType>& data_types, base::Time from_time,
diff --git a/weblayer/browser/session_service.cc b/weblayer/browser/session_service.cc new file mode 100644 index 0000000..75c1669 --- /dev/null +++ b/weblayer/browser/session_service.cc
@@ -0,0 +1,425 @@ +// Copyright 2020 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 "weblayer/browser/session_service.h" + +#include <stddef.h> + +#include <algorithm> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "components/sessions/content/content_serialized_navigation_builder.h" +#include "components/sessions/content/session_tab_helper.h" +#include "components/sessions/core/command_storage_manager.h" +#include "components/sessions/core/session_command.h" +#include "components/sessions/core/session_constants.h" +#include "components/sessions/core/session_id.h" +#include "components/sessions/core/session_types.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_url_handler.h" +#include "content/public/browser/dom_storage_context.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/restore_type.h" +#include "content/public/browser/session_storage_namespace.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" +#include "weblayer/browser/browser_impl.h" +#include "weblayer/browser/profile_impl.h" +#include "weblayer/browser/tab_impl.h" + +using sessions::ContentSerializedNavigationBuilder; +using sessions::SerializedNavigationEntry; + +namespace weblayer { +namespace { + +const SessionID& GetSessionIDForTab(Tab* tab) { + sessions::SessionTabHelper* session_tab_helper = + sessions::SessionTabHelper::FromWebContents( + static_cast<TabImpl*>(tab)->web_contents()); + DCHECK(session_tab_helper); + return session_tab_helper->session_id(); +} + +int GetIndexOfTab(BrowserImpl* browser, Tab* tab) { + const std::vector<Tab*>& tabs = browser->GetTabs(); + auto iter = std::find(tabs.begin(), tabs.end(), tab); + DCHECK(iter != tabs.end()); + return static_cast<int>(iter - tabs.begin()); +} + +} // namespace + +// Every kWritesPerReset commands triggers recreating the file. +constexpr int kWritesPerReset = 250; + +// SessionService ------------------------------------------------------------- + +SessionService::SessionService(const base::FilePath& path, BrowserImpl* browser) + : browser_(browser), + browser_session_id_(SessionID::NewUnique()), + command_storage_manager_( + std::make_unique<sessions::CommandStorageManager>(path, this)), + rebuild_on_next_save_(false) { + browser_->AddObserver(this); + command_storage_manager_->ScheduleGetCurrentSessionCommands( + base::BindOnce(&SessionService::OnGotCurrentSessionCommands, + base::Unretained(this)), + &cancelable_task_tracker_); +} + +SessionService::~SessionService() { + if (command_storage_manager_->HasPendingSave()) + command_storage_manager_->Save(); + browser_->RemoveObserver(this); +} + +bool SessionService::ShouldUseDelayedSave() { + return true; +} + +void SessionService::OnWillSaveCommands() { + if (!rebuild_on_next_save_) + return; + + rebuild_on_next_save_ = false; + command_storage_manager_->set_pending_reset(true); + command_storage_manager_->ClearPendingCommands(); + tab_to_available_range_.clear(); + BuildCommandsForBrowser(); +} + +void SessionService::OnTabAdded(Tab* tab) { + content::WebContents* web_contents = + static_cast<TabImpl*>(tab)->web_contents(); + auto* tab_helper = sessions::SessionTabHelper::FromWebContents(web_contents); + DCHECK(tab_helper); + tab_helper->SetWindowID(browser_session_id_); + + // Record the association between the SessionStorageNamespace and the + // tab. + content::SessionStorageNamespace* session_storage_namespace = + web_contents->GetController().GetDefaultSessionStorageNamespace(); + session_storage_namespace->SetShouldPersist(true); + + if (rebuild_on_next_save_) + return; + + int index = GetIndexOfTab(browser_, tab); + BuildCommandsForTab(static_cast<TabImpl*>(tab), index); + const std::vector<Tab*>& tabs = browser_->GetTabs(); + for (int i = index + 1; i < static_cast<int>(tabs.size()); ++i) { + ScheduleCommand(sessions::CreateSetTabIndexInWindowCommand( + GetSessionIDForTab(tabs[i]), i)); + } +} + +void SessionService::OnTabRemoved(Tab* tab, bool active_tab_changed) { + // Allow the associated sessionStorage to get deleted; it won't be needed + // in the session restore. + content::WebContents* web_contents = + static_cast<TabImpl*>(tab)->web_contents(); + content::SessionStorageNamespace* session_storage_namespace = + web_contents->GetController().GetDefaultSessionStorageNamespace(); + session_storage_namespace->SetShouldPersist(false); + + if (rebuild_on_next_save_) + return; + + ScheduleCommand(sessions::CreateTabClosedCommand(GetSessionIDForTab(tab))); + const std::vector<Tab*>& tabs = browser_->GetTabs(); + for (size_t i = 0; i < tabs.size(); ++i) { + ScheduleCommand(sessions::CreateSetTabIndexInWindowCommand( + GetSessionIDForTab(tabs[i]), i)); + } + auto i = tab_to_available_range_.find(GetSessionIDForTab(tab)); + if (i != tab_to_available_range_.end()) + tab_to_available_range_.erase(i); +} + +void SessionService::OnActiveTabChanged(Tab* tab) { + if (rebuild_on_next_save_) + return; + + const int index = tab == nullptr ? -1 : GetIndexOfTab(browser_, tab); + ScheduleCommand(sessions::CreateSetSelectedTabInWindowCommand( + browser_session_id_, index)); +} + +void SessionService::SetTabUserAgentOverride( + const SessionID& window_id, + const SessionID& tab_id, + const std::string& user_agent_override) { + if (rebuild_on_next_save_) + return; + + ScheduleCommand(sessions::CreateSetTabUserAgentOverrideCommand( + tab_id, user_agent_override)); +} + +void SessionService::SetSelectedNavigationIndex(const SessionID& window_id, + const SessionID& tab_id, + int index) { + if (rebuild_on_next_save_) + return; + + if (tab_to_available_range_.find(tab_id) != tab_to_available_range_.end()) { + if (index < tab_to_available_range_[tab_id].first || + index > tab_to_available_range_[tab_id].second) { + // The new index is outside the range of what we've archived, schedule + // a reset. + ScheduleRebuildOnNextSave(); + return; + } + } + ScheduleCommand( + sessions::CreateSetSelectedNavigationIndexCommand(tab_id, index)); +} + +void SessionService::UpdateTabNavigation( + const SessionID& window_id, + const SessionID& tab_id, + const SerializedNavigationEntry& navigation) { + if (rebuild_on_next_save_) + return; + + if (tab_to_available_range_.find(tab_id) != tab_to_available_range_.end()) { + std::pair<int, int>& range = tab_to_available_range_[tab_id]; + range.first = std::min(navigation.index(), range.first); + range.second = std::max(navigation.index(), range.second); + } + ScheduleCommand(CreateUpdateTabNavigationCommand(tab_id, navigation)); +} + +void SessionService::TabNavigationPathPruned(const SessionID& window_id, + const SessionID& tab_id, + int index, + int count) { + if (rebuild_on_next_save_) + return; + + DCHECK_GE(index, 0); + DCHECK_GT(count, 0); + + // Update the range of available indices. + if (tab_to_available_range_.find(tab_id) != tab_to_available_range_.end()) { + std::pair<int, int>& range = tab_to_available_range_[tab_id]; + + // if both range.first and range.second are also deleted. + if (range.second >= index && range.second < index + count && + range.first >= index && range.first < index + count) { + range.first = range.second = 0; + } else { + // Update range.first + if (range.first >= index + count) + range.first = range.first - count; + else if (range.first >= index && range.first < index + count) + range.first = index; + + // Update range.second + if (range.second >= index + count) + range.second = std::max(range.first, range.second - count); + else if (range.second >= index && range.second < index + count) + range.second = std::max(range.first, index - 1); + } + } + + return ScheduleCommand( + sessions::CreateTabNavigationPathPrunedCommand(tab_id, index, count)); +} + +void SessionService::TabNavigationPathEntriesDeleted(const SessionID& window_id, + const SessionID& tab_id) { + if (rebuild_on_next_save_) + return; + + // Multiple tabs might be affected by this deletion, so the rebuild is + // delayed until next save. + rebuild_on_next_save_ = true; + command_storage_manager_->StartSaveTimer(); +} + +void SessionService::ScheduleRebuildOnNextSave() { + rebuild_on_next_save_ = true; + command_storage_manager_->StartSaveTimer(); +} + +void SessionService::OnGotCurrentSessionCommands( + std::vector<std::unique_ptr<sessions::SessionCommand>> commands) { + ScheduleRebuildOnNextSave(); + + std::vector<std::unique_ptr<sessions::SessionWindow>> windows; + SessionID active_window_id = SessionID::InvalidValue(); + sessions::RestoreSessionFromCommands(commands, &windows, &active_window_id); + ProcessRestoreCommands(windows); + + if (browser_->GetTabs().empty()) { + // Nothing to restore, or restore failed. Create a default tab. + TabImpl* tab = new TabImpl(browser_->profile()); + browser_->AddTab(tab); + browser_->SetActiveTab(tab); + } +} + +void SessionService::BuildCommandsForTab(TabImpl* tab, int index_in_browser) { + DCHECK(tab); + + sessions::SessionTabHelper* session_tab_helper = + sessions::SessionTabHelper::FromWebContents(tab->web_contents()); + DCHECK(session_tab_helper); + const SessionID& session_id(session_tab_helper->session_id()); + command_storage_manager_->AppendRebuildCommand( + sessions::CreateSetTabWindowCommand(browser_session_id_, session_id)); + + content::NavigationController& controller = + tab->web_contents()->GetController(); + const int current_index = controller.GetCurrentEntryIndex(); + const int min_index = + std::max(current_index - sessions::gMaxPersistNavigationCount, 0); + const int max_index = + std::min(current_index + sessions::gMaxPersistNavigationCount, + controller.GetEntryCount()); + const int pending_index = controller.GetPendingEntryIndex(); + tab_to_available_range_[session_id] = + std::pair<int, int>(min_index, max_index); + + command_storage_manager_->AppendRebuildCommand( + sessions::CreateLastActiveTimeCommand( + session_id, tab->web_contents()->GetLastActiveTime())); + + const std::string& ua_override = tab->web_contents()->GetUserAgentOverride(); + if (!ua_override.empty()) { + command_storage_manager_->AppendRebuildCommand( + sessions::CreateSetTabUserAgentOverrideCommand(session_id, + ua_override)); + } + + for (int i = min_index; i < max_index; ++i) { + content::NavigationEntry* entry = (i == pending_index) + ? controller.GetPendingEntry() + : controller.GetEntryAtIndex(i); + DCHECK(entry); + const SerializedNavigationEntry navigation = + ContentSerializedNavigationBuilder::FromNavigationEntry(i, entry); + command_storage_manager_->AppendRebuildCommand( + CreateUpdateTabNavigationCommand(session_id, navigation)); + } + command_storage_manager_->AppendRebuildCommand( + sessions::CreateSetSelectedNavigationIndexCommand(session_id, + current_index)); + + if (index_in_browser != -1) { + command_storage_manager_->AppendRebuildCommand( + sessions::CreateSetTabIndexInWindowCommand(session_id, + index_in_browser)); + } + + // Record the association between the sessionStorage namespace and the tab. + content::SessionStorageNamespace* session_storage_namespace = + controller.GetDefaultSessionStorageNamespace(); + ScheduleCommand(sessions::CreateSessionStorageAssociatedCommand( + session_tab_helper->session_id(), session_storage_namespace->id())); +} + +void SessionService::BuildCommandsForBrowser() { + // This is necessary for SessionService to restore the browser. The type is + // effectively ignored. + command_storage_manager_->AppendRebuildCommand( + sessions::CreateSetWindowTypeCommand( + browser_session_id_, + sessions::SessionWindow::WindowType::TYPE_NORMAL)); + + int active_index = -1; + int tab_index = 0; + for (Tab* tab : browser_->GetTabs()) { + BuildCommandsForTab(static_cast<TabImpl*>(tab), tab_index); + if (tab == browser_->GetActiveTab()) + active_index = tab_index; + ++tab_index; + } + + command_storage_manager_->AppendRebuildCommand( + sessions::CreateSetSelectedTabInWindowCommand(browser_session_id_, + active_index)); +} + +void SessionService::ScheduleCommand( + std::unique_ptr<sessions::SessionCommand> command) { + DCHECK(command); + if (ReplacePendingCommand(command_storage_manager_.get(), &command)) + return; + command_storage_manager_->ScheduleCommand(std::move(command)); + if (command_storage_manager_->commands_since_reset() >= kWritesPerReset) + ScheduleRebuildOnNextSave(); +} + +void SessionService::ProcessRestoreCommands( + const std::vector<std::unique_ptr<sessions::SessionWindow>>& windows) { + if (windows.empty() || windows[0]->tabs.empty()) + return; + + const bool had_tabs = !browser_->GetTabs().empty(); + content::BrowserContext* browser_context = + browser_->profile()->GetBrowserContext(); + for (int i = 0; i < static_cast<int>(windows[0]->tabs.size()); ++i) { + const sessions::SessionTab& session_tab = *(windows[0]->tabs[i]); + if (session_tab.navigations.empty()) + continue; + + // Associate sessionStorage (if any) to the restored tab. + scoped_refptr<content::SessionStorageNamespace> session_storage_namespace; + if (!session_tab.session_storage_persistent_id.empty()) { + session_storage_namespace = + content::BrowserContext::GetDefaultStoragePartition(browser_context) + ->GetDOMStorageContext() + ->RecreateSessionStorage( + session_tab.session_storage_persistent_id); + } + + const int selected_navigation_index = + session_tab.normalized_navigation_index(); + + GURL restore_url = + session_tab.navigations[selected_navigation_index].virtual_url(); + content::SessionStorageNamespaceMap session_storage_namespace_map; + session_storage_namespace_map[std::string()] = session_storage_namespace; + bool reverse_on_redirect; + content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary( + &restore_url, browser_context, &reverse_on_redirect); + content::WebContents::CreateParams create_params( + browser_context, + content::SiteInstance::ShouldAssignSiteForURL(restore_url) + ? content::SiteInstance::CreateForURL(browser_context, restore_url) + : nullptr); + create_params.initially_hidden = true; + create_params.desired_renderer_state = + content::WebContents::CreateParams::kNoRendererProcess; + create_params.last_active_time = session_tab.last_active_time; + std::unique_ptr<content::WebContents> web_contents = + content::WebContents::CreateWithSessionStorage( + create_params, session_storage_namespace_map); + std::vector<std::unique_ptr<content::NavigationEntry>> entries = + ContentSerializedNavigationBuilder::ToNavigationEntries( + session_tab.navigations, browser_context); + web_contents->SetUserAgentOverride(session_tab.user_agent_override, false); + // CURRENT_SESSION matches what clank does. On the desktop, we should + // use a different type. + web_contents->GetController().Restore(selected_navigation_index, + content::RestoreType::CURRENT_SESSION, + &entries); + DCHECK_EQ(0u, entries.size()); + TabImpl* tab = new TabImpl(browser_->profile(), std::move(web_contents)); + browser_->AddTab(tab); + + if (!had_tabs && i == (windows[0])->selected_tab_index) + browser_->SetActiveTab(tab); + } + if (!had_tabs && !browser_->GetTabs().empty() && !browser_->GetActiveTab()) + browser_->SetActiveTab(browser_->GetTabs().back()); +} + +} // namespace weblayer
diff --git a/weblayer/browser/session_service.h b/weblayer/browser/session_service.h new file mode 100644 index 0000000..a7a2d81 --- /dev/null +++ b/weblayer/browser/session_service.h
@@ -0,0 +1,120 @@ +// Copyright 2020 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 WEBLAYER_BROWSER_SESSION_SERVICE_H_ +#define WEBLAYER_BROWSER_SESSION_SERVICE_H_ + +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/macros.h" +#include "base/task/cancelable_task_tracker.h" +#include "components/sessions/content/session_tab_helper_delegate.h" +#include "components/sessions/core/command_storage_manager_delegate.h" +#include "components/sessions/core/session_service_commands.h" +#include "weblayer/public/browser_observer.h" + +class SessionID; + +namespace sessions { +class SessionCommand; +} + +namespace weblayer { + +class BrowserImpl; +class TabImpl; + +// SessionService is responsible for maintaining the state of tabs in a Browser +// so that they can be restored at a later date. To avoid having to write the +// complete state anytime something changes interesting events (represented as +// SessionCommands) are written to disk. To restore, the events are read back +// and the state recreated. At certain times the file is truncated and rebuilt +// from the current state. +class SessionService : public sessions::CommandStorageManagerDelegate, + public sessions::SessionTabHelperDelegate, + public BrowserObserver { + public: + SessionService(const base::FilePath& path, BrowserImpl* browser); + + SessionService(const SessionService&) = delete; + SessionService& operator=(const SessionService&) = delete; + + ~SessionService() override; + + private: + friend class SessionServiceTestHelper; + + using IdToRange = std::map<SessionID, std::pair<int, int>>; + + // CommandStorageManagerDelegate: + bool ShouldUseDelayedSave() override; + void OnWillSaveCommands() override; + + // BrowserObserver; + void OnTabAdded(Tab* tab) override; + void OnTabRemoved(Tab* tab, bool active_tab_changed) override; + void OnActiveTabChanged(Tab* tab) override; + + // sessions::SessionTabHelperDelegate: + void SetTabUserAgentOverride(const SessionID& window_id, + const SessionID& tab_id, + const std::string& user_agent_override) override; + void SetSelectedNavigationIndex(const SessionID& window_id, + const SessionID& tab_id, + int index) override; + void UpdateTabNavigation( + const SessionID& window_id, + const SessionID& tab_id, + const sessions::SerializedNavigationEntry& navigation) override; + void TabNavigationPathPruned(const SessionID& window_id, + const SessionID& tab_id, + int index, + int count) override; + void TabNavigationPathEntriesDeleted(const SessionID& window_id, + const SessionID& tab_id) override; + + // Schedules recreating the file on the next save. + void ScheduleRebuildOnNextSave(); + + // Called with the contents of the previous session. + void OnGotCurrentSessionCommands( + std::vector<std::unique_ptr<sessions::SessionCommand>> commands); + + // Schedules commands to recreate the state of the specified tab. + void BuildCommandsForTab(TabImpl* tab, int index_in_window); + + // Schedules commands to recreate the state of |browser_|. + void BuildCommandsForBrowser(); + + // Schedules the specified command. + void ScheduleCommand(std::unique_ptr<sessions::SessionCommand> command); + + void ProcessRestoreCommands( + const std::vector<std::unique_ptr<sessions::SessionWindow>>& windows); + + BrowserImpl* browser_; + + // ID used for the browser. The sessions code requires each tab to be + // associated with a browser. + const SessionID browser_session_id_; + + std::unique_ptr<sessions::CommandStorageManager> command_storage_manager_; + + // Maps from session tab id to the range of navigation entries that has + // been written to disk. + IdToRange tab_to_available_range_; + + // Force session commands to be rebuild before next save event. + bool rebuild_on_next_save_; + + base::CancelableTaskTracker cancelable_task_tracker_; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_SESSION_SERVICE_H_
diff --git a/weblayer/browser/session_service_browsertest.cc b/weblayer/browser/session_service_browsertest.cc new file mode 100644 index 0000000..76e130c --- /dev/null +++ b/weblayer/browser/session_service_browsertest.cc
@@ -0,0 +1,307 @@ +// Copyright 2020 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 "weblayer/browser/session_service.h" + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "components/sessions/core/command_storage_manager_test_helper.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/url_loader_interceptor.h" +#include "net/base/filename_util.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "weblayer/browser/browser_impl.h" +#include "weblayer/browser/profile_impl.h" +#include "weblayer/browser/tab_impl.h" +#include "weblayer/common/weblayer_paths.h" +#include "weblayer/public/navigation.h" +#include "weblayer/public/navigation_controller.h" +#include "weblayer/public/navigation_observer.h" +#include "weblayer/public/tab.h" +#include "weblayer/shell/browser/shell.h" +#include "weblayer/test/interstitial_utils.h" +#include "weblayer/test/test_navigation_observer.h" +#include "weblayer/test/weblayer_browser_test.h" +#include "weblayer/test/weblayer_browser_test_utils.h" + +namespace weblayer { + +class SessionServiceTestHelper { + public: + static sessions::CommandStorageManager* GetCommandStorageManager( + SessionService* service) { + return service->command_storage_manager_.get(); + } +}; + +namespace { + +class OneShotNavigationObserver : public NavigationObserver { + public: + explicit OneShotNavigationObserver(Shell* shell) : tab_(shell->tab()) { + tab_->GetNavigationController()->AddObserver(this); + } + + ~OneShotNavigationObserver() override { + tab_->GetNavigationController()->RemoveObserver(this); + } + + void WaitForNavigation() { run_loop_.Run(); } + + bool completed() { return completed_; } + bool is_error_page() { return is_error_page_; } + Navigation::LoadError load_error() { return load_error_; } + int http_status_code() { return http_status_code_; } + NavigationState navigation_state() { return navigation_state_; } + + private: + // NavigationObserver implementation: + void NavigationCompleted(Navigation* navigation) override { + completed_ = true; + Finish(navigation); + } + + void NavigationFailed(Navigation* navigation) override { Finish(navigation); } + + void Finish(Navigation* navigation) { + is_error_page_ = navigation->IsErrorPage(); + load_error_ = navigation->GetLoadError(); + http_status_code_ = navigation->GetHttpStatusCode(); + navigation_state_ = navigation->GetState(); + run_loop_.Quit(); + } + + base::RunLoop run_loop_; + Tab* tab_; + bool completed_ = false; + bool is_error_page_ = false; + Navigation::LoadError load_error_ = Navigation::kNoError; + int http_status_code_ = 0; + NavigationState navigation_state_ = NavigationState::kWaitingResponse; +}; + +class BrowserObserverImpl : public BrowserObserver { + public: + static void WaitForNewTab(Browser* browser) { + BrowserObserverImpl observer(browser); + observer.Wait(); + } + + private: + explicit BrowserObserverImpl(Browser* browser) : browser_(browser) { + browser_->AddObserver(this); + } + ~BrowserObserverImpl() override { browser_->RemoveObserver(this); } + + void Wait() { run_loop_.Run(); } + + // BrowserObserver: + void OnTabAdded(Tab* tab) override { run_loop_.Quit(); } + + Browser* browser_; + base::RunLoop run_loop_; +}; + +class BrowserNavigationObserverImpl : public BrowserObserver, + public NavigationObserver { + public: + static void WaitForNewTabToCompleteNavigation(Browser* browser, + const GURL& url, + int tab_to_wait_for = 1) { + BrowserNavigationObserverImpl observer(browser, url, tab_to_wait_for); + observer.Wait(); + } + + private: + BrowserNavigationObserverImpl(Browser* browser, + const GURL& url, + int tab_to_wait_for) + : browser_(browser), url_(url), tab_to_wait_for_(tab_to_wait_for) { + browser_->AddObserver(this); + } + ~BrowserNavigationObserverImpl() override { + tab_->GetNavigationController()->RemoveObserver(this); + } + + void Wait() { run_loop_.Run(); } + + // NavigationObserver; + void NavigationCompleted(Navigation* navigation) override { + if (navigation->GetURL() == url_) + run_loop_.Quit(); + } + + // BrowserObserver: + void OnTabAdded(Tab* tab) override { + if (--tab_to_wait_for_ != 0) + return; + + browser_->RemoveObserver(this); + tab_ = tab; + tab_->GetNavigationController()->AddObserver(this); + } + + Browser* browser_; + const GURL& url_; + Tab* tab_ = nullptr; + int tab_to_wait_for_; + std::unique_ptr<TestNavigationObserver> navigation_observer_; + base::RunLoop run_loop_; +}; + +void ShutdownSessionServiceAndWait(BrowserImpl* browser) { + auto task_runner = sessions::CommandStorageManagerTestHelper( + SessionServiceTestHelper::GetCommandStorageManager( + browser->session_service())) + .GetBackendTaskRunner(); + browser->PrepareForShutdown(); + base::RunLoop run_loop; + task_runner->PostTaskAndReply(FROM_HERE, base::DoNothing(), + run_loop.QuitClosure()); + run_loop.Run(); +} + +} // namespace + +using SessionServiceTest = WebLayerBrowserTest; + +IN_PROC_BROWSER_TEST_F(SessionServiceTest, SingleTab) { + ASSERT_TRUE(embedded_test_server()->Start()); + + std::unique_ptr<BrowserImpl> browser = + std::make_unique<BrowserImpl>(GetProfile(), "x"); + std::unique_ptr<Tab> tab = Tab::Create(GetProfile()); + browser->AddTab(tab.get()); + const GURL url = embedded_test_server()->GetURL("/simple_page.html"); + NavigateAndWaitForCompletion(url, tab.get()); + ShutdownSessionServiceAndWait(browser.get()); + tab.reset(); + browser.reset(); + + browser = std::make_unique<BrowserImpl>(GetProfile(), "x"); + // Should be no tabs while waiting for restore. + EXPECT_TRUE(browser->GetTabs().empty()); + // Wait for the restore and navigation to complete. + BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation( + browser.get(), url); + + ASSERT_EQ(1u, browser->GetTabs().size()); + EXPECT_EQ(browser->GetTabs()[0], browser->GetActiveTab()); + EXPECT_EQ(1, browser->GetTabs()[0] + ->GetNavigationController() + ->GetNavigationListSize()); +} + +IN_PROC_BROWSER_TEST_F(SessionServiceTest, TwoTabs) { + ASSERT_TRUE(embedded_test_server()->Start()); + + std::unique_ptr<BrowserImpl> browser = + std::make_unique<BrowserImpl>(GetProfile(), "x"); + std::unique_ptr<Tab> tab1 = Tab::Create(GetProfile()); + browser->AddTab(tab1.get()); + const GURL url1 = embedded_test_server()->GetURL("/simple_page.html"); + NavigateAndWaitForCompletion(url1, tab1.get()); + + std::unique_ptr<Tab> tab2 = Tab::Create(GetProfile()); + browser->AddTab(tab2.get()); + const GURL url2 = embedded_test_server()->GetURL("/simple_page2.html"); + NavigateAndWaitForCompletion(url2, tab2.get()); + browser->SetActiveTab(tab2.get()); + + // Shutdown the service and run the assertions twice to ensure we handle + // correctly storing state of tabs that need to be reloaded. + for (int i = 0; i < 2; ++i) { + ShutdownSessionServiceAndWait(browser.get()); + tab1.reset(); + tab2.reset(); + browser.reset(); + + browser = std::make_unique<BrowserImpl>(GetProfile(), "x"); + // Should be no tabs while waiting for restore. + EXPECT_TRUE(browser->GetTabs().empty()) << "iteration " << i; + // Wait for the restore and navigation to complete. This waits for the + // second tab as that was the active one. + BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation( + browser.get(), url2, 2); + + ASSERT_EQ(2u, browser->GetTabs().size()) << "iteration " << i; + // The first tab shouldn't have loaded yet, as it's not active. + EXPECT_TRUE(static_cast<TabImpl*>(browser->GetTabs()[0]) + ->web_contents() + ->GetController() + .NeedsReload()) + << "iteration " << i; + EXPECT_EQ(browser->GetTabs()[1], browser->GetActiveTab()) + << "iteration " << i; + EXPECT_EQ(1, browser->GetTabs()[1] + ->GetNavigationController() + ->GetNavigationListSize()) + << "iteration " << i; + } +} + +IN_PROC_BROWSER_TEST_F(SessionServiceTest, MoveBetweenBrowsers) { + ASSERT_TRUE(embedded_test_server()->Start()); + + // Create a browser with two tabs. + std::unique_ptr<BrowserImpl> browser1 = + std::make_unique<BrowserImpl>(GetProfile(), "x"); + std::unique_ptr<Tab> tab1 = Tab::Create(GetProfile()); + browser1->AddTab(tab1.get()); + const GURL url1 = embedded_test_server()->GetURL("/simple_page.html"); + NavigateAndWaitForCompletion(url1, tab1.get()); + + std::unique_ptr<Tab> tab2 = Tab::Create(GetProfile()); + browser1->AddTab(tab2.get()); + const GURL url2 = embedded_test_server()->GetURL("/simple_page2.html"); + NavigateAndWaitForCompletion(url2, tab2.get()); + browser1->SetActiveTab(tab2.get()); + + // Create another browser with a single tab. + std::unique_ptr<BrowserImpl> browser2 = + std::make_unique<BrowserImpl>(GetProfile(), "y"); + std::unique_ptr<Tab> tab3 = Tab::Create(GetProfile()); + browser2->AddTab(tab3.get()); + const GURL url3 = embedded_test_server()->GetURL("/simple_page3.html"); + NavigateAndWaitForCompletion(url3, tab3.get()); + + // Move |tab2| to |browser2|. + browser2->AddTab(tab2.get()); + browser2->SetActiveTab(tab2.get()); + + ShutdownSessionServiceAndWait(browser1.get()); + ShutdownSessionServiceAndWait(browser2.get()); + tab1.reset(); + browser1.reset(); + + tab2.reset(); + tab3.reset(); + browser2.reset(); + + // Restore the browsers. + browser1 = std::make_unique<BrowserImpl>(GetProfile(), "x"); + BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation( + browser1.get(), url1, 1); + ASSERT_EQ(1u, browser1->GetTabs().size()); + EXPECT_EQ(1, browser1->GetTabs()[0] + ->GetNavigationController() + ->GetNavigationListSize()); + + browser2 = std::make_unique<BrowserImpl>(GetProfile(), "y"); + BrowserNavigationObserverImpl::WaitForNewTabToCompleteNavigation( + browser2.get(), url2, 2); + ASSERT_EQ(2u, browser2->GetTabs().size()); + EXPECT_EQ(1, browser2->GetTabs()[1] + ->GetNavigationController() + ->GetNavigationListSize()); + + // As |tab3| isn't active it needs to be loaded. Force that now. + TabImpl* restored_tab_3 = static_cast<TabImpl*>(browser2->GetTabs()[0]); + EXPECT_TRUE(restored_tab_3->web_contents()->GetController().NeedsReload()); + restored_tab_3->web_contents()->GetController().LoadIfNecessary(); + content::WaitForLoadStop(restored_tab_3->web_contents()); +} + +} // namespace weblayer
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc index f7661bd0..f82027d 100644 --- a/weblayer/browser/tab_impl.cc +++ b/weblayer/browser/tab_impl.cc
@@ -10,6 +10,7 @@ #include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_manager.h" #include "components/autofill/core/browser/autofill_provider.h" +#include "components/sessions/content/session_tab_helper.h" #include "content/public/browser/file_select_listener.h" #include "content/public/browser/interstitial_page.h" #include "content/public/browser/navigation_controller.h" @@ -26,6 +27,7 @@ #include "weblayer/browser/isolated_world_ids.h" #include "weblayer/browser/navigation_controller_impl.h" #include "weblayer/browser/profile_impl.h" +#include "weblayer/browser/session_service.h" #include "weblayer/public/download_delegate.h" #include "weblayer/public/fullscreen_delegate.h" #include "weblayer/public/new_tab_delegate.h" @@ -148,6 +150,11 @@ Observe(web_contents_.get()); navigation_controller_ = std::make_unique<NavigationControllerImpl>(this); + + sessions::SessionTabHelper::CreateForWebContents( + web_contents_.get(), + base::BindRepeating(&TabImpl::GetSessionServiceTabHelperDelegate, + base::Unretained(this))); } TabImpl::~TabImpl() { @@ -528,4 +535,10 @@ autofill_provider_.get()); } +sessions::SessionTabHelperDelegate* TabImpl::GetSessionServiceTabHelperDelegate( + content::WebContents* web_contents) { + DCHECK_EQ(web_contents, web_contents_.get()); + return browser_ ? browser_->session_service() : nullptr; +} + } // namespace weblayer
diff --git a/weblayer/browser/tab_impl.h b/weblayer/browser/tab_impl.h index 17045cf..ddd4be7e 100644 --- a/weblayer/browser/tab_impl.h +++ b/weblayer/browser/tab_impl.h
@@ -31,6 +31,10 @@ class WebContents; } +namespace sessions { +class SessionTabHelperDelegate; +} + namespace weblayer { class BrowserImpl; class FullscreenDelegate; @@ -178,6 +182,9 @@ void InitializeAutofill(); + sessions::SessionTabHelperDelegate* GetSessionServiceTabHelperDelegate( + content::WebContents* web_contents); + #if defined(OS_ANDROID) void UpdateBrowserControlsState(content::BrowserControlsState constraints, content::BrowserControlsState current,
diff --git a/weblayer/public/browser.h b/weblayer/public/browser.h index 59b72a4..f9eb934b 100644 --- a/weblayer/public/browser.h +++ b/weblayer/public/browser.h
@@ -18,7 +18,10 @@ // the set of Tabs. class Browser { public: - static std::unique_ptr<Browser> Create(Profile* profile); + // Creates a new Browser. |persistence_id|, if non-empty, is used for saving + // and restoring the state of the browser. + static std::unique_ptr<Browser> Create(Profile* profile, + const std::string& persistence_id); virtual ~Browser() {} @@ -28,6 +31,9 @@ virtual Tab* GetActiveTab() = 0; virtual const std::vector<Tab*>& GetTabs() = 0; + // Called early on in shutdown, before any tabs have been removed. + virtual void PrepareForShutdown() = 0; + virtual void AddObserver(BrowserObserver* observer) = 0; virtual void RemoveObserver(BrowserObserver* observer) = 0; };
diff --git a/weblayer/test/BUILD.gn b/weblayer/test/BUILD.gn index 163f5e6..a39cfdb 100644 --- a/weblayer/test/BUILD.gn +++ b/weblayer/test/BUILD.gn
@@ -74,13 +74,13 @@ deps = [ "//base", - "//base", "//base/test:test_support", "//components/autofill/core/browser", "//components/autofill/core/browser:test_support", "//components/autofill/core/common", "//components/network_time", "//components/security_interstitials/content:security_interstitial_page", + "//components/sessions:test_support", "//components/strings", "//content/public/browser", "//content/test:test_support", @@ -151,5 +151,12 @@ use_default_launcher = false shared_resources = true product_config_java_packages = [ weblayer_product_config_java_package ] + } else { + sources += [ + # This test creates Browser objects from C++, which the Java side is not + # setup for. SessionService related tests for Java will be done as + # integration tests. + "../browser/session_service_browsertest.cc", + ] } }
diff --git a/weblayer/test/data/simple_page3.html b/weblayer/test/data/simple_page3.html new file mode 100644 index 0000000..a1049c4 --- /dev/null +++ b/weblayer/test/data/simple_page3.html
@@ -0,0 +1,6 @@ +<html> +<head><title>OK</title></head> +<body> +Basic html test2. +</body> +</html>
diff --git a/weblayer/test/test_navigation_observer.cc b/weblayer/test/test_navigation_observer.cc index 4b7b351..bd51125 100644 --- a/weblayer/test/test_navigation_observer.cc +++ b/weblayer/test/test_navigation_observer.cc
@@ -16,7 +16,12 @@ TestNavigationObserver::TestNavigationObserver(const GURL& url, NavigationEvent target_event, Shell* shell) - : url_(url), target_event_(target_event), tab_(shell->tab()) { + : TestNavigationObserver(url, target_event, shell->tab()) {} + +TestNavigationObserver::TestNavigationObserver(const GURL& url, + NavigationEvent target_event, + Tab* tab) + : url_(url), target_event_(target_event), tab_(tab) { tab_->GetNavigationController()->AddObserver(this); }
diff --git a/weblayer/test/test_navigation_observer.h b/weblayer/test/test_navigation_observer.h index 535fa536..818042d 100644 --- a/weblayer/test/test_navigation_observer.h +++ b/weblayer/test/test_navigation_observer.h
@@ -26,6 +26,9 @@ TestNavigationObserver(const GURL& url, NavigationEvent target_event, Shell* shell); + TestNavigationObserver(const GURL& url, + NavigationEvent target_event, + Tab* tab); ~TestNavigationObserver() override; // Spins a RunLoop until the requested type of navigation event is observed.
diff --git a/weblayer/test/weblayer_browser_test.cc b/weblayer/test/weblayer_browser_test.cc index bd4876fe..ae789cf 100644 --- a/weblayer/test/weblayer_browser_test.cc +++ b/weblayer/test/weblayer_browser_test.cc
@@ -45,4 +45,8 @@ Shell::CloseAllWindows(); } +ProfileImpl* WebLayerBrowserTest::GetProfile() { + return static_cast<TabImpl*>(shell_->tab())->profile(); +} + } // namespace weblayer
diff --git a/weblayer/test/weblayer_browser_test.h b/weblayer/test/weblayer_browser_test.h index fd527657..4773a88 100644 --- a/weblayer/test/weblayer_browser_test.h +++ b/weblayer/test/weblayer_browser_test.h
@@ -10,6 +10,7 @@ #include "content/public/test/browser_test_base.h" namespace weblayer { +class ProfileImpl; class Shell; class WebLayerBrowserTest : public content::BrowserTestBase { @@ -25,6 +26,8 @@ // Returns the window for the test. Shell* shell() const { return shell_; } + ProfileImpl* GetProfile(); + private: Shell* shell_ = nullptr;
diff --git a/weblayer/test/weblayer_browser_test_utils.cc b/weblayer/test/weblayer_browser_test_utils.cc index b81f4cf..eea58cf 100644 --- a/weblayer/test/weblayer_browser_test_utils.cc +++ b/weblayer/test/weblayer_browser_test_utils.cc
@@ -18,24 +18,29 @@ namespace { -// Navigates to |url| in |shell| and waits for |event| to occur. +// Navigates to |url| in |tab| and waits for |event| to occur. void NavigateAndWaitForEvent(const GURL& url, - Shell* shell, + Tab* tab, TestNavigationObserver::NavigationEvent event) { - TestNavigationObserver test_observer(url, event, shell); - shell->tab()->GetNavigationController()->Navigate(url); + TestNavigationObserver test_observer(url, event, tab); + tab->GetNavigationController()->Navigate(url); test_observer.Wait(); } } // namespace void NavigateAndWaitForCompletion(const GURL& url, Shell* shell) { - NavigateAndWaitForEvent(url, shell, + NavigateAndWaitForEvent(url, shell->tab(), + TestNavigationObserver::NavigationEvent::Completion); +} + +void NavigateAndWaitForCompletion(const GURL& url, Tab* tab) { + NavigateAndWaitForEvent(url, tab, TestNavigationObserver::NavigationEvent::Completion); } void NavigateAndWaitForFailure(const GURL& url, Shell* shell) { - NavigateAndWaitForEvent(url, shell, + NavigateAndWaitForEvent(url, shell->tab(), TestNavigationObserver::NavigationEvent::Failure); }
diff --git a/weblayer/test/weblayer_browser_test_utils.h b/weblayer/test/weblayer_browser_test_utils.h index 916fc99..eda8e82a 100644 --- a/weblayer/test/weblayer_browser_test_utils.h +++ b/weblayer/test/weblayer_browser_test_utils.h
@@ -18,10 +18,13 @@ namespace weblayer { class Shell; +class Tab; // Navigates |shell| to |url| and wait for completed navigation. void NavigateAndWaitForCompletion(const GURL& url, Shell* shell); +void NavigateAndWaitForCompletion(const GURL& url, Tab* tab); + // Navigates |shell| to |url| and wait for failed navigation. void NavigateAndWaitForFailure(const GURL& url, Shell* shell);