diff --git a/.gn b/.gn index c1a1113..eaf210ef 100644 --- a/.gn +++ b/.gn
@@ -85,7 +85,7 @@ "//chrome/app/*", "//chrome/app_shim/*", - #"//chrome/browser/android/*", # Only metrics and vr have errors. + #"//chrome/browser/android/*", # Only vr has errors. https://crbug.com/871623 "//chrome/browser/android/accessibility/*", "//chrome/browser/android/autofill_assistant/*", "//chrome/browser/android/bookmarks/*", @@ -119,6 +119,7 @@ "//chrome/browser/android/history_report/*", "//chrome/browser/android/instantapps/*", "//chrome/browser/android/locale/*", + "//chrome/browser/android/metrics/*", "//chrome/browser/android/mojo/*", "//chrome/browser/android/net/*", "//chrome/browser/android/ntp/*",
diff --git a/BUILD.gn b/BUILD.gn index 45b912d..2543a3a 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -146,8 +146,6 @@ "//third_party/cacheinvalidation:cacheinvalidation_unittests", "//third_party/pdfium/samples:pdfium_test", "//third_party/webrtc/rtc_tools:frame_analyzer", - "//tools/battor_agent", - "//tools/battor_agent:battor_agent_unittests", "//tools/perf/clear_system_cache", "//tools/traffic_annotation/auditor:traffic_annotation_auditor", "//tools/traffic_annotation/auditor:traffic_annotation_auditor_unittests", @@ -952,7 +950,7 @@ "//third_party/WebKit/LayoutTests/", "//third_party/blink/perf_tests/", "//third_party/blink/tools/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", ] if (is_win) {
diff --git a/DEPS b/DEPS index b7332821..7c404d9 100644 --- a/DEPS +++ b/DEPS
@@ -105,11 +105,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': '057c39025a93b03bc9b9e435d1a4685d4bbd97e0', + 'skia_revision': '8af4c40014e3db976bc7da21fbc9c991d68b109b', # 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': 'f43cb96ec2213a32cb3a2fbd528a6ee41de910df', + 'v8_revision': '4fe3de13fc5c2592559bb5e49e1a81a6d09a2efd', # 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. @@ -117,7 +117,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': 'c93eeaab15269253593e929abce8cdfea52242ef', + 'angle_revision': 'c43cdad25851a5602698fedbf1a96bf5673d69a2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -129,7 +129,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': 'f90277e7f4bd99bba419b53341c6c7bdca478eed', + 'pdfium_revision': '60627d6eafd025dde711e532eee6866840c04bef', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -153,7 +153,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': 'a87b168e08d3b69241b7f185e5ee3c96ed8bf478', + 'nacl_revision': '96088f46727b75b2f6a24e1b62e5cc59ddb4612d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -165,7 +165,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '9aa552b15750a6d530b34009589ad5d9b4d4ec83', + 'catapult_revision': 'bca7d20ad76a1d8c3e594443e9100ba4999a266c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -552,7 +552,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '94ec5e5e83b994b7361184ba24f17bdc645575c6', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5570c88a3dce00f73a26cb5e60033f54949355d6', 'condition': 'checkout_linux', }, @@ -925,7 +925,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '964e15665fbc3108deef40af2f07b515173d7401', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '74182d1df594d4b007526412d2a46a87a7f85f21', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1047,7 +1047,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '21dbf06b5aa6c7dc8cf56314d4a3f96f57956c53', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '8e5014a3925eb070aca00fcff0aa9c36fd30fb3b', + Var('webrtc_git') + '/src.git' + '@' + '5f0ce99c04eb18313dd24b3dc31cc6246496d6d5', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index 04298f7c..fd7369cf 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc
@@ -75,17 +75,16 @@ AwBrowserContext* g_browser_context = NULL; -std::unique_ptr<net::ProxyConfigService> CreateProxyConfigService() { - std::unique_ptr<net::ProxyConfigService> config_service = - net::ProxyResolutionService::CreateSystemProxyConfigService( - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); +std::unique_ptr<net::ProxyConfigServiceAndroid> CreateProxyConfigService() { + std::unique_ptr<net::ProxyConfigServiceAndroid> config_service_android = + std::make_unique<net::ProxyConfigServiceAndroid>( + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), + base::ThreadTaskRunnerHandle::Get()); // TODO(csharrison) Architect the wrapper better so we don't need a cast for // android ProxyConfigServices. - net::ProxyConfigServiceAndroid* android_config_service = - static_cast<net::ProxyConfigServiceAndroid*>(config_service.get()); - android_config_service->set_exclude_pac_url(true); - return config_service; + config_service_android->set_exclude_pac_url(true); + return config_service_android; } std::unique_ptr<AwSafeBrowsingWhitelistManager>
diff --git a/android_webview/browser/aw_contents_statics.cc b/android_webview/browser/aw_contents_statics.cc index 1bee668..6f9169e 100644 --- a/android_webview/browser/aw_contents_statics.cc +++ b/android_webview/browser/aw_contents_statics.cc
@@ -130,4 +130,29 @@ AwURLRequestContextGetter::set_check_cleartext_permitted(permitted); } +// static +void JNI_AwContentsStatics_SetProxyOverride( + JNIEnv* env, + const JavaParamRef<jclass>&, + const base::android::JavaParamRef<jstring>& jhost, + jint port, + const base::android::JavaParamRef<jobjectArray>& jexclusion_list) { + std::string host; + base::android::ConvertJavaStringToUTF8(env, jhost, &host); + std::vector<std::string> exclusion_list; + base::android::AppendJavaStringArrayToStringVector(env, jexclusion_list, + &exclusion_list); + + AwBrowserContext::GetDefault()->GetAwURLRequestContext()->SetProxyOverride( + host, port, exclusion_list); +} + +// static +void JNI_AwContentsStatics_ClearProxyOverride(JNIEnv* env, + const JavaParamRef<jclass>&) { + AwBrowserContext::GetDefault() + ->GetAwURLRequestContext() + ->ClearProxyOverride(); +} + } // namespace android_webview
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc index f1f222e..249176a1 100644 --- a/android_webview/browser/aw_permission_manager.cc +++ b/android_webview/browser/aw_permission_manager.cc
@@ -448,8 +448,8 @@ int AwPermissionManager::SubscribePermissionStatusChange( PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(PermissionStatus)>& callback) { return content::PermissionController::kNoPendingOperation; }
diff --git a/android_webview/browser/aw_permission_manager.h b/android_webview/browser/aw_permission_manager.h index 06c94e783..d6ab44a 100644 --- a/android_webview/browser/aw_permission_manager.h +++ b/android_webview/browser/aw_permission_manager.h
@@ -52,8 +52,8 @@ const GURL& requesting_origin) override; int SubscribePermissionStatusChange( content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void UnsubscribePermissionStatusChange(int subscription_id) override;
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index 0b25146..9d28b87 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -51,6 +51,7 @@ #include "net/log/net_log_capture_mode.h" #include "net/log/net_log_util.h" #include "net/net_buildflags.h" +#include "net/proxy_resolution/proxy_config_service_android.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/socket/next_proto.h" #include "net/ssl/channel_id_service.h" @@ -205,7 +206,7 @@ AwURLRequestContextGetter::AwURLRequestContextGetter( const base::FilePath& cache_path, const base::FilePath& channel_id_path, - std::unique_ptr<net::ProxyConfigService> config_service, + std::unique_ptr<net::ProxyConfigServiceAndroid> config_service, PrefService* user_pref_service, net::NetLog* net_log) : cache_path_(cache_path), @@ -421,4 +422,15 @@ auth_android_negotiate_account_type_.GetValue()); } +void AwURLRequestContextGetter::SetProxyOverride( + const std::string& host, + int port, + const std::vector<std::string>& exclusion_list) { + proxy_config_service_->SetProxyOverride(host, port, exclusion_list); +} + +void AwURLRequestContextGetter::ClearProxyOverride() { + proxy_config_service_->ClearProxyOverride(); +} + } // namespace android_webview
diff --git a/android_webview/browser/net/aw_url_request_context_getter.h b/android_webview/browser/net/aw_url_request_context_getter.h index e7f331f9..792c0de 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.h +++ b/android_webview/browser/net/aw_url_request_context_getter.h
@@ -27,6 +27,7 @@ class HttpAuthPreferences; class HttpUserAgentSettings; class NetLog; +class ProxyConfigServiceAndroid; class ProxyConfigService; class URLRequestContext; class URLRequestJobFactory; @@ -39,7 +40,7 @@ AwURLRequestContextGetter( const base::FilePath& cache_path, const base::FilePath& channel_id_path, - std::unique_ptr<net::ProxyConfigService> config_service, + std::unique_ptr<net::ProxyConfigServiceAndroid> config_service, PrefService* pref_service, net::NetLog* net_log); @@ -51,6 +52,12 @@ scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; + // Methods to set and clear proxy override + void SetProxyOverride(const std::string& host, + int port, + const std::vector<std::string>& exclusion_list); + void ClearProxyOverride(); + private: friend class AwBrowserContext; friend class AwURLRequestContextGetterTest; @@ -81,7 +88,7 @@ const base::FilePath channel_id_path_; net::NetLog* net_log_; - std::unique_ptr<net::ProxyConfigService> proxy_config_service_; + std::unique_ptr<net::ProxyConfigServiceAndroid> proxy_config_service_; std::unique_ptr<net::URLRequestJobFactory> job_factory_; std::unique_ptr<net::HttpUserAgentSettings> http_user_agent_settings_; std::unique_ptr<net::FileNetLogObserver> file_net_log_observer_;
diff --git a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc index 3b77941..eb990c8 100644 --- a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc +++ b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
@@ -16,6 +16,7 @@ #include "net/base/net_errors.h" #include "net/log/net_log.h" #include "net/proxy_resolution/proxy_config_service.h" +#include "net/proxy_resolution/proxy_config_service_android.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/ssl/ssl_config.h" #include "net/ssl/ssl_config_service.h" @@ -57,12 +58,16 @@ android_webview::AwURLRequestContextGetter::RegisterPrefs( pref_service_->registry()); - getter_ = base::MakeRefCounted<android_webview::AwURLRequestContextGetter>( - temp_dir_.GetPath(), temp_dir_.GetPath().AppendASCII("ChannelID"), + std::unique_ptr<net::ProxyConfigServiceAndroid> config_service_android; + config_service_android.reset(static_cast<net::ProxyConfigServiceAndroid*>( net::ProxyResolutionService::CreateSystemProxyConfigService( content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::IO)), - pref_service_.get(), &net_log_); + content::BrowserThread::IO)) + .release())); + + getter_ = base::MakeRefCounted<android_webview::AwURLRequestContextGetter>( + temp_dir_.GetPath(), temp_dir_.GetPath().AppendASCII("ChannelID"), + std::move(config_service_android), pref_service_.get(), &net_log_); // AwURLRequestContextGetter implicitly depends on having protocol handlers // provided for url::kBlobScheme, url::kFileSystemScheme, and
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java index 656c455..7fe5fbb 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedStatics.java
@@ -117,4 +117,13 @@ return ThreadUtils.runOnUiThreadBlockingNoException( () -> AwContentsStatics.getSafeBrowsingPrivacyPolicyUrl()); } + + public void setProxyOverride(String host, int port, String[] exclusionList) { + ThreadUtils.runOnUiThread( + () -> AwContentsStatics.setProxyOverride(host, port, exclusionList)); + } + + public void clearProxyOverride() { + ThreadUtils.runOnUiThread(() -> AwContentsStatics.clearProxyOverride()); + } }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java index 2215bf06..6a12a9c 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java
@@ -120,6 +120,14 @@ nativeSetCheckClearTextPermitted(permitted); } + public static void setProxyOverride(String host, int port, String[] exclusionList) { + nativeSetProxyOverride(host, port, exclusionList); + } + + public static void clearProxyOverride() { + nativeClearProxyOverride(); + } + /** * Return the first substring consisting of the address of a physical location. * @see {@link android.webkit.WebView#findAddress(String)} @@ -146,4 +154,7 @@ private static native void nativeSetSafeBrowsingWhitelist( String[] urls, Callback<Boolean> callback); private static native void nativeSetCheckClearTextPermitted(boolean permitted); + private static native void nativeSetProxyOverride( + String host, int port, String[] exclusionList); + private static native void nativeClearProxyOverride(); }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java index d60a60dd..b3b5aac 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java
@@ -17,4 +17,6 @@ void initSafeBrowsing(Context context, ValueCallback<Boolean> callback); void setSafeBrowsingWhitelist(List<String> hosts, ValueCallback<Boolean> callback); Uri getSafeBrowsingPrivacyPolicyUrl(); + void setProxyOverride(String host, int port, String[] exclusionList); + void clearProxyOverride(); }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java index a214a6fd..5092bbe 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
@@ -124,4 +124,8 @@ // WebViewCompat.getWebChromeClient public static final String GET_WEB_CHROME_CLIENT = "GET_WEB_CHROME_CLIENT"; + + // WebViewCompat.setProxyOverride + // WebViewCompat.clearProxyOverride + public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE"; }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java index ffc88c4..76913c7e 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
@@ -62,7 +62,8 @@ Features.POST_WEB_MESSAGE, Features.WEB_MESSAGE_CALLBACK_ON_MESSAGE, Features.GET_WEB_VIEW_CLIENT, - Features.GET_WEB_CHROME_CLIENT + Features.GET_WEB_CHROME_CLIENT, + Features.PROXY_OVERRIDE }; // clang-format on @@ -110,6 +111,16 @@ public Uri getSafeBrowsingPrivacyPolicyUrl() { return mSharedStatics.getSafeBrowsingPrivacyPolicyUrl(); } + + @Override + public void setProxyOverride(String host, int port, String[] exclusionList) { + mSharedStatics.setProxyOverride(host, port, exclusionList); + } + + @Override + public void clearProxyOverride() { + mSharedStatics.clearProxyOverride(); + } } @Override
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index e47786d..9ad989d 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -263,7 +263,7 @@ "network_connect_delegate_mus.h", "new_window_controller.h", "note_taking_controller.h", - "pointer_watcher_adapter_classic.h", + "pointer_watcher_adapter.h", "policy/policy_recommendation_restorer.h", "root_window_controller.h", "root_window_settings.h", @@ -906,7 +906,7 @@ "network_connect_delegate_mus.cc", "new_window_controller.cc", "note_taking_controller.cc", - "pointer_watcher_adapter_classic.cc", + "pointer_watcher_adapter.cc", "policy/policy_recommendation_restorer.cc", "root_window_controller.cc", "root_window_settings.cc", @@ -1781,7 +1781,7 @@ "metrics/user_metrics_recorder_unittest.cc", "multi_device_setup/multi_device_notification_presenter_unittest.cc", "mus_property_mirror_ash_unittest.cc", - "pointer_watcher_adapter_classic_unittest.cc", + "pointer_watcher_adapter_unittest.cc", "policy/policy_recommendation_restorer_unittest.cc", "root_window_controller_unittest.cc", "rotator/screen_rotation_animation_unittest.cc", @@ -1818,8 +1818,8 @@ "system/date/system_info_default_view_unittest.cc", "system/enterprise/tray_enterprise_unittest.cc", "system/flag_warning/flag_warning_tray_unittest.cc", - "system/ime/tray_ime_chromeos_unittest.cc", "system/ime/ime_feature_pod_controller_unittest.cc", + "system/ime/tray_ime_chromeos_unittest.cc", "system/ime_menu/ime_menu_tray_unittest.cc", "system/keyboard_brightness/tray_keyboard_brightness_unittest.cc", "system/media_security/multi_profile_media_tray_item_unittest.cc",
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 84aad11..12749e5 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -653,7 +653,7 @@ EXPECT_TRUE(ProcessInController( ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); EXPECT_TRUE( - ProcessInController(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); + ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE))); EXPECT_TRUE(ProcessInController(ui::Accelerator( ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); @@ -663,7 +663,7 @@ ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); EXPECT_EQ(1, delegate->handle_take_screenshot_count()); EXPECT_TRUE( - ProcessInController(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); + ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE))); EXPECT_EQ(2, delegate->handle_take_screenshot_count()); EXPECT_TRUE(ProcessInController(ui::Accelerator( ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); @@ -909,9 +909,9 @@ // Others are not reserved nor preferred EXPECT_FALSE(GetController()->IsReserved( - ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); + ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE))); EXPECT_FALSE(GetController()->IsPreferred( - ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); + ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE))); EXPECT_FALSE( GetController()->IsReserved(ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE))); EXPECT_FALSE( @@ -1119,7 +1119,7 @@ EXPECT_TRUE(ProcessInController( ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); EXPECT_TRUE( - ProcessInController(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); + ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE))); EXPECT_TRUE(ProcessInController(ui::Accelerator( ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN))); delegate->set_can_take_screenshot(true); @@ -1128,7 +1128,7 @@ ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN))); EXPECT_EQ(1, delegate->handle_take_screenshot_count()); EXPECT_TRUE( - ProcessInController(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE))); + ProcessInController(ui::Accelerator(ui::VKEY_SNAPSHOT, ui::EF_NONE))); EXPECT_EQ(2, delegate->handle_take_screenshot_count()); EXPECT_TRUE(ProcessInController(ui::Accelerator( ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
diff --git a/ash/accelerators/accelerator_filter_unittest.cc b/ash/accelerators/accelerator_filter_unittest.cc index 5c26a67..85d17bc 100644 --- a/ash/accelerators/accelerator_filter_unittest.cc +++ b/ash/accelerators/accelerator_filter_unittest.cc
@@ -35,10 +35,11 @@ ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); // AcceleratorController calls ScreenshotDelegate::HandleTakeScreenshot() when - // VKEY_PRINT is pressed. See kAcceleratorData[] in accelerator_controller.cc. - generator.PressKey(ui::VKEY_PRINT, 0); + // VKEY_SNAPSHOT is pressed. See kAcceleratorData[] in + // accelerator_controller.cc. + generator.PressKey(ui::VKEY_SNAPSHOT, 0); EXPECT_EQ(1, delegate->handle_take_screenshot_count()); - generator.ReleaseKey(ui::VKEY_PRINT, 0); + generator.ReleaseKey(ui::VKEY_SNAPSHOT, 0); EXPECT_EQ(1, delegate->handle_take_screenshot_count()); } @@ -55,9 +56,9 @@ // AcceleratorFilter should ignore the key events since the root window is // not focused. ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - generator.PressKey(ui::VKEY_PRINT, 0); + generator.PressKey(ui::VKEY_SNAPSHOT, 0); EXPECT_EQ(0, delegate->handle_take_screenshot_count()); - generator.ReleaseKey(ui::VKEY_PRINT, 0); + generator.ReleaseKey(ui::VKEY_SNAPSHOT, 0); EXPECT_EQ(0, delegate->handle_take_screenshot_count()); // Reset window before |test_delegate| gets deleted. @@ -70,16 +71,16 @@ EXPECT_EQ(0, delegate->handle_take_screenshot_count()); ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - generator.PressKey(ui::VKEY_PRINT, 0); + generator.PressKey(ui::VKEY_SNAPSHOT, 0); EXPECT_EQ(1, delegate->handle_take_screenshot_count()); - generator.ReleaseKey(ui::VKEY_PRINT, 0); + generator.ReleaseKey(ui::VKEY_SNAPSHOT, 0); EXPECT_EQ(1, delegate->handle_take_screenshot_count()); // Check if AcceleratorFilter ignores the mask for Caps Lock. Note that there // is no ui::EF_ mask for Num Lock. - generator.PressKey(ui::VKEY_PRINT, ui::EF_CAPS_LOCK_ON); + generator.PressKey(ui::VKEY_SNAPSHOT, ui::EF_CAPS_LOCK_ON); EXPECT_EQ(2, delegate->handle_take_screenshot_count()); - generator.ReleaseKey(ui::VKEY_PRINT, ui::EF_CAPS_LOCK_ON); + generator.ReleaseKey(ui::VKEY_SNAPSHOT, ui::EF_CAPS_LOCK_ON); EXPECT_EQ(2, delegate->handle_take_screenshot_count()); }
diff --git a/ash/accelerators/accelerator_interactive_uitest_chromeos.cc b/ash/accelerators/accelerator_interactive_uitest_chromeos.cc index c89e71d..9055584 100644 --- a/ash/accelerators/accelerator_interactive_uitest_chromeos.cc +++ b/ash/accelerators/accelerator_interactive_uitest_chromeos.cc
@@ -155,7 +155,7 @@ EXPECT_EQ(0, screenshot_delegate->handle_take_screenshot_count()); SendKeyPressSync(ui::VKEY_MEDIA_LAUNCH_APP1, true, false, false); EXPECT_EQ(1, screenshot_delegate->handle_take_screenshot_count()); - SendKeyPressSync(ui::VKEY_PRINT, false, false, false); + SendKeyPressSync(ui::VKEY_SNAPSHOT, false, false, false); EXPECT_EQ(2, screenshot_delegate->handle_take_screenshot_count()); SendKeyPressSync(ui::VKEY_MEDIA_LAUNCH_APP1, true, true, false); EXPECT_EQ(2, screenshot_delegate->handle_take_screenshot_count());
diff --git a/ash/accelerators/accelerator_table_unittest.cc b/ash/accelerators/accelerator_table_unittest.cc index 342e11d..5c7002f 100644 --- a/ash/accelerators/accelerator_table_unittest.cc +++ b/ash/accelerators/accelerator_table_unittest.cc
@@ -16,12 +16,11 @@ namespace { -// The number of non-Search-based accelerators as of 2018-04-30. -constexpr int kNonSearchAcceleratorsNum = 88; -// The hash of non-Search-based accelerators as of 2018-04-30. -// See HashAcceleratorData(). +// The number of non-Search-based accelerators. +constexpr int kNonSearchAcceleratorsNum = 89; +// The hash of non-Search-based accelerators. See HashAcceleratorData(). constexpr char kNonSearchAcceleratorsHash[] = - "06096f5c3177fd99f7c30cfbf4b7d635"; + "1da4d0dbc648ec0f008837da1066599e"; struct Cmp { bool operator()(const AcceleratorData& lhs, const AcceleratorData& rhs) {
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 1414f2a..5c54238 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -412,12 +412,18 @@ void AppListControllerImpl::UpdateYPositionAndOpacity( int y_position_in_screen, float background_opacity) { + // Avoid changing app list opacity and position when homecher is enabled. + if (IsHomeLauncherEnabledInTabletMode()) + return; presenter_.UpdateYPositionAndOpacity(y_position_in_screen, background_opacity); } void AppListControllerImpl::EndDragFromShelf( app_list::AppListViewState app_list_state) { + // Avoid dragging app list when homecher is enabled. + if (IsHomeLauncherEnabledInTabletMode()) + return; presenter_.EndDragFromShelf(app_list_state); } @@ -461,8 +467,14 @@ void AppListControllerImpl::OnTabletModeStarted() { if (IsVisible()) { - presenter_.GetView()->OnTabletModeChanged(true); - return; + if (!presenter_.is_animating_to_close()) { + presenter_.GetView()->OnTabletModeChanged(true); + return; + } + + // The launcher is running close animation, so close it immediately before + // reshow the launcher in tablet mode. + presenter_.GetView()->GetWidget()->CloseNow(); } if (!is_home_launcher_enabled_ || !display::Display::HasInternalDisplay())
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 3732d7b2c..17533ae 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -10,6 +10,7 @@ #include "ash/app_list/views/app_list_main_view.h" #include "ash/app_list/views/app_list_view.h" #include "ash/app_list/views/search_box_view.h" +#include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/app_list/app_list_switches.h" #include "ash/public/cpp/ash_switches.h" @@ -1491,4 +1492,82 @@ EXPECT_FALSE(root_window_controller->IsContextMenuShown()); } +// Tests app list visibility when switching to tablet mode during dragging from +// shelf. +TEST_F(AppListPresenterDelegateHomeLauncherTest, + SwitchToTabletModeDuringDraggingFromShelf) { + UpdateDisplay("1080x900"); + GetAppListTestHelper()->CheckVisibility(false); + + // Drag from the shelf to show the app list. + ui::test::EventGenerator* generator = GetEventGenerator(); + const int x = 540; + const int closed_y = 890; + const int fullscreen_y = 0; + generator->MoveTouch(gfx::Point(x, closed_y)); + generator->PressTouch(); + generator->MoveTouch(gfx::Point(x, fullscreen_y)); + GetAppListTestHelper()->CheckVisibility(true); + + // Drag to shelf to close app list. + generator->MoveTouch(gfx::Point(x, closed_y)); + generator->ReleaseTouch(); + GetAppListTestHelper()->WaitUntilIdle(); + GetAppListTestHelper()->CheckVisibility(false); + + // Drag from the shelf to show the app list. + generator->MoveTouch(gfx::Point(x, closed_y)); + generator->PressTouch(); + generator->MoveTouch(gfx::Point(x, fullscreen_y)); + GetAppListTestHelper()->CheckVisibility(true); + + // Switch to tablet mode. + EnableTabletMode(true); + GetAppListTestHelper()->CheckVisibility(true); + + // Drag to shelf to try to close app list. + generator->MoveTouch(gfx::Point(x, closed_y)); + generator->ReleaseTouch(); + GetAppListTestHelper()->WaitUntilIdle(); + GetAppListTestHelper()->CheckVisibility(true); +} + +// Tests app list visibility when switching to tablet mode during dragging to +// close app list. +TEST_F(AppListPresenterDelegateHomeLauncherTest, + SwitchToTabletModeDuringDraggingToClose) { + UpdateDisplay("1080x900"); + + // Open app list. + GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId()); + GetAppListTestHelper()->CheckVisibility(true); + + // Drag to shelf to close app list. + ui::test::EventGenerator* generator = GetEventGenerator(); + const int x = 540; + const int peeking_height = + 900 - app_list::AppListConfig::instance().peeking_app_list_height(); + const int closed_y = 890; + generator->MoveTouch(gfx::Point(x, peeking_height)); + generator->PressTouch(); + generator->MoveTouch(gfx::Point(x, closed_y)); + generator->ReleaseTouch(); + GetAppListTestHelper()->WaitUntilIdle(); + GetAppListTestHelper()->CheckVisibility(false); + + // Open app list. + GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId()); + GetAppListTestHelper()->CheckVisibility(true); + + // Drag to shelf to close app list, meanwhile switch to tablet mode. + generator->MoveTouch(gfx::Point(x, peeking_height)); + generator->PressTouch(); + generator->MoveTouch(gfx::Point(x, peeking_height + 10)); + EnableTabletMode(true); + generator->MoveTouch(gfx::Point(x, closed_y)); + generator->ReleaseTouch(); + GetAppListTestHelper()->WaitUntilIdle(); + GetAppListTestHelper()->CheckVisibility(true); +} + } // namespace ash
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc index c804f6f5..9d33cb47 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.cc +++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -253,6 +253,7 @@ gfx::Transform transform; transform.Translate(-offset.x(), -offset.y()); layer->SetTransform(transform); + is_animating_to_close_ = true; { ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); @@ -318,10 +319,12 @@ // AppListPresenterImpl, ui::ImplicitAnimationObserver implementation: void AppListPresenterImpl::OnImplicitAnimationsCompleted() { - if (is_visible_) + if (is_visible_) { view_->GetWidget()->Activate(); - else + } else { view_->GetWidget()->Close(); + is_animating_to_close_ = false; + } } ////////////////////////////////////////////////////////////////////////////////
diff --git a/ash/app_list/presenter/app_list_presenter_impl.h b/ash/app_list/presenter/app_list_presenter_impl.h index 598e7071..0ce3a83 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.h +++ b/ash/app_list/presenter/app_list_presenter_impl.h
@@ -84,6 +84,8 @@ // Passes a MouseWheelEvent from the shelf to the AppListView. void ProcessMouseWheelOffset(int y_scroll_offset); + bool is_animating_to_close() const { return is_animating_to_close_; } + private: // Sets the app list view and attempts to show it. void SetView(AppListView* view); @@ -151,6 +153,9 @@ bool last_visible_ = false; int64_t last_display_id_ = display::kInvalidDisplayId; + // True if app list is running close animation. + bool is_animating_to_close_ = false; + DISALLOW_COPY_AND_ASSIGN(AppListPresenterImpl); };
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 2313117..c549ccd1 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -1024,7 +1024,8 @@ event->SetHandled(); break; case ui::ET_GESTURE_SCROLL_UPDATE: - if (is_side_shelf_) + // Avoid scrolling events for the app list in tablet mode. + if (is_side_shelf_ || IsHomeLauncherEnabledInTabletMode()) return; SetIsInDrag(true); last_fling_velocity_ = event->details().scroll_y(); @@ -1034,7 +1035,8 @@ case ui::ET_GESTURE_END: if (!is_in_drag_) break; - if (is_side_shelf_) + // Avoid scrolling events for the app list in tablet mode. + if (is_side_shelf_ || IsHomeLauncherEnabledInTabletMode()) return; SetIsInDrag(false); EndDrag(event->location()); @@ -1115,6 +1117,18 @@ return; } + if (is_in_drag_) { + SetIsInDrag(false); + DraggingLayout(); + } + + // Set fullscreen state. When current state is fullscreen, we still need to + // set it again because app list may be in dragging. + SetState(app_list_state_ == AppListViewState::HALF || + app_list_state_ == AppListViewState::FULLSCREEN_SEARCH + ? AppListViewState::FULLSCREEN_SEARCH + : AppListViewState::FULLSCREEN_ALL_APPS); + // Put app list window in corresponding container based on whether the // tablet mode is enabled. aura::Window* window = GetWidget()->GetNativeWindow(); @@ -1131,6 +1145,8 @@ // Update background blur. if (is_background_blur_enabled_) app_list_background_shield_->layer()->SetBackgroundBlur(0); + + return; } if (is_tablet_mode_ && !is_fullscreen()) {
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 5e1a98dc..a1fc57a 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -218,7 +218,7 @@ Braille and ChromeVox are enabled </message> <message name="IDS_ASH_STATUS_TRAY_USER_INFO_ACCESSIBILITY" desc="The accessibility string used for an item in user chooser that tells the user name and the mail address."> - <ph name="USERNAME">$1<ex>Jane Doe</ex></ph> <ph name="MAIL">$2<ex>janedoe@example.com</ex></ph> + <ph name="USERNAME">$1<ex>Jane Doe</ex></ph> (<ph name="MAIL">$2<ex>janedoe@example.com</ex></ph>) </message> <message name="IDS_ASH_STATUS_TRAY_SIGN_OUT" desc="The label used for the button in the status tray to sign out of the system. Should not exceed about 20 latin characters. Overflowed text is truncated with ellipsis."> Sign out
diff --git a/ash/frame/detached_title_area_renderer.cc b/ash/frame/detached_title_area_renderer.cc index cc6f1dc..0d8fea5b 100644 --- a/ash/frame/detached_title_area_renderer.cc +++ b/ash/frame/detached_title_area_renderer.cc
@@ -61,7 +61,9 @@ void CreateHeaderView(views::Widget* frame, views::Widget* detached_widget, Source source) { - HeaderView* header_view = new HeaderView(frame); + HeaderView* header_view = new HeaderView( + frame, source == Source::CLIENT ? mojom::WindowStyle::BROWSER + : mojom::WindowStyle::DEFAULT); if (source == Source::CLIENT) { // HeaderView behaves differently when the widget it is associated with is // fullscreen (HeaderView is normally the
diff --git a/ash/login/ui/scrollable_users_list_view.cc b/ash/login/ui/scrollable_users_list_view.cc index c65b3ed..63c205d 100644 --- a/ash/login/ui/scrollable_users_list_view.cc +++ b/ash/login/ui/scrollable_users_list_view.cc
@@ -258,8 +258,8 @@ SetBackgroundColor(SK_ColorTRANSPARENT); set_draw_overflow_indicator(false); - scroll_bar_ = new ScrollBar(false); - SetVerticalScrollBar(scroll_bar_); + vertical_scroll_bar_ = new ScrollBar(false); + SetVerticalScrollBar(vertical_scroll_bar_); SetHorizontalScrollBar(new ScrollBar(true)); hover_notifier_ = std::make_unique<HoverNotifier>( @@ -303,8 +303,8 @@ ScrollView::Layout(); // Update scrollbar visibility. - if (scroll_bar_) - scroll_bar_->SetThumbVisible(IsMouseHovered()); + if (vertical_scroll_bar_) + vertical_scroll_bar_->SetThumbVisible(IsMouseHovered()); } void ScrollableUsersListView::OnPaintBackground(gfx::Canvas* canvas) { @@ -321,28 +321,35 @@ // Only draw a gradient if the wallpaper is blurred. Otherwise, draw a rounded // rectangle. if (ash::Shell::Get()->wallpaper_controller()->IsWallpaperBlurred()) { - // Draws symmetrical linear gradient at the top and bottom of the view. - SkScalar view_height = render_bounds.height(); - SkScalar gradient_height = gradient_params_.height; - if (gradient_height == 0) - gradient_height = view_height; - - // Start and end point of the drawing in view space. - SkPoint in_view_coordinates[2] = {SkPoint(), - SkPoint::Make(0.f, view_height)}; - // Positions of colors to create gradient define in 0 to 1 range. - SkScalar top_gradient_end = gradient_height / view_height; - SkScalar bottom_gradient_start = 1.f - top_gradient_end; - SkScalar color_positions[4] = {0.f, top_gradient_end, bottom_gradient_start, - 1.f}; - SkColor colors[4] = {gradient_params_.color_from, gradient_params_.color_to, - gradient_params_.color_to, - gradient_params_.color_from}; - cc::PaintFlags flags; - flags.setShader(cc::PaintShader::MakeLinearGradient( - in_view_coordinates, colors, color_positions, 4, - SkShader::kClamp_TileMode)); + + // Only draw a gradient if the content can be scrolled. + if (vertical_scroll_bar_->visible()) { + // Draws symmetrical linear gradient at the top and bottom of the view. + SkScalar view_height = render_bounds.height(); + SkScalar gradient_height = gradient_params_.height; + if (gradient_height == 0) + gradient_height = view_height; + + // Start and end point of the drawing in view space. + SkPoint in_view_coordinates[2] = {SkPoint(), + SkPoint::Make(0.f, view_height)}; + // Positions of colors to create gradient define in 0 to 1 range. + SkScalar top_gradient_end = gradient_height / view_height; + SkScalar bottom_gradient_start = 1.f - top_gradient_end; + SkScalar color_positions[4] = {0.f, top_gradient_end, + bottom_gradient_start, 1.f}; + SkColor colors[4] = {gradient_params_.color_from, + gradient_params_.color_to, gradient_params_.color_to, + gradient_params_.color_from}; + + flags.setShader(cc::PaintShader::MakeLinearGradient( + in_view_coordinates, colors, color_positions, 4, + SkShader::kClamp_TileMode)); + } else { + flags.setColor(gradient_params_.color_to); + } + flags.setStyle(cc::PaintFlags::kFill_Style); canvas->DrawRect(render_bounds, flags); } else { @@ -371,7 +378,7 @@ } void ScrollableUsersListView::OnHover(bool has_hover) { - scroll_bar_->SetThumbVisible(has_hover); + vertical_scroll_bar_->SetThumbVisible(has_hover); } } // namespace ash
diff --git a/ash/login/ui/scrollable_users_list_view.h b/ash/login/ui/scrollable_users_list_view.h index ce3e79b6..587f4576 100644 --- a/ash/login/ui/scrollable_users_list_view.h +++ b/ash/login/ui/scrollable_users_list_view.h
@@ -101,7 +101,7 @@ views::BoxLayout* user_view_host_layout_ = nullptr; // Owned by ScrollView. - ScrollBar* scroll_bar_ = nullptr; + ScrollBar* vertical_scroll_bar_ = nullptr; std::vector<LoginUserView*> user_views_;
diff --git a/ash/pointer_watcher_adapter_classic.cc b/ash/pointer_watcher_adapter.cc similarity index 85% rename from ash/pointer_watcher_adapter_classic.cc rename to ash/pointer_watcher_adapter.cc index 4dabdd9e..96bbea0 100644 --- a/ash/pointer_watcher_adapter_classic.cc +++ b/ash/pointer_watcher_adapter.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/pointer_watcher_adapter_classic.h" +#include "ash/pointer_watcher_adapter.h" #include "ash/shell.h" #include "ui/aura/client/screen_position_client.h" @@ -16,15 +16,15 @@ namespace ash { -PointerWatcherAdapterClassic::PointerWatcherAdapterClassic() { +PointerWatcherAdapter::PointerWatcherAdapter() { Shell::Get()->AddPreTargetHandler(this); } -PointerWatcherAdapterClassic::~PointerWatcherAdapterClassic() { +PointerWatcherAdapter::~PointerWatcherAdapter() { Shell::Get()->RemovePreTargetHandler(this); } -void PointerWatcherAdapterClassic::AddPointerWatcher( +void PointerWatcherAdapter::AddPointerWatcher( views::PointerWatcher* watcher, views::PointerWatcherEventTypes events) { // We only allow a watcher to be added once. That is, we don't consider @@ -40,14 +40,14 @@ non_move_watchers_.AddObserver(watcher); } -void PointerWatcherAdapterClassic::RemovePointerWatcher( +void PointerWatcherAdapter::RemovePointerWatcher( views::PointerWatcher* watcher) { non_move_watchers_.RemoveObserver(watcher); move_watchers_.RemoveObserver(watcher); drag_watchers_.RemoveObserver(watcher); } -void PointerWatcherAdapterClassic::OnMouseEvent(ui::MouseEvent* event) { +void PointerWatcherAdapter::OnMouseEvent(ui::MouseEvent* event) { if (event->type() != ui::ET_MOUSE_PRESSED && event->type() != ui::ET_MOUSE_RELEASED && event->type() != ui::ET_MOUSE_MOVED && @@ -60,7 +60,7 @@ NotifyWatchers(ui::PointerEvent(*event), *event); } -void PointerWatcherAdapterClassic::OnTouchEvent(ui::TouchEvent* event) { +void PointerWatcherAdapter::OnTouchEvent(ui::TouchEvent* event) { if (event->type() != ui::ET_TOUCH_PRESSED && event->type() != ui::ET_TOUCH_RELEASED && event->type() != ui::ET_TOUCH_MOVED) @@ -70,7 +70,7 @@ NotifyWatchers(ui::PointerEvent(*event), *event); } -gfx::Point PointerWatcherAdapterClassic::GetLocationInScreen( +gfx::Point PointerWatcherAdapter::GetLocationInScreen( const ui::LocatedEvent& event) const { gfx::Point location_in_screen; if (event.type() == ui::ET_MOUSE_CAPTURE_CHANGED) { @@ -84,7 +84,7 @@ return location_in_screen; } -void PointerWatcherAdapterClassic::NotifyWatchers( +void PointerWatcherAdapter::NotifyWatchers( const ui::PointerEvent& event, const ui::LocatedEvent& original_event) { const gfx::Point screen_location(GetLocationInScreen(original_event));
diff --git a/ash/pointer_watcher_adapter_classic.h b/ash/pointer_watcher_adapter.h similarity index 81% rename from ash/pointer_watcher_adapter_classic.h rename to ash/pointer_watcher_adapter.h index a4c2f4a..43c202d 100644 --- a/ash/pointer_watcher_adapter_classic.h +++ b/ash/pointer_watcher_adapter.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 ASH_POINTER_WATCHER_ADAPTER_CLASSIC_H_ -#define ASH_POINTER_WATCHER_ADAPTER_CLASSIC_H_ +#ifndef ASH_POINTER_WATCHER_ADAPTER_H_ +#define ASH_POINTER_WATCHER_ADAPTER_H_ #include "ash/ash_export.h" #include "base/macros.h" @@ -27,12 +27,12 @@ namespace ash { -// Support for PointerWatchers in non-mus ash, implemented with a pre-target +// Support for PointerWatchers in ash, implemented with a pre-target // EventHandler on the Shell. -class ASH_EXPORT PointerWatcherAdapterClassic : public ui::EventHandler { +class ASH_EXPORT PointerWatcherAdapter : public ui::EventHandler { public: - PointerWatcherAdapterClassic(); - ~PointerWatcherAdapterClassic() override; + PointerWatcherAdapter(); + ~PointerWatcherAdapter() override; // See Shell::AddPointerWatcher() for details. void AddPointerWatcher(views::PointerWatcher* watcher, @@ -62,9 +62,9 @@ base::ObserverList<views::PointerWatcher, true> move_watchers_; base::ObserverList<views::PointerWatcher, true> drag_watchers_; - DISALLOW_COPY_AND_ASSIGN(PointerWatcherAdapterClassic); + DISALLOW_COPY_AND_ASSIGN(PointerWatcherAdapter); }; } // namespace ash -#endif // ASH_POINTER_WATCHER_ADAPTER_CLASSIC_H_ +#endif // ASH_POINTER_WATCHER_ADAPTER_H_
diff --git a/ash/pointer_watcher_adapter_classic_unittest.cc b/ash/pointer_watcher_adapter_unittest.cc similarity index 94% rename from ash/pointer_watcher_adapter_classic_unittest.cc rename to ash/pointer_watcher_adapter_unittest.cc index 82930e3..e622f2e 100644 --- a/ash/pointer_watcher_adapter_classic_unittest.cc +++ b/ash/pointer_watcher_adapter_unittest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/public/cpp/config.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ui/events/base_event_utils.h" @@ -13,7 +12,7 @@ namespace ash { -using PointerWatcherAdapterClassicTest = AshTestBase; +using PointerWatcherAdapterTest = AshTestBase; enum TestPointerCaptureEvents { NONE = 0x01, @@ -149,11 +148,7 @@ DISALLOW_COPY_AND_ASSIGN(TestHelper); }; -TEST_F(PointerWatcherAdapterClassicTest, MouseEvents) { - // Not relevant for mash. - if (Shell::GetAshConfig() == Config::MASH_DEPRECATED) - return; - +TEST_F(PointerWatcherAdapterTest, MouseEvents) { TestHelper helper; // Move: only the move and drag PointerWatcher should get the event. @@ -195,11 +190,7 @@ helper.ExpectCallCount(CAPTURE, CAPTURE, CAPTURE); } -TEST_F(PointerWatcherAdapterClassicTest, TouchEvents) { - // Not relevant for mash. - if (Shell::GetAshConfig() == Config::MASH_DEPRECATED) - return; - +TEST_F(PointerWatcherAdapterTest, TouchEvents) { TestHelper helper; // Press: all.
diff --git a/ash/public/cpp/accelerators.cc b/ash/public/cpp/accelerators.cc index 447e1a7..85abf44 100644 --- a/ash/public/cpp/accelerators.cc +++ b/ash/public/cpp/accelerators.cc
@@ -99,7 +99,12 @@ {true, ui::VKEY_BROWSER_REFRESH, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, ROTATE_WINDOW}, {true, ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, RESTORE_TAB}, + // These correspond to the "Print Screen" key, which changed from VKEY_PRINT + // to VKEY_SNAPSHOT in the XKB code used by Chrome OS in M66. The X11 code + // used when running an OS_CHROMEOS build on a Linux workstation still uses + // VKEY_PRINT: https://crbug.com/872094 {true, ui::VKEY_PRINT, ui::EF_NONE, TAKE_SCREENSHOT}, + {true, ui::VKEY_SNAPSHOT, ui::EF_NONE, TAKE_SCREENSHOT}, // On Chrome OS, Search key is mapped to LWIN. The Search key binding should // act on release instead of press when using Search as a modifier key for // extended keyboard shortcuts.
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index 42f83a2..e6e85c0 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -212,10 +212,6 @@ // panel height. The Docked Magnifier appears above the ChromeVox panel. void SetDockedMagnifierHeight(int height); - gfx::Rect keyboard_occluded_bounds() const { - return keyboard_occluded_bounds_; - } - private: class UpdateShelfObserver; friend class PanelLayoutManagerTest;
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 22d8571..6218d257 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -967,15 +967,13 @@ EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState()); // Blurred wallpaper. - ash::Shell::Get()->wallpaper_controller()->UpdateWallpaperBlur( - true /*locking*/); + ash::Shell::Get()->wallpaper_controller()->UpdateWallpaperBlur(/*blur=*/true); EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType()); // Non-blurred wallpaper. base::CommandLine::ForCurrentProcess()->AppendSwitch( ash::switches::kAshDisableLoginDimAndBlur); - ash::Shell::Get()->wallpaper_controller()->UpdateWallpaperBlur( - true /*locking*/); + ash::Shell::Get()->wallpaper_controller()->UpdateWallpaperBlur(/*blur=*/true); EXPECT_EQ(SHELF_BACKGROUND_LOGIN_NONBLURRED_WALLPAPER, GetShelfWidget()->GetBackgroundType()); }
diff --git a/ash/shell.cc b/ash/shell.cc index 4ef93d3..b2b099c 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -69,7 +69,7 @@ #include "ash/multi_device_setup/multi_device_notification_presenter.h" #include "ash/new_window_controller.h" #include "ash/note_taking_controller.h" -#include "ash/pointer_watcher_adapter_classic.h" +#include "ash/pointer_watcher_adapter.h" #include "ash/policy/policy_recommendation_restorer.h" #include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_features.h" @@ -1200,7 +1200,7 @@ // Must occur after Shell has installed its early pre-target handlers (for // example, WindowModalityController). - pointer_watcher_adapter_ = std::make_unique<PointerWatcherAdapterClassic>(); + pointer_watcher_adapter_ = std::make_unique<PointerWatcherAdapter>(); resize_shadow_controller_.reset(new ResizeShadowController()); shadow_controller_.reset(new ::wm::ShadowController(
diff --git a/ash/shell.h b/ash/shell.h index eb56c0f..9231682 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -153,7 +153,7 @@ class PartialMagnificationController; class PeripheralBatteryNotifier; class PersistentWindowController; -class PointerWatcherAdapterClassic; +class PointerWatcherAdapter; class PolicyRecommendationRestorer; class PowerButtonController; class PowerEventObserver; @@ -755,7 +755,7 @@ std::unique_ptr<MultiDeviceNotificationPresenter> multidevice_notification_presenter_; std::unique_ptr<NewWindowController> new_window_controller_; - std::unique_ptr<PointerWatcherAdapterClassic> pointer_watcher_adapter_; + std::unique_ptr<PointerWatcherAdapter> pointer_watcher_adapter_; std::unique_ptr<ResizeShadowController> resize_shadow_controller_; std::unique_ptr<SessionController> session_controller_; std::unique_ptr<NightLightController> night_light_controller_;
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index 91169b8b..33a93ec1 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -476,14 +476,8 @@ gfx::Insets anchor_insets = GetBubbleAnchor()->GetInsets(); gfx::Insets tray_bg_insets = GetInsets(); if (GetAnchorAlignment() == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) { - // TODO(blakeo): There are minor variances in padding depending on if the - // keyboard is in anchored accessibility mode or in regular mode. - const gfx::Rect keyboard_occluding_bounds = - shelf_->shelf_layout_manager()->keyboard_occluded_bounds(); - int keyboard_offset = keyboard_occluding_bounds.height(); - return gfx::Insets(-tray_bg_insets.top() - keyboard_offset, - anchor_insets.left(), -tray_bg_insets.bottom(), - anchor_insets.right()); + return gfx::Insets(-tray_bg_insets.top(), anchor_insets.left(), + -tray_bg_insets.bottom(), anchor_insets.right()); } else { return gfx::Insets(anchor_insets.top(), -tray_bg_insets.left(), anchor_insets.bottom(), -tray_bg_insets.right());
diff --git a/ash/system/tray/tray_container.cc b/ash/system/tray/tray_container.cc index f11417b0..18cdf0f 100644 --- a/ash/system/tray/tray_container.cc +++ b/ash/system/tray/tray_container.cc
@@ -9,6 +9,7 @@ #include "ash/shelf/shelf.h" #include "ash/system/tray/tray_constants.h" #include "ui/gfx/geometry/insets.h" +#include "ui/keyboard/keyboard_controller.h" #include "ui/views/border.h" #include "ui/views/layout/box_layout.h" @@ -46,6 +47,18 @@ PreferredSizeChanged(); } +gfx::Rect TrayContainer::GetAnchorBoundsInScreen() const { + if (shelf_->IsHorizontalAlignment()) { + // When the virtual keyboard is up, any anchored widgets should anchor to + // the virtual keyboard instead because it will cover the shelf. + const gfx::Rect occluded_bounds = + keyboard::KeyboardController::Get()->GetWorkspaceOccludedBounds(); + if (!occluded_bounds.IsEmpty()) + return occluded_bounds; + } + return GetBoundsInScreen(); +} + void TrayContainer::UpdateLayout() { const bool is_horizontal = shelf_->IsHorizontalAlignment();
diff --git a/ash/system/tray/tray_container.h b/ash/system/tray/tray_container.h index 1ad0dc3..e07b593 100644 --- a/ash/system/tray/tray_container.h +++ b/ash/system/tray/tray_container.h
@@ -28,6 +28,7 @@ void ChildVisibilityChanged(View* child) override; void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) override; + gfx::Rect GetAnchorBoundsInScreen() const override; private: void UpdateLayout();
diff --git a/ash/system/unified/unified_message_center_view.cc b/ash/system/unified/unified_message_center_view.cc index 969b2d1c..db5b1e71 100644 --- a/ash/system/unified/unified_message_center_view.cc +++ b/ash/system/unified/unified_message_center_view.cc
@@ -17,6 +17,7 @@ #include "ui/message_center/views/notification_control_buttons_view.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/layout/box_layout.h" +#include "ui/views/widget/widget.h" using message_center::MessageCenter; using message_center::MessageView; @@ -232,6 +233,8 @@ void UnifiedMessageCenterView::Update() { SetVisible(message_list_view_->GetNotificationCount() > 0); + if (GetWidget() && !GetWidget()->IsClosed()) + tray_controller_->OnMessageCenterVisibilityUpdated(); size_t notification_count = message_list_view_->GetNotificationCount(); // TODO(tetsui): This is O(n^2).
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc index 397e0f6..a2a78b2 100644 --- a/ash/system/unified/unified_slider_bubble_controller.cc +++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -4,6 +4,7 @@ #include "ash/system/unified/unified_slider_bubble_controller.h" +#include "ash/public/cpp/app_list/app_list_features.h" #include "ash/root_window_controller.h" #include "ash/shell.h" #include "ash/system/audio/unified_volume_slider_controller.h" @@ -12,6 +13,7 @@ #include "ash/system/status_area_widget.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/unified/unified_system_tray.h" +#include "ash/system/unified/unified_system_tray_view.h" using chromeos::CrasAudioHandler; @@ -28,6 +30,12 @@ return false; } +void ConfigureSliderViewStyle(views::View* slider_view) { + slider_view->SetBackground(UnifiedSystemTrayView::CreateBackground()); + slider_view->SetBorder( + views::CreateEmptyBorder(kUnifiedTopShortcutSpacing, 0, 0, 0)); +} + } // namespace UnifiedSliderBubbleController::UnifiedSliderBubbleController( @@ -124,6 +132,7 @@ UnifiedSliderView* slider_view = static_cast<UnifiedSliderView*>(slider_controller_->CreateView()); + ConfigureSliderViewStyle(slider_view); bubble_view_->AddChildView(slider_view); bubble_view_->Layout(); } @@ -148,14 +157,16 @@ init_params.parent_window = tray_->GetBubbleWindowContainer(); init_params.anchor_view = tray_->shelf()->GetSystemTrayAnchor()->GetBubbleAnchor(); + init_params.corner_radius = kUnifiedTrayCornerRadius; + init_params.has_shadow = false; bubble_view_ = new views::TrayBubbleView(init_params); UnifiedSliderView* slider_view = static_cast<UnifiedSliderView*>(slider_controller_->CreateView()); + ConfigureSliderViewStyle(slider_view); bubble_view_->AddChildView(slider_view); - bubble_view_->SetBorder( - views::CreateEmptyBorder(kUnifiedTopShortcutSpacing, 0, 0, 0)); - bubble_view_->set_color(kUnifiedMenuBackgroundColor); + bubble_view_->set_color(SK_ColorTRANSPARENT); + bubble_view_->layer()->SetFillsBoundsOpaquely(false); bubble_view_->set_anchor_view_insets( tray_->shelf()->GetSystemTrayAnchor()->GetBubbleAnchorInsets()); @@ -164,6 +175,11 @@ TrayBackgroundView::InitializeBubbleAnimations(bubble_widget_); bubble_view_->InitializeAndShowBubble(); + if (app_list::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 a8b242e..5b5ff822 100644 --- a/ash/system/unified/unified_slider_view.cc +++ b/ash/system/unified/unified_slider_view.cc
@@ -12,6 +12,7 @@ #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/border.h" #include "ui/views/layout/box_layout.h" +#include "ui/views/widget/widget.h" namespace ash { @@ -111,6 +112,14 @@ } void UnifiedSliderView::SetSliderValue(float value, bool by_user) { + // SetValue() calls |listener|, so we should ignore the call when the widget + // is closed, because controllers are already deleted. + // It should allow the case GetWidget() returning null, so that initial + // position can be properly set by controllers before the view is attached to + // a widget. + if (GetWidget() && GetWidget()->IsClosed()) + return; + slider_->SetValue(value); if (by_user) slider_->set_enable_accessibility_events(true);
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc index f95455e2..725292be 100644 --- a/ash/system/unified/unified_system_tray_controller.cc +++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -171,6 +171,11 @@ message_center::MessageCenter::RemoveType::NON_PINNED); } +void UnifiedSystemTrayController::OnMessageCenterVisibilityUpdated() { + if (bubble_) + bubble_->UpdateTransform(); +} + void UnifiedSystemTrayController::BeginDrag(const gfx::Point& location) { drag_init_point_ = location; was_expanded_ = IsExpanded();
diff --git a/ash/system/unified/unified_system_tray_controller.h b/ash/system/unified/unified_system_tray_controller.h index 69929aec..7f24e96 100644 --- a/ash/system/unified/unified_system_tray_controller.h +++ b/ash/system/unified/unified_system_tray_controller.h
@@ -62,6 +62,9 @@ // Called when notification removing animation is finished. Called from the // view. void OnClearAllAnimationEnded(); + // Called when message center visibility is changed. Called from the + // view. + void OnMessageCenterVisibilityUpdated(); // Handle finger dragging and expand/collapse the view. Called from view. void BeginDrag(const gfx::Point& location);
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc index 544e3fd..1f74ed5 100644 --- a/ash/system/unified/unified_system_tray_view.cc +++ b/ash/system/unified/unified_system_tray_view.cc
@@ -60,15 +60,6 @@ return view; } -std::unique_ptr<views::Background> CreateUnifiedBackground() { - return views::CreateBackgroundFromPainter( - views::Painter::CreateSolidRoundRectPainter( - app_list::features::IsBackgroundBlurEnabled() - ? kUnifiedMenuBackgroundColorWithBlur - : kUnifiedMenuBackgroundColor, - kUnifiedTrayCornerRadius)); -} - // Border applied to SystemTrayContainer and DetailedViewContainer to iminate // notification list scrolling under SystemTray part of UnifiedSystemTray. // The border paints mock notification frame behind the top corners based on @@ -120,7 +111,7 @@ SystemTrayContainer() { SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); - SetBackground(CreateUnifiedBackground()); + SetBackground(UnifiedSystemTrayView::CreateBackground()); SetBorder(std::make_unique<TopCornerBorder>()); } @@ -138,7 +129,7 @@ class DetailedViewContainer : public views::View { public: DetailedViewContainer() { - SetBackground(CreateUnifiedBackground()); + SetBackground(UnifiedSystemTrayView::CreateBackground()); SetBorder(std::make_unique<TopCornerBorder>()); } @@ -267,7 +258,7 @@ auto* layout = SetLayoutManager( std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); - SetBackground(CreateUnifiedBackground()); + SetBackground(CreateBackground()); SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); @@ -410,6 +401,16 @@ SchedulePaint(); } +// static +std::unique_ptr<views::Background> UnifiedSystemTrayView::CreateBackground() { + return views::CreateBackgroundFromPainter( + views::Painter::CreateSolidRoundRectPainter( + app_list::features::IsBackgroundBlurEnabled() + ? kUnifiedMenuBackgroundColorWithBlur + : kUnifiedMenuBackgroundColor, + kUnifiedTrayCornerRadius)); +} + void UnifiedSystemTrayView::OnGestureEvent(ui::GestureEvent* event) { gfx::Point screen_location = event->location(); ConvertPointToScreen(this, &screen_location);
diff --git a/ash/system/unified/unified_system_tray_view.h b/ash/system/unified/unified_system_tray_view.h index b089a2a..250e859 100644 --- a/ash/system/unified/unified_system_tray_view.h +++ b/ash/system/unified/unified_system_tray_view.h
@@ -99,6 +99,10 @@ // scrolling under SystemTray. |height_below_scroll| should not be negative. void SetNotificationHeightBelowScroll(int height_below_scroll); + // Create background of UnifiedSystemTray that is semi-transparent and has + // rounded corners. + static std::unique_ptr<views::Background> CreateBackground(); + // views::View: void OnGestureEvent(ui::GestureEvent* event) override; void ChildPreferredSizeChanged(views::View* child) override;
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index c69da28..ba2eccb 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -708,8 +708,8 @@ info.type == POLICY; } -void WallpaperController::UpdateWallpaperBlur(bool locking) { - bool needs_blur = locking && IsBlurEnabled(); +void WallpaperController::UpdateWallpaperBlur(bool blur) { + bool needs_blur = blur && IsBlurAllowed(); if (needs_blur == is_wallpaper_blurred_) return; @@ -732,7 +732,7 @@ switches::kAshDisableLoginDimAndBlur); } -bool WallpaperController::IsBlurEnabled() const { +bool WallpaperController::IsBlurAllowed() const { return !IsDevicePolicyWallpaper() && !base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kAshDisableLoginDimAndBlur); @@ -1441,7 +1441,7 @@ Shell::Get()->session_controller()->IsUserSessionBlocked(); bool in_overview = Shell::Get()->window_selector_controller()->IsSelecting(); bool is_wallpaper_blurred = - (session_blocked || in_overview) && IsBlurEnabled(); + (session_blocked || in_overview) && IsBlurAllowed(); if (is_wallpaper_blurred_ != is_wallpaper_blurred) { is_wallpaper_blurred_ = is_wallpaper_blurred;
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h index 04e9f02..9ae7714b 100644 --- a/ash/wallpaper/wallpaper_controller.h +++ b/ash/wallpaper/wallpaper_controller.h
@@ -159,17 +159,17 @@ // including device policy). bool IsPolicyControlled(const AccountId& account_id, bool is_ephemeral) const; - // Prepares wallpaper to lock screen transition. Will apply blur if |locking| - // is true and blur is enabled by the controller, otherwise any existing blur - // will be removed. - void UpdateWallpaperBlur(bool locking); + // Update the blurred state of the current wallpaper. Applies blur if |blur| + // is true and blur is allowed by the controller, otherwise any existing blur + // is removed. + void UpdateWallpaperBlur(bool blur); // Wallpaper should be dimmed for login, lock, OOBE and add user screens. bool ShouldApplyDimming() const; - // Returns whether blur is enabled for login, lock, OOBE and add user screens. - // See crbug.com/775591. - bool IsBlurEnabled() const; + // Returns whether the current wallpaper is allowed to be blurred. See + // https://crbug.com/775591. + bool IsBlurAllowed() const; // Returns whether the current wallpaper is blurred. bool IsWallpaperBlurred() const { return is_wallpaper_blurred_; }
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index b6451ce..f1081cd9 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -1803,7 +1803,7 @@ } TEST_F(WallpaperControllerTest, WallpaperBlur) { - ASSERT_TRUE(controller_->IsBlurEnabled()); + ASSERT_TRUE(controller_->IsBlurAllowed()); ASSERT_FALSE(controller_->IsWallpaperBlurred()); TestWallpaperControllerObserver observer; @@ -1843,7 +1843,7 @@ } TEST_F(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) { - ASSERT_TRUE(controller_->IsBlurEnabled()); + ASSERT_TRUE(controller_->IsBlurAllowed()); ASSERT_FALSE(controller_->IsWallpaperBlurred()); TestWallpaperControllerObserver observer; @@ -1876,7 +1876,7 @@ EXPECT_EQ(1, GetWallpaperCount()); EXPECT_TRUE(IsDevicePolicyWallpaper()); // Verify the device policy wallpaper shouldn't be blurred. - ASSERT_FALSE(controller_->IsBlurEnabled()); + ASSERT_FALSE(controller_->IsBlurAllowed()); ASSERT_FALSE(controller_->IsWallpaperBlurred()); // Verify the device policy wallpaper is replaced when session state is no
diff --git a/ash/wm/overview/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc index 6921bb2..b9f04db 100644 --- a/ash/wm/overview/window_selector_controller.cc +++ b/ash/wm/overview/window_selector_controller.cc
@@ -73,9 +73,9 @@ return false; } -bool IsBlurEnabled() { +bool IsBlurAllowed() { return !g_disable_wallpaper_blur_for_tests && - Shell::Get()->wallpaper_controller()->IsBlurEnabled(); + Shell::Get()->wallpaper_controller()->IsBlurAllowed(); } } // namespace @@ -260,7 +260,7 @@ window_selector_.reset(new WindowSelector(this)); Shell::Get()->NotifyOverviewModeStarting(); window_selector_->Init(windows, hide_windows); - if (IsBlurEnabled()) + if (IsBlurAllowed()) overview_blur_controller_->Blur(); OnSelectionStarted(); } @@ -401,7 +401,7 @@ if (is_shutting_down_) return; - if (IsBlurEnabled()) + if (IsBlurAllowed()) overview_blur_controller_->Unblur(); is_shutting_down_ = true; Shell::Get()->NotifyOverviewModeEnding();
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index dea2fc5..16caca96 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -2529,4 +2529,44 @@ EXPECT_TRUE(shelf_layout_manager->IsVisible()); } +// Tests that the app drag will be reverted if the screen is being rotated. +TEST_F(SplitViewAppDraggingTest, DisplayConfigurationChangeTest) { + UpdateDisplay("800x600"); + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + display::DisplayManager* display_manager = Shell::Get()->display_manager(); + display::test::ScopedSetInternalDisplayId set_internal(display_manager, + display_id); + ScreenOrientationControllerTestApi test_api( + Shell::Get()->screen_orientation_controller()); + // Set the screen orientation to LANDSCAPE_PRIMARY. + test_api.SetDisplayRotation(display::Display::ROTATE_0, + display::Display::RotationSource::ACTIVE); + EXPECT_EQ(test_api.GetCurrentOrientation(), + OrientationLockType::kLandscapePrimary); + + std::unique_ptr<aura::Window> window = CreateTestWindowWithWidget(); + EXPECT_TRUE(wm::GetWindowState(window.get())->IsMaximized()); + gfx::Rect display_bounds = + split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window.get()); + + // Start to drag the window long enough to snap. + const float long_scroll_delta = display_bounds.height() / 4 + 5; + base::TimeTicks timestamp = base::TimeTicks::Now(); + SendScrollStartAndUpdate(gfx::Point(0, 0), long_scroll_delta, timestamp, + window.get()); + WindowSelectorController* window_selector_controller = + Shell::Get()->window_selector_controller(); + EXPECT_TRUE(window_selector_controller->IsSelecting()); + EXPECT_TRUE(wm::GetWindowState(window.get())->is_dragged()); + + // Rotate the screen during drag. + test_api.SetDisplayRotation(display::Display::ROTATE_270, + display::Display::RotationSource::ACTIVE); + EXPECT_EQ(test_api.GetCurrentOrientation(), + OrientationLockType::kPortraitPrimary); + EXPECT_TRUE(wm::GetWindowState(window.get())->IsMaximized()); + EXPECT_FALSE(window_selector_controller->IsSelecting()); + EXPECT_FALSE(wm::GetWindowState(window.get())->is_dragged()); +} + } // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.cc b/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.cc index 0d2c414..167f56b 100644 --- a/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.cc +++ b/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.cc
@@ -53,13 +53,17 @@ } // namespace TabletModeAppWindowDragController::TabletModeAppWindowDragController() - : drag_delegate_(std::make_unique<TabletModeAppWindowDragDelegate>()) {} + : drag_delegate_(std::make_unique<TabletModeAppWindowDragDelegate>()) { + display::Screen::GetScreen()->AddObserver(this); +} -TabletModeAppWindowDragController::~TabletModeAppWindowDragController() = - default; +TabletModeAppWindowDragController::~TabletModeAppWindowDragController() { + display::Screen::GetScreen()->RemoveObserver(this); +} bool TabletModeAppWindowDragController::DragWindowFromTop( ui::GestureEvent* event) { + previous_location_in_screen_ = GetEventLocationInScreen(event); if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) return StartWindowDrag(event); @@ -114,4 +118,21 @@ drag_delegate_->EndWindowDrag(result, GetEventLocationInScreen(event)); } +void TabletModeAppWindowDragController::OnDisplayMetricsChanged( + const display::Display& display, + uint32_t metrics) { + if (!drag_delegate_->dragged_window() || !(metrics & DISPLAY_METRIC_ROTATION)) + return; + + display::Display current_display = + display::Screen::GetScreen()->GetDisplayNearestWindow( + drag_delegate_->dragged_window()); + if (display.id() != current_display.id()) + return; + + drag_delegate_->EndWindowDrag( + wm::WmToplevelWindowEventHandler::DragResult::REVERT, + previous_location_in_screen_); +} + } // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h b/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h index f745936..a0a13a2 100644 --- a/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h +++ b/ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h
@@ -7,6 +7,7 @@ #include "ash/ash_export.h" #include "ash/wm/wm_toplevel_window_event_handler.h" +#include "ui/display/display_observer.h" namespace ui { class GestureEvent; @@ -17,13 +18,14 @@ // Handles app windows dragging in tablet mode. App windows can be dragged into // splitscreen through swiping from the top of the screen in tablet mode. -class ASH_EXPORT TabletModeAppWindowDragController { +class ASH_EXPORT TabletModeAppWindowDragController + : public display::DisplayObserver { public: // Threshold of the fling velocity to drop the window into overview. static constexpr float kFlingToOverviewThreshold = 100.0f; TabletModeAppWindowDragController(); - ~TabletModeAppWindowDragController(); + ~TabletModeAppWindowDragController() override; // Processes a gesture event and updates the transform of |dragged_window_|. // Returns true if the gesture has been handled and it should not be processed @@ -38,7 +40,12 @@ void EndWindowDrag(ui::GestureEvent* event, wm::WmToplevelWindowEventHandler::DragResult result); + // display::DisplayObserver: + void OnDisplayMetricsChanged(const display::Display& display, + uint32_t metrics) override; + std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_; + gfx::Point previous_location_in_screen_; DISALLOW_COPY_AND_ASSIGN(TabletModeAppWindowDragController); };
diff --git a/base/BUILD.gn b/base/BUILD.gn index 9a0e580..bb9ba9f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2423,6 +2423,7 @@ "test/metrics/user_action_tester_unittest.cc", "test/mock_callback_unittest.cc", "test/scoped_feature_list_unittest.cc", + "test/scoped_mock_clock_override_unittest.cc", "test/scoped_mock_time_message_loop_task_runner_unittest.cc", "test/scoped_task_environment_unittest.cc", "test/test_mock_time_task_runner_unittest.cc",
diff --git a/base/android/jni_generator/jni_exception_list.gni b/base/android/jni_generator/jni_exception_list.gni index 11c7f6a..31d027ca 100644 --- a/base/android/jni_generator/jni_exception_list.gni +++ b/base/android/jni_generator/jni_exception_list.gni
@@ -9,5 +9,5 @@ # Exclude it from JNI registration if VR is not enabled. if (!enable_vr) { - jni_exception_files += [ "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java" ] + jni_exception_files += [ "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java" ] }
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index 62ee862..12812a5 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py
@@ -294,8 +294,6 @@ content = h2.Generate() for k in jni_registration_generator.MERGEABLE_KEYS: content[k] = content.get(k, '') - content['HEADER_GUARD'] = 'HEADER_GUARD' - content['NAMESPACE'] = 'test' self.assertGoldenTextEquals( jni_registration_generator.CreateFromDict(content), @@ -385,8 +383,6 @@ content = h2.Generate() for k in jni_registration_generator.MERGEABLE_KEYS: content[k] = content.get(k, '') - content['HEADER_GUARD'] = 'HEADER_GUARD' - content['NAMESPACE'] = 'test' self.assertGoldenTextEquals( jni_registration_generator.CreateFromDict(content),
diff --git a/base/android/jni_generator/jni_registration_generator.py b/base/android/jni_generator/jni_registration_generator.py index 44f97df..d4fb39a 100755 --- a/base/android/jni_generator/jni_registration_generator.py +++ b/base/android/jni_generator/jni_registration_generator.py
@@ -12,7 +12,6 @@ import argparse import jni_generator import multiprocessing -import os import string import sys from util import build_utils @@ -55,10 +54,6 @@ for key in MERGEABLE_KEYS: combined_dict[key] = ''.join(d.get(key, '') for d in results) - combined_dict['HEADER_GUARD'] = \ - os.path.splitext(output_file)[0].replace('/', '_').upper() + '_' - combined_dict['NAMESPACE'] = args.namespace - header_content = CreateFromDict(combined_dict) if output_file: jni_generator.WriteOutput(output_file, header_content) @@ -96,8 +91,8 @@ // base/android/jni_generator/jni_registration_generator.py // Please do not change its content. -#ifndef ${HEADER_GUARD} -#define ${HEADER_GUARD} +#ifndef HEADER_GUARD +#define HEADER_GUARD #include <jni.h> @@ -118,8 +113,6 @@ ${JNI_NATIVE_METHOD} // Step 4: Main dex and non-main dex registration functions. -namespace ${NAMESPACE} { - bool RegisterMainDexNatives(JNIEnv* env) { ${REGISTER_MAIN_DEX_NATIVES} return true; @@ -130,9 +123,7 @@ return true; } -} // namespace ${NAMESPACE} - -#endif // ${HEADER_GUARD} +#endif // HEADER_GUARD """) if len(registration_dict['FORWARD_DECLARATIONS']) == 0: return '' @@ -324,13 +315,8 @@ arg_parser.add_argument('--output', help='The output file path.') arg_parser.add_argument('--no_register_java', - default=[], help='A list of Java files which should be ignored ' 'by the parser.') - arg_parser.add_argument('--namespace', - default='', - help='Namespace to wrap the registration functions ' - 'into.') args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:])) args.sources_files = build_utils.ParseGnList(args.sources_files)
diff --git a/base/android/jni_generator/testInnerClassNativesBothInnerAndOuterRegistrations.golden b/base/android/jni_generator/testInnerClassNativesBothInnerAndOuterRegistrations.golden index 1109d142..44842c3 100644 --- a/base/android/jni_generator/testInnerClassNativesBothInnerAndOuterRegistrations.golden +++ b/base/android/jni_generator/testInnerClassNativesBothInnerAndOuterRegistrations.golden
@@ -94,8 +94,6 @@ // Step 4: Main dex and non-main dex registration functions. -namespace test { - bool RegisterMainDexNatives(JNIEnv* env) { if (!RegisterNative_org_chromium_TestJni(env)) return false; @@ -108,6 +106,4 @@ return true; } -} // namespace test - #endif // HEADER_GUARD
diff --git a/base/android/jni_generator/testNativesRegistrations.golden b/base/android/jni_generator/testNativesRegistrations.golden index b3b99745..8856e05f 100644 --- a/base/android/jni_generator/testNativesRegistrations.golden +++ b/base/android/jni_generator/testNativesRegistrations.golden
@@ -160,8 +160,6 @@ // Step 4: Main dex and non-main dex registration functions. -namespace test { - bool RegisterMainDexNatives(JNIEnv* env) { if (!RegisterNative_org_chromium_TestJni(env)) return false; @@ -174,6 +172,4 @@ return true; } -} // namespace test - #endif // HEADER_GUARD
diff --git a/base/task/sequence_manager/lazily_deallocated_deque_unittest.cc b/base/task/sequence_manager/lazily_deallocated_deque_unittest.cc index 2afa048a..49f70289 100644 --- a/base/task/sequence_manager/lazily_deallocated_deque_unittest.cc +++ b/base/task/sequence_manager/lazily_deallocated_deque_unittest.cc
@@ -4,7 +4,7 @@ #include "base/task/sequence_manager/lazily_deallocated_deque.h" -#include "base/time/time_override.h" +#include "base/test/scoped_mock_clock_override.h" #include "testing/gmock/include/gmock/gmock.h" namespace base { @@ -162,13 +162,8 @@ EXPECT_EQ(LazilyDeallocatedDeque<int>::kMinimumRingSize, d.capacity()); } -namespace { -TimeTicks fake_now; -} - TEST_F(LazilyDeallocatedDequeTest, MaybeShrinkQueueRateLimiting) { - subtle::ScopedTimeClockOverrides time_overrides( - nullptr, []() { return fake_now; }, nullptr); + ScopedMockClockOverride clock; LazilyDeallocatedDeque<int> d; for (int i = 0; i < 1000; i++) { @@ -211,8 +206,8 @@ EXPECT_EQ(901u, d.capacity()); // After time passes we re-sample max_size. - fake_now += TimeDelta::FromSeconds( - LazilyDeallocatedDeque<int>::kMinimumShrinkIntervalInSeconds); + clock.Advance(TimeDelta::FromSeconds( + LazilyDeallocatedDeque<int>::kMinimumShrinkIntervalInSeconds)); d.MaybeShrinkQueue(); EXPECT_EQ(800u, d.max_size()); EXPECT_EQ(901u, d.capacity());
diff --git a/base/task/sequence_manager/sequence_manager.h b/base/task/sequence_manager/sequence_manager.h index b198189..20e9a704 100644 --- a/base/task/sequence_manager/sequence_manager.h +++ b/base/task/sequence_manager/sequence_manager.h
@@ -9,6 +9,7 @@ #include <utility> #include "base/message_loop/message_loop.h" +#include "base/message_loop/timer_slack.h" #include "base/single_thread_task_runner.h" #include "base/task/sequence_manager/task_queue_impl.h" #include "base/task/sequence_manager/task_time_observer.h" @@ -113,6 +114,10 @@ // logic at the cost of a potentially worse latency. 1 by default. virtual void SetWorkBatchSize(int work_batch_size) = 0; + // Requests desired timer precision from the OS. + // Has no effect on some platforms. + virtual void SetTimerSlack(TimerSlack timer_slack) = 0; + // Enables crash keys that can be set in the scope of a task which help // to identify the culprit if upcoming work results in a crash. // Key names must be thread-specific to avoid races and corrupted crash dumps.
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc index 4b9ed06c..3de7d1b7 100644 --- a/base/task/sequence_manager/sequence_manager_impl.cc +++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -582,6 +582,11 @@ controller_->SetWorkBatchSize(work_batch_size); } +void SequenceManagerImpl::SetTimerSlack(TimerSlack timer_slack) { + DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); + controller_->SetTimerSlack(timer_slack); +} + void SequenceManagerImpl::AddTaskObserver( MessageLoop::TaskObserver* task_observer) { DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h index ea8c53d7..f5e54ce 100644 --- a/base/task/sequence_manager/sequence_manager_impl.h +++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -114,6 +114,7 @@ void SweepCanceledDelayedTasks() override; bool GetAndClearSystemIsQuiescentBit() override; void SetWorkBatchSize(int work_batch_size) override; + void SetTimerSlack(TimerSlack timer_slack) override; void EnableCrashKeys(const char* file_name_crash_key, const char* function_name_crash_key) override; const MetricRecordingSettings& GetMetricRecordingSettings() const override;
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc index 5f007b2..9ccac1eb 100644 --- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc +++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_current.h" +#include "base/message_loop/message_pump_default.h" #include "base/optional.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" @@ -177,7 +178,8 @@ mock_clock_.Advance(TimeDelta::FromMilliseconds(1)); start_time_ = mock_clock_.NowTicks(); manager_ = SequenceManagerForTest::Create( - std::make_unique<ThreadControllerWithMessagePumpImpl>(&mock_clock_)); + std::make_unique<ThreadControllerWithMessagePumpImpl>( + std::make_unique<MessagePumpDefault>(), &mock_clock_)); // ThreadControllerWithMessagePumpImpl doesn't provide a default tas runner. scoped_refptr<TaskQueue> default_task_queue = manager_->CreateTaskQueue<TestTaskQueue>(TaskQueue::Spec("default"));
diff --git a/base/task/sequence_manager/sequence_manager_perftest.cc b/base/task/sequence_manager/sequence_manager_perftest.cc index 4bcffa8..ddc4fd4 100644 --- a/base/task/sequence_manager/sequence_manager_perftest.cc +++ b/base/task/sequence_manager/sequence_manager_perftest.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" +#include "base/message_loop/message_pump_default.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" @@ -101,6 +102,7 @@ void CreateSequenceManagerWithMessagePump() { manager_ = SequenceManagerForTest::Create( std::make_unique<internal::ThreadControllerWithMessagePumpImpl>( + std::make_unique<MessagePumpDefault>(), DefaultTickClock::GetInstance())); // ThreadControllerWithMessagePumpImpl doesn't provide a default tas runner. scoped_refptr<TaskQueue> default_task_queue =
diff --git a/base/task/sequence_manager/thread_controller.h b/base/task/sequence_manager/thread_controller.h index 0ba52d85..be31660 100644 --- a/base/task/sequence_manager/thread_controller.h +++ b/base/task/sequence_manager/thread_controller.h
@@ -5,6 +5,7 @@ #ifndef BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_H_ #define BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_H_ +#include "base/message_loop/timer_slack.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/task/sequence_manager/lazy_now.h" @@ -62,6 +63,10 @@ // Must be called before the first call to Schedule*Work(). virtual void SetSequencedTaskSource(SequencedTaskSource*) = 0; + // Requests desired timer precision from the OS. + // Has no effect on some platforms. + virtual void SetTimerSlack(TimerSlack timer_slack) = 0; + // TODO(altimin): Get rid of the methods below. // These methods exist due to current integration of SequenceManager // with MessageLoop.
diff --git a/base/task/sequence_manager/thread_controller_impl.cc b/base/task/sequence_manager/thread_controller_impl.cc index 228b34c..230e5a9 100644 --- a/base/task/sequence_manager/thread_controller_impl.cc +++ b/base/task/sequence_manager/thread_controller_impl.cc
@@ -62,6 +62,12 @@ sequence_ = sequence; } +void ThreadControllerImpl::SetTimerSlack(TimerSlack timer_slack) { + if (!message_loop_) + return; + message_loop_->SetTimerSlack(timer_slack); +} + void ThreadControllerImpl::ScheduleWork() { DCHECK(sequence_); AutoLock lock(any_sequence_lock_);
diff --git a/base/task/sequence_manager/thread_controller_impl.h b/base/task/sequence_manager/thread_controller_impl.h index 609c85c2..efa771a3 100644 --- a/base/task/sequence_manager/thread_controller_impl.h +++ b/base/task/sequence_manager/thread_controller_impl.h
@@ -42,6 +42,7 @@ void ScheduleWork() override; void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) override; void SetSequencedTaskSource(SequencedTaskSource* sequence) override; + void SetTimerSlack(TimerSlack timer_slack) override; bool RunsTasksInCurrentSequence() override; const TickClock* GetClock() override; void SetDefaultTaskRunner(scoped_refptr<SingleThreadTaskRunner>) override;
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc index 3dad1c5..9483a8d 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -5,7 +5,6 @@ #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" #include "base/auto_reset.h" -#include "base/message_loop/message_pump_default.h" #include "base/time/tick_clock.h" #include "base/trace_event/trace_event.h" @@ -14,16 +13,22 @@ namespace internal { ThreadControllerWithMessagePumpImpl::ThreadControllerWithMessagePumpImpl( + std::unique_ptr<MessagePump> message_pump, const TickClock* time_source) : associated_thread_(AssociatedThreadId::CreateUnbound()), - pump_(new MessagePumpDefault()), + pump_(std::move(message_pump)), time_source_(time_source) { + scoped_set_sequence_local_storage_map_for_current_thread_ = std::make_unique< + base::internal::ScopedSetSequenceLocalStorageMapForCurrentThread>( + &sequence_local_storage_map_); RunLoop::RegisterDelegateForCurrentThread(this); } ThreadControllerWithMessagePumpImpl::~ThreadControllerWithMessagePumpImpl() { // Destructors of RunLoop::Delegate and ThreadTaskRunnerHandle // will do all the clean-up. + // ScopedSetSequenceLocalStorageMapForCurrentThread destructor will + // de-register the current thread as a sequence. } ThreadControllerWithMessagePumpImpl::MainThreadOnly::MainThreadOnly() = default; @@ -44,34 +49,28 @@ main_thread_only().batch_size = work_batch_size; } +void ThreadControllerWithMessagePumpImpl::SetTimerSlack( + TimerSlack timer_slack) { + pump_->SetTimerSlack(timer_slack); +} + void ThreadControllerWithMessagePumpImpl::WillQueueTask( PendingTask* pending_task) { task_annotator_.WillQueueTask("ThreadController::Task", pending_task); } void ThreadControllerWithMessagePumpImpl::ScheduleWork() { - // Continuation will be posted if necessary. - if (RunsTasksInCurrentSequence() && is_doing_work()) - return; - pump_->ScheduleWork(); } void ThreadControllerWithMessagePumpImpl::SetNextDelayedDoWork( LazyNow* lazy_now, TimeTicks run_time) { - if (main_thread_only().next_delayed_work == run_time) - return; - main_thread_only().next_delayed_work = run_time; - - if (run_time == TimeTicks::Max()) - return; - - // Continuation will be posted if necessary. + // Since this method must be called on the main thread, we're probably + // inside of DoWork() except some initialization code. + // DoWork() will schedule next wake-up if necessary. if (is_doing_work()) return; - - // |lazy_now| will be removed in this method soon. DCHECK_LT(time_source_->NowTicks(), run_time); pump_->ScheduleDelayedWork(run_time); } @@ -151,9 +150,8 @@ // Need to run new work immediately. pump_->ScheduleWork(); } else if (do_work_delay != TimeDelta::Max()) { - SetNextDelayedDoWork(&lazy_now, lazy_now.Now() + do_work_delay); - } else { - SetNextDelayedDoWork(&lazy_now, TimeTicks::Max()); + // Cancels any previously scheduled delayed wake-ups. + pump_->ScheduleDelayedWork(lazy_now.Now() + do_work_delay); } return task_ran;
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.h b/base/task/sequence_manager/thread_controller_with_message_pump_impl.h index 73a942e5..d69c21f 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.h +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.h
@@ -13,6 +13,7 @@ #include "base/task/sequence_manager/sequenced_task_source.h" #include "base/task/sequence_manager/thread_controller.h" #include "base/threading/platform_thread.h" +#include "base/threading/sequence_local_storage_map.h" #include "base/threading/thread_task_runner_handle.h" namespace base { @@ -27,7 +28,8 @@ public MessagePump::Delegate, public RunLoop::Delegate { public: - explicit ThreadControllerWithMessagePumpImpl(const TickClock* time_source); + ThreadControllerWithMessagePumpImpl(std::unique_ptr<MessagePump> message_pump, + const TickClock* time_source); ~ThreadControllerWithMessagePumpImpl() override; // ThreadController implementation: @@ -36,6 +38,7 @@ void WillQueueTask(PendingTask* pending_task) override; void ScheduleWork() override; void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) override; + void SetTimerSlack(TimerSlack timer_slack) override; const TickClock* GetClock() override; bool RunsTasksInCurrentSequence() override; void SetDefaultTaskRunner( @@ -67,9 +70,6 @@ RunLoop::NestingObserver* nesting_observer = nullptr; // Not owned. std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle; - // Next delayed DoWork time for scheduling de-duplication purpose. - TimeTicks next_delayed_work; - // Indicates that we should yield DoWork ASAP. bool quit_do_work = false; @@ -102,6 +102,12 @@ debug::TaskAnnotator task_annotator_; const TickClock* time_source_; // Not owned. + // Required to register the current thread as a sequence. + base::internal::SequenceLocalStorageMap sequence_local_storage_map_; + std::unique_ptr< + base::internal::ScopedSetSequenceLocalStorageMapForCurrentThread> + scoped_set_sequence_local_storage_map_for_current_thread_; + DISALLOW_COPY_AND_ASSIGN(ThreadControllerWithMessagePumpImpl); };
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index 7f07ee0..42645bcab 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn
@@ -96,6 +96,8 @@ "scoped_environment_variable_override.h", "scoped_feature_list.cc", "scoped_feature_list.h", + "scoped_mock_clock_override.cc", + "scoped_mock_clock_override.h", "scoped_mock_time_message_loop_task_runner.cc", "scoped_mock_time_message_loop_task_runner.h", "scoped_path_override.cc",
diff --git a/base/test/scoped_mock_clock_override.cc b/base/test/scoped_mock_clock_override.cc new file mode 100644 index 0000000..46cc884 --- /dev/null +++ b/base/test/scoped_mock_clock_override.cc
@@ -0,0 +1,46 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/scoped_mock_clock_override.h" + +namespace base { + +ScopedMockClockOverride* ScopedMockClockOverride::scoped_mock_clock_ = nullptr; + +ScopedMockClockOverride::ScopedMockClockOverride() + : // Start the offset past zero so that it's not treated as a null value. + offset_(TimeDelta::FromDays(365)) { + DCHECK(!scoped_mock_clock_) + << "Nested ScopedMockClockOverrides are not supported."; + + scoped_mock_clock_ = this; + + time_clock_overrides_ = std::make_unique<subtle::ScopedTimeClockOverrides>( + &ScopedMockClockOverride::Now, &ScopedMockClockOverride::NowTicks, + &ScopedMockClockOverride::NowThreadTicks); +} + +ScopedMockClockOverride::~ScopedMockClockOverride() { + scoped_mock_clock_ = nullptr; +} + +Time ScopedMockClockOverride::Now() { + return Time() + scoped_mock_clock_->offset_; +} + +TimeTicks ScopedMockClockOverride::NowTicks() { + return TimeTicks() + scoped_mock_clock_->offset_; +} + +ThreadTicks ScopedMockClockOverride::NowThreadTicks() { + return ThreadTicks() + scoped_mock_clock_->offset_; +} + +void ScopedMockClockOverride::Advance(TimeDelta delta) { + DCHECK_GT(delta, base::TimeDelta()) + << "Monotonically increasing time may not go backwards"; + offset_ += delta; +} + +} // namespace base
diff --git a/base/test/scoped_mock_clock_override.h b/base/test/scoped_mock_clock_override.h new file mode 100644 index 0000000..c980502 --- /dev/null +++ b/base/test/scoped_mock_clock_override.h
@@ -0,0 +1,48 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TEST_SCOPED_MOCK_CLOCK_OVERRIDE_H_ +#define BASE_TEST_SCOPED_MOCK_CLOCK_OVERRIDE_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "base/time/time_override.h" + +namespace base { + +// Override the return value of Time::Now(), Time::NowFromSystemTime(), +// TimeTicks::Now(), and ThreadTicks::Now() through a simple advanceable clock. +// +// This utility is intended to support tests that: +// +// - Depend on large existing codebases that call TimeXYZ::Now() directly or +// - Have no ability to inject a TickClock into the code getting the time +// (e.g. integration tests in which a TickClock would be several layers +// removed from the test code) +// +// For new unit tests, developers are highly encouraged to structure new code +// around a dependency injected base::Clock, base::TickClock, etc. to be able +// to supply a mock time in tests without a global override. +class ScopedMockClockOverride { + public: + ScopedMockClockOverride(); + ~ScopedMockClockOverride(); + + static Time Now(); + static TimeTicks NowTicks(); + static ThreadTicks NowThreadTicks(); + + void Advance(TimeDelta delta); + + private: + std::unique_ptr<base::subtle::ScopedTimeClockOverrides> time_clock_overrides_; + TimeDelta offset_; + static ScopedMockClockOverride* scoped_mock_clock_; + + DISALLOW_COPY_AND_ASSIGN(ScopedMockClockOverride); +}; + +} // namespace base + +#endif // BASE_TEST_SCOPED_MOCK_CLOCK_OVERRIDE_H_
diff --git a/base/test/scoped_mock_clock_override_unittest.cc b/base/test/scoped_mock_clock_override_unittest.cc new file mode 100644 index 0000000..f4d22b6 --- /dev/null +++ b/base/test/scoped_mock_clock_override_unittest.cc
@@ -0,0 +1,97 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/scoped_mock_clock_override.h" + +#include "base/build_time.h" +#include "base/time/time.h" +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +namespace { + +TEST(ScopedMockClockOverrideTest, Time) { + // Choose a reference time that we know to be in the past but close to now. + Time build_time = GetBuildTime(); + + // Override is not active. All Now() methods should return a time greater than + // the build time. + EXPECT_LT(build_time, Time::Now()); + EXPECT_GT(Time::Max(), Time::Now()); + EXPECT_LT(build_time, Time::NowFromSystemTime()); + EXPECT_GT(Time::Max(), Time::NowFromSystemTime()); + + { + // Set override. + ScopedMockClockOverride mock_clock; + + EXPECT_NE(Time(), Time::Now()); + Time start = Time::Now(); + mock_clock.Advance(TimeDelta::FromSeconds(1)); + EXPECT_EQ(start + TimeDelta::FromSeconds(1), Time::Now()); + } + + // All methods return real time again. + EXPECT_LT(build_time, Time::Now()); + EXPECT_GT(Time::Max(), Time::Now()); + EXPECT_LT(build_time, Time::NowFromSystemTime()); + EXPECT_GT(Time::Max(), Time::NowFromSystemTime()); +} + +TEST(ScopedMockClockOverrideTest, TimeTicks) { + // Override is not active. All Now() methods should return a sensible value. + EXPECT_LT(TimeTicks::UnixEpoch(), TimeTicks::Now()); + EXPECT_GT(TimeTicks::Max(), TimeTicks::Now()); + EXPECT_LT(TimeTicks::UnixEpoch() + TimeDelta::FromDays(365), + TimeTicks::Now()); + + { + // Set override. + ScopedMockClockOverride mock_clock; + + EXPECT_NE(TimeTicks(), TimeTicks::Now()); + TimeTicks start = TimeTicks::Now(); + mock_clock.Advance(TimeDelta::FromSeconds(1)); + EXPECT_EQ(start + TimeDelta::FromSeconds(1), TimeTicks::Now()); + } + + // All methods return real ticks again. + EXPECT_LT(TimeTicks::UnixEpoch(), TimeTicks::Now()); + EXPECT_GT(TimeTicks::Max(), TimeTicks::Now()); + EXPECT_LT(TimeTicks::UnixEpoch() + TimeDelta::FromDays(365), + TimeTicks::Now()); +} + +TEST(ScopedMockClockOverrideTest, ThreadTicks) { + if (ThreadTicks::IsSupported()) { + ThreadTicks::WaitUntilInitialized(); + + // Override is not active. All Now() methods should return a sensible value. + ThreadTicks initial_thread_ticks = ThreadTicks::Now(); + EXPECT_LE(initial_thread_ticks, ThreadTicks::Now()); + EXPECT_GT(ThreadTicks::Max(), ThreadTicks::Now()); + EXPECT_LT(ThreadTicks(), ThreadTicks::Now()); + + { + // Set override. + ScopedMockClockOverride mock_clock; + + EXPECT_NE(ThreadTicks(), ThreadTicks::Now()); + ThreadTicks start = ThreadTicks::Now(); + mock_clock.Advance(TimeDelta::FromSeconds(1)); + EXPECT_EQ(start + TimeDelta::FromSeconds(1), ThreadTicks::Now()); + } + + // All methods return real ticks again. + EXPECT_LE(initial_thread_ticks, ThreadTicks::Now()); + EXPECT_GT(ThreadTicks::Max(), ThreadTicks::Now()); + EXPECT_LT(ThreadTicks(), ThreadTicks::Now()); + } +} + +} // namespace + +} // namespace base
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py index fdc7f092..5a61968 100755 --- a/build/android/gyp/proguard.py +++ b/build/android/gyp/proguard.py
@@ -92,10 +92,7 @@ proguard.config_exclusions(options.proguard_config_exclusions) proguard.outjar(options.output_path) - # If a jar is part of input no need to include it as library jar. - classpath = [ - p for p in set(options.classpath) if p not in options.input_paths - ] + classpath = list(set(options.classpath)) proguard.libraryjars(classpath) proguard.verbose(options.verbose) if not options.enable_dangerous_optimizations:
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 761dc18..d4339b0 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -1012,10 +1012,7 @@ else: gradle['dependent_java_projects'].append(c['path']) - # TODO(tiborg): Remove creation of JNI info for type group and java_library - # once we can generate the JNI registration based on APK / module targets as - # opposed to groups and libraries. - if is_apk_or_module_target or options.type in ('group', 'java_library'): + if is_apk_or_module_target: config['jni'] = {} all_java_sources = [c['java_sources_file'] for c in all_library_deps if 'java_sources_file' in c] @@ -1171,28 +1168,23 @@ # Deps to add to the compile-time classpath (but not the runtime classpath). # TODO(agrieve): Might be less confusing to fold these into bootclasspath. - javac_extra_jars = [c['unprocessed_jar_path'] - for c in classpath_deps.Direct('java_library')] - extra_jars = [c['jar_path'] + extra_jars = [c['unprocessed_jar_path'] for c in classpath_deps.Direct('java_library')] if options.extra_classpath_jars: # These are .jars to add to javac classpath but not to runtime classpath. - javac_extra_jars.extend( - build_utils.ParseGnList(options.extra_classpath_jars)) extra_jars.extend(build_utils.ParseGnList(options.extra_classpath_jars)) + extra_jars = [p for p in extra_jars if p not in javac_classpath] + javac_classpath.extend(extra_jars) + javac_interface_classpath.extend(extra_jars) + javac_full_interface_classpath.extend( + p for p in extra_jars if p not in javac_full_classpath) + javac_full_classpath.extend( + p for p in extra_jars if p not in javac_full_classpath) if extra_jars: deps_info['extra_classpath_jars'] = extra_jars - javac_extra_jars = [p for p in javac_extra_jars if p not in javac_classpath] - javac_classpath.extend(javac_extra_jars) - javac_interface_classpath.extend(javac_extra_jars) - javac_full_interface_classpath.extend( - p for p in javac_extra_jars if p not in javac_full_classpath) - javac_full_classpath.extend( - p for p in javac_extra_jars if p not in javac_full_classpath) - if is_java_target or options.type == 'android_app_bundle': # The classpath to use to run this target (or as an input to ProGuard). java_full_classpath = []
diff --git a/build/android/pylib/valgrind_tools.py b/build/android/pylib/valgrind_tools.py index 4c27b08..431b798 100644 --- a/build/android/pylib/valgrind_tools.py +++ b/build/android/pylib/valgrind_tools.py
@@ -4,7 +4,6 @@ # pylint: disable=R0201 -import glob import logging import os.path import subprocess @@ -12,7 +11,8 @@ from devil.android import device_errors from devil.android.valgrind_tools import base_tool -from pylib.constants import DIR_SOURCE_ROOT +from pylib import constants + def SetChromeTimeoutScale(device, scale): @@ -42,17 +42,15 @@ @classmethod def CopyFiles(cls, device): """Copies ASan tools to the device.""" - libs = glob.glob(os.path.join(DIR_SOURCE_ROOT, - 'third_party/llvm-build/Release+Asserts/', - 'lib/clang/*/lib/linux/', - 'libclang_rt.asan-arm-android.so')) - assert len(libs) == 1 + # build/config/sanitizers/BUILD.gn puts the runtime in the build dir. + lib = os.path.join(constants.GetOutDirectory(), + 'libclang_rt.asan-arm-android.so') subprocess.call( [os.path.join( - DIR_SOURCE_ROOT, + constants.DIR_SOURCE_ROOT, 'tools/android/asan/third_party/asan_device_setup.sh'), '--device', str(device), - '--lib', libs[0], + '--lib', lib, '--extra-options', AddressSanitizerTool.EXTRA_OPTIONS]) device.WaitUntilFullyBooted()
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index ab1b52f0..63f5e24 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -396,8 +396,7 @@ # target: The Apk target to generate registrations for. # output: Path to the generated .h file. # exception_files: List of .java files that should be ignored when searching - # for native methods. (optional) - # namespace: Registration functions will be wrapped into this. (optional) + # for native methods. (optional) # # Example # generate_jni_registration("chrome_jni_registration") { @@ -414,6 +413,9 @@ get_label_info(invoker.target, "name") + ".build_config" _rebased_build_config = rebase_path(_build_config, root_build_dir) + _rebase_exception_java_files = + rebase_path(invoker.exception_files, root_build_dir) + script = "//base/android/jni_generator/jni_registration_generator.py" deps = [ "${invoker.target}__build_config", @@ -431,17 +433,10 @@ "--sources_files=@FileArg($_rebased_build_config:jni:all_source)", "--output", rebase_path(invoker.output, root_build_dir), + "--no_register_java=$_rebase_exception_java_files", "--depfile", rebase_path(depfile, root_build_dir), ] - if (defined(invoker.exception_files)) { - _rebase_exception_java_files = - rebase_path(invoker.exception_files, root_build_dir) - args += [ "--no_register_java=$_rebase_exception_java_files" ] - } - if (defined(invoker.namespace)) { - args += [ "--namespace=${invoker.namespace}" ] - } } }
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index faa533b..7be37c7 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn
@@ -45,7 +45,7 @@ # ASAN is supported on iOS but the runtime library depends on the compiler # used (Chromium version of clang versus Xcode version of clang). Only copy # the ASAN runtime on iOS if building with Chromium clang. - if (is_win || is_mac || (is_ios && !use_xcode_clang)) { + if (is_android || is_mac || is_win || (is_ios && !use_xcode_clang)) { data_deps = [ ":copy_asan_runtime", ] @@ -58,8 +58,13 @@ } } -if ((is_mac || is_win || (is_ios && !use_xcode_clang)) && using_sanitizer) { - if (is_mac) { +if ((is_android || is_mac || is_win || (is_ios && !use_xcode_clang)) && + using_sanitizer) { + if (is_android) { + # All asan bots currently use 32-bit arm. + # If you change this, also change build/android/pylib/valgrind_tools.py. + _clang_rt_dso_path = "linux/libclang_rt.asan-arm-android.so" + } else if (is_mac) { _clang_rt_dso_path = "darwin/libclang_rt.asan_osx_dynamic.dylib" } else if (is_ios) { _clang_rt_dso_path = "darwin/libclang_rt.asan_iossim_dynamic.dylib" @@ -74,9 +79,14 @@ if (!is_ios) { copy("copy_asan_runtime") { + # The android runtime path contains "linux", which by default gets + # filtered out. Temporarily deactivate the filename filter. + set_sources_assignment_filter([]) sources = [ _clang_rt_dso_full_path, ] + set_sources_assignment_filter(sources_assignment_filter) + outputs = [ "$root_out_dir/{{source_file_part}}", ]
diff --git a/build/fuchsia/sdk.sha1 b/build/fuchsia/sdk.sha1 index c07c9387..a086cd7 100644 --- a/build/fuchsia/sdk.sha1 +++ b/build/fuchsia/sdk.sha1
@@ -1 +1 @@ -43e0834be00a65cd7f811ad3cb5c2528e456ec52 \ No newline at end of file +5ba2f403a63325723801c92142f788bebf37f819 \ No newline at end of file
diff --git a/cc/paint/paint_record.cc b/cc/paint/paint_record.cc index 6609e82..ac329d3 100644 --- a/cc/paint/paint_record.cc +++ b/cc/paint/paint_record.cc
@@ -9,22 +9,28 @@ namespace cc { -sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record, - const SkRect& bounds, - ImageProvider* image_provider) { +sk_sp<SkPicture> ToSkPicture( + sk_sp<PaintRecord> record, + const SkRect& bounds, + ImageProvider* image_provider, + PlaybackParams::CustomDataRasterCallback callback) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(bounds); PlaybackParams params(image_provider); + params.custom_callback = callback; record->Playback(canvas, params); return recorder.finishRecordingAsPicture(); } -sk_sp<const SkPicture> ToSkPicture(sk_sp<const PaintRecord> record, - const SkRect& bounds, - ImageProvider* image_provider) { +sk_sp<const SkPicture> ToSkPicture( + sk_sp<const PaintRecord> record, + const SkRect& bounds, + ImageProvider* image_provider, + PlaybackParams::CustomDataRasterCallback callback) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(bounds); PlaybackParams params(image_provider); + params.custom_callback = callback; record->Playback(canvas, params); return recorder.finishRecordingAsPicture(); }
diff --git a/cc/paint/paint_record.h b/cc/paint/paint_record.h index 6e0c1d7..38b878e 100644 --- a/cc/paint/paint_record.h +++ b/cc/paint/paint_record.h
@@ -21,12 +21,16 @@ CC_PAINT_EXPORT sk_sp<SkPicture> ToSkPicture( sk_sp<PaintRecord> record, const SkRect& bounds, - ImageProvider* image_provider = nullptr); + ImageProvider* image_provider = nullptr, + PlaybackParams::CustomDataRasterCallback callback = + PlaybackParams::CustomDataRasterCallback()); CC_PAINT_EXPORT sk_sp<const SkPicture> ToSkPicture( sk_sp<const PaintRecord> record, const SkRect& bounds, - ImageProvider* image_provider = nullptr); + ImageProvider* image_provider = nullptr, + PlaybackParams::CustomDataRasterCallback callback = + PlaybackParams::CustomDataRasterCallback()); } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 8373b3c..97e7aaf 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -119,6 +119,11 @@ // V1 saw errors of ~0.065 between computed window and content widths. const float kMobileViewportWidthEpsilon = 0.15f; +// We report frames and their display time to the FrameMetrics to analyze fps +// for every |kFrameMetricsScrollReportFrequency|th scroll event after the last +// report. +const int kFrameMetricsScrollReportFrequency = 10; + bool HasFixedPageScale(LayerTreeImpl* active_tree) { return active_tree->min_page_scale_factor() == active_tree->max_page_scale_factor(); @@ -1908,13 +1913,17 @@ active_tree_->GetViewportSelection(&metadata.selection); + // Skip recording frame metrics for android_webview + // (using_synchronous_renderer_compositor) scrolls because different + // application is handling frame presentation in android webview. if (active_tree_->has_presentation_callbacks() || - settings_.always_request_presentation_time) { + settings_.always_request_presentation_time || + (scroll_events_after_reporting_ == 0 && CurrentlyScrollingNode() && + !settings_.using_synchronous_renderer_compositor)) { metadata.request_presentation_feedback = true; frame_token_infos_.emplace_back(metadata.frame_token, CurrentBeginFrameArgs().frame_time, active_tree_->TakePresentationCallbacks()); - DCHECK_LE(frame_token_infos_.size(), 25u); } @@ -2522,6 +2531,7 @@ gfx::Transform surface_to_root_transform = layer->ScreenSpaceTransform(); surface_to_root_transform.Scale(SK_MScalar1 / device_scale_factor, SK_MScalar1 / device_scale_factor); + surface_to_root_transform.FlattenTo2d(); // TODO(sunxd): Avoid losing precision by not using inverse if possible. bool ok = surface_to_root_transform.GetInverse(&hit_test_region->transform); // Note: If |ok| is false, the |transform| is set to the identity before @@ -4409,6 +4419,14 @@ DistributeScrollDelta(scroll_state); browser_controls_offset_manager_->ScrollEnd(); ClearCurrentlyScrollingNode(); + + // At the end of a scrolling event, increases |scroll_events_after_reporting_| + // by 1. If it is the |kFrameMetricsScrollReportFrequency| scrolling event + // after the previous report to the frame metrics, then + // |scroll_events_after_reporting_| becomes 0 and the data will be reported + // back the frame metrics. + scroll_events_after_reporting_ = + (scroll_events_after_reporting_ + 1) % kFrameMetricsScrollReportFrequency; } void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index a910202..df5170d 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -1102,6 +1102,9 @@ ui::FrameMetrics frame_metrics_; ui::SkippedFrameTracker skipped_frame_tracker_; bool is_animating_for_snap_; + // The number of scroll events happened after the last report to frame + // metrics. + int scroll_events_after_reporting_ = 0; DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl); };
diff --git a/chrome/VERSION b/chrome/VERSION index 327b3b4..d509745 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=70 MINOR=0 -BUILD=3517 +BUILD=3518 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 6f3ab1b..0bd8aa2 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -348,6 +348,7 @@ srcjar_deps += feed_srcjar_deps if (enable_vr) { + java_files += chrome_vr_java_sources deps += [ "//device/vr:java", "//third_party/gvr-android-keyboard:kb_java", @@ -680,7 +681,6 @@ "//base:base_java_test_support", "//chrome/android:app_hooks_java", "//chrome/android:chrome_java", - "//chrome/browser/android/vr:java", "//chrome/test/android:chrome_java_test_support", "//components/policy/android:policy_java", "//content/public/android:content_java", @@ -930,11 +930,6 @@ deps = [ ":chrome_jni_registration($default_toolchain)", ] - if (enable_vr) { - sources += [ "../browser/android/vr/register_jni.cc" ] - deps += - [ "//chrome/browser/android/vr:jni_registration($default_toolchain)" ] - } } chrome_shared_library("libchromefortest") { @@ -950,11 +945,6 @@ "//components/heap_profiling:test_support", "//content/public/test/android:content_native_test_support", ] - if (enable_vr) { - sources += [ "../browser/android/vr/register_jni.cc" ] - deps += - [ "//chrome/browser/android/vr:jni_registration($default_toolchain)" ] - } } # Ensure that .pak files are built only once (build them in the default @@ -962,21 +952,21 @@ # is generated from Java code so it just needs to be generated once. if (current_toolchain == default_toolchain) { generate_jni_registration("chrome_jni_registration") { - target = ":chrome_public_base_module_java" + target = ":chrome_public_apk" output = "$root_gen_dir/chrome/browser/android/${target_name}.h" exception_files = jni_exception_files } generate_jni_registration("chrome_jni_for_test_registration") { testonly = true - target = ":chrome_public_base_module_java_for_test" + target = ":chrome_public_apk_for_test" output = "$root_gen_dir/chrome/browser/android/${target_name}.h" exception_files = jni_exception_files } generate_jni_registration("chrome_sync_shell_jni_registration") { testonly = true - target = ":chrome_sync_shell_java" + target = ":chrome_sync_shell_apk" output = "$root_gen_dir/chrome/browser/android/${target_name}.h" exception_files = jni_exception_files } @@ -1119,9 +1109,6 @@ sources = [ "../browser/android/monochrome_entry_point.cc", ] - if (enable_vr) { - sources += [ "../browser/android/vr/register_jni_monochrome.cc" ] - } deps = [ "//android_webview:common", "//chrome:chrome_android_core", @@ -1167,62 +1154,17 @@ if (chromium_linker_supported && use_lld) { configs += [ "//build/config/android:lld_pack_relocations" ] } - if (enable_vr) { - sources += [ "../browser/android/vr/register_jni.cc" ] - deps += - [ "//chrome/browser/android/vr:jni_registration($default_toolchain)" ] - } -} - -# Java libraries that go into each public chrome APK and base module. The chrome -# JNI registration is generated based on this target. -# TODO(tiborg): Remove the following three groups once we have a APK / module -# target that contain exactly the grouped java libraries. -java_group("chrome_public_base_module_java") { - deps = [ - ":app_hooks_java", - ":chrome_java", - ] -} - -# Similar to chrome_public_base_module_java but for Java libraries that go into -# the public chrome test APK. -java_group("chrome_public_base_module_java_for_test") { - testonly = true - deps = [ - ":browser_java_test_support", - ":chrome_public_base_module_java", - "//chrome/browser/android/metrics:ukm_utils_java", - "//components/heap_profiling:heap_profiling_java_test_support", - "//content/public/test/android:content_java_test_support", - "//third_party/android_tools:android_test_mock_java", - ] -} - -# Similar to chrome_public_base_module_java but for Java libraries that go into -# the chrome sync shell APK. -android_library("chrome_sync_shell_java") { - # This exists here rather than in chrome_sync_shell_test_apk for JNI - # registration to be able to find the native side functions. - java_files = [ "sync_shell/javatests/src/org/chromium/chrome/browser/sync/FakeServerHelper.java" ] - deps = [ - ":chrome_public_base_module_java", - - # This exists here because com.google.protobuf.nano is needed in tests, - # but that code is stripped out via proguard. Adding this deps adds - # usages and prevents removal of the proto code. - "//components/sync:test_support_proto_java", - "//third_party/android_protobuf:protobuf_nano_javalib", - ] } # Dependencies that are common to any chrome_public derivative targets, as well # as to chrome_sync_shell_apk. _chrome_public_and_sync_shell_shared_deps = [ + ":app_hooks_java", + ":chrome_java", ":chrome_public_apk_resources", - ":chrome_public_base_module_java", ":chrome_public_non_pak_assets", ":chrome_public_pak_assets", + "//base:base_java", ] generate_jni("test_support_jni_headers") { @@ -1361,8 +1303,13 @@ if (_add_unwind_tables_in_chrome_public_apk) { shared_library_for_unwind_asset = "chromefortest" } - deps = _chrome_public_and_sync_shell_shared_deps + - [ ":chrome_public_base_module_java_for_test" ] + deps = _chrome_public_and_sync_shell_shared_deps + [ + ":browser_java_test_support", + "//chrome/browser/android/metrics:ukm_utils_java", + "//components/heap_profiling:heap_profiling_java_test_support", + "//content/public/test/android:content_java_test_support", + "//third_party/android_tools:android_test_mock_java", + ] if (!is_java_debug) { proguard_configs = [ "//chrome/android/java/apk_for_test.flags" ] } @@ -1454,10 +1401,19 @@ apk_name = "ChromeSyncShell" shared_libraries = [ ":chrome_sync_shell" ] - deps = _chrome_public_and_sync_shell_shared_deps + [ - ":chrome_sync_shell_apk_template_resources", - ":chrome_sync_shell_java", - ] + # This exists here rather than in chrome_sync_shell_test_apk for JNI + # registration to be able to find the native side functions. + java_files = [ "sync_shell/javatests/src/org/chromium/chrome/browser/sync/FakeServerHelper.java" ] + deps = + _chrome_public_and_sync_shell_shared_deps + [ + ":chrome_sync_shell_apk_template_resources", + + # This exists here because com.google.protobuf.nano is needed in tests, + # but that code is stripped out via proguard. Adding this deps adds + # usages and prevents removal of the proto code. + "//components/sync:test_support_proto_java", + "//third_party/android_protobuf:protobuf_nano_javalib", + ] } chrome_public_test_apk_manifest =
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 353441c..44ae5f0 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -170,10 +170,6 @@ invoker.add_unwind_tables_in_apk) { deps += [ ":$_unwind_asset" ] } - - if (enable_vr) { - deps += [ "//chrome/browser/android/vr:java" ] - } } }
diff --git a/chrome/android/java/res/layout/button_preference_button.xml b/chrome/android/java/res/layout/button_preference_button.xml index d5dd9ab..46284baa 100644 --- a/chrome/android/java/res/layout/button_preference_button.xml +++ b/chrome/android/java/res/layout/button_preference_button.xml
@@ -14,5 +14,5 @@ android:layout_width="wrap_content" android:minHeight="40dp" android:focusable="false" - android:textColor="@android:color/white" + android:textAppearance="@style/WhiteButtonText" app:buttonColor="@color/pref_accent_color" />
diff --git a/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml b/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml index 37c7c4c..a8d2b40d 100644 --- a/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml +++ b/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml
@@ -63,8 +63,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/search_engine_dialog_footer" - android:textColor="@color/descriptive_text_color" - android:textSize="@dimen/text_size_medium" + android:textAppearance="@style/BlackBody" android:padding="@dimen/signin_chooser_padding" /> <!--suppress ButtonStyle --> @@ -79,9 +78,7 @@ android:paddingStart="@dimen/fre_button_padding" android:paddingEnd="@dimen/fre_button_padding" android:text="@string/ok" - android:textAllCaps="true" - android:textColor="@android:color/white" - android:textSize="14sp" + android:textAppearance="@style/WhiteButtonText" app:buttonColor="@color/light_active_color" app:buttonRaised="false" />
diff --git a/chrome/android/java/res/layout/explore_sites_category_tile_view.xml b/chrome/android/java/res/layout/experimental_explore_sites_category_tile_view.xml similarity index 100% rename from chrome/android/java/res/layout/explore_sites_category_tile_view.xml rename to chrome/android/java/res/layout/experimental_explore_sites_category_tile_view.xml
diff --git a/chrome/android/java/res/layout/explore_sites_section.xml b/chrome/android/java/res/layout/experimental_explore_sites_section.xml similarity index 100% rename from chrome/android/java/res/layout/explore_sites_section.xml rename to chrome/android/java/res/layout/experimental_explore_sites_section.xml
diff --git a/chrome/android/java/res/layout/item_chooser_dialog.xml b/chrome/android/java/res/layout/item_chooser_dialog.xml index aba9003..c0496a6 100644 --- a/chrome/android/java/res/layout/item_chooser_dialog.xml +++ b/chrome/android/java/res/layout/item_chooser_dialog.xml
@@ -20,7 +20,7 @@ android:paddingBottom="8dp" android:paddingStart="16dp" android:paddingEnd="16dp" - android:textSize="16sp" /> + android:textAppearance="@style/BlackHint1" /> <!-- The "no item found" message. --> <org.chromium.ui.widget.TextViewWithClickableSpans @@ -30,7 +30,7 @@ android:layout_marginTop="8dp" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" - android:textSize="16sp" + android:textAppearance="@style/BlackHint1" android:visibility="gone" /> <!-- A layout containing a spinning progress bar that gets replaced with a @@ -66,7 +66,7 @@ android:layout_marginTop="12dp" android:paddingStart="16dp" android:paddingEnd="16dp" - android:textSize="14sp" /> + android:textAppearance="@style/BlackBody" /> <!-- Button row. --> <org.chromium.ui.widget.ButtonCompat @@ -78,7 +78,6 @@ android:layout_marginEnd="12dp" android:paddingStart="16dp" android:paddingEnd="16dp" - android:textAllCaps="true" - android:textColor="#fff" + android:textAppearance="@style/WhiteButtonText" app:buttonColor="@color/pref_accent_color" /> </LinearLayout>
diff --git a/chrome/android/java/res/layout/navigation_popup_item.xml b/chrome/android/java/res/layout/navigation_popup_item.xml index d9b2b69c..83bd45d 100644 --- a/chrome/android/java/res/layout/navigation_popup_item.xml +++ b/chrome/android/java/res/layout/navigation_popup_item.xml
@@ -7,7 +7,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="@dimen/navigation_popup_item_height" + android:layout_height="wrap_content" android:paddingStart="@dimen/navigation_popup_default_padding" android:paddingEnd="@dimen/navigation_popup_default_padding" android:gravity="center_vertical" @@ -32,9 +32,11 @@ <TextView android:id="@+id/entry_title" + android:gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/navigation_popup_default_padding" + android:minHeight="@dimen/navigation_popup_item_height" android:textAppearance="@style/BlackTitle1" android:singleLine="true" /> </LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml index eb755b6..fe391b0d 100644 --- a/chrome/android/java/res/layout/new_tab_page_layout.xml +++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -58,8 +58,7 @@ android:gravity="center_vertical" android:inputType="text" android:singleLine="true" - android:textSize="@dimen/location_bar_url_text_size" - android:textColorHint="@color/search_box_hint" /> + android:textAppearance="@style/TextAppearance.NewTabPageSearchBoxText" /> <org.chromium.chrome.browser.widget.TintedImageView android:id="@+id/voice_search_button" android:layout_width="wrap_content" @@ -92,7 +91,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:inflatedId="@+id/explore_sites" - android:layout="@layout/explore_sites_section" /> + android:layout="@layout/experimental_explore_sites_section" /> <!-- Site suggestion tile grid placeholder --> <ViewStub
diff --git a/chrome/android/java/res/layout/page_info.xml b/chrome/android/java/res/layout/page_info.xml index cc2ef7f3..6374953 100644 --- a/chrome/android/java/res/layout/page_info.xml +++ b/chrome/android/java/res/layout/page_info.xml
@@ -29,8 +29,7 @@ android:lineSpacingExtra="6dp" android:paddingTop="16dp" android:textAlignment="viewStart" - android:textColor="@color/url_emphasis_default_text" - android:textSize="16sp"/> + android:textAppearance="@style/BlackTitle1" /> <TextView android:id="@+id/page_info_connection_summary" @@ -62,8 +61,7 @@ android:paddingEnd="@dimen/page_info_popup_button_padding_sides" android:paddingStart="@dimen/page_info_popup_button_padding_sides" android:text="@string/page_info_instant_app_button" - android:textSize="14sp" - android:textColor="@android:color/white" + android:textAppearance="@style/WhiteButtonText" app:buttonRaised="false" app:buttonColor="@color/app_banner_install_button_bg" />
diff --git a/chrome/android/java/res/layout/sad_tab.xml b/chrome/android/java/res/layout/sad_tab.xml index b79b4ac1..9c9a89e 100644 --- a/chrome/android/java/res/layout/sad_tab.xml +++ b/chrome/android/java/res/layout/sad_tab.xml
@@ -72,7 +72,7 @@ android:id="@+id/sad_tab_button" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textColor="#fff" + android:textAppearance="@style/WhiteButtonText" android:minWidth="222dp" app:buttonColor="@color/light_active_color" android:layout_gravity="end" />
diff --git a/chrome/android/java/res/layout/sync_promo_view.xml b/chrome/android/java/res/layout/sync_promo_view.xml index 18f307b..50cfb8c 100644 --- a/chrome/android/java/res/layout/sync_promo_view.xml +++ b/chrome/android/java/res/layout/sync_promo_view.xml
@@ -44,8 +44,7 @@ android:id="@+id/sign_in" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textAllCaps="true" - android:textAppearance="@style/WhiteLink" + android:textAppearance="@style/WhiteButtonText" app:buttonColor="@color/light_active_color" /> </LinearLayout>
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index f7807130..931d0ea 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -616,10 +616,14 @@ <item name="android:textAppearance">@style/BlueLink2</item> </style> - <!-- New tab page RecyclerView overscroll color --> + <!-- New Tab Page --> <style name="NewTabPageRecyclerView"> <item name="android:colorEdgeEffect" tools:targetApi="21">@color/google_grey_300</item> </style> + <style name="TextAppearance.NewTabPageSearchBoxText"> + <item name="android:textSize">@dimen/location_bar_url_text_size</item> + <item name="android:textColorHint">@color/search_box_hint</item> + </style> <!-- Modern List Item --> <style name="ListItemContainer"> @@ -771,7 +775,7 @@ <item name="android:focusable">true</item> <item name="android:textAppearance">@style/BlueButtonText1</item> <item name="android:padding">16dp</item> - </style> + </style> <!-- TODO(https://crbug.com/850138): Confirm with UX whether this should be a one-off text appearance or a pre-defined text appearance. --> <style name="TextAppearance.IncognitoNewTabLearnMoreLinkModern"> @@ -780,7 +784,6 @@ </style> <!-- Picker Dialog animations --> - <style name="PickerDialogAnimation"> <item name="android:windowEnterAnimation">@anim/design_bottom_sheet_slide_in</item> <item name="android:windowExitAnimation">@null</item>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index 437a8cb..49625ea 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -593,5 +593,6 @@ <dimen name="navigation_popup_width">312dp</dimen> <dimen name="navigation_popup_item_height">56dp</dimen> <dimen name="navigation_popup_default_padding">16dp</dimen> + <dimen name="navigation_popup_top_padding">8dp</dimen> <dimen name="navigation_popup_favicon_bg_size">36dp</dimen> </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java index 044fb8a..53b38ed4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
@@ -260,7 +260,7 @@ } private class NavigationAdapter extends BaseAdapter { - private boolean mInReverseOrder; + boolean mInReverseOrder; public void reverseOrder() { mInReverseOrder = true; @@ -299,6 +299,8 @@ } private class NewNavigationAdapter extends NavigationAdapter { + private Integer mTopPadding; + @Override public View getView(int position, View convertView, ViewGroup parent) { EntryViewHolder viewHolder; @@ -306,6 +308,7 @@ LayoutInflater inflater = LayoutInflater.from(parent.getContext()); convertView = inflater.inflate(R.layout.navigation_popup_item, parent, false); viewHolder = new EntryViewHolder(); + viewHolder.mContainer = convertView; viewHolder.mImageView = convertView.findViewById(R.id.favicon_img); viewHolder.mTextView = convertView.findViewById(R.id.entry_title); convertView.setTag(viewHolder); @@ -317,11 +320,23 @@ setViewText(entry, viewHolder.mTextView); viewHolder.mImageView.setImageBitmap(entry.getFavicon()); + if (mInReverseOrder) { + View container = viewHolder.mContainer; + if (mTopPadding == null) { + mTopPadding = container.getResources().getDimensionPixelSize( + R.dimen.navigation_popup_top_padding); + } + viewHolder.mContainer.setPadding(container.getPaddingLeft(), + position == 0 ? mTopPadding : 0, container.getPaddingRight(), + container.getPaddingBottom()); + } + return convertView; } } private static class EntryViewHolder { + View mContainer; ImageView mImageView; TextView mTextView; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryMediator.java index 78010fcd..d748af6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryMediator.java
@@ -64,6 +64,7 @@ @Override public void keyboardVisibilityChanged(boolean isShowing) { + if (isShowing) closeActiveTab(); mIsKeyboardVisible = isShowing; updateVisibility(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java new file mode 100644 index 0000000..07dd9db --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java
@@ -0,0 +1,55 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.browserservices; + +import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate; +import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate; +import org.chromium.chrome.browser.tab.Tab; + +/** + * Class to handle the state and logic for CustomTabActivity to do with Trusted Web Activities. + */ +public class TrustedWebActivityUi { + private boolean mInTrustedWebActivity; + + /** + * A {@link BrowserControlsVisibilityDelegate} that disallows showing the Browser Controls when + * we are in a Trusted Web Activity. + */ + private final BrowserControlsVisibilityDelegate mInTwaVisibilityDelegate = + new BrowserControlsVisibilityDelegate() { + @Override + public boolean canShowBrowserControls() { + return !mInTrustedWebActivity; + } + + @Override + public boolean canAutoHideBrowserControls() { + return true; + } + }; + + /** + * Gets a {@link BrowserControlsVisibilityDelegate} that will hide/show the Custom Tab toolbar + * on verification/leaving the verified origin. + */ + public BrowserControlsVisibilityDelegate getBrowserControlsVisibilityDelegate() { + return mInTwaVisibilityDelegate; + } + + /** + * Updates the UI appropriately for whether or not Trusted Web Activity mode is enabled. + */ + public void setTrustedWebActivityMode(boolean enabled, Tab tab, + BrowserStateBrowserControlsVisibilityDelegate delegate) { + mInTrustedWebActivity = enabled; + + // Force showing the controls for a bit when leaving Trusted Web Activity mode. + if (!enabled) delegate.showControlsTransient(); + + // Reflect the browser controls update in the Tab. + tab.updateFullscreenEnabledState(); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index 955f2e5f..4bc4d43 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -58,6 +58,7 @@ import org.chromium.chrome.browser.autofill_assistant.AssistantUiController; import org.chromium.chrome.browser.browserservices.BrowserSessionContentHandler; import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityUi; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.customtabs.dynamicmodule.ActivityDelegate; import org.chromium.chrome.browser.customtabs.dynamicmodule.ActivityHostImpl; @@ -66,7 +67,7 @@ import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; -import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate; +import org.chromium.chrome.browser.fullscreen.ComposedBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.gsa.GSAState; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.page_info.PageInfoController; @@ -97,7 +98,6 @@ import org.chromium.content_public.browser.NavigationEntry; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.PageTransition; -import org.chromium.ui.base.WindowAndroid; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -158,6 +158,8 @@ /** Adds and removes observers from tabs when needed. */ private final TabObserverRegistrar mTabObserverRegistrar = new TabObserverRegistrar(); + private final TrustedWebActivityUi mTrustedWebActivityUi = new TrustedWebActivityUi(); + private String mSpeculatedUrl; private boolean mUsingHiddenTab; @@ -185,27 +187,6 @@ private boolean mModuleOnResumePending; private boolean mHasSetOverlayView; - private static class CustomTabCreator extends ChromeTabCreator { - private final boolean mSupportsUrlBarHiding; - private final boolean mIsOpenedByChrome; - private final BrowserStateBrowserControlsVisibilityDelegate mVisibilityDelegate; - - public CustomTabCreator( - ChromeActivity activity, WindowAndroid nativeWindow, boolean incognito, - boolean supportsUrlBarHiding, boolean isOpenedByChrome) { - super(activity, nativeWindow, incognito); - mSupportsUrlBarHiding = supportsUrlBarHiding; - mIsOpenedByChrome = isOpenedByChrome; - mVisibilityDelegate = activity.getFullscreenManager().getBrowserVisibilityDelegate(); - } - - @Override - public TabDelegateFactory createDefaultTabDelegateFactory() { - return new CustomTabDelegateFactory( - mSupportsUrlBarHiding, mIsOpenedByChrome, mVisibilityDelegate); - } - } - private TabModelObserver mCloseActivityWhenEmptyTabModelObserver = new EmptyTabModelObserver() { @Override public void didCloseTab(int tabId, boolean incognito) { @@ -431,16 +412,26 @@ } @Override - protected Pair<CustomTabCreator, CustomTabCreator> createTabCreators() { - return Pair.create( - new CustomTabCreator( - this, getWindowAndroid(), false, - mIntentDataProvider.shouldEnableUrlBarHiding(), - mIntentDataProvider.isOpenedByChrome()), - new CustomTabCreator( - this, getWindowAndroid(), true, - mIntentDataProvider.shouldEnableUrlBarHiding(), - mIntentDataProvider.isOpenedByChrome())); + protected Pair<ChromeTabCreator, ChromeTabCreator> createTabCreators() { + return Pair.create(createTabCreator(false), createTabCreator(true)); + } + + private ChromeTabCreator createTabCreator(boolean incognito) { + return new ChromeTabCreator(this, getWindowAndroid(), incognito) { + @Override + public TabDelegateFactory createDefaultTabDelegateFactory() { + return createCustomTabDelegateFactory(); + } + }; + } + + private CustomTabDelegateFactory createCustomTabDelegateFactory() { + return new CustomTabDelegateFactory(mIntentDataProvider.shouldEnableUrlBarHiding(), + mIntentDataProvider.isOpenedByChrome(), + new ComposedBrowserControlsVisibilityDelegate( + getFullscreenManager().getBrowserVisibilityDelegate(), + mTrustedWebActivityUi.getBrowserControlsVisibilityDelegate() + )); } @Override @@ -486,10 +477,7 @@ if (mUsingHiddenTab) { TabReparentingParams params = (TabReparentingParams) AsyncTabParamsManager.remove(mMainTab.getId()); - mMainTab.attachAndFinishReparenting(this, - new CustomTabDelegateFactory(mIntentDataProvider.shouldEnableUrlBarHiding(), - mIntentDataProvider.isOpenedByChrome(), - getFullscreenManager().getBrowserVisibilityDelegate()), + mMainTab.attachAndFinishReparenting(this, createCustomTabDelegateFactory(), (params == null ? null : params.getFinalizeCallback())); } @@ -654,12 +642,7 @@ } else { tab.setAppAssociatedWith(mConnection.getClientPackageNameForSession(mSession)); } - tab.initialize( - webContents, getTabContentManager(), - new CustomTabDelegateFactory( - mIntentDataProvider.shouldEnableUrlBarHiding(), - mIntentDataProvider.isOpenedByChrome(), - getFullscreenManager().getBrowserVisibilityDelegate()), + tab.initialize(webContents, getTabContentManager(), createCustomTabDelegateFactory(), false, false); if (mIntentDataProvider.shouldEnableEmbeddedMediaExperience()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java index 6d26fed..ef8894ea 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
@@ -18,7 +18,6 @@ import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler; -import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.fullscreen.ComposedBrowserControlsVisibilityDelegate; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.tab.BrowserControlsVisibilityDelegate; @@ -184,7 +183,7 @@ private final boolean mShouldHideBrowserControls; private final boolean mIsOpenedByChrome; - private final BrowserStateBrowserControlsVisibilityDelegate mBrowserStateVisibilityDelegate; + private final BrowserControlsVisibilityDelegate mBrowserStateVisibilityDelegate; private ExternalNavigationDelegateImpl mNavigationDelegate; private ExternalNavigationHandler mNavigationHandler; @@ -196,7 +195,7 @@ * with browser actions (as opposed to tab state). */ public CustomTabDelegateFactory(boolean shouldHideBrowserControls, boolean isOpenedByChrome, - BrowserStateBrowserControlsVisibilityDelegate visibilityDelegate) { + BrowserControlsVisibilityDelegate visibilityDelegate) { mShouldHideBrowserControls = shouldHideBrowserControls; mIsOpenedByChrome = isOpenedByChrome; mBrowserStateVisibilityDelegate = visibilityDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryTileView.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesCategoryTileView.java similarity index 94% rename from chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryTileView.java rename to chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesCategoryTileView.java index 5806424..60bf266 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryTileView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesCategoryTileView.java
@@ -23,7 +23,7 @@ * The View representing a single explore sites category. * Consists of a large image icon over descriptive text. */ -public class ExploreSitesCategoryTileView extends LinearLayout { +public class ExperimentalExploreSitesCategoryTileView extends LinearLayout { /** The data represented by this tile. */ private ExploreSitesCategoryTile mCategoryData; @@ -37,7 +37,7 @@ private int mIconHeightPx; /** Constructor for inflating from XML. */ - public ExploreSitesCategoryTileView(Context context, AttributeSet attrs) { + public ExperimentalExploreSitesCategoryTileView(Context context, AttributeSet attrs) { super(context, attrs); mResources = context.getResources(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesSection.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesSection.java similarity index 86% rename from chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesSection.java rename to chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesSection.java index 156e8425..5165aaf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesSection.java
@@ -23,7 +23,7 @@ * Describes a portion of UI responsible for rendering a group of categories. * It abstracts general tasks related to initializing and fetching data for the UI. */ -public class ExploreSitesSection { +public class ExperimentalExploreSitesSection { private static final int MAX_TILES = 3; private Profile mProfile; @@ -31,7 +31,7 @@ private View mExploreSection; private LinearLayout mCategorySection; - public ExploreSitesSection( + public ExperimentalExploreSitesSection( View view, Profile profile, SuggestionsNavigationDelegate navigationDelegate) { mProfile = profile; mExploreSection = view; @@ -72,10 +72,11 @@ tileCount++; if (tileCount > MAX_TILES) break; - final ExploreSitesCategoryTileView tileView = - (ExploreSitesCategoryTileView) LayoutInflater.from(mExploreSection.getContext()) - .inflate(R.layout.explore_sites_category_tile_view, mCategorySection, - false); + final ExperimentalExploreSitesCategoryTileView tileView = + (ExperimentalExploreSitesCategoryTileView) LayoutInflater + .from(mExploreSection.getContext()) + .inflate(R.layout.experimental_explore_sites_category_tile_view, + mCategorySection, false); tileView.initialize(tile, tileWidth); mCategorySection.addView(tileView); @@ -88,7 +89,7 @@ } } - private void onIconRetrieved(ExploreSitesCategoryTileView tileView, Bitmap icon) { + private void onIconRetrieved(ExperimentalExploreSitesCategoryTileView tileView, Bitmap icon) { tileView.updateIcon(icon); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java index e69f8ef..1e03115 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -30,7 +30,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider; -import org.chromium.chrome.browser.explore_sites.ExploreSitesSection; +import org.chromium.chrome.browser.explore_sites.ExperimentalExploreSitesSection; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.ntp.NewTabPage.OnSearchBoxScrollListener; import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; @@ -83,7 +83,7 @@ @Nullable private View mExploreSectionView; // View is null if explore flag is disabled. @Nullable - private ExploreSitesSection mExploreSection; // Null when explore sites disabled. + private ExperimentalExploreSitesSection mExploreSection; // Null when explore sites disabled. private OnSearchBoxScrollListener mSearchBoxScrollListener; @@ -225,7 +225,7 @@ mSiteSectionViewHolder.bindDataSource(mTileGroup, tileRenderer); if (ChromeFeatureList.isEnabled(ChromeFeatureList.EXPLORE_SITES)) { - mExploreSection = new ExploreSitesSection( + mExploreSection = new ExperimentalExploreSitesSection( mExploreSectionView, profile, mManager.getNavigationDelegate()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java index cbf0c10..6ead434 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -2815,6 +2815,10 @@ if (mExperimentalButton == null) { ViewStub viewStub = findViewById(R.id.experimental_button_stub); mExperimentalButton = (TintedImageButton) viewStub.inflate(); + + if (FeatureUtilities.isBottomToolbarEnabled()) { + mExperimentalButton.setPadding(0, 0, 0, 0); + } } else { assert mExperimentalButton.getVisibility() == View.GONE : "#disableExperimentalButton() should be called first.";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java index a140c66..7b18b956 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java
@@ -4,9 +4,6 @@ package org.chromium.chrome.browser.vr; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.chrome.R; - import java.util.ArrayList; import java.util.List; @@ -14,7 +11,6 @@ * Instantiates the VR delegates. If the VR module is not available this provider will * instantiate a fallback implementation. */ -@JNINamespace("vr") public class VrModuleProvider { private static VrDelegateProvider sDelegateProvider; private static final List<VrModeObserver> sVrModeObservers = new ArrayList<>(); @@ -53,12 +49,6 @@ for (VrModeObserver observer : sVrModeObservers) observer.onExitVr(); } - // TODO(crbug.com/870055): JNI should be registered in the shared VR library's JNI_OnLoad - // function. Do this once we have a shared VR library. - /* package */ static void registerJni() { - nativeRegisterJni(); - } - private static VrDelegateProvider getDelegateProvider() { if (sDelegateProvider == null) { try { @@ -75,19 +65,4 @@ } private VrModuleProvider() {} - - // TODO(crbug/870056): Move resources into VR DFM. - private void silenceLintErrors() { - int[] res = new int[] { - R.string.vr_shell_feedback_infobar_feedback_button, - R.string.vr_shell_feedback_infobar_description, - R.string.vr_services_check_infobar_install_text, - R.string.vr_services_check_infobar_update_text, - R.string.vr_services_check_infobar_install_button, - R.string.vr_services_check_infobar_update_button, R.anim.stay_hidden, - R.drawable.vr_services, - }; - } - - private static native void nativeRegisterJni(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java index 06d07c3..58e8ff77 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
@@ -364,7 +364,6 @@ * Called when the native library is first available. */ public static void onNativeLibraryAvailable() { - VrModuleProvider.registerJni(); nativeOnLibraryAvailable(); }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 5a42d9b..d9e4848 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -168,6 +168,7 @@ "java/src/org/chromium/chrome/browser/browserservices/PostMessageHandler.java", "java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java", "java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityDisclosure.java", + "java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUi.java", "java/src/org/chromium/chrome/browser/browserservices/UkmRecorder.java", "java/src/org/chromium/chrome/browser/browserservices/VerificationState.java", "java/src/org/chromium/chrome/browser/browsing_data/UrlFilters.java", @@ -534,10 +535,10 @@ "java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java", "java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java", "java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java", + "java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesCategoryTileView.java", + "java/src/org/chromium/chrome/browser/explore_sites/ExperimentalExploreSitesSection.java", "java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBridge.java", "java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryTile.java", - "java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategoryTileView.java", - "java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesSection.java", "java/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtils.java", "java/src/org/chromium/chrome/browser/externalauth/UserRecoverableErrorHandler.java", "java/src/org/chromium/chrome/browser/externalauth/VerifiedHandler.java", @@ -1622,6 +1623,42 @@ "java/src/org/chromium/chrome/browser/widget/textbubble/TextBubble.java", ] +chrome_vr_java_sources = [ + "java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java", + "java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java", + "java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java", + "java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java", + "java/src/org/chromium/chrome/browser/vr/NoopCanvas.java", + "java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java", + "java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java", + "java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java", + "java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java", + "java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java", + "java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java", + "java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java", + "java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java", + "java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java", + "java/src/org/chromium/chrome/browser/vr/VrDialog.java", + "java/src/org/chromium/chrome/browser/vr/VrDialogManager.java", + "java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java", + "java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java", + "java/src/org/chromium/chrome/browser/vr/VrInputConnection.java", + "java/src/org/chromium/chrome/browser/vr/VrIntentUtils.java", + "java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java", + "java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java", + "java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java", + "java/src/org/chromium/chrome/browser/vr/VrShell.java", + "java/src/org/chromium/chrome/browser/vr/VrToast.java", + "java/src/org/chromium/chrome/browser/vr/VrToastManager.java", + "java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java", + "java/src/org/chromium/chrome/browser/vr/VrViewContainer.java", + "java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java", +] + chrome_test_java_sources = [ "javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java", "javatests/src/org/chromium/chrome/browser/AudioTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java index 312eb6837..a24bd02 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingIntegrationTest.java
@@ -127,6 +127,31 @@ @Test @SmallTest + public void testAccessorySheetHiddenWhenRefocusingField() + throws InterruptedException, TimeoutException { + mHelper.loadTestPage(false); + mHelper.createTestTab(); + + // Focus the field to bring up the accessory. + mHelper.clickPasswordField(); + mHelper.waitForKeyboard(); + + // Check that ONLY the accessory is there but the sheet is still hidden. + whenDisplayed(withId(R.id.keyboard_accessory)); + onView(withId(R.id.keyboard_accessory_sheet)).check(doesNotExist()); + + // Trigger the sheet and wait for it to open and the keyboard to disappear. + onView(withId(R.id.tabs)).perform(selectTabAtPosition(0)); + mHelper.waitForKeyboardToDisappear(); + whenDisplayed(withId(R.id.keyboard_accessory_sheet)); + + mHelper.clickPasswordField(); + mHelper.waitForKeyboard(); + mHelper.waitToBeHidden(withId(R.id.keyboard_accessory_sheet)); + } + + @Test + @SmallTest public void testHidingSheetBringsBackKeyboard() throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); mHelper.createTestTab();
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index c605f388..1e755d9e 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-70.0.3510.3_rc-r1.afdo.bz2 +chromeos-chrome-amd64-70.0.3517.0_rc-r1.afdo.bz2 \ No newline at end of file
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn index dc22933..279f50c 100644 --- a/chrome/app/BUILD.gn +++ b/chrome/app/BUILD.gn
@@ -6,6 +6,7 @@ import("//chrome/common/features.gni") import("//chromeos/assistant/assistant.gni") import("//components/nacl/features.gni") +import("//device/vr/buildflags/buildflags.gni") import("//ppapi/buildflags/buildflags.gni") import("//printing/buildflags/buildflags.gni") import("//services/catalog/public/tools/catalog.gni") @@ -436,6 +437,11 @@ "//chrome/services/wifi_util_win:manifest", ] } + + if (enable_isolated_xr_service) { + packaged_services += [ "//chrome/services/isolated_xr_device:manifest" ] + } + if (is_android) { packaged_services += [ ":chrome_download_manager_manifest" ] } else {
diff --git a/chrome/app/vector_icons/picture_in_picture_control_background.icon b/chrome/app/vector_icons/picture_in_picture_control_background.icon index b243eb24..cf4d0c5 100644 --- a/chrome/app/vector_icons/picture_in_picture_control_background.icon +++ b/chrome/app/vector_icons/picture_in_picture_control_background.icon
@@ -2,12 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -CANVAS_DIMENSIONS, 24, -MOVE_TO, 12, 2, -CUBIC_TO, 6.48f, 2, 2, 6.48f, 2, 12, -R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10, -R_CUBIC_TO, 5.52f, 0, 10, -4.48f, 10, -10, -CUBIC_TO_SHORTHAND, 17.52f, 2, 12, 2, -CLOSE, -R_MOVE_TO, -1, -CLOSE \ No newline at end of file +CANVAS_DIMENSIONS, 16, +CIRCLE, 8, 8, 8 \ No newline at end of file
diff --git a/chrome/app/vr_strings.grdp b/chrome/app/vr_strings.grdp index 55907e3..6e47881 100644 --- a/chrome/app/vr_strings.grdp +++ b/chrome/app/vr_strings.grdp
@@ -6,6 +6,10 @@ Press App button to exit </message> + <message name="IDS_ISOLATED_XR_PROCESS_NAME" desc="The name of the utility process used for XR compositing."> + XR Isolated Device Service + </message> + <!-- Powerful feature use and permission indicators. --> <message name="IDS_VR_SHELL_SITE_IS_TRACKING_LOCATION" desc="Text displayed in a transient bubble to inform the user that the page is tracking location."> Site is tracking your location
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 569af2c..995dff3 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4293,6 +4293,10 @@ deps += [ "//chrome/browser/vr:vr_common" ] } + if (enable_isolated_xr_service) { + deps += [ "//device/vr/public/mojom" ] + } + if (enable_wayland_server) { deps += [ "//components/exo",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 12f65817..05207e8 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -29,6 +29,7 @@ "+device/gamepad/public/cpp", "+device/usb", "+device/vr/buildflags/buildflags.h", + "+device/vr/public", "+extensions/browser", "+extensions/common", "+extensions/components/javascript_dialog_extensions_client",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 12e5e71..15560b2 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4220,6 +4220,13 @@ flag_descriptions::kSyncStandaloneTransportDescription, kOsAll, FEATURE_VALUE_TYPE(switches::kSyncStandaloneTransport)}, +#if defined(OS_CHROMEOS) + {"enable-chromevox-developer-option", + flag_descriptions::kEnableChromevoxDeveloperOptionName, + flag_descriptions::kEnableChromevoxDeveloperOptionDescription, kOsCrOS, + SINGLE_VALUE_TYPE(chromeos::switches::kEnableChromevoxDeveloperOption)}, +#endif + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/metrics/BUILD.gn b/chrome/browser/android/metrics/BUILD.gn index af1cf686e..2180062 100644 --- a/chrome/browser/android/metrics/BUILD.gn +++ b/chrome/browser/android/metrics/BUILD.gn
@@ -13,6 +13,8 @@ deps = [ "//chrome/browser:browser", "//chrome/browser/android/metrics:jni_headers", + "//components/metrics_services_manager:metrics_services_manager", + "//components/ukm:ukm", ] }
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn index 3d80b3b..2856e3b2 100644 --- a/chrome/browser/android/vr/BUILD.gn +++ b/chrome/browser/android/vr/BUILD.gn
@@ -31,7 +31,6 @@ "mailbox_to_surface_bridge.h", "metrics_util_android.cc", "metrics_util_android.h", - "register_jni.h", "scoped_gpu_trace.cc", "scoped_gpu_trace.h", "vr_controller.cc", @@ -42,7 +41,6 @@ "vr_gl_thread.h", "vr_input_connection.cc", "vr_input_connection.h", - "vr_module_provider.cc", "vr_shell.cc", "vr_shell.h", "vr_shell_delegate.cc", @@ -129,66 +127,12 @@ } } -android_library("java") { - java_files = [ - "//chrome/android/java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/NoopCanvas.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialog.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialogManager.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentUtils.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrToast.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrToastManager.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrViewContainer.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java", - ] - - classpath_deps = [ - "//base:base_java", - "//chrome/android:chrome_java", - "//components/policy/android:policy_java", - "//content/public/android:content_java", - "//third_party/android_tools:android_arch_lifecycle_common_java", - "//third_party/android_tools:android_arch_lifecycle_runtime_java", - "//third_party/android_tools:android_support_annotations_java", - "//third_party/android_tools:android_support_v7_appcompat_java", - "//third_party/gvr-android-keyboard:kb_java", - "//third_party/gvr-android-sdk:gvr_common_java", - "//ui/android:ui_full_java", - "//ui/android:ui_utils_java", - ] -} - generate_jni("vr_jni_headers") { sources = [ "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java", "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java", @@ -205,11 +149,3 @@ jni_package = "vr" } } - -if (current_toolchain == default_toolchain) { - generate_jni_registration("jni_registration") { - target = ":java" - output = "$target_gen_dir/${target_name}.h" - namespace = "vr" - } -}
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.cc b/chrome/browser/android/vr/arcore_device/arcore_device.cc index e03b990..46e5139 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_device.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_device.cc
@@ -34,9 +34,9 @@ namespace { -mojom::VRDisplayInfoPtr CreateVRDisplayInfo(uint32_t device_id) { +mojom::VRDisplayInfoPtr CreateVRDisplayInfo(mojom::XRDeviceId device_id) { mojom::VRDisplayInfoPtr device = mojom::VRDisplayInfo::New(); - device->index = device_id; + device->id = device_id; device->displayName = "ARCore VR Device"; device->capabilities = mojom::VRDisplayCapabilities::New(); device->capabilities->hasPosition = true; @@ -68,7 +68,7 @@ } // namespace ARCoreDevice::ARCoreDevice() - : VRDeviceBase(VRDeviceId::ARCORE_DEVICE_ID), + : VRDeviceBase(mojom::XRDeviceId::ARCORE_DEVICE_ID), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), mailbox_bridge_(std::make_unique<vr::MailboxToSurfaceBridge>()), weak_ptr_factory_(this) {
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc b/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc index fe9666fa6..51a4e428 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc
@@ -13,10 +13,10 @@ ARCoreDeviceProvider::~ARCoreDeviceProvider() = default; void ARCoreDeviceProvider::Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) { arcore_device_ = base::WrapUnique(new ARCoreDevice()); add_device_callback.Run(arcore_device_->GetId(),
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device_provider.h b/chrome/browser/android/vr/arcore_device/arcore_device_provider.h index 48317db..47e1f00 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_device_provider.h +++ b/chrome/browser/android/vr/arcore_device/arcore_device_provider.h
@@ -19,10 +19,10 @@ ARCoreDeviceProvider(); ~ARCoreDeviceProvider() override; void Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) override; bool Initialized() override;
diff --git a/chrome/browser/android/vr/register_jni.cc b/chrome/browser/android/vr/register_jni.cc deleted file mode 100644 index c1e87c5..0000000 --- a/chrome/browser/android/vr/register_jni.cc +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/android/vr/register_jni.h" - -#include "base/android/jni_utils.h" -#include "chrome/browser/android/vr/jni_registration.h" - -namespace vr { - -bool RegisterJni(JNIEnv* env) { - if (!base::android::IsSelectiveJniRegistrationEnabled(env) && - !vr::RegisterNonMainDexNatives(env)) { - return false; - } - if (!vr::RegisterMainDexNatives(env)) { - return false; - } - return true; -} - -} // namespace vr
diff --git a/chrome/browser/android/vr/register_jni.h b/chrome/browser/android/vr/register_jni.h deleted file mode 100644 index 63fa103..0000000 --- a/chrome/browser/android/vr/register_jni.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_ANDROID_VR_REGISTER_JNI_H_ -#define CHROME_BROWSER_ANDROID_VR_REGISTER_JNI_H_ - -#include <jni.h> - -namespace vr { - -bool RegisterJni(JNIEnv* env); - -} // namespace vr - -#endif // CHROME_BROWSER_ANDROID_VR_REGISTER_JNI_H_
diff --git a/chrome/browser/android/vr/register_jni_monochrome.cc b/chrome/browser/android/vr/register_jni_monochrome.cc deleted file mode 100644 index 24834a9..0000000 --- a/chrome/browser/android/vr/register_jni_monochrome.cc +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/android/vr/register_jni.h" - -namespace vr { - -bool RegisterJni(JNIEnv* env) { - return true; -} - -} // namespace vr
diff --git a/chrome/browser/android/vr/vr_module_provider.cc b/chrome/browser/android/vr/vr_module_provider.cc deleted file mode 100644 index 15e49ba..0000000 --- a/chrome/browser/android/vr/vr_module_provider.cc +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/android/vr/register_jni.h" -#include "jni/VrModuleProvider_jni.h" - -namespace vr { - -static void JNI_VrModuleProvider_RegisterJni( - JNIEnv* env, - const base::android::JavaParamRef<jclass>& clazz) { - CHECK(RegisterJni(env)); -} - -} // namespace vr
diff --git a/chrome/browser/android/vr/vr_shell_delegate.cc b/chrome/browser/android/vr/vr_shell_delegate.cc index 6057159e..c6c75e9 100644 --- a/chrome/browser/android/vr/vr_shell_delegate.cc +++ b/chrome/browser/android/vr/vr_shell_delegate.cc
@@ -271,7 +271,7 @@ VrSupportLevel::kVrNeedsUpdate; } -void VrShellDelegate::SetDeviceId(unsigned int device_id) { +void VrShellDelegate::SetDeviceId(device::mojom::XRDeviceId device_id) { device_id_ = device_id; if (vr_shell_) { device::GvrDevice* device = GetDevice();
diff --git a/chrome/browser/android/vr/vr_shell_delegate.h b/chrome/browser/android/vr/vr_shell_delegate.h index 5f025ae..0d9e60d8 100644 --- a/chrome/browser/android/vr/vr_shell_delegate.h +++ b/chrome/browser/android/vr/vr_shell_delegate.h
@@ -76,7 +76,7 @@ private: // device::GvrDelegateProvider implementation. bool ShouldDisableGvrDevice() override; - void SetDeviceId(unsigned int device_id) override; + void SetDeviceId(device::mojom::XRDeviceId device_id) override; void StartWebXRPresentation( device::mojom::VRDisplayInfoPtr display_info, device::mojom::XRRuntimeSessionOptionsPtr options, @@ -94,7 +94,8 @@ std::unique_ptr<VrCoreInfo> MakeVrCoreInfo(JNIEnv* env); base::android::ScopedJavaGlobalRef<jobject> j_vr_shell_delegate_; - unsigned int device_id_ = 0; + device::mojom::XRDeviceId device_id_ = + device::mojom::XRDeviceId::GVR_DEVICE_ID; VrShell* vr_shell_ = nullptr; // Deferred callback stored for later use in cases where vr_shell
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index 5a8030a9..3d8e362 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h
@@ -40,7 +40,6 @@ class WebRtcLogUploader; namespace network { -class NetworkConnectionTracker; class NetworkQualityTracker; class SharedURLLoaderFactory; } @@ -183,10 +182,6 @@ // backed by the IOThread's URLRequestContext. virtual SystemNetworkContextManager* system_network_context_manager() = 0; - // Returns a NetworkConnectionTracker that can be used to subscribe for - // network change events. - virtual network::NetworkConnectionTracker* network_connection_tracker() = 0; - // Returns a NetworkQualityTracker that can be used to subscribe for // network quality change events. virtual network::NetworkQualityTracker* network_quality_tracker() = 0;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 94d19844..cca59ea3d 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -134,7 +134,6 @@ #include "net/url_request/url_request_context_getter.h" #include "ppapi/buildflags/buildflags.h" #include "printing/buildflags/buildflags.h" -#include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/network_quality_tracker.h" #include "services/network/public/cpp/network_switches.h" #include "services/preferences/public/cpp/in_process_service_factory.h" @@ -632,18 +631,6 @@ return system_network_context_manager()->GetSharedURLLoaderFactory(); } -network::NetworkConnectionTracker* -BrowserProcessImpl::network_connection_tracker() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(io_thread_); - if (!network_connection_tracker_) { - network_connection_tracker_ = - std::make_unique<network::NetworkConnectionTracker>( - base::BindRepeating(&content::GetNetworkService)); - } - return network_connection_tracker_.get(); -} - network::NetworkQualityTracker* BrowserProcessImpl::network_quality_tracker() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_);
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index ecd6a24..89ebadfe 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h
@@ -123,7 +123,6 @@ SystemNetworkContextManager* system_network_context_manager() override; scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory() override; - network::NetworkConnectionTracker* network_connection_tracker() override; network::NetworkQualityTracker* network_quality_tracker() override; WatchDogThread* watchdog_thread() override; ProfileManager* profile_manager() override; @@ -240,9 +239,6 @@ std::unique_ptr<SystemNetworkContextManager> system_network_context_manager_; - std::unique_ptr<network::NetworkConnectionTracker> - network_connection_tracker_; - std::unique_ptr<network::NetworkQualityTracker> network_quality_tracker_; bool created_icon_manager_ = false;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 0458d3db..f34402e 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -211,6 +211,7 @@ #include "components/translate/core/common/translate_switches.h" #include "components/url_formatter/url_fixer.h" #include "components/variations/variations_associated_data.h" +#include "components/variations/variations_http_header_provider.h" #include "components/variations/variations_switches.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_child_process_host.h" @@ -250,6 +251,7 @@ #include "content/public/common/web_preferences.h" #include "device/usb/public/mojom/chooser_service.mojom.h" #include "device/usb/public/mojom/device_manager.mojom.h" +#include "device/vr/buildflags/buildflags.h" #include "extensions/buildflags/buildflags.h" #include "google_apis/gaia/gaia_urls.h" #include "google_apis/google_api_keys.h" @@ -515,6 +517,10 @@ #include "services/content/simple_browser/public/mojom/constants.mojom.h" #endif +#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) +#include "device/vr/public/mojom/isolated_xr_service.mojom.h" +#endif + using base::FileDescriptor; using content::BrowserThread; using content::BrowserURLHandler; @@ -3626,6 +3632,11 @@ void ChromeContentBrowserClient::RegisterOutOfProcessServices( OutOfProcessServiceMap* services) { +#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) + (*services)[device::mojom::kVrIsolatedServiceName] = base::BindRepeating( + &l10n_util::GetStringUTF16, IDS_ISOLATED_XR_PROCESS_NAME); +#endif + #if BUILDFLAG(ENABLE_PRINTING) (*services)[printing::mojom::kServiceName] = base::BindRepeating(&l10n_util::GetStringUTF16, @@ -4229,11 +4240,14 @@ !is_off_the_record && !io_data->google_services_account_id()->GetValue().empty(); + std::string variation_ids_header = + variations::VariationsHttpHeaderProvider::GetInstance() + ->GetClientDataHeader(is_signed_in); + result.push_back(std::make_unique<GoogleURLLoaderThrottle>( - is_off_the_record, is_signed_in, - io_data->force_google_safesearch()->GetValue(), + is_off_the_record, io_data->force_google_safesearch()->GetValue(), io_data->force_youtube_restrict()->GetValue(), - io_data->allowed_domains_for_apps()->GetValue())); + io_data->allowed_domains_for_apps()->GetValue(), variation_ids_header)); } #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index a4b7c78..b1a077cc 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -72,7 +72,8 @@ ], "unzip": [ "unzip_file" ], "util_win" : [ "shell_util_win" ], - "wifi_util_win": [ "wifi_credentials" ] + "wifi_util_win": [ "wifi_credentials" ], + "xr_device_service": [ "xr_device_provider" ] } }, "navigation:frame": {
diff --git a/chrome/browser/chrome_do_not_track_browsertest.cc b/chrome/browser/chrome_do_not_track_browsertest.cc index 694e3ad..a1f355a0 100644 --- a/chrome/browser/chrome_do_not_track_browsertest.cc +++ b/chrome/browser/chrome_do_not_track_browsertest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -31,6 +33,10 @@ &text)); EXPECT_EQ(expected_content, text); } + + content::WebContents* GetWebContents() { + return browser()->tab_strip_model()->GetActiveWebContents(); + } }; IN_PROC_BROWSER_TEST_F(ChromeDoNotTrackTest, NotEnabled) { @@ -39,11 +45,8 @@ GURL url = embedded_test_server()->GetURL("/echoheader?DNT"); ui_test_utils::NavigateToURL(browser(), url); - EXPECT_EQ(false, browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetMutableRendererPrefs() - ->enable_do_not_track); + EXPECT_EQ(false, + GetWebContents()->GetMutableRendererPrefs()->enable_do_not_track); ExpectPageTextEq("None"); } @@ -53,12 +56,120 @@ GURL url = embedded_test_server()->GetURL("/echoheader?DNT"); ui_test_utils::NavigateToURL(browser(), url); - EXPECT_EQ(true, browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetMutableRendererPrefs() - ->enable_do_not_track); + EXPECT_EQ(true, + GetWebContents()->GetMutableRendererPrefs()->enable_do_not_track); ExpectPageTextEq("1"); } +// Checks that the DNT header is preserved when fetching from a dedicated +// worker. +IN_PROC_BROWSER_TEST_F(ChromeDoNotTrackTest, FetchFromWorker) { + ASSERT_TRUE(embedded_test_server()->Start()); + SetEnableDoNotTrack(true /* enabled */); + + const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT"); + const GURL url = embedded_test_server()->GetURL( + std::string("/workers/fetch_from_worker.html")); + ui_test_utils::NavigateToURL(browser(), url); + + const std::string script = "fetch_from_worker('" + fetch_url.spec() + "');"; + ASSERT_TRUE(ExecJs(GetWebContents(), script)); + const base::string16 title = base::ASCIIToUTF16("DONE"); + { + content::TitleWatcher watcher(GetWebContents(), title); + EXPECT_EQ(title, watcher.WaitAndGetTitle()); + } + ExpectPageTextEq("1"); + + // Updating settings should be reflected immediately. + // Disabled due to crbug.com/853085. + // + // SetEnableDoNotTrack(false /* enabled */); + // ASSERT_TRUE(ExecJs(GetWebContents(), script)); + // { + // content::TitleWatcher watcher(GetWebContents(), title); + // EXPECT_EQ(title, watcher.WaitAndGetTitle()); + // } + // ExpectPageTextEq("None"); +} + +// Checks that the DNT header is preserved when fetching from a shared worker. +// +// Disabled on Android since a shared worker is not available on Android: +// crbug.com/869745. +#if defined(OS_ANDROID) +#define MAYBE_FetchFromSharedWorker DISABLED_FetchFromSharedWorker +#else +#define MAYBE_FetchFromSharedWorker FetchFromSharedWorker +#endif +IN_PROC_BROWSER_TEST_F(ChromeDoNotTrackTest, MAYBE_FetchFromSharedWorker) { + ASSERT_TRUE(embedded_test_server()->Start()); + SetEnableDoNotTrack(true /* enabled */); + + const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT"); + const GURL url = embedded_test_server()->GetURL( + std::string("/workers/fetch_from_shared_worker.html")); + ui_test_utils::NavigateToURL(browser(), url); + + const std::string script = + "fetch_from_shared_worker('" + fetch_url.spec() + "');"; + ASSERT_TRUE(ExecJs(GetWebContents(), script)); + const base::string16 title = base::ASCIIToUTF16("DONE"); + { + content::TitleWatcher watcher(GetWebContents(), title); + EXPECT_EQ(title, watcher.WaitAndGetTitle()); + } + ExpectPageTextEq("1"); + + // Updating settings should be reflected immediately. + // Disabled due to crbug.com/853085. + // + // SetEnableDoNotTrack(false /* enabled */); + // ASSERT_TRUE(ExecJs(GetWebContents(), script)); + // { + // content::TitleWatcher watcher(GetWebContents(), title); + // EXPECT_EQ(title, watcher.WaitAndGetTitle()); + // } + // ExpectPageTextEq("None"); +} + +// Checks that the DNT header is preserved when fetching from a service worker. +IN_PROC_BROWSER_TEST_F(ChromeDoNotTrackTest, FetchFromServiceWorker) { + ASSERT_TRUE(embedded_test_server()->Start()); + SetEnableDoNotTrack(true /* enabled */); + + const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT"); + const GURL url = embedded_test_server()->GetURL( + std::string("/workers/fetch_from_service_worker.html")); + ui_test_utils::NavigateToURL(browser(), url); + + // Wait until service worker become ready. + const base::string16 title = base::ASCIIToUTF16("DONE"); + { + content::TitleWatcher watcher(GetWebContents(), title); + EXPECT_EQ(title, watcher.WaitAndGetTitle()); + } + ExpectPageTextEq("ready"); + + const std::string script = + "fetch_from_service_worker('" + fetch_url.spec() + "');"; + ASSERT_TRUE(ExecJs(GetWebContents(), script)); + { + content::TitleWatcher watcher(GetWebContents(), title); + EXPECT_EQ(title, watcher.WaitAndGetTitle()); + } + ExpectPageTextEq("1"); + + // Updating settings should be reflected immediately. + // Disabled due to crbug.com/853085. + // + // SetEnableDoNotTrack(false /* enabled */); + // ASSERT_TRUE(ExecJs(GetWebContents(), script)); + // { + // content::TitleWatcher watcher(GetWebContents(), title); + // EXPECT_EQ(title, watcher.WaitAndGetTitle()); + // } + // ExpectPageTextEq("None"); +} + } // namespace
diff --git a/chrome/browser/chromeos/arc/intent_helper/open_with_menu.cc b/chrome/browser/chromeos/arc/intent_helper/open_with_menu.cc index 2141168..32255b31 100644 --- a/chrome/browser/chromeos/arc/intent_helper/open_with_menu.cc +++ b/chrome/browser/chromeos/arc/intent_helper/open_with_menu.cc
@@ -14,6 +14,7 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/grit/generated_resources.h" #include "components/renderer_context_menu/render_view_context_menu_proxy.h" +#include "content/public/browser/browser_context.h" #include "content/public/common/context_menu_params.h" #include "ui/base/l10n/l10n_util.h" @@ -45,6 +46,10 @@ OpenWithMenu::~OpenWithMenu() = default; void OpenWithMenu::InitMenu(const content::ContextMenuParams& params) { + // Enforcing no items are added to the context menu during incognito mode. + if (context_->IsOffTheRecord()) + return; + menu_model_ = LinkHandlerModel::Create(context_, params.link_url); if (!menu_model_) return;
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index 969e670..164ef66 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -532,6 +532,8 @@ void CrostiniManager::MaybeUpgradeCrostiniAfterTerminaCheck( bool is_registered) { is_cros_termina_registered_ = is_registered; + VLOG(1) << "cros-termina is " + << (is_registered ? "registered" : "not registered"); if (!is_cros_termina_registered_) { return; } @@ -606,7 +608,9 @@ bool is_successful = error == component_updater::CrOSComponentManager::Error::NONE; - if (!is_successful) { + if (is_successful) { + is_cros_termina_registered_ = true; + } else { LOG(ERROR) << "Failed to install the cros-termina component with error code: " << static_cast<int>(error);
diff --git a/chrome/browser/chromeos/extensions/arc_apps_private_apitest.cc b/chrome/browser/chromeos/extensions/arc_apps_private_apitest.cc index 99368eb..407d889 100644 --- a/chrome/browser/chromeos/extensions/arc_apps_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/arc_apps_private_apitest.cc
@@ -17,6 +17,7 @@ #include "components/arc/arc_util.h" #include "components/arc/test/connection_holder_util.h" #include "components/arc/test/fake_app_instance.h" +#include "extensions/common/switches.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" @@ -45,6 +46,10 @@ void SetUpCommandLine(base::CommandLine* command_line) override { extensions::ExtensionApiTest::SetUpCommandLine(command_line); arc::SetArcAvailableCommandLineForTesting(command_line); + // Whitelist the test platform app. + command_line->AppendSwitchASCII( + extensions::switches::kWhitelistedExtensionID, + "fgkfegllpjfhppblcabhjjipnfelohej"); } void SetUpInProcessBrowserTestFixture() override {
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index f4baac8..191c0ec 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -245,14 +245,8 @@ TestCase("createFolderDrive"), TestCase("createFolderDrive").EnableDriveFs())); -// crbug.com/871684 -#if !defined(NDEBUG) -#define MAYBE_KeyboardOperations DISABLED_KeyboardOperations -#else -#define MAYBE_KeyboardOperations KeyboardOperations -#endif WRAPPED_INSTANTIATE_TEST_CASE_P( - MAYBE_KeyboardOperations, /* keyboard_operations.js */ + KeyboardOperations, /* keyboard_operations.js */ FilesAppBrowserTest, ::testing::Values(TestCase("keyboardDeleteDownloads").InGuestMode(), TestCase("keyboardDeleteDownloads"),
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc index 6702e88..62840e6 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest_base.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/chromeos/file_manager/file_manager_jstest_base.h" -#include <vector> #include "base/path_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -19,16 +18,31 @@ void FileManagerJsTestBase::RunTest(const base::FilePath& file) { base::FilePath root_path; ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path)); + base::FilePath full_path = root_path.Append(base_path_).Append(file); + ASSERT_TRUE(base::PathExists(full_path)) << full_path.value(); + RunTestImpl(net::FilePathToFileURL(full_path)); +} - const GURL url = net::FilePathToFileURL( - root_path.Append(base_path_) - .Append(file)); +void FileManagerJsTestBase::RunGeneratedTest(const std::string& file) { + base::FilePath path; + ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &path)); + path = path.AppendASCII("gen"); + + // Serve the generated html file from out/gen. It references files from + // DIR_SOURCE_ROOT, so serve from there as well. An alternative would be to + // copy the js files as a build step and serve file:// URLs, but the embedded + // test server gives better output for troubleshooting errors. + embedded_test_server()->ServeFilesFromDirectory(path.Append(base_path_)); + embedded_test_server()->ServeFilesFromSourceDirectory(base::FilePath()); + + ASSERT_TRUE(embedded_test_server()->Start()); + RunTestImpl(embedded_test_server()->GetURL(file)); +} + +void FileManagerJsTestBase::RunTestImpl(const GURL& url) { ui_test_utils::NavigateToURL(browser(), url); - content::WebContents* const web_contents = browser()->tab_strip_model()->GetActiveWebContents(); ASSERT_TRUE(web_contents); - - const std::vector<int> empty_libraries; - EXPECT_TRUE(ExecuteWebUIResourceTest(web_contents, empty_libraries)); + EXPECT_TRUE(ExecuteWebUIResourceTest(web_contents, {})); }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest_base.h b/chrome/browser/chromeos/file_manager/file_manager_jstest_base.h index 7095cf26..80faa2c86 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest_base.h +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest_base.h
@@ -15,7 +15,13 @@ // Runs all test functions in |file|, waiting for them to complete. void RunTest(const base::FilePath& file); + // Same as RunTest, but starts the EmbeddedTestServer to serve a generated + // |file|, relative to DIR_EXE/gen/base_path. + void RunGeneratedTest(const std::string& file); + private: + void RunTestImpl(const GURL& url); + base::FilePath base_path_; };
diff --git a/chrome/browser/chromeos/file_manager/gallery_jstest.cc b/chrome/browser/chromeos/file_manager/gallery_jstest.cc index 375abe1..3c9b71a 100644 --- a/chrome/browser/chromeos/file_manager/gallery_jstest.cc +++ b/chrome/browser/chromeos/file_manager/gallery_jstest.cc
@@ -6,13 +6,13 @@ class GalleryJsTest : public FileManagerJsTestBase { protected: - GalleryJsTest() : FileManagerJsTestBase( - base::FilePath(FILE_PATH_LITERAL("ui/file_manager/gallery/js"))) {} + GalleryJsTest() + : FileManagerJsTestBase( + base::FilePath(FILE_PATH_LITERAL("ui/file_manager/gallery/js"))) {} }; IN_PROC_BROWSER_TEST_F(GalleryJsTest, ImageEncoderTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("image_editor/image_encoder_unittest.html"))); + RunGeneratedTest("/image_editor/image_encoder_unittest.html"); } // Disabled on ASan builds due to a consistent failure. https://crbug.com/762831 @@ -22,33 +22,29 @@ #define MAYBE_ExifEncoderTest ExifEncoderTest #endif IN_PROC_BROWSER_TEST_F(GalleryJsTest, MAYBE_ExifEncoderTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("image_editor/exif_encoder_unittest.html"))); + RunGeneratedTest("/image_editor/exif_encoder_unittest.html"); } IN_PROC_BROWSER_TEST_F(GalleryJsTest, ImageViewTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("image_editor/image_view_unittest.html"))); + RunGeneratedTest("/image_editor/image_view_unittest.html"); } IN_PROC_BROWSER_TEST_F(GalleryJsTest, EntryListWatcherTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("entry_list_watcher_unittest.html"))); + RunTest( + base::FilePath(FILE_PATH_LITERAL("entry_list_watcher_unittest.html"))); } IN_PROC_BROWSER_TEST_F(GalleryJsTest, GalleryUtilTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("gallery_util_unittest.html"))); + RunTest(base::FilePath(FILE_PATH_LITERAL("gallery_util_unittest.html"))); } IN_PROC_BROWSER_TEST_F(GalleryJsTest, GalleryItemTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("gallery_item_unittest.html"))); + RunTest(base::FilePath(FILE_PATH_LITERAL("gallery_item_unittest.html"))); } IN_PROC_BROWSER_TEST_F(GalleryJsTest, GalleryDataModelTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("gallery_data_model_unittest.html"))); + RunTest( + base::FilePath(FILE_PATH_LITERAL("gallery_data_model_unittest.html"))); } IN_PROC_BROWSER_TEST_F(GalleryJsTest, RibbonTest) {
diff --git a/chrome/browser/chromeos/logging.cc b/chrome/browser/chromeos/logging.cc index edd99c39..e5b4260 100644 --- a/chrome/browser/chromeos/logging.cc +++ b/chrome/browser/chromeos/logging.cc
@@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "base/sys_info.h" #include "base/task/post_task.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/logging_chrome.h" @@ -46,6 +47,11 @@ void RedirectChromeLogging(const base::CommandLine& command_line) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // Only redirect when on an actual device. To do otherwise conflicts with + // --vmodule that developers may want to use. + if (!base::SysInfo::IsRunningOnChromeOS()) + return; + if (chrome_logging_redirected_) { // TODO: Support multiple active users. http://crbug.com/230345 LOG(WARNING) << "NOT redirecting logging for multi-profiles case.";
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc index a19791f..ce6f9929 100644 --- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc +++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/chromeos/boot_times_recorder.h" #include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service_factory.h" #include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/lock_screen_apps/state_controller.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/lock/webui_screen_locker.h" @@ -142,6 +143,8 @@ policy::AppInstallEventLogManagerWrapper::CreateForProfile(user_profile); } arc::ArcServiceLauncher::Get()->OnPrimaryUserProfilePrepared(user_profile); + crostini::CrostiniManager::GetInstance()->MaybeUpgradeCrostini( + user_profile); if (user->GetType() == user_manager::USER_TYPE_CHILD) { ScreenTimeControllerFactory::GetForBrowserContext(user_profile);
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 98c95274..203617b 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1070,8 +1070,7 @@ void UserSessionManager::PreStartSession() { // Switch log file as soon as possible. - if (base::SysInfo::IsRunningOnChromeOS()) - logging::RedirectChromeLogging(*base::CommandLine::ForCurrentProcess()); + logging::RedirectChromeLogging(*base::CommandLine::ForCurrentProcess()); } void UserSessionManager::StoreUserContextDataBeforeProfileIsCreated() {
diff --git a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc index 4d01e5b..f4de75c6 100644 --- a/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/chrome_user_manager_impl.cc
@@ -775,7 +775,9 @@ std::string owner_email; cros_settings_->GetString(kDeviceOwner, &owner_email); - SetOwnerId(AccountId::FromUserEmail(owner_email)); + const AccountId owner_account_id = user_manager::known_user::GetAccountId( + owner_email, std::string() /* id */, AccountType::UNKNOWN); + SetOwnerId(owner_account_id); EnsureUsersLoaded();
diff --git a/chrome/browser/chromeos/policy/app_install_event_log_collector.cc b/chrome/browser/chromeos/policy/app_install_event_log_collector.cc index 7b00403..cb3e693 100644 --- a/chrome/browser/chromeos/policy/app_install_event_log_collector.cc +++ b/chrome/browser/chromeos/policy/app_install_event_log_collector.cc
@@ -16,6 +16,7 @@ #include "chromeos/network/network_type_pattern.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_service.h" +#include "content/public/browser/network_service_instance.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace em = enterprise_management; @@ -65,8 +66,7 @@ pending_packages_(pending_packages) { chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver( this); - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); // Might not be available in unit test. arc::ArcPolicyBridge* const policy_bridge = arc::ArcPolicyBridge::GetForBrowserContext(profile_); @@ -86,8 +86,7 @@ } chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver( this); - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); arc::ArcPolicyBridge* const policy_bridge = arc::ArcPolicyBridge::GetForBrowserContext(profile_); if (policy_bridge) {
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc index 3bd6673..5724ac4 100644 --- a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc +++ b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
@@ -14,7 +14,6 @@ #include "base/metrics/histogram_macros.h" #include "base/optional.h" #include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/policy/server_backed_device_state.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/pref_names.h" @@ -24,6 +23,7 @@ #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "crypto/sha2.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "url/gurl.h" @@ -376,8 +376,7 @@ } AutoEnrollmentClientImpl::~AutoEnrollmentClientImpl() { - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); } // static @@ -388,10 +387,8 @@ void AutoEnrollmentClientImpl::Start() { // (Re-)register the network change observer. - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); // Drop the previous job and reset state. request_job_.reset();
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager.cc b/chrome/browser/chromeos/power/ml/user_activity_manager.cc index da1f5895..ae08692 100644 --- a/chrome/browser/chromeos/power/ml/user_activity_manager.cc +++ b/chrome/browser/chromeos/power/ml/user_activity_manager.cc
@@ -241,7 +241,9 @@ // Default is to enable smart dim, unless user profile specifically says // otherwise. bool smart_dim_enabled = true; - const Profile* const profile = ProfileManager::GetActiveUserProfile(); + // If there are multiple users, the primary one may have more-restrictive + // policy-controlled settings. + const Profile* const profile = ProfileManager::GetPrimaryUserProfile(); if (profile) { smart_dim_enabled = profile->GetPrefs()->GetBoolean(ash::prefs::kPowerSmartDimEnabled);
diff --git a/chrome/browser/devtools/devtools_auto_opener.cc b/chrome/browser/devtools/devtools_auto_opener.cc index 834030e3..af0bda1 100644 --- a/chrome/browser/devtools/devtools_auto_opener.cc +++ b/chrome/browser/devtools/devtools_auto_opener.cc
@@ -15,10 +15,14 @@ DevToolsAutoOpener::~DevToolsAutoOpener() { } -void DevToolsAutoOpener::TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index, - bool foreground) { - if (!DevToolsWindow::IsDevToolsWindow(contents)) - DevToolsWindow::OpenDevToolsWindow(contents); +void DevToolsAutoOpener::OnTabStripModelChanged( + const TabStripModelChange& change, + const TabStripSelectionChange& selection) { + if (change.type() != TabStripModelChange::kInserted) + return; + + for (const auto& delta : change.deltas()) { + if (!DevToolsWindow::IsDevToolsWindow(delta.insert.contents)) + DevToolsWindow::OpenDevToolsWindow(delta.insert.contents); + } }
diff --git a/chrome/browser/devtools/devtools_auto_opener.h b/chrome/browser/devtools/devtools_auto_opener.h index 7efe2ea7..ae5bb89 100644 --- a/chrome/browser/devtools/devtools_auto_opener.h +++ b/chrome/browser/devtools/devtools_auto_opener.h
@@ -15,10 +15,9 @@ private: // TabStripModelObserver overrides. - void TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* contents, - int index, - bool foreground) override; + void OnTabStripModelChanged( + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override; BrowserTabStripTracker browser_tab_strip_tracker_;
diff --git a/chrome/browser/devtools/global_confirm_info_bar.cc b/chrome/browser/devtools/global_confirm_info_bar.cc index d283a99..1e1dc7f2 100644 --- a/chrome/browser/devtools/global_confirm_info_bar.cc +++ b/chrome/browser/devtools/global_confirm_info_bar.cc
@@ -177,11 +177,14 @@ } } -void GlobalConfirmInfoBar::TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* web_contents, - int index, - bool foreground) { - MaybeAddInfoBar(web_contents); +void GlobalConfirmInfoBar::OnTabStripModelChanged( + const TabStripModelChange& change, + const TabStripSelectionChange& selection) { + if (change.type() != TabStripModelChange::kInserted) + return; + + for (const auto& delta : change.deltas()) + MaybeAddInfoBar(delta.insert.contents); } void GlobalConfirmInfoBar::TabChangedAt(content::WebContents* web_contents,
diff --git a/chrome/browser/devtools/global_confirm_info_bar.h b/chrome/browser/devtools/global_confirm_info_bar.h index 7843f26..a91996d3 100644 --- a/chrome/browser/devtools/global_confirm_info_bar.h +++ b/chrome/browser/devtools/global_confirm_info_bar.h
@@ -43,10 +43,9 @@ class DelegateProxy; // TabStripModelObserver: - void TabInsertedAt(TabStripModel* tab_strip_model, - content::WebContents* web_contents, - int index, - bool foreground) override; + void OnTabStripModelChanged( + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override; void TabChangedAt(content::WebContents* web_contents, int index, TabChangeType change_type) override;
diff --git a/chrome/browser/extensions/api/declarative/declarative_apitest.cc b/chrome/browser/extensions/api/declarative/declarative_apitest.cc index b9f2d90..b82c58c 100644 --- a/chrome/browser/extensions/api/declarative/declarative_apitest.cc +++ b/chrome/browser/extensions/api/declarative/declarative_apitest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/storage_partition.h" #include "extensions/browser/api/declarative/rules_registry_service.h" #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h" @@ -186,6 +187,9 @@ const Extension* extension = InstallExtensionWithUIAutoConfirm( ext_dir.Pack(), 1 /*+1 installed extension*/, browser()); ASSERT_TRUE(extension); + // Wait for declarative rules to be set up. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); std::string extension_id(extension->id()); ASSERT_TRUE(ready.WaitUntilSatisfied()); ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl)); @@ -260,6 +264,9 @@ const Extension* extension = InstallExtensionWithUIAutoConfirm( ext_dir.Pack(), 1 /*+1 installed extension*/, browser()); ASSERT_TRUE(extension); + // Wait for declarative rules to be set up. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); std::string extension_id(extension->id()); ASSERT_TRUE(ready.WaitUntilSatisfied()); ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl)); @@ -270,6 +277,9 @@ // 2. Uninstall the extension. Rules are gone and preferences should be empty. UninstallExtension(extension_id); + // Wait for declarative rules to be removed. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl)); EXPECT_NE(kTestTitle, GetTitle()); EXPECT_EQ(0u, NumberOfRegisteredRules(extension_id));
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc index df8b818..792970c 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "components/bookmarks/browser/bookmark_model.h" +#include "content/public/browser/storage_partition.h" #include "content/public/test/browser_test_utils.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" @@ -361,6 +362,9 @@ ExtensionTestMessageListener ready("ready", false); const Extension* extension = LoadExtension(ext_dir_.UnpackedPath()); ASSERT_TRUE(extension); + // Wait for declarative rules to be set up. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); const ExtensionAction* page_action = ExtensionActionManager::Get(browser()->profile()) ->GetPageAction(*extension); @@ -605,6 +609,9 @@ ext_dir_.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundHelpers); const Extension* extension = LoadExtension(ext_dir_.UnpackedPath()); ASSERT_TRUE(extension); + // Wait for declarative rules to be set up. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); const std::string extension_id = extension->id(); const ExtensionAction* page_action = ExtensionActionManager::Get( browser()->profile())->GetPageAction(*extension); @@ -631,6 +638,9 @@ EXPECT_EQ(1u, extension_action_test_util::GetTotalPageActionCount(tab)); ReloadExtension(extension_id); // Invalidates page_action and extension. + // Wait for declarative rules to be removed. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); EXPECT_EQ("test_rule", ExecuteScriptInBackgroundPage(extension_id, kTestRule)); // TODO(jyasskin): Apply new rules to existing tabs, without waiting for a @@ -641,6 +651,9 @@ EXPECT_EQ(1u, extension_action_test_util::GetTotalPageActionCount(tab)); UnloadExtension(extension_id); + // Wait for declarative rules to be removed. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); NavigateInRenderer(tab, GURL("http://test/")); EXPECT_TRUE(WaitForPageActionVisibilityChangeTo(0)); EXPECT_EQ(0u, extension_action_test_util::GetVisiblePageActionCount(tab)); @@ -722,6 +735,9 @@ scoped_refptr<const Extension> extension = loader.LoadExtension(ext_dir_.UnpackedPath()); ASSERT_TRUE(extension); + // Wait for declarative rules to be set up. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); const char kScript[] = "setRules([{\n"
diff --git a/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc b/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc index 72a79c3..b06f930 100644 --- a/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc +++ b/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "components/version_info/version_info.h" +#include "content/public/browser/storage_partition.h" #include "extensions/common/features/feature_channel.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/test_extension_dir.h" @@ -74,6 +75,9 @@ ExtensionTestMessageListener ready("ready", false); const Extension* extension = LoadExtension(ext_dir_.UnpackedPath()); ASSERT_TRUE(extension); + // Wait for declarative rules to be set up. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); const ExtensionAction* page_action = ExtensionActionManager::Get(browser()->profile())-> GetPageAction(*extension);
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 68810f8..46d68e7 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -1547,6 +1547,9 @@ LoadExtension(test_data_dir_.AppendASCII("extension")); ASSERT_TRUE(extension); EXPECT_TRUE(listener.WaitUntilSatisfied()); + // Wait for webRequest listeners to be set up. + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); // Have the extension listen for requests to |fake_ntp_script.js|. listener.Reply(https_test_server()->GetURL("/fake_ntp_script.js").spec());
diff --git a/chrome/browser/extensions/app_data_migrator_unittest.cc b/chrome/browser/extensions/app_data_migrator_unittest.cc index 1f804ee..c6c6ecb 100644 --- a/chrome/browser/extensions/app_data_migrator_unittest.cc +++ b/chrome/browser/extensions/app_data_migrator_unittest.cc
@@ -170,13 +170,12 @@ base::Bind(&DidCreate)); content::RunAllTasksUntilIdle(); - fs_context->operation_runner()->Write(url_request_context, fs_temp_url, - blob1.GetBlobDataHandle(), 0, - base::Bind(&DidWrite)); + fs_context->operation_runner()->Write(fs_temp_url, blob1.GetBlobDataHandle(), + 0, base::BindRepeating(&DidWrite)); content::RunAllTasksUntilIdle(); - fs_context->operation_runner()->Write(url_request_context, fs_persistent_url, + fs_context->operation_runner()->Write(fs_persistent_url, blob1.GetBlobDataHandle(), 0, - base::Bind(&DidWrite)); + base::BindRepeating(&DidWrite)); content::RunAllTasksUntilIdle(); }
diff --git a/chrome/browser/extensions/background_xhr_browsertest.cc b/chrome/browser/extensions/background_xhr_browsertest.cc index 03b32ac..cc98616d 100644 --- a/chrome/browser/extensions/background_xhr_browsertest.cc +++ b/chrome/browser/extensions/background_xhr_browsertest.cc
@@ -15,7 +15,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/network_service_instance.h" +#include "content/public/browser/storage_partition.h" #include "extensions/browser/browsertest_util.h" #include "extensions/common/extension.h" #include "extensions/common/extension_urls.h" @@ -60,7 +60,8 @@ GURL test_url = net::AppendQueryParameter(extension->GetResourceURL(path), "url", url.spec()); ui_test_utils::NavigateToURL(browser(), test_url); - content::FlushNetworkServiceInstanceForTesting(); + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); constexpr char kSendXHRScript[] = R"( var xhr = new XMLHttpRequest(); xhr.open('GET', '%s');
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc index 18a69668..6ea2b79 100644 --- a/chrome/browser/extensions/bookmark_app_helper.cc +++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include <cctype> #include <string> #include <utility> @@ -46,7 +45,6 @@ #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/origin_trials/chrome_origin_trial_policy.h" #include "chrome/common/url_constants.h" -#include "chrome/grit/platform_locale_settings.h" #include "components/prefs/pref_service.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/notification_service.h" @@ -61,21 +59,9 @@ #include "extensions/common/extension.h" #include "extensions/common/url_pattern.h" #include "net/base/load_flags.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/url_request/url_request.h" -#include "skia/ext/image_operations.h" -#include "skia/ext/platform_canvas.h" #include "third_party/blink/public/common/manifest/web_display_mode.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/color_analysis.h" -#include "ui/gfx/color_utils.h" -#include "ui/gfx/font.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/image/canvas_image_source.h" -#include "ui/gfx/image/image.h" #if defined(OS_MACOSX) #include "chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h" @@ -92,62 +78,6 @@ namespace { -// Overlays a shortcut icon over the bottom left corner of a given image. -class GeneratedIconImageSource : public gfx::CanvasImageSource { - public: - explicit GeneratedIconImageSource(char letter, SkColor color, int output_size) - : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false), - letter_(letter), - color_(color), - output_size_(output_size) {} - ~GeneratedIconImageSource() override {} - - private: - // gfx::CanvasImageSource overrides: - void Draw(gfx::Canvas* canvas) override { - const uint8_t kLumaThreshold = 190; - const int icon_size = output_size_ * 3 / 4; - const int icon_inset = output_size_ / 8; - const size_t border_radius = output_size_ / 16; - const size_t font_size = output_size_ * 7 / 16; - - std::string font_name = - l10n_util::GetStringUTF8(IDS_SANS_SERIF_FONT_FAMILY); -#if defined(OS_CHROMEOS) - const std::string kChromeOSFontFamily = "Noto Sans"; - font_name = kChromeOSFontFamily; -#endif - - // Draw a rounded rect of the given |color|. - cc::PaintFlags background_flags; - background_flags.setAntiAlias(true); - background_flags.setColor(color_); - - gfx::Rect icon_rect(icon_inset, icon_inset, icon_size, icon_size); - canvas->DrawRoundRect(icon_rect, border_radius, background_flags); - - // The text rect's size needs to be odd to center the text correctly. - gfx::Rect text_rect(icon_inset, icon_inset, icon_size + 1, icon_size + 1); - // Draw the letter onto the rounded rect. The letter's color depends on the - // luma of |color|. - const uint8_t luma = color_utils::GetLuma(color_); - canvas->DrawStringRectWithFlags( - base::string16(1, std::toupper(letter_)), - gfx::FontList(gfx::Font(font_name, font_size)), - (luma > kLumaThreshold) ? SK_ColorBLACK : SK_ColorWHITE, - text_rect, - gfx::Canvas::TEXT_ALIGN_CENTER); - } - - char letter_; - - SkColor color_; - - int output_size_; - - DISALLOW_COPY_AND_ASSIGN(GeneratedIconImageSource); -}; - std::set<int> SizesToGenerate() { // Generate container icons from smaller icons. const int kIconSizesToGenerate[] = { @@ -162,49 +92,8 @@ kIconSizesToGenerate + arraysize(kIconSizesToGenerate)); } -void GenerateIcons( - std::set<int> generate_sizes, - const GURL& app_url, - SkColor generated_icon_color, - std::map<int, BookmarkAppHelper::BitmapAndSource>* bitmap_map) { - // The letter that will be painted on the generated icon. - char icon_letter = ' '; - std::string domain_and_registry( - net::registry_controlled_domains::GetDomainAndRegistry( - app_url, - net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)); - if (!domain_and_registry.empty()) { - icon_letter = domain_and_registry[0]; - } else if (app_url.has_host()) { - icon_letter = app_url.host_piece()[0]; - } - - // If no color has been specified, use a dark gray so it will stand out on the - // black shelf. - if (generated_icon_color == SK_ColorTRANSPARENT) - generated_icon_color = SK_ColorDKGRAY; - - for (int size : generate_sizes) { - BookmarkAppHelper::GenerateIcon(bitmap_map, size, generated_icon_color, - icon_letter); - } -} - -SkBitmap GenerateBitmap(int output_size, SkColor color, char letter) { - gfx::ImageSkia icon_image( - std::make_unique<GeneratedIconImageSource>(letter, color, output_size), - gfx::Size(output_size, output_size)); - SkBitmap dst; - if (dst.tryAllocPixels(icon_image.bitmap()->info())) { - icon_image.bitmap()->readPixels(dst.info(), dst.getPixels(), dst.rowBytes(), - 0, 0); - } - return dst; -} - -void ReplaceWebAppIcons( - std::map<int, BookmarkAppHelper::BitmapAndSource> bitmap_map, - WebApplicationInfo* web_app_info) { +void ReplaceWebAppIcons(std::map<int, web_app::BitmapAndSource> bitmap_map, + WebApplicationInfo* web_app_info) { web_app_info->icons.clear(); // Populate the icon data into the WebApplicationInfo we are using to @@ -297,7 +186,7 @@ continue; downloaded_bitmaps_.push_back( - BookmarkAppHelper::BitmapAndSource(url_bitmaps.first, bitmap)); + web_app::BitmapAndSource(url_bitmaps.first, bitmap)); } } } @@ -319,7 +208,7 @@ for (const auto& icon : web_app_info_.icons) sizes_to_generate.insert(icon.width); - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map = + std::map<int, web_app::BitmapAndSource> size_map = BookmarkAppHelper::ResizeIconsAndGenerateMissing( downloaded_bitmaps_, sizes_to_generate, &web_app_info_); BookmarkAppHelper::UpdateWebAppIconsWithoutChangingLinks(size_map, @@ -335,7 +224,7 @@ std::unique_ptr<content::WebContents> web_contents_; std::unique_ptr<WebAppIconDownloader> web_app_icon_downloader_; std::vector<GURL> urls_to_download_; - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded_bitmaps_; + std::vector<web_app::BitmapAndSource> downloaded_bitmaps_; }; } // namespace @@ -383,54 +272,6 @@ } // static -std::map<int, BookmarkAppHelper::BitmapAndSource> -BookmarkAppHelper::ConstrainBitmapsToSizes( - const std::vector<BookmarkAppHelper::BitmapAndSource>& bitmaps, - const std::set<int>& sizes) { - std::map<int, BitmapAndSource> output_bitmaps; - std::map<int, BitmapAndSource> ordered_bitmaps; - for (const BitmapAndSource& bitmap_and_source : bitmaps) { - const SkBitmap& bitmap = bitmap_and_source.bitmap; - DCHECK(bitmap.width() == bitmap.height()); - ordered_bitmaps[bitmap.width()] = bitmap_and_source; - } - - if (ordered_bitmaps.size() > 0) { - for (const auto& size : sizes) { - // Find the closest not-smaller bitmap, or failing that use the largest - // icon available. - auto bitmaps_it = ordered_bitmaps.lower_bound(size); - if (bitmaps_it != ordered_bitmaps.end()) - output_bitmaps[size] = bitmaps_it->second; - else - output_bitmaps[size] = ordered_bitmaps.rbegin()->second; - - // Resize the bitmap if it does not exactly match the desired size. - if (output_bitmaps[size].bitmap.width() != size) { - output_bitmaps[size].bitmap = skia::ImageOperations::Resize( - output_bitmaps[size].bitmap, skia::ImageOperations::RESIZE_LANCZOS3, - size, size); - } - } - } - - return output_bitmaps; -} - -// static -void BookmarkAppHelper::GenerateIcon( - std::map<int, BookmarkAppHelper::BitmapAndSource>* bitmaps, - int output_size, - SkColor color, - char letter) { - // Do nothing if there is already an icon of |output_size|. - if (bitmaps->count(output_size)) - return; - - (*bitmaps)[output_size].bitmap = GenerateBitmap(output_size, color, letter); -} - -// static WebApplicationInfo::IconInfo BookmarkAppHelper::GenerateIconInfo( int output_size, SkColor color, @@ -438,7 +279,7 @@ WebApplicationInfo::IconInfo icon_info; icon_info.width = output_size; icon_info.height = output_size; - icon_info.data = GenerateBitmap(output_size, color, letter); + icon_info.data = web_app::GenerateBitmap(output_size, color, letter); return icon_info; } @@ -464,47 +305,25 @@ } // static -std::map<int, BookmarkAppHelper::BitmapAndSource> +std::map<int, web_app::BitmapAndSource> BookmarkAppHelper::ResizeIconsAndGenerateMissing( - std::vector<BookmarkAppHelper::BitmapAndSource> icons, + std::vector<web_app::BitmapAndSource> icons, std::set<int> sizes_to_generate, WebApplicationInfo* web_app_info) { - // Resize provided icons to make sure we have versions for each size in - // |sizes_to_generate|. - std::map<int, BitmapAndSource> resized_bitmaps( - ConstrainBitmapsToSizes(icons, sizes_to_generate)); + SkColor generated_icon_color = SK_ColorTRANSPARENT; - // Also add all provided icon sizes. - for (const BitmapAndSource& icon : icons) { - if (resized_bitmaps.find(icon.bitmap.width()) == resized_bitmaps.end()) - resized_bitmaps.insert(std::make_pair(icon.bitmap.width(), icon)); - } + std::map<int, web_app::BitmapAndSource> resized_bitmaps = + web_app::ResizeIconsAndGenerateMissing(icons, sizes_to_generate, + web_app_info->app_url, + &generated_icon_color); - // Determine the color that will be used for the icon's background. For this - // the dominant color of the first icon found is used. - if (resized_bitmaps.size()) { - color_utils::GridSampler sampler; - web_app_info->generated_icon_color = - color_utils::CalculateKMeanColorOfBitmap( - resized_bitmaps.begin()->second.bitmap); - } - - // Work out what icons we need to generate here. Icons are only generated if - // there is no icon in the required size. - std::set<int> generate_sizes; - for (int size : sizes_to_generate) { - if (resized_bitmaps.find(size) == resized_bitmaps.end()) - generate_sizes.insert(size); - } - GenerateIcons(generate_sizes, web_app_info->app_url, - web_app_info->generated_icon_color, &resized_bitmaps); - + web_app_info->generated_icon_color = generated_icon_color; return resized_bitmaps; } // static void BookmarkAppHelper::UpdateWebAppIconsWithoutChangingLinks( - std::map<int, BookmarkAppHelper::BitmapAndSource> bitmap_map, + std::map<int, web_app::BitmapAndSource> bitmap_map, WebApplicationInfo* web_app_info) { // First add in the icon data that have urls with the url / size data from the // original web app info, and the data from the new icons (if any). @@ -528,17 +347,6 @@ } } -BookmarkAppHelper::BitmapAndSource::BitmapAndSource() { -} - -BookmarkAppHelper::BitmapAndSource::BitmapAndSource(const GURL& source_url_p, - const SkBitmap& bitmap_p) - : source_url(source_url_p), - bitmap(bitmap_p) { -} - -BookmarkAppHelper::BitmapAndSource::~BitmapAndSource() { -} BookmarkAppHelper::BookmarkAppHelper(Profile* profile, WebApplicationInfo web_app_info, @@ -676,13 +484,14 @@ return; } - std::vector<BitmapAndSource> downloaded_icons; + std::vector<web_app::BitmapAndSource> downloaded_icons; for (const std::pair<GURL, std::vector<SkBitmap>>& url_bitmap : bitmaps) { for (const SkBitmap& bitmap : url_bitmap.second) { if (bitmap.empty() || bitmap.width() != bitmap.height()) continue; - downloaded_icons.push_back(BitmapAndSource(url_bitmap.first, bitmap)); + downloaded_icons.push_back( + web_app::BitmapAndSource(url_bitmap.first, bitmap)); } } @@ -690,7 +499,7 @@ for (const WebApplicationInfo::IconInfo& icon_info : web_app_info_.icons) { const SkBitmap& icon = icon_info.data; if (!icon.drawsNothing() && icon.width() == icon.height()) { - downloaded_icons.push_back(BitmapAndSource(icon_info.url, icon)); + downloaded_icons.push_back(web_app::BitmapAndSource(icon_info.url, icon)); } } @@ -698,8 +507,9 @@ // icons down to smaller sizes, and generating icons for sizes where resizing // is not possible. web_app_info_.generated_icon_color = SK_ColorTRANSPARENT; - std::map<int, BitmapAndSource> size_to_icons = ResizeIconsAndGenerateMissing( - downloaded_icons, SizesToGenerate(), &web_app_info_); + std::map<int, web_app::BitmapAndSource> size_to_icons = + ResizeIconsAndGenerateMissing(downloaded_icons, SizesToGenerate(), + &web_app_info_); ReplaceWebAppIcons(size_to_icons, &web_app_info_); web_app_icon_downloader_.reset();
diff --git a/chrome/browser/extensions/bookmark_app_helper.h b/chrome/browser/extensions/bookmark_app_helper.h index 31827d5a0..382dd3c9 100644 --- a/chrome/browser/extensions/bookmark_app_helper.h +++ b/chrome/browser/extensions/bookmark_app_helper.h
@@ -15,6 +15,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/installable/installable_metrics.h" +#include "chrome/browser/web_applications/components/web_app_icon_generator.h" #include "chrome/common/web_application_info.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -45,15 +46,6 @@ kUnknown, }; - struct BitmapAndSource { - BitmapAndSource(); - BitmapAndSource(const GURL& source_url_p, const SkBitmap& bitmap_p); - ~BitmapAndSource(); - - GURL source_url; - SkBitmap bitmap; - }; - typedef base::Callback<void(const Extension*, const WebApplicationInfo&)> CreateBookmarkAppCallback; @@ -75,24 +67,10 @@ WebApplicationInfo* web_app_info, ForInstallableSite installable_site); - // This finds the closest not-smaller bitmap in |bitmaps| for each size in - // |sizes| and resizes it to that size. This returns a map of sizes to bitmaps - // which contains only bitmaps of a size in |sizes| and at most one bitmap of - // each size. - static std::map<int, BitmapAndSource> ConstrainBitmapsToSizes( - const std::vector<BitmapAndSource>& bitmaps, - const std::set<int>& sizes); - // Adds a square container icon of |output_size| and 2 * |output_size| pixels // to |bitmaps| by drawing the given |letter| into a rounded background of // |color|. For each size, if an icon of the requested size already exists in - // |bitmaps|, nothing will happen. - static void GenerateIcon(std::map<int, BitmapAndSource>* bitmaps, - int output_size, - SkColor color, - char letter); - - // Same as above, but the generated icon is returned in a + // |bitmaps|, nothing will happen. The generated icon is returned in a // `WebApplicationInfo::IconInfo`. static WebApplicationInfo::IconInfo GenerateIconInfo(int output_size, SkColor color, @@ -105,8 +83,8 @@ // Resize icons to the accepted sizes, and generate any that are missing. Does // not update |web_app_info| except to update |generated_icon_color|. - static std::map<int, BitmapAndSource> ResizeIconsAndGenerateMissing( - std::vector<BitmapAndSource> icons, + static std::map<int, web_app::BitmapAndSource> ResizeIconsAndGenerateMissing( + std::vector<web_app::BitmapAndSource> icons, std::set<int> sizes_to_generate, WebApplicationInfo* web_app_info); @@ -118,7 +96,7 @@ // |bitmap_map| that has a URL and size matching that in |web_app_info|, as // well as adding any new images from |bitmap_map| that have no URL. static void UpdateWebAppIconsWithoutChangingLinks( - std::map<int, BookmarkAppHelper::BitmapAndSource> bitmap_map, + std::map<int, web_app::BitmapAndSource> bitmap_map, WebApplicationInfo* web_app_info); // Begins the asynchronous bookmark app creation.
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc index 3255caa..4c430cf 100644 --- a/chrome/browser/extensions/bookmark_app_helper_unittest.cc +++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -53,18 +53,11 @@ const char kAppIcon3[] = "fav3.png"; const char kAppIconURL1[] = "http://foo.com/1.png"; const char kAppIconURL2[] = "http://foo.com/2.png"; -const char kAppIconURL3[] = "http://foo.com/3.png"; -const char kAppIconURL4[] = "http://foo.com/4.png"; const int kIconSizeTiny = extension_misc::EXTENSION_ICON_BITTY; const int kIconSizeSmall = extension_misc::EXTENSION_ICON_SMALL; const int kIconSizeMedium = extension_misc::EXTENSION_ICON_MEDIUM; const int kIconSizeLarge = extension_misc::EXTENSION_ICON_LARGE; -const int kIconSizeGigantor = extension_misc::EXTENSION_ICON_GIGANTOR; -const int kIconSizeUnsupported = 123; - -const int kIconSizeSmallBetweenMediumAndLarge = 63; -const int kIconSizeLargeBetweenMediumAndLarge = 96; class BookmarkAppHelperTest : public testing::Test { public: @@ -112,20 +105,6 @@ return bitmap; } -BookmarkAppHelper::BitmapAndSource CreateSquareBitmapAndSourceWithColor( - int size, - SkColor color) { - return BookmarkAppHelper::BitmapAndSource( - GURL(), CreateSquareBitmapWithColor(size, color)); -} - -void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) { - // Obtain pixel lock to access pixels. - EXPECT_EQ(color, bitmap.getColor(0, 0)); - EXPECT_EQ(size, bitmap.width()); - EXPECT_EQ(size, bitmap.height()); -} - WebApplicationInfo::IconInfo CreateIconInfoWithBitmap(int size, SkColor color) { WebApplicationInfo::IconInfo icon_info; icon_info.width = size; @@ -134,152 +113,6 @@ return icon_info; } -std::set<int> TestSizesToGenerate() { - const int kIconSizesToGenerate[] = { - extension_misc::EXTENSION_ICON_SMALL, - extension_misc::EXTENSION_ICON_MEDIUM, - extension_misc::EXTENSION_ICON_LARGE, - }; - return std::set<int>(kIconSizesToGenerate, - kIconSizesToGenerate + arraysize(kIconSizesToGenerate)); -} - -void ValidateAllIconsWithURLsArePresent(const WebApplicationInfo& info_to_check, - const WebApplicationInfo& other_info) { - for (const auto& icon : info_to_check.icons) { - if (!icon.url.is_empty()) { - bool found = false; - for (const auto& other_icon : info_to_check.icons) { - if (other_icon.url == icon.url && other_icon.width == icon.width) { - found = true; - break; - } - } - EXPECT_TRUE(found); - } - } -} - -std::vector<BookmarkAppHelper::BitmapAndSource>::const_iterator -FindLargestBitmapAndSourceVector( - const std::vector<BookmarkAppHelper::BitmapAndSource>& bitmap_vector) { - auto result = bitmap_vector.end(); - int largest = -1; - for (std::vector<BookmarkAppHelper::BitmapAndSource>::const_iterator it = - bitmap_vector.begin(); - it != bitmap_vector.end(); ++it) { - if (it->bitmap.width() > largest) { - result = it; - } - } - return result; -} - -std::vector<BookmarkAppHelper::BitmapAndSource>::const_iterator -FindMatchingBitmapAndSourceVector( - const std::vector<BookmarkAppHelper::BitmapAndSource>& bitmap_vector, - int size) { - for (std::vector<BookmarkAppHelper::BitmapAndSource>::const_iterator it = - bitmap_vector.begin(); - it != bitmap_vector.end(); ++it) { - if (it->bitmap.width() == size) { - return it; - } - } - return bitmap_vector.end(); -} - -std::vector<BookmarkAppHelper::BitmapAndSource>::const_iterator -FindEqualOrLargerBitmapAndSourceVector( - const std::vector<BookmarkAppHelper::BitmapAndSource>& bitmap_vector, - int size) { - for (std::vector<BookmarkAppHelper::BitmapAndSource>::const_iterator it = - bitmap_vector.begin(); - it != bitmap_vector.end(); ++it) { - if (it->bitmap.width() >= size) { - return it; - } - } - return bitmap_vector.end(); -} - -void ValidateIconsGeneratedAndResizedCorrectly( - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded, - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map, - std::set<int> sizes_to_generate, - int expected_generated, - int expected_resized) { - GURL empty_url(""); - int number_generated = 0; - int number_resized = 0; - - auto icon_largest = FindLargestBitmapAndSourceVector(downloaded); - for (const auto& size : sizes_to_generate) { - auto icon_downloaded = FindMatchingBitmapAndSourceVector(downloaded, size); - auto icon_larger = FindEqualOrLargerBitmapAndSourceVector(downloaded, size); - if (icon_downloaded == downloaded.end()) { - auto icon_resized = size_map.find(size); - if (icon_largest == downloaded.end()) { - // There are no downloaded icons. Expect an icon to be generated. - EXPECT_NE(size_map.end(), icon_resized); - EXPECT_EQ(size, icon_resized->second.bitmap.width()); - EXPECT_EQ(size, icon_resized->second.bitmap.height()); - EXPECT_EQ(size, icon_resized->second.bitmap.height()); - EXPECT_EQ(empty_url, icon_resized->second.source_url); - ++number_generated; - } else { - // If there is a larger downloaded icon, it should be resized. Otherwise - // the largest downloaded icon should be resized. - auto icon_to_resize = icon_largest; - if (icon_larger != downloaded.end()) - icon_to_resize = icon_larger; - EXPECT_NE(size_map.end(), icon_resized); - EXPECT_EQ(size, icon_resized->second.bitmap.width()); - EXPECT_EQ(size, icon_resized->second.bitmap.height()); - EXPECT_EQ(size, icon_resized->second.bitmap.height()); - EXPECT_EQ(icon_to_resize->source_url, icon_resized->second.source_url); - ++number_resized; - } - } else { - // There is an icon of exactly this size downloaded. Expect no icon to be - // generated, and the existing downloaded icon to be used. - auto icon_resized = size_map.find(size); - EXPECT_NE(size_map.end(), icon_resized); - EXPECT_EQ(size, icon_resized->second.bitmap.width()); - EXPECT_EQ(size, icon_resized->second.bitmap.height()); - EXPECT_EQ(size, icon_downloaded->bitmap.width()); - EXPECT_EQ(size, icon_downloaded->bitmap.height()); - EXPECT_EQ(icon_downloaded->source_url, icon_resized->second.source_url); - } - } - EXPECT_EQ(expected_generated, number_generated); - EXPECT_EQ(expected_resized, number_resized); -} - -void TestIconGeneration(int icon_size, - int expected_generated, - int expected_resized) { - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded; - - // Add an icon with a URL and bitmap. 'Download' it. - WebApplicationInfo::IconInfo icon_info = - CreateIconInfoWithBitmap(icon_size, SK_ColorRED); - icon_info.url = GURL(kAppIconURL1); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - // Now run the resizing/generation and validation. - WebApplicationInfo web_app_info; - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map = - BookmarkAppHelper::ResizeIconsAndGenerateMissing( - downloaded, TestSizesToGenerate(), &web_app_info); - - ValidateIconsGeneratedAndResizedCorrectly(downloaded, size_map, - TestSizesToGenerate(), - expected_generated, - expected_resized); -} - class TestBookmarkAppHelper : public BookmarkAppHelper { public: TestBookmarkAppHelper(ExtensionService* service, @@ -691,53 +524,6 @@ } } -TEST_F(BookmarkAppHelperExtensionServiceTest, LinkedAppIconsAreNotChanged) { - WebApplicationInfo web_app_info; - - // Add two icons with a URL and bitmap, two icons with just a bitmap, an - // icon with just URL and an icon in an unsupported size with just a URL. - WebApplicationInfo::IconInfo icon_info = - CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED); - icon_info.url = GURL(kAppIconURL1); - web_app_info.icons.push_back(icon_info); - - icon_info = CreateIconInfoWithBitmap(kIconSizeMedium, SK_ColorRED); - icon_info.url = GURL(kAppIconURL2); - web_app_info.icons.push_back(icon_info); - - icon_info.data = SkBitmap(); - icon_info.url = GURL(kAppIconURL3); - icon_info.width = 0; - icon_info.height = 0; - web_app_info.icons.push_back(icon_info); - - icon_info.url = GURL(kAppIconURL4); - web_app_info.icons.push_back(icon_info); - - icon_info = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorRED); - web_app_info.icons.push_back(icon_info); - - icon_info = CreateIconInfoWithBitmap(kIconSizeUnsupported, SK_ColorRED); - web_app_info.icons.push_back(icon_info); - - // 'Download' one of the icons without a size or bitmap. - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded; - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - GURL(kAppIconURL3), - CreateSquareBitmapWithColor(kIconSizeLarge, SK_ColorBLACK))); - - // Now run the resizing and generation into a new web app info. - WebApplicationInfo new_web_app_info; - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map = - BookmarkAppHelper::ResizeIconsAndGenerateMissing( - downloaded, TestSizesToGenerate(), &new_web_app_info); - - // Now check that the linked app icons (i.e. those with URLs) are matching in - // both lists. - ValidateAllIconsWithURLsArePresent(web_app_info, new_web_app_info); - ValidateAllIconsWithURLsArePresent(new_web_app_info, web_app_info); -} - TEST_F(BookmarkAppHelperTest, UpdateWebAppInfoFromManifest) { WebApplicationInfo web_app_info; web_app_info.title = base::UTF8ToUTF16(kAlternativeAppTitle); @@ -812,53 +598,6 @@ } } -TEST_F(BookmarkAppHelperTest, ConstrainBitmapsToSizes) { - std::set<int> desired_sizes; - desired_sizes.insert(16); - desired_sizes.insert(32); - desired_sizes.insert(48); - desired_sizes.insert(96); - desired_sizes.insert(128); - desired_sizes.insert(256); - - { - std::vector<BookmarkAppHelper::BitmapAndSource> bitmaps; - bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(16, SK_ColorRED)); - bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(32, SK_ColorGREEN)); - bitmaps.push_back( - CreateSquareBitmapAndSourceWithColor(144, SK_ColorYELLOW)); - - std::map<int, BookmarkAppHelper::BitmapAndSource> results( - BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes)); - - EXPECT_EQ(6u, results.size()); - ValidateBitmapSizeAndColor(results[16].bitmap, 16, SK_ColorRED); - ValidateBitmapSizeAndColor(results[32].bitmap, 32, SK_ColorGREEN); - ValidateBitmapSizeAndColor(results[48].bitmap, 48, SK_ColorYELLOW); - ValidateBitmapSizeAndColor(results[96].bitmap, 96, SK_ColorYELLOW); - ValidateBitmapSizeAndColor(results[128].bitmap, 128, SK_ColorYELLOW); - ValidateBitmapSizeAndColor(results[256].bitmap, 256, SK_ColorYELLOW); - } - { - std::vector<BookmarkAppHelper::BitmapAndSource> bitmaps; - bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(512, SK_ColorRED)); - bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(18, SK_ColorGREEN)); - bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(33, SK_ColorBLUE)); - bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(17, SK_ColorYELLOW)); - - std::map<int, BookmarkAppHelper::BitmapAndSource> results( - BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes)); - - EXPECT_EQ(6u, results.size()); - ValidateBitmapSizeAndColor(results[16].bitmap, 16, SK_ColorYELLOW); - ValidateBitmapSizeAndColor(results[32].bitmap, 32, SK_ColorBLUE); - ValidateBitmapSizeAndColor(results[48].bitmap, 48, SK_ColorRED); - ValidateBitmapSizeAndColor(results[96].bitmap, 96, SK_ColorRED); - ValidateBitmapSizeAndColor(results[128].bitmap, 128, SK_ColorRED); - ValidateBitmapSizeAndColor(results[256].bitmap, 256, SK_ColorRED); - } -} - TEST_F(BookmarkAppHelperTest, IsValidBookmarkAppUrl) { EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://chromium.org"))); EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://www.chromium.org"))); @@ -879,140 +618,4 @@ EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("chrome://extensions"))); } -TEST_F(BookmarkAppHelperTest, IconsResizedFromOddSizes) { - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded; - - // Add three icons with a URL and bitmap. 'Download' each of them. - WebApplicationInfo::IconInfo icon_info = - CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED); - icon_info.url = GURL(kAppIconURL1); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - icon_info = CreateIconInfoWithBitmap(kIconSizeSmallBetweenMediumAndLarge, - SK_ColorRED); - icon_info.url = GURL(kAppIconURL2); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - icon_info = CreateIconInfoWithBitmap(kIconSizeLargeBetweenMediumAndLarge, - SK_ColorRED); - icon_info.url = GURL(kAppIconURL3); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - // Now run the resizing and generation. - WebApplicationInfo web_app_info; - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map = - BookmarkAppHelper::ResizeIconsAndGenerateMissing( - downloaded, TestSizesToGenerate(), &web_app_info); - - // No icons should be generated. The LARGE and MEDIUM sizes should be resized. - ValidateIconsGeneratedAndResizedCorrectly( - downloaded, size_map, TestSizesToGenerate(), 0, 2); -} - -TEST_F(BookmarkAppHelperTest, IconsResizedFromLarger) { - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded; - - // Add three icons with a URL and bitmap. 'Download' two of them and pretend - // the third failed to download. - WebApplicationInfo::IconInfo icon_info = - CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED); - icon_info.url = GURL(kAppIconURL1); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - icon_info = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorBLUE); - icon_info.url = GURL(kAppIconURL2); - - icon_info = CreateIconInfoWithBitmap(kIconSizeGigantor, SK_ColorBLACK); - icon_info.url = GURL(kAppIconURL3); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - // Now run the resizing and generation. - WebApplicationInfo web_app_info; - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map = - BookmarkAppHelper::ResizeIconsAndGenerateMissing( - downloaded, TestSizesToGenerate(), &web_app_info); - - // Expect icon for MEDIUM and LARGE to be resized from the gigantor icon - // as it was not downloaded. - ValidateIconsGeneratedAndResizedCorrectly( - downloaded, size_map, TestSizesToGenerate(), 0, 2); -} - -TEST_F(BookmarkAppHelperTest, AllIconsGeneratedWhenNotDownloaded) { - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded; - - // Add three icons with a URL and bitmap. 'Download' none of them. - WebApplicationInfo::IconInfo icon_info = - CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED); - icon_info.url = GURL(kAppIconURL1); - - icon_info = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorBLUE); - icon_info.url = GURL(kAppIconURL2); - - icon_info = CreateIconInfoWithBitmap(kIconSizeGigantor, SK_ColorBLACK); - icon_info.url = GURL(kAppIconURL3); - - // Now run the resizing and generation. - WebApplicationInfo web_app_info; - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map = - BookmarkAppHelper::ResizeIconsAndGenerateMissing( - downloaded, TestSizesToGenerate(), &web_app_info); - - // Expect all icons to be generated. - ValidateIconsGeneratedAndResizedCorrectly( - downloaded, size_map, TestSizesToGenerate(), 3, 0); -} - -TEST_F(BookmarkAppHelperTest, IconResizedFromLargerAndSmaller) { - std::vector<BookmarkAppHelper::BitmapAndSource> downloaded; - - // Pretend the huge icon wasn't downloaded but two smaller ones were. - WebApplicationInfo::IconInfo icon_info = - CreateIconInfoWithBitmap(kIconSizeTiny, SK_ColorRED); - icon_info.url = GURL(kAppIconURL1); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - icon_info = CreateIconInfoWithBitmap(kIconSizeMedium, SK_ColorBLUE); - icon_info.url = GURL(kAppIconURL2); - downloaded.push_back(BookmarkAppHelper::BitmapAndSource( - icon_info.url, icon_info.data)); - - icon_info = CreateIconInfoWithBitmap(kIconSizeGigantor, SK_ColorBLACK); - icon_info.url = GURL(kAppIconURL3); - - // Now run the resizing and generation. - WebApplicationInfo web_app_info; - std::map<int, BookmarkAppHelper::BitmapAndSource> size_map = - BookmarkAppHelper::ResizeIconsAndGenerateMissing( - downloaded, TestSizesToGenerate(), &web_app_info); - - // Expect no icons to be generated, but the LARGE and SMALL icons to be - // resized from the MEDIUM icon. - ValidateIconsGeneratedAndResizedCorrectly( - downloaded, size_map, TestSizesToGenerate(), 0, 2); - - // Verify specifically that the LARGE icons was resized from the medium icon. - const auto it = size_map.find(kIconSizeLarge); - EXPECT_NE(size_map.end(), it); - EXPECT_EQ(GURL(kAppIconURL2), it->second.source_url); -} - -TEST_F(BookmarkAppHelperTest, IconsResizedWhenOnlyATinyOneIsProvided) { - // When only a tiny icon is downloaded (smaller than the three desired - // sizes), 3 icons should be resized. - TestIconGeneration(kIconSizeTiny, 0, 3); -} - -TEST_F(BookmarkAppHelperTest, IconsResizedWhenOnlyAGigantorOneIsProvided) { - // When an enormous icon is provided, each desired icon size should be resized - // from it, and no icons should be generated. - TestIconGeneration(kIconSizeGigantor, 0, 3); -} - } // namespace extensions
diff --git a/chrome/browser/extensions/dev_mode_bubble_delegate.cc b/chrome/browser/extensions/dev_mode_bubble_delegate.cc index 0be3704..2cb5204 100644 --- a/chrome/browser/extensions/dev_mode_bubble_delegate.cc +++ b/chrome/browser/extensions/dev_mode_bubble_delegate.cc
@@ -17,7 +17,6 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_system.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/ui_features.h" namespace extensions { @@ -76,13 +75,6 @@ } base::string16 DevModeBubbleDelegate::GetDismissButtonLabel() const { -// TODO(https://crbug.com/671656): Keep the cancel button on MACOSX unless -// using views or the Cocoa version is updated. -#if defined(OS_MACOSX) - if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) - return l10n_util::GetStringUTF16(IDS_CANCEL); -#endif - return base::string16(); }
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 99567696..7dd201c 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -443,6 +443,11 @@ const char kEnableCaptivePortalRandomUrlDescription[] = "Enable Captive Portal URL randomization."; +const char kEnableChromevoxDeveloperOptionName[] = + "Enable Chromevox developer option"; +const char kEnableChromevoxDeveloperOptionDescription[] = + "This option provides tools for developing in chromevox."; + const char kEnableClientLoFiName[] = "Client-side Lo-Fi previews"; const char kEnableClientLoFiDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index da903110..feb88988 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -299,6 +299,9 @@ extern const char kEnableCaptivePortalRandomUrl[]; extern const char kEnableCaptivePortalRandomUrlDescription[]; +extern const char kEnableChromevoxDeveloperOptionName[]; +extern const char kEnableChromevoxDeveloperOptionDescription[]; + extern const char kEnableClientLoFiName[]; extern const char kEnableClientLoFiDescription[];
diff --git a/chrome/browser/global_keyboard_shortcuts_mac.mm b/chrome/browser/global_keyboard_shortcuts_mac.mm index 86402d4..0cfb801 100644 --- a/chrome/browser/global_keyboard_shortcuts_mac.mm +++ b/chrome/browser/global_keyboard_shortcuts_mac.mm
@@ -18,11 +18,28 @@ #import "chrome/browser/ui/cocoa/nsmenuitem_additions.h" #include "chrome/browser/ui/views_mode_controller.h" #include "ui/base/accelerators/accelerator.h" +#include "ui/base/accelerators/platform_accelerator_cocoa.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_code_conversion_mac.h" namespace { +// Returns a ui::Accelerator given a KeyboardShortcutData. +ui::Accelerator AcceleratorFromShortcut(const KeyboardShortcutData& shortcut) { + int modifiers = 0; + if (shortcut.command_key) + modifiers |= ui::EF_COMMAND_DOWN; + if (shortcut.shift_key) + modifiers |= ui::EF_SHIFT_DOWN; + if (shortcut.cntrl_key) + modifiers |= ui::EF_CONTROL_DOWN; + if (shortcut.opt_key) + modifiers |= ui::EF_ALT_DOWN; + + return ui::Accelerator(ui::KeyboardCodeFromKeyCode(shortcut.vkey_code), + modifiers); +} + // Returns the menu item associated with |key| in |menu|, or nil if not found. NSMenuItem* FindMenuItem(NSEvent* key, NSMenu* menu) { NSMenuItem* result = nil; @@ -154,6 +171,30 @@ return *keys; } +const std::vector<NSMenuItem*>& GetMenuItemsNotPresentInMainMenu() { + static base::NoDestructor<std::vector<NSMenuItem*>> menu_items; + if (menu_items->empty()) { + for (const auto& shortcut : GetShortcutsNotPresentInMainMenu()) { + ui::Accelerator accelerator = AcceleratorFromShortcut(shortcut); + NSString* key_equivalent = nil; + NSUInteger modifier_mask = 0; + ui::GetKeyEquivalentAndModifierMaskFromAccelerator( + accelerator, &key_equivalent, &modifier_mask); + + // Intentionally leaked! + NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:@"" + action:NULL + keyEquivalent:key_equivalent]; + item.keyEquivalentModifierMask = modifier_mask; + + // We store the command in the tag. + item.tag = shortcut.chrome_command; + menu_items->push_back(item); + } + } + return *menu_items; +} + CommandForKeyEventResult CommandForKeyEvent(NSEvent* event) { DCHECK(event); if ([event type] != NSKeyDown) @@ -163,21 +204,11 @@ if (cmdNum != -1) return MainMenuCommand(cmdNum); - // Look in secondary keyboard shortcuts. - NSUInteger modifiers = [event modifierFlags]; - const bool cmdKey = (modifiers & NSCommandKeyMask) != 0; - const bool shiftKey = (modifiers & NSShiftKeyMask) != 0; - const bool cntrlKey = (modifiers & NSControlKeyMask) != 0; - const bool optKey = (modifiers & NSAlternateKeyMask) != 0; - const int keyCode = [event keyCode]; - // Scan through keycodes and see if it corresponds to one of the non-menu // shortcuts. - for (const auto& shortcut : GetShortcutsNotPresentInMainMenu()) { - if (MatchesEventForKeyboardShortcut(shortcut, cmdKey, shiftKey, cntrlKey, - optKey, keyCode)) { - return ShortcutCommand(shortcut.chrome_command); - } + for (NSMenuItem* menu_item : GetMenuItemsNotPresentInMainMenu()) { + if ([menu_item cr_firesForKeyEvent:event]) + return ShortcutCommand(menu_item.tag); } return NoCommand(); @@ -226,18 +257,7 @@ // See if it corresponds to one of the non-menu shortcuts. for (const auto& shortcut : GetShortcutsNotPresentInMainMenu()) { if (shortcut.chrome_command == command_id) { - int modifiers = 0; - if (shortcut.command_key) - modifiers |= ui::EF_COMMAND_DOWN; - if (shortcut.shift_key) - modifiers |= ui::EF_SHIFT_DOWN; - if (shortcut.cntrl_key) - modifiers |= ui::EF_CONTROL_DOWN; - if (shortcut.opt_key) - modifiers |= ui::EF_ALT_DOWN; - - *accelerator = ui::Accelerator( - ui::KeyboardCodeFromKeyCode(shortcut.vkey_code), modifiers); + *accelerator = AcceleratorFromShortcut(shortcut); return true; } }
diff --git a/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm b/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm index efd5857..df9f519 100644 --- a/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm +++ b/chrome/browser/global_keyboard_shortcuts_mac_unittest.mm
@@ -13,6 +13,7 @@ #include "chrome/app/chrome_command_ids.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ui_features.h" +#include "ui/events/keycodes/keyboard_code_conversion_mac.h" namespace { @@ -31,19 +32,25 @@ if (opt_key) modifierFlags |= NSAlternateKeyMask; - // Use a two-length string as a dummy character. - NSString* chars = @"ab"; + unichar shifted_character; + unichar character; + int result = ui::MacKeyCodeForWindowsKeyCode( + ui::KeyboardCodeFromKeyCode(vkey_code), modifierFlags, &shifted_character, + &character); + DCHECK_NE(result, -1); - NSEvent* event = [NSEvent keyEventWithType:NSKeyDown - location:NSZeroPoint - modifierFlags:modifierFlags - timestamp:0.0 - windowNumber:0 - context:nil - characters:chars - charactersIgnoringModifiers:chars - isARepeat:NO - keyCode:vkey_code]; + NSEvent* event = [NSEvent + keyEventWithType:NSKeyDown + location:NSZeroPoint + modifierFlags:modifierFlags + timestamp:0.0 + windowNumber:0 + context:nil + characters:[NSString stringWithFormat:@"%C", character] + charactersIgnoringModifiers:[NSString + stringWithFormat:@"%C", shifted_character] + isARepeat:NO + keyCode:vkey_code]; return CommandForKeyEvent(event).chrome_command; } @@ -86,20 +93,21 @@ {kVK_ANSI_9, kVK_ANSI_Keypad9}, }; + // We only consider unshifted keys. A shifted numpad key gives a different + // keyEquivalent than a shifted number key. + int shift = 0; for (unsigned int i = 0; i < base::size(equivalents); ++i) { for (int command = 0; command <= 1; ++command) { - for (int shift = 0; shift <= 1; ++shift) { - for (int control = 0; control <= 1; ++control) { - for (int option = 0; option <= 1; ++option) { - EXPECT_EQ(CommandForKeys(command, shift, control, option, - equivalents[i].keycode), - CommandForKeys(command, shift, control, option, - equivalents[i].keypad_keycode)); - EXPECT_EQ(CommandForKeys(command, shift, control, option, - equivalents[i].keycode), - CommandForKeys(command, shift, control, option, - equivalents[i].keypad_keycode)); - } + for (int control = 0; control <= 1; ++control) { + for (int option = 0; option <= 1; ++option) { + EXPECT_EQ(CommandForKeys(command, shift, control, option, + equivalents[i].keycode), + CommandForKeys(command, shift, control, option, + equivalents[i].keypad_keycode)); + EXPECT_EQ(CommandForKeys(command, shift, control, option, + equivalents[i].keycode), + CommandForKeys(command, shift, control, option, + equivalents[i].keypad_keycode)); } } }
diff --git a/chrome/browser/intranet_redirect_detector.cc b/chrome/browser/intranet_redirect_detector.cc index b7c2862..283d0c2 100644 --- a/chrome/browser/intranet_redirect_detector.cc +++ b/chrome/browser/intranet_redirect_detector.cc
@@ -22,6 +22,7 @@ #include "components/prefs/pref_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" @@ -48,13 +49,11 @@ weak_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(kStartFetchDelaySeconds)); - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); } IntranetRedirectDetector::~IntranetRedirectDetector() { - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); } // static
diff --git a/chrome/browser/media/router/discovery/dial/dial_registry.cc b/chrome/browser/media/router/discovery/dial/dial_registry.cc index 9cb3142..889d7d61 100644 --- a/chrome/browser/media/router/discovery/dial/dial_registry.cc +++ b/chrome/browser/media/router/discovery/dial/dial_registry.cc
@@ -12,10 +12,10 @@ #include "base/time/default_clock.h" #include "base/time/time.h" #include "base/values.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/media/router/discovery/dial/dial_device_data.h" #include "chrome/browser/media/router/discovery/dial/dial_service.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" using base::Time; using base::TimeDelta; @@ -49,8 +49,7 @@ DCHECK_GT(max_devices_, 0U); BrowserThread::PostTaskAndReplyWithResult( BrowserThread::UI, FROM_HERE, - base::BindOnce(&BrowserProcess::network_connection_tracker, - base::Unretained(g_browser_process)), + base::BindOnce(&content::GetNetworkConnectionTracker), base::BindOnce(&DialRegistry::SetNetworkConnectionTracker, base::Unretained(this))); }
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor.cc b/chrome/browser/media/router/discovery/discovery_network_monitor.cc index a7074b9..75b250bf 100644 --- a/chrome/browser/media/router/discovery/discovery_network_monitor.cc +++ b/chrome/browser/media/router/discovery/discovery_network_monitor.cc
@@ -16,9 +16,9 @@ #include "base/task/task_traits.h" #include "base/task_runner_util.h" #include "base/time/default_tick_clock.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/media/router/discovery/discovery_network_list.h" #include "chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.h" +#include "content/public/browser/network_service_instance.h" #include "net/base/network_interfaces.h" namespace media_router { @@ -106,7 +106,7 @@ DETACH_FROM_SEQUENCE(sequence_checker_); AddObserver(metric_observer_.get()); - g_browser_process->network_connection_tracker() + content::GetNetworkConnectionTracker() ->AddLeakyNetworkConnectionObserver(this); task_runner_->PostTask(
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor_unittest.cc b/chrome/browser/media/router/discovery/discovery_network_monitor_unittest.cc index f8a443e..ceb0b07 100644 --- a/chrome/browser/media/router/discovery/discovery_network_monitor_unittest.cc +++ b/chrome/browser/media/router/discovery/discovery_network_monitor_unittest.cc
@@ -8,7 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/task/task_scheduler/task_scheduler.h" -#include "base/test/scoped_task_environment.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -31,7 +31,7 @@ fake_network_info.clear(); discovery_network_monitor = DiscoveryNetworkMonitor::CreateInstanceForTest(&FakeGetNetworkInfo); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); } static std::vector<DiscoveryNetworkInfo> FakeGetNetworkInfo() { @@ -42,7 +42,7 @@ discovery_network_monitor->OnConnectionChanged(connection_type); } - base::test::ScopedTaskEnvironment scoped_task_environment; + content::TestBrowserThreadBundle thread_bundle; MockDiscoveryObserver mock_observer; std::vector<DiscoveryNetworkInfo> fake_ethernet_info{ @@ -72,7 +72,7 @@ .WillOnce(Invoke(capture_network_id)); ChangeConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); std::string ethernet_network_id = current_network_id; @@ -81,14 +81,14 @@ .WillOnce(Invoke(capture_network_id)); ChangeConnectionType(network::mojom::ConnectionType::CONNECTION_NONE); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); fake_network_info = fake_wifi_info; EXPECT_CALL(mock_observer, OnNetworksChanged(_)) .WillOnce(Invoke(capture_network_id)); ChangeConnectionType(network::mojom::ConnectionType::CONNECTION_WIFI); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); std::string wifi_network_id = current_network_id; fake_network_info = fake_ethernet_info; @@ -96,7 +96,7 @@ .WillOnce(Invoke(capture_network_id)); ChangeConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); EXPECT_EQ(ethernet_network_id, current_network_id); EXPECT_NE(ethernet_network_id, wifi_network_id); @@ -111,13 +111,13 @@ EXPECT_CALL(mock_observer, OnNetworksChanged(_)); ChangeConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); discovery_network_monitor->RemoveObserver(&mock_observer); fake_network_info.clear(); ChangeConnectionType(network::mojom::ConnectionType::CONNECTION_NONE); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorTest, RefreshIndependentOfChangeObserver) { @@ -133,11 +133,11 @@ }; discovery_network_monitor->Refresh(base::BindOnce(force_refresh_callback)); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorTest, GetNetworkIdWithoutRefresh) { - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); fake_network_info = fake_ethernet_info; @@ -145,7 +145,7 @@ EXPECT_EQ(DiscoveryNetworkMonitor::kNetworkIdDisconnected, network_id); }; discovery_network_monitor->GetNetworkId(base::BindOnce(check_network_id)); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorTest, GetNetworkIdWithRefresh) { @@ -162,7 +162,7 @@ }; discovery_network_monitor->Refresh( base::BindOnce(capture_network_id, ¤t_network_id)); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); auto check_network_id = [](const std::string& refresh_network_id, const std::string& network_id) { @@ -170,7 +170,7 @@ }; discovery_network_monitor->GetNetworkId( base::BindOnce(check_network_id, base::ConstRef(current_network_id))); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); } TEST_F(DiscoveryNetworkMonitorTest, GetNetworkIdWithObserver) { @@ -180,7 +180,7 @@ EXPECT_CALL(mock_observer, OnNetworksChanged(_)); ChangeConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); std::string current_network_id; auto check_network_id = [](const std::string& network_id) { @@ -190,7 +190,7 @@ network_id); }; discovery_network_monitor->GetNetworkId(base::BindOnce(check_network_id)); - scoped_task_environment.RunUntilIdle(); + thread_bundle.RunUntilIdle(); } } // namespace media_router
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc index eae926aa..f4c8e72 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
@@ -13,6 +13,7 @@ #include "components/prefs/pref_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/render_process_host.h" namespace { @@ -527,7 +528,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); network::NetworkConnectionTracker* network_connection_tracker = - g_browser_process->network_connection_tracker(); + content::GetNetworkConnectionTracker(); DCHECK(network_connection_tracker); net::URLRequestContextGetter* url_request_context_getter =
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc index b9258c94..1cf5a9c4 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
@@ -47,6 +47,7 @@ #include "components/prefs/testing_pref_store.h" #include "components/sync_preferences/pref_service_mock_factory.h" #include "components/sync_preferences/pref_service_syncable.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_thread_bundle.h" #include "net/url_request/url_request_test_util.h" @@ -235,8 +236,9 @@ } void SetUp(std::unique_ptr<network::NetworkConnectionTracker> tracker) { - TestingBrowserProcess::GetGlobal()->SetNetworkConnectionTracker( - std::move(tracker)); + network_connection_tracker_ = std::move(tracker); + content::SetNetworkConnectionTrackerForTesting( + network_connection_tracker_.get()); SetLocalLogsObserver(&local_observer_); SetRemoteLogsObserver(&remote_observer_); LoadMainTestProfile(); @@ -674,6 +676,10 @@ // Unit under test. std::unique_ptr<WebRtcEventLogManager> event_log_manager_; + // The NetworkConnectionTracker instance used by the WebRtcEventLogManager. + std::unique_ptr<network::NetworkConnectionTracker> + network_connection_tracker_; + // Extensions associated with local/remote-bound event logs. Depends on // whether they're compressed. base::FilePath::StringPieceType local_log_extension_;
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index a0f6ff69..e89716e 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -92,6 +92,7 @@ #include "content/public/browser/notification_service.h" #include "ppapi/buildflags/buildflags.h" #include "printing/buildflags/buildflags.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #if defined(OS_ANDROID) #include "base/android/build_info.h" @@ -528,7 +529,7 @@ metrics::MetricsLogUploader::MetricServiceType service_type, const metrics::MetricsLogUploader::UploadCallback& on_upload_complete) { return std::make_unique<metrics::NetMetricsLogUploader>( - g_browser_process->system_request_context(), server_url, + g_browser_process->shared_url_loader_factory(), server_url, insecure_server_url, mime_type, service_type, on_upload_complete); }
diff --git a/chrome/browser/net/network_connection_tracker_browsertest.cc b/chrome/browser/net/network_connection_tracker_browsertest.cc index 4038f2d..d26610db 100644 --- a/chrome/browser/net/network_connection_tracker_browsertest.cc +++ b/chrome/browser/net/network_connection_tracker_browsertest.cc
@@ -10,11 +10,11 @@ #include "base/sequence_checker.h" #include "base/test/bind_test_util.h" #include "build/build_config.h" -#include "chrome/browser/browser_process_impl.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" @@ -127,7 +127,7 @@ return; #endif network::NetworkConnectionTracker* tracker = - g_browser_process->network_connection_tracker(); + content::GetNetworkConnectionTracker(); EXPECT_NE(nullptr, tracker); // Issue a GetConnectionType() request to make sure NetworkService has been // started up. This way, NetworkService will receive the broadcast when @@ -162,7 +162,7 @@ return; network::NetworkConnectionTracker* tracker = - g_browser_process->network_connection_tracker(); + content::GetNetworkConnectionTracker(); EXPECT_NE(nullptr, tracker); // Issue a GetConnectionType() request to make sure NetworkService has been
diff --git a/chrome/browser/net/variations_http_headers_browsertest.cc b/chrome/browser/net/variations_http_headers_browsertest.cc index 859cc89..cac1650 100644 --- a/chrome/browser/net/variations_http_headers_browsertest.cc +++ b/chrome/browser/net/variations_http_headers_browsertest.cc
@@ -6,10 +6,13 @@ #include <map> +#include "base/macros.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_browser_main.h" +#include "chrome/browser/chrome_browser_main_extra_parts.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -36,12 +39,34 @@ namespace { +class VariationHeaderSetter : public ChromeBrowserMainExtraParts { + public: + VariationHeaderSetter() = default; + ~VariationHeaderSetter() override = default; + + // ChromeBrowserMainExtraParts: + void PostEarlyInitialization() override { + // Set up some fake variations. + auto* variations_provider = + variations::VariationsHttpHeaderProvider::GetInstance(); + variations_provider->ForceVariationIds({"12", "456", "t789"}, ""); + } + + private: + DISALLOW_COPY_AND_ASSIGN(VariationHeaderSetter); +}; + class VariationsHttpHeadersBrowserTest : public InProcessBrowserTest { public: VariationsHttpHeadersBrowserTest() : https_server_(net::test_server::EmbeddedTestServer::TYPE_HTTPS) {} ~VariationsHttpHeadersBrowserTest() override = default; + void CreatedBrowserMainParts(content::BrowserMainParts* parts) override { + static_cast<ChromeBrowserMainParts*>(parts)->AddParts( + new VariationHeaderSetter()); + } + void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); @@ -52,11 +77,6 @@ base::Unretained(this))); ASSERT_TRUE(server()->Start()); - - // Set up some fake variations. - auto* variations_provider = - variations::VariationsHttpHeaderProvider::GetInstance(); - variations_provider->ForceVariationIds({"12", "456", "t789"}, ""); } void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/chrome/browser/payments/chrome_payment_request_delegate.cc b/chrome/browser/payments/chrome_payment_request_delegate.cc index b0a4f63..47c7d76 100644 --- a/chrome/browser/payments/chrome_payment_request_delegate.cc +++ b/chrome/browser/payments/chrome_payment_request_delegate.cc
@@ -63,9 +63,8 @@ void ChromePaymentRequestDelegate::ShowDialog(PaymentRequest* request) { DCHECK_EQ(nullptr, shown_dialog_); - hidden_dialog_ = std::unique_ptr<PaymentRequestDialog>( - chrome::CreatePaymentRequestDialog(request)); - MaybeShowHiddenDialog(request); + shown_dialog_ = chrome::CreatePaymentRequestDialog(request); + shown_dialog_->ShowDialog(); } void ChromePaymentRequestDelegate::CloseDialog() { @@ -73,9 +72,6 @@ shown_dialog_->CloseDialog(); shown_dialog_ = nullptr; } - - if (hidden_dialog_) - hidden_dialog_.reset(); } void ChromePaymentRequestDelegate::ShowErrorMessage() { @@ -180,10 +176,7 @@ void ChromePaymentRequestDelegate::EmbedPaymentHandlerWindow( const GURL& url, PaymentHandlerOpenWindowCallback callback) { - if (hidden_dialog_) { - shown_dialog_ = hidden_dialog_.release(); - shown_dialog_->ShowDialogAtPaymentHandlerSheet(url, std::move(callback)); - } else if (shown_dialog_) { + if (shown_dialog_) { shown_dialog_->ShowPaymentHandlerScreen(url, std::move(callback)); } else { std::move(callback).Run(/*success=*/false, @@ -192,14 +185,4 @@ } } -void ChromePaymentRequestDelegate::MaybeShowHiddenDialog( - PaymentRequest* request) { - if (request->SatisfiesSkipUIConstraints()) { - request->Pay(); - } else { - shown_dialog_ = hidden_dialog_.release(); - shown_dialog_->ShowDialog(); - } -} - } // namespace payments
diff --git a/chrome/browser/payments/chrome_payment_request_delegate.h b/chrome/browser/payments/chrome_payment_request_delegate.h index 761c1c6..a519a5b6 100644 --- a/chrome/browser/payments/chrome_payment_request_delegate.h +++ b/chrome/browser/payments/chrome_payment_request_delegate.h
@@ -58,21 +58,6 @@ // for testing. PaymentRequestDialog* shown_dialog_; - // The instance of the dialog that was created but not shown yet. Since it - // hasn't been shown, it's still owned by it's creator. This is non null only - // when the current Payment Request supports skipping the payment sheet (see - // PaymentRequest::SatisfiesSkipUIConstraints) and is reset once the - // underlying pointer becomes owned by the views:: machinery (when the dialog - // is shown). - std::unique_ptr<PaymentRequestDialog> hidden_dialog_; - - // Shows |hidden_dialog_| if the current Payment Request doesn't support the - // skip UI flow. This also transfer its ownership to the views dialog code and - // keep a reference to it in |shown_dialog_|. - // Otherwise, this calls Pay() on the current Payment Request to allow the - // skip UI flow to carry on. - void MaybeShowHiddenDialog(PaymentRequest* request); - private: // Not owned but outlives the PaymentRequest object that owns this. content::WebContents* web_contents_;
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc index c3e0e0b..042b3e15 100644 --- a/chrome/browser/permissions/permission_manager.cc +++ b/chrome/browser/permissions/permission_manager.cc
@@ -253,7 +253,8 @@ struct PermissionManager::Subscription { ContentSettingsType permission; GURL requesting_origin; - GURL embedding_origin; + int render_frame_id = -1; + int render_process_id = -1; base::Callback<void(ContentSetting)> callback; ContentSetting current_value; }; @@ -537,9 +538,7 @@ GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); result = context->UpdatePermissionStatusWithDeviceStatus( result, GetCanonicalOrigin(requesting_origin, embedding_origin), - content::WebContents::FromRenderFrameHost(render_frame_host) - ->GetLastCommittedURL() - .GetOrigin()); + embedding_origin); } return ContentSettingToPermissionStatus(result.content_setting); @@ -547,8 +546,8 @@ int PermissionManager::SubscribePermissionStatusChange( PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(PermissionStatus)>& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (subscriptions_.IsEmpty()) @@ -556,16 +555,33 @@ ContentSettingsType content_type = PermissionTypeToContentSetting(permission); auto subscription = std::make_unique<Subscription>(); + + // The RFH may be null if the request is for a worker. + GURL embedding_origin; + if (render_frame_host) { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(render_frame_host); + embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); + subscription->render_frame_id = render_frame_host->GetRoutingID(); + subscription->render_process_id = render_frame_host->GetProcess()->GetID(); + subscription->current_value = + GetPermissionStatusForFrame(content_type, render_frame_host, + requesting_origin) + .content_setting; + } else { + embedding_origin = requesting_origin; + subscription->render_frame_id = -1; + subscription->render_process_id = -1; + subscription->current_value = + GetPermissionStatus(content_type, requesting_origin, requesting_origin) + .content_setting; + } + subscription->permission = content_type; subscription->requesting_origin = GetCanonicalOrigin(requesting_origin, embedding_origin); - subscription->embedding_origin = embedding_origin; subscription->callback = base::Bind(&SubscriptionCallbackWrapper, callback); - subscription->current_value = - GetPermissionStatus(content_type, requesting_origin, embedding_origin) - .content_setting; - return subscriptions_.Add(std::move(subscription)); } @@ -599,18 +615,37 @@ if (subscription->permission != content_type) continue; + // The RFH may be null if the request is for a worker. + content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( + subscription->render_process_id, subscription->render_frame_id); + GURL embedding_origin; + if (rfh) { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(rfh); + embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); + } else { + embedding_origin = subscription->requesting_origin; + } + if (primary_pattern.IsValid() && !primary_pattern.Matches(subscription->requesting_origin)) continue; if (secondary_pattern.IsValid() && - !secondary_pattern.Matches(subscription->embedding_origin)) + !secondary_pattern.Matches(embedding_origin)) continue; - ContentSetting new_value = - GetPermissionStatus(subscription->permission, - subscription->requesting_origin, - subscription->embedding_origin) - .content_setting; + ContentSetting new_value; + if (rfh) { + new_value = GetPermissionStatusForFrame(subscription->permission, rfh, + subscription->requesting_origin) + .content_setting; + } else { + new_value = GetPermissionStatus(subscription->permission, + subscription->requesting_origin, + subscription->requesting_origin) + .content_setting; + } + if (subscription->current_value == new_value) continue;
diff --git a/chrome/browser/permissions/permission_manager.h b/chrome/browser/permissions/permission_manager.h index beb9cae..223f67e 100644 --- a/chrome/browser/permissions/permission_manager.h +++ b/chrome/browser/permissions/permission_manager.h
@@ -108,8 +108,8 @@ const GURL& requesting_origin) override; int SubscribePermissionStatusChange( content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void UnsubscribePermissionStatusChange(int subscription_id) override;
diff --git a/chrome/browser/permissions/permission_manager_unittest.cc b/chrome/browser/permissions/permission_manager_unittest.cc index 6cfbd058..8832ac6 100644 --- a/chrome/browser/permissions/permission_manager_unittest.cc +++ b/chrome/browser/permissions/permission_manager_unittest.cc
@@ -140,6 +140,7 @@ true /* has_android_location_permission */, true /* is_system_location_setting_enabled */); #endif + NavigateAndCommit(url()); } void TearDown() override { @@ -226,7 +227,7 @@ // Test that the PermissionManager shuts down cleanly with subscriptions that // haven't been removed, crbug.com/720071. GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); } @@ -234,7 +235,7 @@ TEST_F(PermissionManagerTest, SameTypeChangeNotifies) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -252,7 +253,7 @@ TEST_F(PermissionManagerTest, DifferentTypeChangeDoesNotNotify) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -269,7 +270,7 @@ TEST_F(PermissionManagerTest, ChangeAfterUnsubscribeDoesNotNotify) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -286,7 +287,7 @@ TEST_F(PermissionManagerTest, DifferentPrimaryUrlDoesNotNotify) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -303,7 +304,7 @@ TEST_F(PermissionManagerTest, DifferentSecondaryUrlDoesNotNotify) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -320,7 +321,7 @@ TEST_F(PermissionManagerTest, WildCardPatternNotifies) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -341,7 +342,7 @@ int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -358,7 +359,7 @@ TEST_F(PermissionManagerTest, NewValueCorrectlyPassed) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -380,7 +381,7 @@ int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -401,7 +402,38 @@ int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::GEOLOCATION, url(), url(), + PermissionType::GEOLOCATION, main_rfh(), url(), + base::Bind(&PermissionManagerTest::OnPermissionChange, + base::Unretained(this))); + + GetHostContentSettingsMap()->SetContentSettingDefaultScope( + url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), + CONTENT_SETTING_ALLOW); + + EXPECT_TRUE(callback_called()); + EXPECT_EQ(PermissionStatus::GRANTED, callback_result()); + + Reset(); + + GetHostContentSettingsMap()->SetContentSettingDefaultScope( + url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), + CONTENT_SETTING_ASK); + + EXPECT_TRUE(callback_called()); + EXPECT_EQ(PermissionStatus::ASK, callback_result()); + + GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange( + subscription_id); +} + +TEST_F(PermissionManagerTest, ChangesBackAndForthWorker) { + GetHostContentSettingsMap()->SetContentSettingDefaultScope( + url(), url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), + CONTENT_SETTING_ASK); + + int subscription_id = + GetPermissionControllerDelegate()->SubscribePermissionStatusChange( + PermissionType::GEOLOCATION, nullptr, url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this))); @@ -428,7 +460,7 @@ TEST_F(PermissionManagerTest, SubscribeMIDIPermission) { int subscription_id = GetPermissionControllerDelegate()->SubscribePermissionStatusChange( - PermissionType::MIDI, url(), url(), + PermissionType::MIDI, main_rfh(), url(), base::Bind(&PermissionManagerTest::OnPermissionChange, base::Unretained(this)));
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc index 975b291..5c5058a 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -6,6 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -19,6 +20,7 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" #include "net/dns/mock_host_resolver.h" +#include "testing/gmock/include/gmock/gmock.h" #if !defined(OS_ANDROID) #include "chrome/browser/ui/views/overlay/overlay_window_views.h" @@ -26,6 +28,34 @@ #include "ui/views/widget/widget_observer.h" #endif +using ::testing::_; + +namespace { + +class MockPictureInPictureWindowController + : public content::PictureInPictureWindowController { + public: + MockPictureInPictureWindowController() = default; + + // PictureInPictureWindowController: + MOCK_METHOD0(Show, gfx::Size()); + MOCK_METHOD1(Close, void(bool)); + MOCK_METHOD0(OnWindowDestroyed, void()); + MOCK_METHOD1(ClickCustomControl, void(const std::string&)); + MOCK_METHOD2(EmbedSurface, void(const viz::SurfaceId&, const gfx::Size&)); + MOCK_METHOD0(GetWindowForTesting, content::OverlayWindow*()); + MOCK_METHOD0(UpdateLayerBounds, void()); + MOCK_METHOD0(IsPlayerActive, bool()); + MOCK_METHOD0(GetInitiatorWebContents, content::WebContents*()); + MOCK_METHOD2(UpdatePlaybackState, void(bool, bool)); + MOCK_METHOD0(TogglePlayPause, bool()); + + private: + DISALLOW_COPY_AND_ASSIGN(MockPictureInPictureWindowController); +}; + +} // namespace + class PictureInPictureWindowControllerBrowserTest : public InProcessBrowserTest { public: @@ -47,6 +77,10 @@ return pip_window_controller_; } + MockPictureInPictureWindowController& mock_controller() { + return mock_controller_; + } + void LoadTabAndEnterPictureInPicture(Browser* browser) { GURL test_page_url = ui_test_utils::GetTestUrl( base::FilePath(base::FilePath::kCurrentDirectory), @@ -95,6 +129,7 @@ private: content::PictureInPictureWindowController* pip_window_controller_ = nullptr; + MockPictureInPictureWindowController mock_controller_; DISALLOW_COPY_AND_ASSIGN(PictureInPictureWindowControllerBrowserTest); }; @@ -1003,4 +1038,107 @@ } } +IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, + EnterUsingControllerShowsWindow) { + auto* pip_window_manager = PictureInPictureWindowManager::GetInstance(); + ASSERT_NE(nullptr, pip_window_manager); + + // Show the non-WebContents based Picture-in-Picture window controller. + EXPECT_CALL(mock_controller(), Show()); + pip_window_manager->EnterPictureInPictureWithController(&mock_controller()); +} + +IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, + EnterUsingWebContentsThenUsingController) { + // Enter using WebContents. + LoadTabAndEnterPictureInPicture(browser()); + + OverlayWindowViews* overlay_window = static_cast<OverlayWindowViews*>( + window_controller()->GetWindowForTesting()); + ASSERT_NE(nullptr, overlay_window); + EXPECT_TRUE(overlay_window->IsVisible()); + + auto* pip_window_manager = PictureInPictureWindowManager::GetInstance(); + ASSERT_NE(nullptr, pip_window_manager); + + // The new Picture-in-Picture window should be shown. + EXPECT_CALL(mock_controller(), Show()); + pip_window_manager->EnterPictureInPictureWithController(&mock_controller()); + + // WebContents sourced Picture-in-Picture should stop. + bool in_picture_in_picture = false; + content::WebContents* active_web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(ExecuteScriptAndExtractBool( + active_web_contents, "isInPictureInPicture();", &in_picture_in_picture)); + EXPECT_FALSE(in_picture_in_picture); + + // TODO(edcourtney): When the renderer process is destroyed, it calls into + // MediaWebContentsObserver::ExitPictureInPictureInternal which Closes the + // current PIP. However, this may not be a WebContents sourced PIP, so this + // close can be spurious. + EXPECT_CALL(mock_controller(), Close(_)); +} + +IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, + EnterUsingControllerThenEnterUsingWebContents) { + auto* pip_window_manager = PictureInPictureWindowManager::GetInstance(); + ASSERT_NE(nullptr, pip_window_manager); + + // Show the non-WebContents based Picture-in-Picture window controller. + EXPECT_CALL(mock_controller(), Show()); + pip_window_manager->EnterPictureInPictureWithController(&mock_controller()); + + // Now show the WebContents based Picture-in-Picture window controller. + // This should close the existing window and show the new one. + EXPECT_CALL(mock_controller(), Close(_)); + LoadTabAndEnterPictureInPicture(browser()); + + OverlayWindowViews* overlay_window = static_cast<OverlayWindowViews*>( + window_controller()->GetWindowForTesting()); + ASSERT_TRUE(overlay_window); + EXPECT_TRUE(overlay_window->IsVisible()); +} + #endif // !defined(OS_ANDROID) + +// This checks that a video in Picture-in-Picture with preload none, when +// changing source willproperly update the associated media player id. This is +// checked by closing the window because the test it at a too high level to be +// able to check the actual media player id being used. +IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest, + PreloadNoneSrcChangeThenLoad) { + GURL test_page_url = ui_test_utils::GetTestUrl( + base::FilePath(base::FilePath::kCurrentDirectory), + base::FilePath(FILE_PATH_LITERAL( + "media/picture-in-picture/player_preload_none.html"))); + ui_test_utils::NavigateToURL(browser(), test_page_url); + + content::WebContents* active_web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(active_web_contents); + + SetUpWindowController(active_web_contents); + + bool result = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool(active_web_contents, + "play();", &result)); + ASSERT_TRUE(result); + + result = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + active_web_contents, "enterPictureInPicture();", &result)); + ASSERT_TRUE(result); + + result = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + active_web_contents, "changeSrcAndLoad();", &result)); + ASSERT_TRUE(result); + + window_controller()->Close(true /* should_pause_video */); + + result = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + active_web_contents, "isInPictureInPicture();", &result)); + EXPECT_FALSE(result); +}
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc index f1270718..299757d 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc
@@ -40,6 +40,18 @@ return base::Singleton<PictureInPictureWindowManager>::get(); } +void PictureInPictureWindowManager::EnterPictureInPictureWithController( + content::PictureInPictureWindowController* pip_window_controller) { + // If there was already a controller, close the existing window before + // creating the next one. + if (pip_window_controller_) + CloseWindowInternal(); + + pip_window_controller_ = pip_window_controller; + + pip_window_controller_->Show(); +} + gfx::Size PictureInPictureWindowManager::EnterPictureInPicture( content::WebContents* web_contents, const viz::SurfaceId& surface_id, @@ -49,9 +61,11 @@ if (pip_window_controller_) CloseWindowInternal(); - // Create or update |pip_window_controller_| for the current WebContents. + // Create or update |pip_window_controller_| for the current WebContents, if + // it is a WebContents based PIP. if (!pip_window_controller_ || - pip_window_controller_->GetInitiatorWebContents() != web_contents) { + (pip_window_controller_->GetInitiatorWebContents() != nullptr && + pip_window_controller_->GetInitiatorWebContents() != web_contents)) { CreateWindowInternal(web_contents); } @@ -73,7 +87,6 @@ } void PictureInPictureWindowManager::CloseWindowInternal() { - DCHECK(contents_observer_); DCHECK(pip_window_controller_); contents_observer_.reset();
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h index 12cb157f..0b544a53 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h
@@ -29,6 +29,11 @@ // Returns the singleton instance. static PictureInPictureWindowManager* GetInstance(); + // Some PIP windows (e.g. from ARC) may not have a WebContents as the source + // of the PIP content. This function lets them provide their own window + // controller directly. + void EnterPictureInPictureWithController( + content::PictureInPictureWindowController* pip_window_controller); gfx::Size EnterPictureInPicture(content::WebContents*, const viz::SurfaceId&, const gfx::Size&);
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chrome/browser/prefs/pref_service_incognito_whitelist.cc index 01d92c0f..4da7559 100644 --- a/chrome/browser/prefs/pref_service_incognito_whitelist.cc +++ b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -47,9 +47,7 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/ash_pref_names.h" #include "chromeos/chromeos_pref_names.h" -#include "components/drive/drive_pref_names.h" #include "ui/base/ime/chromeos/extension_ime_util.h" -#include "ui/chromeos/events/pref_names.h" #endif // defined(OS_CHROMEOS) namespace { @@ -750,12 +748,6 @@ dom_distiller::prefs::kFontScale, dom_distiller::prefs::kReaderForAccessibility, -// components/drive/drive_pref_names.h -#if defined(OS_CHROMEOS) - drive::prefs::kDisableDrive, drive::prefs::kDisableDriveOverCellular, - drive::prefs::kDisableDriveHostedFiles, -#endif // defined(OS_CHROMEOS) - // components/feed/core/pref_names.h #if defined(OS_ANDROID) #if BUILDFLAG(ENABLE_FEED_IN_CHROME) @@ -852,14 +844,6 @@ chromeos::extension_ime_util::kBrailleImeEngineId, chromeos::extension_ime_util::kArcImeLanguage, #endif // defined(OS_CHROMEOS) - -// ui/chromeos/events/pref_names.h -#if defined(OS_CHROMEOS) - prefs::kLanguageRemapCapsLockKeyTo, prefs::kLanguageRemapSearchKeyTo, - prefs::kLanguageRemapControlKeyTo, prefs::kLanguageRemapAltKeyTo, - prefs::kLanguageRemapEscapeKeyTo, prefs::kLanguageRemapBackspaceKeyTo, - prefs::kLanguageRemapDiamondKeyTo, -#endif // defined(OS_CHROMEOS) }; } // namespace
diff --git a/chrome/browser/printing/cloud_print/privet_traffic_detector.cc b/chrome/browser/printing/cloud_print/privet_traffic_detector.cc index d241f91..5176dad 100644 --- a/chrome/browser/printing/cloud_print/privet_traffic_detector.cc +++ b/chrome/browser/printing/cloud_print/privet_traffic_detector.cc
@@ -14,8 +14,8 @@ #include "base/task/post_task.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/browser_process.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "net/base/ip_address.h" #include "net/base/net_errors.h" @@ -80,8 +80,7 @@ void PrivetTrafficDetector::Start() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::BindOnce(&PrivetTrafficDetector::ScheduleRestart, @@ -90,8 +89,7 @@ void PrivetTrafficDetector::Stop() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); } void PrivetTrafficDetector::HandleConnectionChanged(
diff --git a/chrome/browser/profiles/renderer_updater.cc b/chrome/browser/profiles/renderer_updater.cc index 0b301b2..6200888c 100644 --- a/chrome/browser/profiles/renderer_updater.cc +++ b/chrome/browser/profiles/renderer_updater.cc
@@ -53,6 +53,15 @@ RendererUpdater::RendererUpdater(Profile* profile) : profile_(profile) { signin_manager_ = SigninManagerFactory::GetForProfile(profile_); signin_manager_->AddObserver(this); + variations_http_header_provider_ = + variations::VariationsHttpHeaderProvider::GetInstance(); + variations_http_header_provider_->AddObserver(this); + cached_variation_ids_header_ = + variations_http_header_provider_->GetClientDataHeader( + false /* is_signed_in */); + cached_variation_ids_header_signed_in_ = + variations_http_header_provider_->GetClientDataHeader( + true /* is_signed_in */); PrefService* pref_service = profile->GetPrefs(); force_google_safesearch_.Init(prefs::kForceGoogleSafeSearch, pref_service); @@ -81,6 +90,8 @@ void RendererUpdater::Shutdown() { signin_manager_->RemoveObserver(this); signin_manager_ = nullptr; + variations_http_header_provider_->RemoveObserver(this); + variations_http_header_provider_ = nullptr; } void RendererUpdater::InitializeRenderer( @@ -147,6 +158,14 @@ UpdateAllRenderers(); } +void RendererUpdater::VariationIdsHeaderUpdated( + const std::string& variation_ids_header, + const std::string& variation_ids_header_signed_in) { + cached_variation_ids_header_ = variation_ids_header; + cached_variation_ids_header_signed_in_ = variation_ids_header_signed_in; + UpdateAllRenderers(); +} + void RendererUpdater::UpdateAllRenderers() { auto renderer_configurations = GetRendererConfigurations(); for (auto& renderer_configuration : renderer_configurations) @@ -155,9 +174,11 @@ void RendererUpdater::UpdateRenderer( chrome::mojom::RendererConfigurationAssociatedPtr* renderer_configuration) { + bool is_signed_in = signin_manager_->IsAuthenticated(); (*renderer_configuration) - ->SetConfiguration(signin_manager_->IsAuthenticated(), - force_google_safesearch_.GetValue(), + ->SetConfiguration(force_google_safesearch_.GetValue(), force_youtube_restrict_.GetValue(), - allowed_domains_for_apps_.GetValue()); + allowed_domains_for_apps_.GetValue(), + is_signed_in ? cached_variation_ids_header_signed_in_ + : cached_variation_ids_header_); }
diff --git a/chrome/browser/profiles/renderer_updater.h b/chrome/browser/profiles/renderer_updater.h index 863ab90..06a8460 100644 --- a/chrome/browser/profiles/renderer_updater.h +++ b/chrome/browser/profiles/renderer_updater.h
@@ -5,12 +5,15 @@ #ifndef CHROME_BROWSER_PROFILES_RENDERER_UPDATER_H_ #define CHROME_BROWSER_PROFILES_RENDERER_UPDATER_H_ +#include <string> + #include "base/macros.h" #include "chrome/common/renderer_configuration.mojom.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_member.h" #include "components/signin/core/browser/signin_manager.h" +#include "components/variations/variations_http_header_provider.h" class Profile; @@ -19,8 +22,10 @@ } // The RendererUpdater is responsible for updating renderers about state change. -class RendererUpdater : public KeyedService, - public SigninManagerBase::Observer { +class RendererUpdater + : public KeyedService, + public SigninManagerBase::Observer, + public variations::VariationsHttpHeaderProvider::Observer { public: explicit RendererUpdater(Profile* profile); ~RendererUpdater() override; @@ -42,6 +47,11 @@ void GoogleSigninSucceeded(const AccountInfo& account_info) override; void GoogleSignedOut(const AccountInfo& account_info) override; + // VariationsHttpHeaderProvider::Observer: + void VariationIdsHeaderUpdated( + const std::string& variation_ids_header, + const std::string& variation_ids_header_signed_in) override; + // Update all renderers due to a configuration change. void UpdateAllRenderers(); @@ -52,12 +62,16 @@ Profile* profile_; PrefChangeRegistrar pref_change_registrar_; SigninManagerBase* signin_manager_; + variations::VariationsHttpHeaderProvider* variations_http_header_provider_; // Prefs that we sync to the renderers. BooleanPrefMember force_google_safesearch_; IntegerPrefMember force_youtube_restrict_; StringPrefMember allowed_domains_for_apps_; + std::string cached_variation_ids_header_; + std::string cached_variation_ids_header_signed_in_; + DISALLOW_COPY_AND_ASSIGN(RendererUpdater); };
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css index 78406965..612c5e4c 100644 --- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css +++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.css
@@ -17,6 +17,7 @@ max-height: 300px; overflow: auto; padding: 12px 64px 0 64px; + width: 640px; } .shadow {
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js index 376e0e60..246c8a6 100644 --- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js +++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js
@@ -75,18 +75,27 @@ return selectedPackages; } -// Add the scrolling shadow effect. -(function() { -const shadowThreshold = 5; -var doc = document; -doc.getElementById('recommend-apps-container').onscroll = function() { +function toggleScrollShadow(container) { + const shadowThreshold = 5; + var doc = document; doc.getElementById('scroll-top') - .classList[this.scrollTop > shadowThreshold ? 'add' : 'remove']('shadow'); + .classList.toggle('shadow', container.scrollTop > shadowThreshold); doc.getElementById('scroll-bottom') - .classList - [this.scrollHeight - this.clientHeight - this.scrollTop < - shadowThreshold ? - 'remove' : - 'add']('shadow'); -}; -})(); \ No newline at end of file + .classList.toggle( + 'shadow', + container.scrollHeight - container.clientHeight - + container.scrollTop >= + shadowThreshold); +} + +// Add the scroll shadow effect. This contains two parts. First initialize the +// effect after all the contents have been generated. Then attach it to the +// onscroll event. +function addScrollShadowEffect() { + var doc = document; + var container = doc.getElementById('recommend-apps-container'); + toggleScrollShadow(container); + container.onscroll = function() { + toggleScrollShadow(this); + }; +} \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.html b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.html index 0ea8dad..5ca9076 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.html +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.html
@@ -130,6 +130,17 @@ <button id="changeDisplayStyle"></button> </div> + <h2 class="i18n" msgid="options_developer_options" id="developerDescription"> + Developer Options + </h2> + <div class="option" id="developerOption"> + <input id="developerOptionCheckBox" type="checkbox" class="checkbox pref" + name="developerOptionCheckBox"> + <label> + Enable developer option test. + </label> + </div> + <div id="status" role="live" aria-live="assertive"> </div>
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js index c3b158c..27519b1 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/options.js
@@ -88,6 +88,14 @@ } }); + chrome.commandLinePrivate.hasSwitch( + 'enable-chromevox-developer-option', function(enable) { + if (!enable) { + $('developerDescription').hidden = true; + $('developerOption').hidden = true; + } + }); + Msgs.addTranslatedMessagesToDom(document); cvox.OptionsPage.hidePlatformSpecifics();
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.html b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.html index 3d75bd4..feca3b8 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.html +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.html
@@ -1,9 +1,11 @@ <!-- Components to load uncompressed ChromeVox --> -<script src="../../closure/base.js"></script> -<script src="../../deps.js"></script> +<!-- + <script src="../../closure/base.js"></script> + <script src="../../deps.js"></script> +--> <!-- ChromeVox Next --> -<script src="loader.js"></script> +<!-- <script src="loader.js"></script> --> <script src="../../chromeVox2ChromeBackgroundScript.js"></script> <!-- Third party -->
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index bd4de2e..195df15 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -559,6 +559,9 @@ <message desc="An option for setting the key combination that will be used as the ChromeVox modifier key (aka, the 'Cvox' key)." name="IDS_CHROMEVOX_OPTIONS_CVOX_MODIFIER_KEY"> ChromeVox modifier key </message> + <message desc="List of chromevox developer options." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_OPTIONS"> + Developer Options + </message> <message desc="The title of ChromeVox Learn Mode page. The keyboard explorer voices the name of each key when the user presses it." name="IDS_CHROMEVOX_KBEXPLORER_TITLE"> ChromeVox Learn Mode </message>
diff --git a/chrome/browser/resources/chromeos/login/screen_recommend_apps.js b/chrome/browser/resources/chromeos/login/screen_recommend_apps.js index 3e8b8fb..5e0c2a8 100644 --- a/chrome/browser/resources/chromeos/login/screen_recommend_apps.js +++ b/chrome/browser/resources/chromeos/login/screen_recommend_apps.js
@@ -102,6 +102,8 @@ var generateContents = {code: generateItemScript}; appListView.executeScript(generateContents); }); + var addScrollShadowEffectScript = 'addScrollShadowEffect();'; + appListView.executeScript({code: addScrollShadowEffectScript}); this.onGenerateContents(); });
diff --git a/chrome/browser/resources/discards/discards.js b/chrome/browser/resources/discards/discards.js index aa3fbc1..d9b3c13 100644 --- a/chrome/browser/resources/discards/discards.js +++ b/chrome/browser/resources/discards/discards.js
@@ -351,9 +351,10 @@ boolToString(info.canFreeze); row.querySelector('.can-discard-div').textContent = boolToString(info.canDiscard); - // The lifecycle state is meaningless for 'unloaded' tabs. + // The lifecycle state is meaningless for tabs that have never been loaded. row.querySelector('.state-cell').textContent = - (info.loadingState != mojom.LifecycleUnitLoadingState.UNLOADED) ? + (info.loadingState != mojom.LifecycleUnitLoadingState.UNLOADED || + info.discardCount > 0) ? lifecycleStateToString(info.state) : ''; row.querySelector('.discard-count-cell').textContent = @@ -371,9 +372,11 @@ row.querySelector('.is-auto-discardable-link').removeAttribute('disabled'); setActionLinkEnabled( - row.querySelector('.can-freeze-link'), !info.canFreeze); + row.querySelector('.can-freeze-link'), + (!info.canFreeze && info.cannotFreezeReasons.length > 0)); setActionLinkEnabled( - row.querySelector('.can-discard-link'), !info.canDiscard); + row.querySelector('.can-discard-link'), + (!info.canDiscard && info.cannotDiscardReasons.length > 0)); let loadLink = row.querySelector('.load-link'); let freezeLink = row.querySelector('.freeze-link'); let discardLink = row.querySelector('.discard-link');
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.css b/chrome/browser/resources/local_ntp/most_visited_single.css index 6ab3fa9..d1beddaa 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.css +++ b/chrome/browser/resources/local_ntp/most_visited_single.css
@@ -433,6 +433,7 @@ display: flex; flex-flow: column nowrap; height: 100%; + position: relative; width: 100%; z-index: -1; }
diff --git a/chrome/browser/resources/settings/multidevice_page/BUILD.gn b/chrome/browser/resources/settings/multidevice_page/BUILD.gn index 43db27b..49e73d9 100644 --- a/chrome/browser/resources/settings/multidevice_page/BUILD.gn +++ b/chrome/browser/resources/settings/multidevice_page/BUILD.gn
@@ -61,6 +61,7 @@ js_library("multidevice_subpage") { deps = [ + ":multidevice_constants", "..:route", "../prefs:prefs_behavior", "//ui/webui/resources/js:i18n_behavior",
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html b/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html index f97c9047..3a79427 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html
@@ -19,7 +19,8 @@ padding-inline-start: 18px; } </style> - <div class="settings-box two-line" + <div id="card" + class="settings-box two-line" on-click="handleItemClick_" actionable$="[[hasSubpageClickHandler_(subpageRoute)]]"> <iron-icon icon="[[iconName]]"></iron-icon> @@ -37,7 +38,7 @@ </paper-icon-button-light> <div class="separator"></div> </template> - <slot name="feature-contoller"></slot> + <slot name="feature-controller"></slot> </div> </template> <script src="multidevice_feature_item.js"></script>
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html index 804ffe8..79e86fc 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
@@ -8,6 +8,7 @@ <link rel="import" href="../route.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="../settings_vars_css.html"> +<link rel="import" href="multidevice_constants.html"> <link rel="import" href="multidevice_feature_item.html"> <link rel="import" href="multidevice_feature_toggle.html"> @@ -36,7 +37,8 @@ if="[[shouldShowIndividualFeatures_(pageContentData)]]" restamp> <div class="feature-item-container"> - <settings-multidevice-feature-item icon-name="settings:smart-lock" + <settings-multidevice-feature-item id="smart-lock-item" + icon-name="settings:smart-lock" subpage-route="[[routes.LOCK_SCREEN]]" feature-name="$i18n{multideviceSmartLockItemTitle}" feature-summary-html="$i18n{multideviceSmartLockItemSummary}"> @@ -49,16 +51,21 @@ </settings-multidevice-feature-toggle> </div> </settings-multidevice-feature-item> - <settings-multidevice-feature-item icon-name="settings:sms-connect" + <settings-multidevice-feature-item id="android-messages-item" + icon-name="settings:sms-connect" feature-name="$i18n{multideviceAndroidMessagesItemTitle}" feature-summary-html="$i18n{multideviceAndroidMessagesItemSummary}"> - <div slot="feature-contoller"> - <template is="dom-if" if="[[androidMessagesRequiresSetup_]]"> + <div slot="feature-controller"> + <template is="dom-if" + if="[[androidMessagesRequiresSetup_]]" + restamp> <paper-button on-click="handleAndroidMessagesButtonClick_"> $i18n{multideviceSetupButton} </paper-button> </template> - <template is="dom-if" if="[[!androidMessagesRequiresSetup_]]"> + <template is="dom-if" + if="[[!androidMessagesRequiresSetup_]]" + restamp> <settings-multidevice-feature-toggle pref="{{prefs.multidevice.sms_connect_enabled}}"> </settings-multidevice-feature-toggle>
diff --git a/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc b/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc index 98657a5..88f6736 100644 --- a/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc +++ b/chrome/browser/safe_browsing/download_protection/ppapi_download_request.cc
@@ -291,13 +291,6 @@ DownloadCheckResult response) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(2) << __func__ << " response: " << static_cast<int>(response); - base::UmaHistogramSparse( - "SBClientDownload.PPAPIDownloadRequest.RequestOutcome", - static_cast<int>(reason)); - base::UmaHistogramSparse("SBClientDownload.PPAPIDownloadRequest.Result", - static_cast<int>(response)); - UMA_HISTOGRAM_TIMES("SBClientDownload.PPAPIDownloadRequest.RequestDuration", - base::TimeTicks::Now() - start_time_); if (!callback_.is_null()) base::ResetAndReturn(&callback_).Run(response); loader_.reset();
diff --git a/chrome/browser/sessions/tab_loader_delegate.cc b/chrome/browser/sessions/tab_loader_delegate.cc index 4c6bb81b..4cbaa52 100644 --- a/chrome/browser/sessions/tab_loader_delegate.cc +++ b/chrome/browser/sessions/tab_loader_delegate.cc
@@ -7,11 +7,11 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_number_conversions.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/resource_coordinator/session_restore_policy.h" #include "chrome/browser/resource_coordinator/tab_manager_features.h" #include "chrome/browser/sessions/session_restore_observer.h" #include "components/variations/variations_associated_data.h" +#include "content/public/browser/network_service_instance.h" #include "services/network/public/cpp/network_connection_tracker.h" namespace { @@ -79,10 +79,9 @@ TabLoaderDelegateImpl::TabLoaderDelegateImpl(TabLoaderCallback* callback) : callback_(callback), weak_factory_(this) { - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); auto type = network::mojom::ConnectionType::CONNECTION_UNKNOWN; - g_browser_process->network_connection_tracker()->GetConnectionType( + content::GetNetworkConnectionTracker()->GetConnectionType( &type, base::BindOnce(&TabLoaderDelegateImpl::OnConnectionChanged, weak_factory_.GetWeakPtr())); if (type == network::mojom::ConnectionType::CONNECTION_NONE) { @@ -98,8 +97,7 @@ } TabLoaderDelegateImpl::~TabLoaderDelegateImpl() { - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); } void TabLoaderDelegateImpl::OnConnectionChanged(
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 4aa7746..d726bff 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -44,6 +44,7 @@ #include "components/signin/core/browser/signin_pref_names.h" #include "components/signin/core/browser/signin_switches.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_urls.h" @@ -79,8 +80,7 @@ weak_ptr_factory_(this) { signin_error_controller_->AddObserver(this); #if !defined(OS_CHROMEOS) - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); #else // UserManager may not exist in unit_tests. if (!user_manager::UserManager::IsInitialized()) @@ -113,8 +113,7 @@ ChromeSigninClient::~ChromeSigninClient() { signin_error_controller_->RemoveObserver(this); #if !defined(OS_CHROMEOS) - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); #endif } @@ -398,10 +397,9 @@ #else // Don't bother if we don't have any kind of network connection. network::mojom::ConnectionType type; - bool sync = - g_browser_process->network_connection_tracker()->GetConnectionType( - &type, base::BindOnce(&ChromeSigninClient::OnConnectionChanged, - weak_ptr_factory_.GetWeakPtr())); + bool sync = content::GetNetworkConnectionTracker()->GetConnectionType( + &type, base::BindOnce(&ChromeSigninClient::OnConnectionChanged, + weak_ptr_factory_.GetWeakPtr())); if (!sync || type == network::mojom::ConnectionType::CONNECTION_NONE) { // Connection type cannot be retrieved synchronously so delay the callback. delayed_callbacks_.push_back(callback);
diff --git a/chrome/browser/signin/chrome_signin_client_unittest.cc b/chrome/browser/signin/chrome_signin_client_unittest.cc index e39a4fef..0fa3d156 100644 --- a/chrome/browser/signin/chrome_signin_client_unittest.cc +++ b/chrome/browser/signin/chrome_signin_client_unittest.cc
@@ -20,6 +20,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/signin/core/browser/profile_management_switches.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/test/test_browser_thread_bundle.h" #include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/test/test_network_connection_tracker.h" @@ -63,8 +64,9 @@ ChromeSigninClientTest() {} void Initialize(std::unique_ptr<network::NetworkConnectionTracker> tracker) { - TestingBrowserProcess::GetGlobal()->SetNetworkConnectionTracker( - std::move(tracker)); + network_connection_tracker_ = std::move(tracker); + content::SetNetworkConnectionTrackerForTesting( + network_connection_tracker_.get()); // Create a signed-in profile. TestingProfile::Builder builder; profile_ = builder.Build(); @@ -77,6 +79,8 @@ private: content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<network::NetworkConnectionTracker> + network_connection_tracker_; std::unique_ptr<Profile> profile_; SigninClient* signin_client_; };
diff --git a/chrome/browser/signin/force_signin_verifier.cc b/chrome/browser/signin/force_signin_verifier.cc index 383e375..ff6de48 100644 --- a/chrome/browser/signin/force_signin_verifier.cc +++ b/chrome/browser/signin/force_signin_verifier.cc
@@ -8,11 +8,11 @@ #include "base/bind.h" #include "base/metrics/histogram_macros.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "components/signin/core/browser/signin_manager.h" +#include "content/public/browser/network_service_instance.h" #include "google_apis/gaia/gaia_constants.h" namespace { @@ -44,8 +44,7 @@ oauth2_token_service_( ProfileOAuth2TokenServiceFactory::GetForProfile(profile)), signin_manager_(SigninManagerFactory::GetForProfile(profile)) { - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); UMA_HISTOGRAM_BOOLEAN(kForceSigninVerificationMetricsName, ShouldSendRequest()); SendRequest(); @@ -62,8 +61,7 @@ UMA_HISTOGRAM_MEDIUM_TIMES(kForceSigninVerificationSuccessTimeMetricsName, base::TimeTicks::Now() - creation_time_); has_token_verified_ = true; - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); Cancel(); } @@ -75,8 +73,8 @@ base::TimeTicks::Now() - creation_time_); has_token_verified_ = true; CloseAllBrowserWindows(); - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver( + this); Cancel(); } else { backoff_entry_.InformOfRequest(false); @@ -103,8 +101,7 @@ backoff_entry_.Reset(); backoff_request_timer_.Stop(); access_token_request_.reset(); - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); } bool ForceSigninVerifier::HasTokenBeenVerified() { @@ -124,8 +121,8 @@ bool ForceSigninVerifier::ShouldSendRequest() { auto type = network::mojom::ConnectionType::CONNECTION_NONE; - g_browser_process->network_connection_tracker()->GetConnectionType( - &type, base::DoNothing()); + content::GetNetworkConnectionTracker()->GetConnectionType(&type, + base::DoNothing()); return !has_token_verified_ && access_token_request_.get() == nullptr && type != network::mojom::ConnectionType::CONNECTION_NONE && signin_manager_->IsAuthenticated();
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc index adb742f..8b2abb13 100644 --- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc +++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
@@ -14,7 +14,6 @@ #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_macros.h" #include "build/build_config.h" -#include "chrome/browser/browser_process.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/signin_client.h" @@ -22,6 +21,7 @@ #include "components/signin/core/browser/signin_pref_names.h" #include "components/signin/core/browser/webdata/token_web_data.h" #include "components/webdata/common/web_data_service_base.h" +#include "content/public/browser/network_service_instance.h" #include "google_apis/gaia/gaia_auth_fetcher.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_constants.h" @@ -359,8 +359,7 @@ backoff_policy_.maximum_backoff_ms = 15 * 60 * 1000; backoff_policy_.entry_lifetime_ms = -1; backoff_policy_.always_use_initial_delay = false; - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); #if !defined(OS_CHROMEOS) // Ensure the device ID is not empty. @@ -373,8 +372,7 @@ ~MutableProfileOAuth2TokenServiceDelegate() { VLOG(1) << "MutablePO2TS::~MutablePO2TS"; DCHECK(server_revokes_.empty()); - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); } // static
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc index c87d0e33..ab1d039d 100644 --- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc +++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -11,7 +11,6 @@ #include "base/bind.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -28,6 +27,7 @@ #include "components/signin/core/browser/test_signin_client.h" #include "components/signin/core/browser/webdata/token_web_data.h" #include "components/sync_preferences/testing_pref_service_syncable.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/google_service_auth_error.h" @@ -121,6 +121,7 @@ } void TearDown() override { + base::RunLoop().RunUntilIdle(); oauth2_service_delegate_->RemoveObserver(this); oauth2_service_delegate_->Shutdown(); OSCryptMocker::TearDown(); @@ -216,7 +217,7 @@ } protected: - base::MessageLoop message_loop_; + content::TestBrowserThreadBundle thread_bundle_; std::unique_ptr<TestSigninClient> client_; std::unique_ptr<MutableProfileOAuth2TokenServiceDelegate> oauth2_service_delegate_;
diff --git a/chrome/browser/sync/test/integration/autofill_helper.cc b/chrome/browser/sync/test/integration/autofill_helper.cc index 92188d7..32172f5 100644 --- a/chrome/browser/sync/test/integration/autofill_helper.cc +++ b/chrome/browser/sync/test/integration/autofill_helper.cc
@@ -110,6 +110,14 @@ return entries; } +void SetServerCardsOnDBSequence( + AutofillWebDataService* wds, + const std::vector<autofill::CreditCard>& credit_cards) { + DCHECK(wds->GetDBTaskRunner()->RunsTasksInCurrentSequence()); + AutofillTable::FromWebDatabase(wds->GetDatabase()) + ->SetServerCreditCards(credit_cards); +} + bool ProfilesMatchImpl( int profile_a, const std::vector<AutofillProfile*>& autofill_profiles_a, @@ -284,6 +292,16 @@ GetPersonalDataManager(profile)->SetCreditCards(credit_cards); } +void SetServerCreditCards( + int profile, + const std::vector<autofill::CreditCard>& credit_cards) { + scoped_refptr<AutofillWebDataService> wds = GetProfileWebDataService(profile); + wds->GetDBTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&SetServerCardsOnDBSequence, + base::Unretained(wds.get()), credit_cards)); + WaitForCurrentTasksToComplete(wds->GetDBTaskRunner()); +} + void AddProfile(int profile, const AutofillProfile& autofill_profile) { std::vector<AutofillProfile> autofill_profiles; for (AutofillProfile* profile : GetAllAutoFillProfiles(profile)) {
diff --git a/chrome/browser/sync/test/integration/autofill_helper.h b/chrome/browser/sync/test/integration/autofill_helper.h index 241d61d0..199977b0 100644 --- a/chrome/browser/sync/test/integration/autofill_helper.h +++ b/chrome/browser/sync/test/integration/autofill_helper.h
@@ -75,6 +75,10 @@ void SetCreditCards(int profile, std::vector<autofill::CreditCard>* credit_cards); +void SetServerCreditCards( + int profile, + const std::vector<autofill::CreditCard>& credit_cards); + // Adds the autofill profile |autofill_profile| to sync profile |profile|. void AddProfile(int profile, const autofill::AutofillProfile& autofill_profile);
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc index 79454e6d..1fb1af2 100644 --- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -4,6 +4,7 @@ #include "base/command_line.h" #include "base/macros.h" +#include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/sync/test/integration/autofill_helper.h" @@ -15,6 +16,7 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/personal_data_manager_observer.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_prefs.h" #include "components/browser_sync/profile_sync_service.h" @@ -24,20 +26,29 @@ #include "components/sync/test/fake_server/fake_server.h" #include "components/webdata/common/web_data_service_consumer.h" #include "content/public/browser/notification_service.h" +#include "testing/gmock/include/gmock/gmock.h" +using autofill::CreditCard; using autofill_helper::GetPersonalDataManager; using autofill_helper::GetProfileWebDataService; using autofill_helper::GetAccountWebDataService; namespace { +ACTION_P(QuitMessageLoop, loop) { + loop->Quit(); +} + const char kDefaultCardID[] = "wallet entity ID"; const int kDefaultCardExpMonth = 8; const int kDefaultCardExpYear = 2087; const char kDefaultCardLastFour[] = "1234"; const char kDefaultCardName[] = "Patrick Valenzuela"; +const char kDefaultBillingAddressId[] = "address entity ID"; const sync_pb::WalletMaskedCreditCard_WalletCardType kDefaultCardType = sync_pb::WalletMaskedCreditCard::AMEX; +const char kLocalGuidA[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44A"; +const char kDifferentBillingAddressId[] = "another address entity ID"; template <class T> class AutofillWebDataServiceConsumer : public WebDataServiceConsumer { @@ -63,10 +74,18 @@ DISALLOW_COPY_AND_ASSIGN(AutofillWebDataServiceConsumer); }; -std::vector<std::unique_ptr<autofill::CreditCard>> GetServerCards( +class PersonalDataLoadedObserverMock + : public autofill::PersonalDataManagerObserver { + public: + PersonalDataLoadedObserverMock() {} + ~PersonalDataLoadedObserverMock() override {} + + MOCK_METHOD0(OnPersonalDataChanged, void()); +}; + +std::vector<std::unique_ptr<CreditCard>> GetServerCards( scoped_refptr<autofill::AutofillWebDataService> service) { - AutofillWebDataServiceConsumer< - std::vector<std::unique_ptr<autofill::CreditCard>>> + AutofillWebDataServiceConsumer<std::vector<std::unique_ptr<CreditCard>>> consumer; service->GetServerCreditCards(&consumer); consumer.Wait(); @@ -89,12 +108,27 @@ credit_card->set_name_on_card(kDefaultCardName); credit_card->set_status(sync_pb::WalletMaskedCreditCard::VALID); credit_card->set_type(kDefaultCardType); + credit_card->set_billing_address_id(kDefaultBillingAddressId); server->InjectEntity( syncer::PersistentUniqueClientEntity::CreateFromEntitySpecifics( kDefaultCardID, specifics, 12345, 12345)); } +CreditCard GetDefaultCreditCard() { + CreditCard card(CreditCard::MASKED_SERVER_CARD, kDefaultCardID); + card.SetExpirationMonth(kDefaultCardExpMonth); + card.SetExpirationYear(kDefaultCardExpYear); + card.SetNumber(base::UTF8ToUTF16(kDefaultCardLastFour)); + card.SetRawInfo(autofill::CREDIT_CARD_NAME_FULL, + base::UTF8ToUTF16(kDefaultCardName)); + card.SetServerStatus(CreditCard::OK); + card.SetNetworkForMaskedCard(autofill::kAmericanExpressCard); + card.set_card_type(CreditCard::CARD_TYPE_CREDIT); + card.set_billing_address_id(kDefaultBillingAddressId); + return card; +} + } // namespace class SingleClientWalletSyncTest : public SyncTest { @@ -102,6 +136,20 @@ SingleClientWalletSyncTest() : SyncTest(SINGLE_CLIENT) {} ~SingleClientWalletSyncTest() override {} + protected: + void RefreshAndWaitForOnPersonalDataChanged( + autofill::PersonalDataManager* pdm) { + pdm->AddObserver(&personal_data_observer_); + pdm->Refresh(); + base::RunLoop run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .WillRepeatedly(QuitMessageLoop(&run_loop)); + run_loop.Run(); + pdm->RemoveObserver(&personal_data_observer_); + } + + PersonalDataLoadedObserverMock personal_data_observer_; + private: DISALLOW_COPY_AND_ASSIGN(SingleClientWalletSyncTest); }; @@ -143,7 +191,7 @@ }; IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, EnabledByDefault) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed"; + ASSERT_TRUE(SetupSync()); ASSERT_TRUE(GetClient(0)->service()->GetActiveDataTypes().Has( syncer::AUTOFILL_WALLET_DATA)); // TODO(pvalenzuela): Assert that the local root node for AUTOFILL_WALLET_DATA @@ -160,7 +208,7 @@ // Disabled. {autofill::features::kAutofillEnableAccountWalletStorage}); AddDefaultCard(GetFakeServer()); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed"; + ASSERT_TRUE(SetupSync()); auto profile_data = GetProfileWebDataService(0); ASSERT_NE(nullptr, profile_data); @@ -169,11 +217,11 @@ autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); - std::vector<autofill::CreditCard*> cards = pdm->GetCreditCards(); + std::vector<CreditCard*> cards = pdm->GetCreditCards(); ASSERT_EQ(1uL, cards.size()); - autofill::CreditCard* card = cards[0]; - EXPECT_EQ(autofill::CreditCard::MASKED_SERVER_CARD, card->record_type()); + CreditCard* card = cards[0]; + EXPECT_EQ(CreditCard::MASKED_SERVER_CARD, card->record_type()); EXPECT_EQ(kDefaultCardID, card->server_id()); EXPECT_EQ(base::UTF8ToUTF16(kDefaultCardLastFour), card->LastFourDigits()); EXPECT_EQ(autofill::kAmericanExpressCard, card->network()); @@ -181,6 +229,7 @@ EXPECT_EQ(kDefaultCardExpYear, card->expiration_year()); EXPECT_EQ(base::UTF8ToUTF16(kDefaultCardName), card->GetRawInfo(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)); + EXPECT_EQ(kDefaultBillingAddressId, card->billing_address_id()); // Check that the card is stored in the profile storage. EXPECT_EQ(1U, GetServerCards(GetProfileWebDataService(0)).size()); @@ -203,6 +252,7 @@ ASSERT_TRUE(SetupClients()); AddDefaultCard(GetFakeServer()); + ASSERT_TRUE(GetClient(0)->SignIn()); ASSERT_TRUE(GetClient(0)->AwaitEngineInitialization( /*skip_passphrase_verification=*/false)); @@ -225,11 +275,11 @@ autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); - std::vector<autofill::CreditCard*> cards = pdm->GetCreditCards(); + std::vector<CreditCard*> cards = pdm->GetCreditCards(); ASSERT_EQ(1uL, cards.size()); - autofill::CreditCard* card = cards[0]; - EXPECT_EQ(autofill::CreditCard::MASKED_SERVER_CARD, card->record_type()); + CreditCard* card = cards[0]; + EXPECT_EQ(CreditCard::MASKED_SERVER_CARD, card->record_type()); EXPECT_EQ(kDefaultCardID, card->server_id()); EXPECT_EQ(base::UTF8ToUTF16(kDefaultCardLastFour), card->LastFourDigits()); EXPECT_EQ(autofill::kAmericanExpressCard, card->network()); @@ -237,18 +287,19 @@ EXPECT_EQ(kDefaultCardExpYear, card->expiration_year()); EXPECT_EQ(base::UTF8ToUTF16(kDefaultCardName), card->GetRawInfo(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)); + EXPECT_EQ(kDefaultBillingAddressId, card->billing_address_id()); } #endif // !defined(OS_CHROMEOS) // Wallet data should get cleared from the database when sync is disabled. IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ClearOnDisableSync) { AddDefaultCard(GetFakeServer()); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed"; + ASSERT_TRUE(SetupSync()); // Make sure the card is in the DB. autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); - std::vector<autofill::CreditCard*> cards = pdm->GetCreditCards(); + std::vector<CreditCard*> cards = pdm->GetCreditCards(); ASSERT_EQ(1uL, cards.size()); // Turn off sync, the card should be gone. @@ -261,12 +312,12 @@ // flag is disabled. IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ClearOnDisableWalletSync) { AddDefaultCard(GetFakeServer()); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed"; + ASSERT_TRUE(SetupSync()); // Make sure the card is in the DB. autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); - std::vector<autofill::CreditCard*> cards = pdm->GetCreditCards(); + std::vector<CreditCard*> cards = pdm->GetCreditCards(); ASSERT_EQ(1uL, cards.size()); // Turn off autofill sync, the card should be gone. @@ -280,12 +331,12 @@ IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, ClearOnDisableWalletAutofill) { AddDefaultCard(GetFakeServer()); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed"; + ASSERT_TRUE(SetupSync()); // Make sure the card is in the DB. autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); - std::vector<autofill::CreditCard*> cards = pdm->GetCreditCards(); + std::vector<CreditCard*> cards = pdm->GetCreditCards(); ASSERT_EQ(1uL, cards.size()); // Turn off the wallet autofill pref, the card should be gone as a side @@ -295,3 +346,104 @@ cards = pdm->GetCreditCards(); ASSERT_EQ(0uL, cards.size()); } + +// Wallet data present on the client should be cleared in favor of the new data +// synced down form the server. +IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, + NewWalletCardRemovesExistingCard) { + ASSERT_TRUE(SetupClients()); + autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); + ASSERT_NE(nullptr, pdm); + + // Add a server credit card on the client. + CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123"); + std::vector<CreditCard> credit_cards = {credit_card}; + autofill_helper::SetServerCreditCards(0, credit_cards); + + // Refresh the pdm so that it gets cards from autofill table. + RefreshAndWaitForOnPersonalDataChanged(pdm); + + // Make sure the card was added correctly. + std::vector<CreditCard*> cards = pdm->GetCreditCards(); + ASSERT_EQ(1uL, cards.size()); + EXPECT_EQ("a123", cards[0]->server_id()); + + // Add a new card from the server and sync it down. + AddDefaultCard(GetFakeServer()); + ASSERT_TRUE(SetupSync()); + + // The only card present on the client should be the one from the server. + cards = pdm->GetCreditCards(); + ASSERT_EQ(1uL, cards.size()); + EXPECT_EQ(kDefaultCardID, cards[0]->server_id()); +} + +// Tests that a local billing address id set on a card on the client should not +// be overwritten when that same card is synced again. +IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, + SameWalletCard_PreservesLocalBillingAddressId) { + ASSERT_TRUE(SetupClients()); + autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); + ASSERT_NE(nullptr, pdm); + + // Add a server credit card on the client but with the billing address id of a + // local profile. + CreditCard credit_card = GetDefaultCreditCard(); + credit_card.set_billing_address_id(kLocalGuidA); + std::vector<CreditCard> credit_cards = {credit_card}; + autofill_helper::SetServerCreditCards(0, credit_cards); + + // Refresh the pdm so that it gets cards from autofill table. + RefreshAndWaitForOnPersonalDataChanged(pdm); + + // Make sure the card was added correctly. + std::vector<CreditCard*> cards = pdm->GetCreditCards(); + ASSERT_EQ(1uL, cards.size()); + EXPECT_EQ(kDefaultCardID, cards[0]->server_id()); + + // Sync the same card from the server, except with a default billing address + // id. + AddDefaultCard(GetFakeServer()); + ASSERT_TRUE(SetupSync()); + + // The billing address is should still refer to the local profile. + cards = pdm->GetCreditCards(); + ASSERT_EQ(1uL, cards.size()); + EXPECT_EQ(kDefaultCardID, cards[0]->server_id()); + EXPECT_EQ(kLocalGuidA, cards[0]->billing_address_id()); +} + +// Tests that a server billing address id set on a card on the client is +// overwritten when that same card is synced again. +IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, + SameWalletCard_DiscardsOldServerBillingAddressId) { + ASSERT_TRUE(SetupClients()); + autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); + ASSERT_NE(nullptr, pdm); + + // Add a server credit card on the client but with the billing address id of a + // server profile. + CreditCard credit_card = GetDefaultCreditCard(); + credit_card.set_billing_address_id(kDifferentBillingAddressId); + std::vector<CreditCard> credit_cards = {credit_card}; + autofill_helper::SetServerCreditCards(0, credit_cards); + + // Refresh the pdm so that it gets cards from autofill table. + RefreshAndWaitForOnPersonalDataChanged(pdm); + + // Make sure the card was added correctly. + std::vector<CreditCard*> cards = pdm->GetCreditCards(); + ASSERT_EQ(1uL, cards.size()); + EXPECT_EQ(kDefaultCardID, cards[0]->server_id()); + + // Sync the same card from the server, except with a default billing address + // id. + AddDefaultCard(GetFakeServer()); + ASSERT_TRUE(SetupSync()); + + // The billing address should be the one from the server card. + cards = pdm->GetCreditCards(); + ASSERT_EQ(1uL, cards.size()); + EXPECT_EQ(kDefaultCardID, cards[0]->server_id()); + EXPECT_EQ(kDefaultBillingAddressId, cards[0]->billing_address_id()); +}
diff --git a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc index 056df0ca..0412945 100644 --- a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
@@ -72,7 +72,7 @@ IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, PersonalDataManagerSanity) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); // Client0 adds a profile. AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); @@ -109,18 +109,18 @@ } IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, AddDuplicateProfiles) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + ASSERT_TRUE(SetupClients()); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size()); } IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, SameProfileWithConflict) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + ASSERT_TRUE(SetupClients()); AutofillProfile profile0 = CreateAutofillProfile(PROFILE_HOMER); AutofillProfile profile1 = CreateAutofillProfile(PROFILE_HOMER); @@ -129,14 +129,14 @@ AddProfile(0, profile0); AddProfile(1, profile1); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); EXPECT_EQ(1U, GetAllAutoFillProfiles(0).size()); } // Tests that a null profile does not get synced across clients. IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, AddEmptyProfile) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); AddProfile(0, CreateAutofillProfile(PROFILE_NULL)); EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); @@ -146,7 +146,7 @@ // Tests that adding a profile on one client results in it being added on the // other client when sync is running. IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, AddProfile) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); @@ -166,7 +166,7 @@ // Add the new autofill profile before starting sync. AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); // Wait for the sync to happen. EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); @@ -191,7 +191,7 @@ GetAllAutoFillProfiles(1)[0]->guid()); // Wait for the sync to happen. - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); // Make sure that both clients have one profile. @@ -207,12 +207,12 @@ // being added to the other client. IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, AddMultipleProfilesOnOneClient) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + ASSERT_TRUE(SetupClients()); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); AddProfile(0, CreateAutofillProfile(PROFILE_MARION)); AddProfile(0, CreateAutofillProfile(PROFILE_FRASIER)); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); EXPECT_EQ(3U, GetAllAutoFillProfiles(0).size()); } @@ -221,12 +221,12 @@ // all profiles. IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, AddMultipleProfilesOnTwoClients) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + ASSERT_TRUE(SetupClients()); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); AddProfile(1, CreateAutofillProfile(PROFILE_MARION)); AddProfile(1, CreateAutofillProfile(PROFILE_FRASIER)); - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); EXPECT_EQ(3U, GetAllAutoFillProfiles(0).size()); } @@ -234,7 +234,7 @@ // Tests that deleting a profile on one client results in it being deleted on // the other client. IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, DeleteProfile) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); // Setup the test by making the 2 clients have the same profile. AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); @@ -252,7 +252,7 @@ // Tests that modifying a profile while syncing results in the other client // getting the updated profile. IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, UpdateFields) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); @@ -284,7 +284,7 @@ // which one). IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, UpdateConflictingFields) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); // Make the two clients have the same profile. AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); @@ -309,7 +309,7 @@ // which one). IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, UpdateConflictingFieldsDuringInitialMerge) { - ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + ASSERT_TRUE(SetupClients()); // Make the two clients have the same profile. AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); @@ -322,7 +322,7 @@ AutofillType(autofill::NAME_FIRST), base::ASCIIToUTF16("Bart")); // Start sync. - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); // Don't care which write wins the conflict, only that the two clients agree. EXPECT_TRUE(AutofillProfileChecker(0, 1).Wait()); @@ -333,7 +333,7 @@ // syncing results in both client having the same profile (doesn't matter which // one). IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, DeleteAndUpdate) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); // Make the two clients have the same profile. AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); @@ -353,7 +353,7 @@ } IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, MaxLength) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); ASSERT_TRUE(AutofillProfileChecker(0, 1).Wait()); @@ -377,7 +377,7 @@ } IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, ExceedsMaxLength) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); AddProfile(0, CreateAutofillProfile(PROFILE_HOMER)); ASSERT_TRUE(AutofillProfileChecker(0, 1).Wait()); @@ -408,7 +408,7 @@ // Test credit cards don't sync. IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, NoCreditCardSync) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); CreditCard card; card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, @@ -431,7 +431,7 @@ IN_PROC_BROWSER_TEST_P(TwoClientAutofillProfileSyncTest, E2E_ONLY(TwoClientsAddAutofillProfiles)) { - ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(SetupSync()); // All profiles should sync same autofill profiles. ASSERT_TRUE(AutofillProfileChecker(0, 1).Wait())
diff --git a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc index ffb8d9c..27a6ba99 100644 --- a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
@@ -1680,7 +1680,7 @@ // Test a scenario of updating the name of the same bookmark from two clients at // the same time. -IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, +IN_PROC_BROWSER_TEST_P(TwoClientBookmarksSyncTestIncludingUssTests, MC_BookmarkNameChangeConflict) { ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; @@ -1705,7 +1705,7 @@ // Test a scenario of updating the URL of the same bookmark from two clients at // the same time. -IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, +IN_PROC_BROWSER_TEST_P(TwoClientBookmarksSyncTestIncludingUssTests, MC_BookmarkURLChangeConflict) { ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; @@ -1732,7 +1732,7 @@ // Test a scenario of updating the BM Folder name from two clients at the same // time. -IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, +IN_PROC_BROWSER_TEST_P(TwoClientBookmarksSyncTestIncludingUssTests, MC_FolderNameChangeConflict) { ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; DisableVerifier();
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc index 8228ee8..6eb3ed5 100644 --- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc +++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -14,7 +14,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/values.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/drive/drive_notification_manager_factory.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" @@ -50,6 +49,7 @@ #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/service_manager_connection.h" #include "extensions/browser/extension_system.h" @@ -249,8 +249,7 @@ SyncEngine::~SyncEngine() { Reset(); - g_browser_process->network_connection_tracker() - ->RemoveNetworkConnectionObserver(this); + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); if (signin_manager_) signin_manager_->RemoveObserver(this); if (notification_manager_) @@ -370,7 +369,7 @@ service_state_ = REMOTE_SERVICE_TEMPORARY_UNAVAILABLE; auto connection_type = network::mojom::ConnectionType::CONNECTION_NONE; - g_browser_process->network_connection_tracker()->GetConnectionType( + content::GetNetworkConnectionTracker()->GetConnectionType( &connection_type, base::BindOnce(&SyncEngine::OnConnectionChanged, weak_ptr_factory_.GetWeakPtr())); OnConnectionChanged(connection_type); @@ -764,8 +763,7 @@ notification_manager_->AddObserver(this); if (signin_manager_) signin_manager_->AddObserver(this); - g_browser_process->network_connection_tracker()->AddNetworkConnectionObserver( - this); + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); } void SyncEngine::OnPendingFileListUpdated(int item_count) {
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc index 20818232..312b76a0 100644 --- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc +++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
@@ -437,13 +437,12 @@ } int64_t CannedSyncableFileSystem::Write( - net::URLRequestContext* url_request_context, const FileSystemURL& url, std::unique_ptr<storage::BlobDataHandle> blob_data_handle) { return RunOnThread<int64_t>( io_task_runner_.get(), FROM_HERE, base::BindOnce(&CannedSyncableFileSystem::DoWrite, base::Unretained(this), - url_request_context, url, std::move(blob_data_handle))); + url, std::move(blob_data_handle))); } int64_t CannedSyncableFileSystem::WriteString(const FileSystemURL& url, @@ -636,7 +635,6 @@ } void CannedSyncableFileSystem::DoWrite( - net::URLRequestContext* url_request_context, const FileSystemURL& url, std::unique_ptr<storage::BlobDataHandle> blob_data_handle, const WriteCallback& callback) { @@ -644,7 +642,7 @@ EXPECT_TRUE(is_filesystem_opened_); WriteHelper* helper = new WriteHelper; operation_runner()->Write( - url_request_context, url, std::move(blob_data_handle), 0, + url, std::move(blob_data_handle), 0, base::Bind(&WriteHelper::DidWrite, base::Owned(helper), callback)); } @@ -657,10 +655,10 @@ MockBlobURLRequestContext* url_request_context( new MockBlobURLRequestContext()); WriteHelper* helper = new WriteHelper(url_request_context, data); - operation_runner()->Write(url_request_context, url, + operation_runner()->Write(url, helper->scoped_text_blob()->GetBlobDataHandle(), 0, - base::Bind(&WriteHelper::DidWrite, - base::Owned(helper), callback)); + base::BindRepeating(&WriteHelper::DidWrite, + base::Owned(helper), callback)); } void CannedSyncableFileSystem::DoGetUsageAndQuota(
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.h b/chrome/browser/sync_file_system/local/canned_syncable_file_system.h index 03bee0b..16635ed 100644 --- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.h +++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.h
@@ -36,10 +36,6 @@ class FileSystemURL; } -namespace net { -class URLRequestContext; -} - namespace storage { class QuotaManager; } @@ -137,8 +133,7 @@ FileEntryList* entries); // Returns the # of bytes written (>=0) or an error code (<0). - int64_t Write(net::URLRequestContext* url_request_context, - const storage::FileSystemURL& url, + int64_t Write(const storage::FileSystemURL& url, std::unique_ptr<storage::BlobDataHandle> blob_data_handle); int64_t WriteString(const storage::FileSystemURL& url, const std::string& data); @@ -200,8 +195,7 @@ void DoReadDirectory(const storage::FileSystemURL& url, FileEntryList* entries, const StatusCallback& callback); - void DoWrite(net::URLRequestContext* url_request_context, - const storage::FileSystemURL& url, + void DoWrite(const storage::FileSystemURL& url, std::unique_ptr<storage::BlobDataHandle> blob_data_handle, const WriteCallback& callback); void DoWriteString(const storage::FileSystemURL& url,
diff --git a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc index 411cdf75..d90f119 100644 --- a/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc +++ b/chrome/browser/sync_file_system/local/local_file_change_tracker_unittest.cc
@@ -297,8 +297,7 @@ EXPECT_EQ(base::File::FILE_OK, file_system_.CreateFile(URL(kPath4))); // Creates another file. EXPECT_EQ(static_cast<int64_t>(kData.size()), // Modifies the file. - file_system_.Write(&url_request_context, URL(kPath4), - blob.GetBlobDataHandle())); + file_system_.Write(URL(kPath4), blob.GetBlobDataHandle())); // Verify the changes. file_system_.GetChangedURLsInTracker(&urls); @@ -448,8 +447,8 @@ EXPECT_EQ(base::File::FILE_OK, file_system_.CreateFile(URL(kPath4))); // Creates another file. EXPECT_EQ(static_cast<int64_t>(kData.size()), - file_system_.Write(&url_request_context, // Modifies the file. - URL(kPath4), blob.GetBlobDataHandle())); + file_system_.Write(URL(kPath4), // Modifies the file. + blob.GetBlobDataHandle())); // Verify we have 5 changes for preparation. file_system_.GetChangedURLsInTracker(&urls);
diff --git a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc index 65a4edd..56658e32 100644 --- a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc +++ b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
@@ -316,7 +316,6 @@ ResetCallbackStatus(); file_system_.operation_runner()->Write( - &url_request_context_, URL(kFile), blob.GetBlobDataHandle(), 0, GetWriteCallback(FROM_HERE)); content::RunAllTasksUntilIdle(); EXPECT_EQ(0, callback_count_);
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc index 09e84bc..e61a8b37 100644 --- a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc +++ b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
@@ -215,7 +215,7 @@ void SyncableFileSystemOperation::Write( const FileSystemURL& url, std::unique_ptr<storage::FileWriterDelegate> writer_delegate, - std::unique_ptr<net::URLRequest> blob_request, + std::unique_ptr<storage::BlobReader> blob_reader, const WriteCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (!operation_runner_.get()) { @@ -229,7 +229,7 @@ weak_factory_.GetWeakPtr(), base::Bind( &FileSystemOperation::Write, base::Unretained(impl_.get()), url, - base::Passed(&writer_delegate), base::Passed(&blob_request), + base::Passed(&writer_delegate), base::Passed(&blob_reader), base::Bind(&self::DidWrite, weak_factory_.GetWeakPtr(), callback)))); operation_runner_->PostOperationTask(std::move(task)); }
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_operation.h b/chrome/browser/sync_file_system/local/syncable_file_system_operation.h index 6d662d00..9341b2894 100644 --- a/chrome/browser/sync_file_system/local/syncable_file_system_operation.h +++ b/chrome/browser/sync_file_system/local/syncable_file_system_operation.h
@@ -63,7 +63,7 @@ const StatusCallback& callback) override; void Write(const storage::FileSystemURL& url, std::unique_ptr<storage::FileWriterDelegate> writer_delegate, - std::unique_ptr<net::URLRequest> blob_request, + std::unique_ptr<storage::BlobReader> blob_reader, const WriteCallback& callback) override; void Truncate(const storage::FileSystemURL& url, int64_t length,
diff --git a/chrome/browser/translate/translate_service.cc b/chrome/browser/translate/translate_service.cc index 364be494c4..aa44331 100644 --- a/chrome/browser/translate/translate_service.cc +++ b/chrome/browser/translate/translate_service.cc
@@ -20,7 +20,6 @@ #include "components/translate/core/browser/translate_download_manager.h" #include "components/translate/core/browser/translate_manager.h" #include "content/public/common/url_constants.h" -#include "ui/base/material_design/material_design_controller.h" #include "url/gurl.h" #if defined(OS_CHROMEOS) @@ -105,12 +104,8 @@ // static bool TranslateService::IsTranslateBubbleEnabled() { -#if defined(USE_AURA) +#if defined(USE_AURA) || defined(OS_MACOSX) return true; -#elif defined(OS_MACOSX) - // On Mac, the translate bubble is shown instead of the infobar if the - // --secondary-ui-md flag is enabled. - return ui::MaterialDesignController::IsSecondaryUiMaterial(); #else // The bubble UX is not implemented on other platforms. return false;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index ae06d05..fa0ae0a 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -85,10 +85,11 @@ constexpr char kAndroidClockAppId[] = "ddmmnabaeomoacfpfjgghfpocfolhjlg"; constexpr char kAndroidFilesAppId[] = "gmiohhmfhgfclpeacmdfancbipocempm"; constexpr char kAndroidCameraAppId[] = "goamfaniemdfcajgcmmflhchgkmbngka"; +constexpr char kAndroidLegacyCameraAppId[] = "obfofkigjfamlldmipdegnjlcpincibc"; constexpr char const* kAppIdsHiddenInLauncher[] = { - kAndroidClockAppId, kSettingsAppId, kAndroidFilesAppId, - kAndroidCameraAppId}; + kAndroidClockAppId, kSettingsAppId, kAndroidFilesAppId, kAndroidCameraAppId, + kAndroidLegacyCameraAppId}; // Returns true if |event_flags| came from a mouse or touch event. bool IsMouseOrTouchEventFromFlags(int event_flags) {
diff --git a/chrome/browser/ui/app_list/internal_app/internal_app_metadata.cc b/chrome/browser/ui/app_list/internal_app/internal_app_metadata.cc index 24493cf..0317cea4 100644 --- a/chrome/browser/ui/app_list/internal_app/internal_app_metadata.cc +++ b/chrome/browser/ui/app_list/internal_app/internal_app_metadata.cc
@@ -46,6 +46,7 @@ namespace { constexpr char kChromeCameraAppId[] = "hfhhnacclhffhdffklopdkcgdhifgngh"; constexpr char kAndroidCameraAppId[] = "goamfaniemdfcajgcmmflhchgkmbngka"; +constexpr char kAndroidLegacyCameraAppId[] = "obfofkigjfamlldmipdegnjlcpincibc"; } // namespace const std::vector<InternalApp>& GetInternalAppList() { @@ -121,9 +122,13 @@ AppListClientImpl* controller = AppListClientImpl::GetInstance(); if (arc_enabled && (!extension || media_consolidated)) { // Open ARC++ camera app. - arc::LaunchApp(profile, kAndroidCameraAppId, event_flags, - arc::UserInteractionType::APP_STARTED_FROM_LAUNCHER, - controller->GetAppListDisplayId()); + if (!arc::LaunchApp(profile, kAndroidCameraAppId, event_flags, + arc::UserInteractionType::APP_STARTED_FROM_LAUNCHER, + controller->GetAppListDisplayId())) { + arc::LaunchApp(profile, kAndroidLegacyCameraAppId, event_flags, + arc::UserInteractionType::APP_STARTED_FROM_LAUNCHER, + controller->GetAppListDisplayId()); + } } else if (extension) { // Open Chrome camera app. AppLaunchParams params = CreateAppLaunchParamsWithEventFlags(
diff --git a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc index 0df8b77..b981592 100644 --- a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc +++ b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
@@ -18,7 +18,6 @@ #include "ui/accessibility/ax_tree_serializer.h" #include "ui/accessibility/ax_tree_update.h" #include "ui/aura/window.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" #include "ui/views/controls/textfield/textfield.h" @@ -102,8 +101,7 @@ std::vector<AXAuraObjWrapper*> textfield_children; ax_tree.GetChildren(textfield, &textfield_children); // The textfield has an extra child in Harmony, the focus ring. - const size_t expected_children = - ui::MaterialDesignController::IsSecondaryUiMaterial() ? 2 : 1; + const size_t expected_children = 2; ASSERT_EQ(expected_children, textfield_children.size()); ASSERT_EQ(content, textfield->GetParent());
diff --git a/chrome/browser/ui/ash/assistant/assistant_setup.cc b/chrome/browser/ui/ash/assistant/assistant_setup.cc index a27a214..99003d8 100644 --- a/chrome/browser/ui/ash/assistant/assistant_setup.cc +++ b/chrome/browser/ui/ash/assistant/assistant_setup.cc
@@ -29,7 +29,6 @@ constexpr char kAssistantSubPage[] = "googleAssistant"; constexpr char kHotwordNotificationId[] = "assistant/hotword"; constexpr char kNotifierAssistant[] = "assistant"; -constexpr int kAssistantIconSize = 24; // Delegate for assistant hotword notification. class AssistantHotwordNotificationDelegate @@ -119,17 +118,15 @@ const base::string16 display_source = base::UTF8ToUTF16(kAssistantDisplaySource); - message_center::Notification notification( + auto notification = message_center::Notification::CreateSystemNotification( message_center::NOTIFICATION_TYPE_SIMPLE, kHotwordNotificationId, title, - base::string16(), gfx::Image(), display_source, GURL(), + base::string16(), display_source, GURL(), message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, kNotifierAssistant), - {}, base::MakeRefCounted<AssistantHotwordNotificationDelegate>(profile)); - - gfx::Image image(CreateVectorIcon(ash::kNotificationAssistantIcon, - kAssistantIconSize, gfx::kGoogleBlue700)); - notification.set_small_image(image); + {}, base::MakeRefCounted<AssistantHotwordNotificationDelegate>(profile), + ash::kNotificationAssistantIcon, + message_center::SystemNotificationWarningLevel::NORMAL); NotificationDisplayService::GetForProfile(profile)->Display( - NotificationHandler::Type::TRANSIENT, notification); + NotificationHandler::Type::TRANSIENT, *notification); }
diff --git a/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc index a42d3c3..c338583 100644 --- a/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc +++ b/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -20,9 +20,9 @@ namespace { // The total number of Ash accelerators. -constexpr int kAshAcceleratorsTotalNum = 100; +constexpr int kAshAcceleratorsTotalNum = 101; // The hash of Ash accelerators. -constexpr char kAshAcceleratorsHash[] = "4232f3c0c55cc5e487c820b1c2813dcc"; +constexpr char kAshAcceleratorsHash[] = "48e2af8115132ccec79dc16ebe7da7fb"; #if defined(GOOGLE_CHROME_BUILD) // Internal builds add an extra accelerator for the Feedback app. // The total number of Chrome accelerators (available on Chrome OS).
diff --git a/chrome/browser/ui/browser_tab_strip_tracker.cc b/chrome/browser/ui/browser_tab_strip_tracker.cc index bfe522d..cfd10f82 100644 --- a/chrome/browser/ui/browser_tab_strip_tracker.cc +++ b/chrome/browser/ui/browser_tab_strip_tracker.cc
@@ -68,11 +68,22 @@ TabStripModel* tab_strip_model = browser->tab_strip_model(); tab_strip_model->AddObserver(tab_strip_model_observer_); const int active_index = tab_strip_model->active_index(); + + std::vector<TabStripModelChange::Delta> deltas; for (int i = 0; i < tab_strip_model->count(); ++i) { + // TODO(sangwoo108): Delete this. https://crbug.com/842194. tab_strip_model_observer_->TabInsertedAt( tab_strip_model, tab_strip_model->GetWebContentsAt(i), i, i == active_index); + + deltas.push_back(TabStripModelChange::CreateInsertDelta( + tab_strip_model->GetWebContentsAt(i), i)); } + + TabStripModelChange change(TabStripModelChange::kInserted, deltas); + TabStripSelectionChange selection(tab_strip_model->GetActiveWebContents(), + tab_strip_model->selection_model()); + tab_strip_model_observer_->OnTabStripModelChanged(change, selection); } void BrowserTabStripTracker::OnBrowserAdded(Browser* browser) {
diff --git a/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm b/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm index d51af844..1f171bbb 100644 --- a/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm +++ b/chrome/browser/ui/cocoa/accelerator_utils_cocoa.mm
@@ -16,6 +16,11 @@ namespace chrome { bool IsChromeAccelerator(const ui::Accelerator& accelerator, Profile* profile) { + NSUInteger modifiers = (accelerator.IsCtrlDown() ? NSControlKeyMask : 0) | + (accelerator.IsCmdDown() ? NSCommandKeyMask : 0) | + (accelerator.IsAltDown() ? NSAlternateKeyMask : 0) | + (accelerator.IsShiftDown() ? NSShiftKeyMask : 0); + // The |accelerator| passed in contains a Windows key code but no platform // accelerator info. The Accelerator list is the opposite: It has accelerators // that have key_code() == VKEY_UNKNOWN but they contain a platform @@ -23,17 +28,15 @@ // code to a character and use that when comparing against the Accelerator // list. unichar shifted_character; - ui::MacKeyCodeForWindowsKeyCode(accelerator.key_code(), 0, &shifted_character, - nullptr); - NSString* characters = - [[[NSString alloc] initWithCharacters:&shifted_character - length:1] autorelease]; + unichar character; + int mac_keycode = ui::MacKeyCodeForWindowsKeyCode( + accelerator.key_code(), modifiers, &shifted_character, &character); + if (mac_keycode == -1) + return false; - NSUInteger modifiers = - (accelerator.IsCtrlDown() ? NSControlKeyMask : 0) | - (accelerator.IsCmdDown() ? NSCommandKeyMask : 0) | - (accelerator.IsAltDown() ? NSAlternateKeyMask : 0) | - (accelerator.IsShiftDown() ? NSShiftKeyMask : 0); + NSString* characters = [NSString stringWithFormat:@"%C", character]; + NSString* charactersIgnoringModifiers = + [NSString stringWithFormat:@"%C", shifted_character]; NSEvent* event = [NSEvent keyEventWithType:NSKeyDown location:NSZeroPoint @@ -42,9 +45,9 @@ windowNumber:0 context:nil characters:characters - charactersIgnoringModifiers:characters + charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO - keyCode:accelerator.key_code()]; + keyCode:mac_keycode]; return CommandForKeyEvent(event).found(); }
diff --git a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc index 57dec6f3..7184bde 100644 --- a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc +++ b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc
@@ -26,7 +26,6 @@ #include "chrome/browser/ui/views/update_recommended_message_box.h" #include "chrome/common/chrome_features.h" #include "components/constrained_window/constrained_window_views.h" -#include "ui/base/material_design/material_design_controller.h" // This file provides definitions of desktop browser dialog-creation methods for // Mac where a Cocoa browser is using Views dialogs. I.e. it is included in the @@ -36,14 +35,9 @@ namespace chrome { -bool ShowPilotDialogsWithViewsToolkit() { - return ui::MaterialDesignController::IsSecondaryUiMaterial(); -} - bool ShowAllDialogsWithViewsToolkit() { - return ShowPilotDialogsWithViewsToolkit() && - base::FeatureList::IsEnabled( - features::kShowAllDialogsWithViewsToolkit); + return base::FeatureList::IsEnabled( + features::kShowAllDialogsWithViewsToolkit); } void ShowPageInfoBubbleViews(Browser* browser,
diff --git a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h index 27cbde7b..2ca3b94 100644 --- a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h +++ b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h
@@ -34,9 +34,6 @@ namespace chrome { -// Whether to use toolkit-views rather than Cocoa for dialogs ready to "pilot". -bool ShowPilotDialogsWithViewsToolkit(); - // Whether to show all dialogs with toolkit-views on Mac, rather than Cocoa. bool ShowAllDialogsWithViewsToolkit();
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 1cf88f3..c1f2ec89 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -489,11 +489,7 @@ } void BrowserWindowCocoa::ShowUpdateChromeDialog() { - if (chrome::ShowPilotDialogsWithViewsToolkit()) { - chrome::ShowUpdateChromeDialogViews(GetNativeWindow()); - } else { - restart_browser::RequestRestart(window()); - } + chrome::ShowUpdateChromeDialogViews(GetNativeWindow()); } void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
diff --git a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm index 9750b4f47..3e3e323 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_popup_controller.mm
@@ -27,7 +27,6 @@ #include "extensions/browser/notification_types.h" #include "ui/base/cocoa/cocoa_base_utils.h" #include "ui/base/cocoa/window_size_constants.h" -#include "ui/base/material_design/material_design_controller.h" using content::BrowserContext; using content::RenderViewHost; @@ -181,14 +180,8 @@ anchoredAt:anchoredAt])) { beingInspected_ = devMode; ignoreWindowDidResignKey_ = NO; - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - // Under MD, bubbles never have arrows. - [[self bubble] setArrowLocation:info_bubble::kNoArrow]; - [[self bubble] setAlignment:info_bubble::kAlignTrailingEdgeToAnchorEdge]; - } else { - [[self bubble] setArrowLocation:info_bubble::kTopTrailing]; - [[self bubble] setAlignment:info_bubble::kAlignArrowToAnchor]; - } + [[self bubble] setArrowLocation:info_bubble::kNoArrow]; + [[self bubble] setAlignment:info_bubble::kAlignTrailingEdgeToAnchorEdge]; if (!gAnimationsEnabled) [window setAllowedAnimations:info_bubble::kAnimateNone]; }
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm index bfc41d9..b472721 100644 --- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm +++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
@@ -292,16 +292,6 @@ } - (NSPoint)bubblePointForDecoration:(LocationBarDecoration*)decoration { - // Use MD-style anchoring, even if only pilot dialogs are enabled. MD dialogs - // have no arrow and align corners. Cocoa dialogs will always have an arrow. - // This causes the arrows on Cocoa dialogs to align to the omnibox corner. - if (!chrome::ShowPilotDialogsWithViewsToolkit()) { - const NSRect frame = - [[self cell] frameForDecoration:decoration inFrame:[self bounds]]; - NSPoint point = decoration->GetBubblePointInFrame(frame); - return [self convertPoint:point toView:nil]; - } - // Under MD, dialogs have no arrow and anchor to corner of the location bar // frame, not a specific point within it. See http://crbug.com/566115.
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm index fa85ad6..81b2603 100644 --- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm +++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
@@ -26,7 +26,7 @@ // Whether the toolkit-views zoom bubble should be used. bool UseViews() { - return chrome::ShowPilotDialogsWithViewsToolkit(); + return true; } } // namespace
diff --git a/chrome/browser/ui/cocoa/login_handler_cocoa.mm b/chrome/browser/ui/cocoa/login_handler_cocoa.mm index 1a436ba8c..b947f7a 100644 --- a/chrome/browser/ui/cocoa/login_handler_cocoa.mm +++ b/chrome/browser/ui/cocoa/login_handler_cocoa.mm
@@ -141,12 +141,8 @@ net::AuthChallengeInfo* auth_info, content::ResourceRequestInfo::WebContentsGetter web_contents_getter, LoginAuthRequiredCallback auth_required_callback) { - if (chrome::ShowPilotDialogsWithViewsToolkit()) { - return chrome::CreateLoginHandlerViews(auth_info, web_contents_getter, - std::move(auth_required_callback)); - } - return base::MakeRefCounted<LoginHandlerMac>( - auth_info, web_contents_getter, std::move(auth_required_callback)); + return chrome::CreateLoginHandlerViews(auth_info, web_contents_getter, + std::move(auth_required_callback)); } // ----------------------------------------------------------------------------
diff --git a/chrome/browser/ui/cocoa/nsmenuitem_additions.mm b/chrome/browser/ui/cocoa/nsmenuitem_additions.mm index 9cd13b7..488ff778 100644 --- a/chrome/browser/ui/cocoa/nsmenuitem_additions.mm +++ b/chrome/browser/ui/cocoa/nsmenuitem_additions.mm
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" +#include "ui/events/keycodes/keyboard_code_conversion_mac.h" namespace { bool g_is_input_source_dvorak_qwerty = false; @@ -127,24 +128,15 @@ // We typically want to compare [NSMenuItem keyEquivalent] against [NSEvent // charactersIgnoringModifiers]. There is a special keyboard layout "Dvorak - // QWERTY" which uses QWERTY-style shortcuts when the Command key is held - // down. In this case, we want to use [NSEvent characters] instead of [NSEvent - // charactersIgnoringModifiers]. The problem is, this has the wrong behavior - // for every other keyboard layout. - // - // The documentation for -[NSEvent charactersIgnoringModifiers] states that - // it is the appropriate method to use for implementing keyEquivalents. + // down. In this case, we want to use the keycode of the event rather than + // looking at the characters. if (g_is_input_source_dvorak_qwerty) { - // When both |characters| and |charactersIgnoringModifiers| are ascii, we - // want to use |characters| if it's a character and - // |charactersIgnoringModifiers| else (on dvorak, cmd-shift-z should fire - // "cmd-:" instead of "cmd-;", but on dvorak-qwerty, cmd-shift-z should fire - // cmd-shift-z instead of cmd-:). - if ([eventString characterAtIndex:0] <= 0x7f && - [[event characters] length] > 0 && - [[event characters] characterAtIndex:0] <= 0x7f && - isalpha([[event characters] characterAtIndex:0])) { - eventString = [event characters]; - } + ui::KeyboardCode windows_keycode = + ui::KeyboardCodeFromKeyCode(event.keyCode); + unichar shifted_character, character; + ui::MacKeyCodeForWindowsKeyCode(windows_keycode, event.modifierFlags, + &shifted_character, &character); + eventString = [NSString stringWithFormat:@"%C", shifted_character]; } // [ctr + shift + tab] generates the "End of Medium" keyEquivalent rather than
diff --git a/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm b/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm index 41823864..9884e1d 100644 --- a/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm +++ b/chrome/browser/ui/cocoa/nsmenuitem_additions_unittest.mm
@@ -267,12 +267,30 @@ ExpectKeyDoesntFireItem(key, MenuItem(@"z", 0x100000)); ExpectKeyFiresItem(key, MenuItem(@";", 0x100000)); + // Change to Dvorak-QWERTY + SetIsInputSourceDvorakQwertyForTesting(true); + // cmd-z on dvorak qwerty layout (so that the key produces ';', but 'z' if // cmd is down) - SetIsInputSourceDvorakQwertyForTesting(true); key = KeyEvent(0x100108, @"z", @";", 6); ExpectKeyFiresItem(key, MenuItem(@"z", 0x100000), false); ExpectKeyDoesntFireItem(key, MenuItem(@";", 0x100000), false); + + // On dvorak-qwerty, pressing the keys for 'cmd' and '=' triggers an event + // whose characters are cmd-'+'. + // cmd-'+' on dvorak qwerty should not trigger a menu item for cmd-']', and + // not a menu item for cmd-'+'. + key = KeyEvent(0x100108, @"+", @"+", 30); + ExpectKeyFiresItem(key, MenuItem(@"]", 0x100000), false); + ExpectKeyDoesntFireItem(key, MenuItem(@"+", 0x100000), false); + + // cmd-shift-'+' on dvorak qwerty should trigger a menu item for cmd-shift-'}' + // and not a menu item for cmd-shift-'+'. + key = KeyEvent(0x12010a, @"}", @"+", 30); + ExpectKeyFiresItem(key, MenuItem(@"}", 0x100000), false); + ExpectKeyDoesntFireItem(key, MenuItem(@"+", 0x100000), false); + + // Change away from Dvorak-QWERTY SetIsInputSourceDvorakQwertyForTesting(false); // cmd-shift-z on dvorak layout (so that we get a ':')
diff --git a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm index 5b2b8c6b..d6a311f 100644 --- a/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm +++ b/chrome/browser/ui/cocoa/touchbar/web_textfield_touch_bar_controller.mm
@@ -44,7 +44,8 @@ if ((self = [super init])) { controller_ = controller; - if (base::FeatureList::IsEnabled(features::kTextSuggestionsTouchBar)) { + if (base::FeatureList::IsEnabled(features::kTextSuggestionsTouchBar) || + base::FeatureList::IsEnabled(features::kExperimentalUi)) { textSuggestionsTouchBarController_.reset( [[TextSuggestionsTouchBarController alloc] initWithWebContents:[controller_ webContents]
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index a4d98a20..0c69708 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -64,7 +64,6 @@ #include "ppapi/buildflags/buildflags.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/window_open_disposition.h" #include "ui/resources/grit/ui_resources.h" @@ -1013,18 +1012,11 @@ else title = base::UTF8ToUTF16(url.spec()); - const bool use_md = ui::MaterialDesignController::IsSecondaryUiMaterial(); - if (use_md) { - // Format the title to include the unicode single dot bullet code-point - // \u2022 and two spaces. - title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); - } + // Format the title to include the unicode single dot bullet code-point \u2022 + // and two spaces. + title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); - return ListItem(use_md - ? gfx::Image() - : ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_DEFAULT_FAVICON), - title, true, id); + return ListItem(gfx::Image(), title, true, id); } void ContentSettingPopupBubbleModel::OnListItemClicked(int index, @@ -1646,18 +1638,11 @@ ? base::UTF8ToUTF16(url.spec()) : l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE); - const bool use_md = ui::MaterialDesignController::IsSecondaryUiMaterial(); - if (use_md) { - // Format the title to include the unicode single dot bullet code-point - // \u2022 and two spaces. - title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); - } + // Format the title to include the unicode single dot bullet code-point + // \u2022 and two spaces. + title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title); - gfx::Image image = - use_md ? gfx::Image() - : ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_DEFAULT_FAVICON); - return ListItem(image, title, true, 0); + return ListItem(gfx::Image(), title, true, 0); } // ContentSettingBubbleModel ---------------------------------------------------
diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc index e968f1b7..a33b8008 100644 --- a/chrome/browser/ui/layout_constants.cc +++ b/chrome/browser/ui/layout_constants.cc
@@ -54,9 +54,7 @@ // move to views/layout_provider.h so that all bubbles are consistent. return newer_material ? 8 : 2; case LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET: - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) - return 1; - return hybrid ? 8 : 6; + return 1; case LOCATION_BAR_ELEMENT_PADDING: { const int kPadding[] = {1, 3, 3, 2, 3}; return kPadding[mode];
diff --git a/chrome/browser/ui/page_info/permission_menu_model.cc b/chrome/browser/ui/page_info/permission_menu_model.cc index 8e943a32..add1cfe39 100644 --- a/chrome/browser/ui/page_info/permission_menu_model.cc +++ b/chrome/browser/ui/page_info/permission_menu_model.cc
@@ -12,7 +12,6 @@ #include "content/public/common/origin_util.h" #include "ppapi/buildflags/buildflags.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" PermissionMenuModel::PermissionMenuModel(Profile* profile, const GURL& url, @@ -28,6 +27,7 @@ // Retrieve the string to show for the default setting for this permission. ContentSetting effective_default_setting = permission_.default_setting; + DCHECK_NE(effective_default_setting, CONTENT_SETTING_NUM_SETTINGS); #if BUILDFLAG(ENABLE_PLUGINS) effective_default_setting = PluginsFieldTrial::EffectiveContentSetting( @@ -35,51 +35,20 @@ permission_.default_setting); #endif // BUILDFLAG(ENABLE_PLUGINS) - switch (effective_default_setting) { - case CONTENT_SETTING_ALLOW: - label = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MENU_ITEM_DEFAULT_ALLOW); - break; - case CONTENT_SETTING_BLOCK: - label = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MENU_ITEM_DEFAULT_BLOCK); - break; - case CONTENT_SETTING_ASK: - label = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MENU_ITEM_DEFAULT_ASK); - break; - case CONTENT_SETTING_DETECT_IMPORTANT_CONTENT: - // TODO(tommycli): We display the ASK string for DETECT because with - // HTML5 by Default, Chrome will ask before running Flash on most sites. - // Once the feature flag is gone, migrate the actual setting to ASK. - label = l10n_util::GetStringUTF16( - PluginUtils::ShouldPreferHtmlOverPlugins(host_content_settings_map_) - ? IDS_PAGE_INFO_MENU_ITEM_DEFAULT_ASK - : IDS_PAGE_INFO_MENU_ITEM_DEFAULT_DETECT_IMPORTANT_CONTENT); - break; - case CONTENT_SETTING_NUM_SETTINGS: - NOTREACHED(); - break; - default: - break; - } - // The Material UI for site settings uses comboboxes instead of menubuttons, // which means the elements of the menu themselves have to be shorter, instead // of simply setting a shorter label on the menubutton. - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - label = PageInfoUI::PermissionActionToUIString( - profile, permission_.type, CONTENT_SETTING_DEFAULT, - effective_default_setting, permission_.source); - } + label = PageInfoUI::PermissionActionToUIString( + profile, permission_.type, CONTENT_SETTING_DEFAULT, + effective_default_setting, permission_.source); AddCheckItem(CONTENT_SETTING_DEFAULT, label); // Retrieve the string to show for allowing the permission. if (ShouldShowAllow(url)) { - label = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MENU_ITEM_ALLOW); - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - label = PageInfoUI::PermissionActionToUIString( - profile, permission_.type, CONTENT_SETTING_ALLOW, - effective_default_setting, permission_.source); - } + label = PageInfoUI::PermissionActionToUIString( + profile, permission_.type, CONTENT_SETTING_ALLOW, + effective_default_setting, permission_.source); AddCheckItem(CONTENT_SETTING_ALLOW, label); } @@ -94,26 +63,17 @@ } // Retrieve the string to show for blocking the permission. - label = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MENU_ITEM_BLOCK); - if (permission_.type == CONTENT_SETTINGS_TYPE_ADS) { - label = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MENU_ITEM_ADS_BLOCK); - } - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - label = PageInfoUI::PermissionActionToUIString( - profile, info.type, CONTENT_SETTING_BLOCK, effective_default_setting, - info.source); - } + label = PageInfoUI::PermissionActionToUIString( + profile, info.type, CONTENT_SETTING_BLOCK, effective_default_setting, + info.source); AddCheckItem(CONTENT_SETTING_BLOCK, label); // Retrieve the string to show for allowing the user to be asked about the // permission. if (ShouldShowAsk(url)) { - label = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MENU_ITEM_ASK); - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - label = PageInfoUI::PermissionActionToUIString( - profile, info.type, CONTENT_SETTING_ASK, effective_default_setting, - info.source); - } + label = PageInfoUI::PermissionActionToUIString( + profile, info.type, CONTENT_SETTING_ASK, effective_default_setting, + info.source); AddCheckItem(CONTENT_SETTING_ASK, label); } }
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index d5d831b1..00caf563 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -62,21 +62,6 @@ ui::PAGE_TRANSITION_AUTO_TOPLEVEL); } -// Fill TabStripSelectionChange with given |contents| and |selection_model|. -// note that |new_contents| and |new_model| will be filled too so that -// selection_changed() and active_tab_changed() won't return true. -TabStripSelectionChange GetDefaultSelection( - content::WebContents* contents, - const ui::ListSelectionModel& selection_model) { - TabStripSelectionChange selection; - selection.old_contents = contents; - selection.new_contents = contents; - selection.old_model = selection_model; - selection.new_model = selection_model; - selection.reason = 0; - return selection; -} - // This tracks (and reports via UMA and tracing) how long it takes before a // RenderWidgetHost is requested to become visible. class RenderWidgetHostVisibilityTracker @@ -358,8 +343,7 @@ if (manager) data->set_blocked(manager->IsDialogActive()); - TabStripSelectionChange selection = - GetDefaultSelection(GetActiveWebContents(), selection_model_); + TabStripSelectionChange selection(GetActiveWebContents(), selection_model_); contents_data_.insert(contents_data_.begin() + index, std::move(data)); @@ -376,9 +360,9 @@ /*triggered_by_other_operation=*/true); } - base::Optional<TabStripModelChange> change(TabStripModelChange( + TabStripModelChange change( TabStripModelChange::kInserted, - TabStripModelChange::CreateInsertDelta(raw_contents, index))); + TabStripModelChange::CreateInsertDelta(raw_contents, index)); for (auto& observer : observers_) observer.OnTabStripModelChanged(change, selection); } @@ -392,8 +376,7 @@ FixOpenersAndGroupsReferencing(index); - TabStripSelectionChange selection = - GetDefaultSelection(GetActiveWebContents(), selection_model_); + TabStripSelectionChange selection(GetActiveWebContents(), selection_model_); WebContents* raw_new_contents = new_contents.get(); std::unique_ptr<WebContents> old_contents = contents_data_[index]->ReplaceWebContents(std::move(new_contents)); @@ -414,10 +397,9 @@ } } - base::Optional<TabStripModelChange> change( - TabStripModelChange(TabStripModelChange::kReplaced, - TabStripModelChange::CreateReplaceDelta( - old_contents.get(), raw_new_contents, index))); + TabStripModelChange change(TabStripModelChange::kReplaced, + TabStripModelChange::CreateReplaceDelta( + old_contents.get(), raw_new_contents, index)); for (auto& observer : observers_) observer.OnTabStripModelChanged(change, selection); @@ -573,8 +555,7 @@ observer.TabStripEmpty(); } - base::Optional<TabStripModelChange> change( - TabStripModelChange(TabStripModelChange::kRemoved, deltas)); + TabStripModelChange change(TabStripModelChange::kRemoved, deltas); for (auto& observer : observers_) observer.OnTabStripModelChanged(change, selection); } @@ -1553,8 +1534,9 @@ if (!triggered_by_other_operation && (selection.active_tab_changed() || selection.selection_changed())) { + TabStripModelChange change; for (auto& observer : observers_) - observer.OnTabStripModelChanged({}, selection); + observer.OnTabStripModelChanged(change, selection); } return selection; @@ -1577,8 +1559,7 @@ bool select_after_move) { FixOpenersAndGroupsReferencing(index); - TabStripSelectionChange selection = - GetDefaultSelection(GetActiveWebContents(), selection_model_); + TabStripSelectionChange selection(GetActiveWebContents(), selection_model_); std::unique_ptr<WebContentsData> moved_data = std::move(contents_data_[index]); @@ -1597,9 +1578,9 @@ for (auto& observer : observers_) observer.TabMoved(web_contents, index, to_position); - base::Optional<TabStripModelChange> change(TabStripModelChange( + TabStripModelChange change( TabStripModelChange::kMoved, - TabStripModelChange::CreateMoveDelta(web_contents, index, to_position))); + TabStripModelChange::CreateMoveDelta(web_contents, index, to_position)); for (auto& observer : observers_) observer.OnTabStripModelChanged(change, selection); }
diff --git a/chrome/browser/ui/tabs/tab_strip_model_observer.cc b/chrome/browser/ui/tabs/tab_strip_model_observer.cc index f358b01..9e45343 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_observer.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_observer.cc
@@ -45,6 +45,8 @@ return delta; } +TabStripModelChange::TabStripModelChange() = default; + TabStripModelChange::TabStripModelChange(Type type, const Delta& delta) : type_(type), deltas_({delta}) {} @@ -59,11 +61,20 @@ TabStripSelectionChange::TabStripSelectionChange() = default; +TabStripSelectionChange::TabStripSelectionChange( + content::WebContents* contents, + const ui::ListSelectionModel& selection_model) + : old_contents(contents), + new_contents(contents), + old_model(selection_model), + new_model(selection_model), + reason(0) {} + TabStripModelObserver::TabStripModelObserver() { } void TabStripModelObserver::OnTabStripModelChanged( - const base::Optional<TabStripModelChange>& change, + const TabStripModelChange& change, const TabStripSelectionChange& selection) {} void TabStripModelObserver::TabInsertedAt(TabStripModel* tab_strip_model,
diff --git a/chrome/browser/ui/tabs/tab_strip_model_observer.h b/chrome/browser/ui/tabs/tab_strip_model_observer.h index 10295cae..42fa5e0e 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_observer.h +++ b/chrome/browser/ui/tabs/tab_strip_model_observer.h
@@ -8,7 +8,6 @@ #include <vector> #include "base/macros.h" -#include "base/optional.h" #include "chrome/browser/ui/tabs/tab_change_type.h" #include "ui/base/models/list_selection_model.h" @@ -33,12 +32,7 @@ //////////////////////////////////////////////////////////////////////////////// class TabStripModelChange { public: - enum Type { - kInserted, - kRemoved, - kMoved, - kReplaced, - }; + enum Type { kSelectionOnly, kInserted, kRemoved, kMoved, kReplaced }; // A WebContents was inserted at |index|. This implicitly changes the existing // selection model by calling IncrementFrom(index). @@ -97,6 +91,7 @@ content::WebContents* new_contents, int index); + TabStripModelChange(); TabStripModelChange(Type type, const Delta& delta); TabStripModelChange(Type type, const std::vector<Delta>& deltas); ~TabStripModelChange(); @@ -107,7 +102,7 @@ const std::vector<Delta>& deltas() const { return deltas_; } private: - const Type type_; + const Type type_ = kSelectionOnly; const std::vector<Delta> deltas_; DISALLOW_COPY_AND_ASSIGN(TabStripModelChange); @@ -117,6 +112,12 @@ struct TabStripSelectionChange { TabStripSelectionChange(); + // Fill TabStripSelectionChange with given |contents| and |selection_model|. + // note that |new_contents| and |new_model| will be filled too so that + // selection_changed() and active_tab_changed() won't return true. + TabStripSelectionChange(content::WebContents* contents, + const ui::ListSelectionModel& model); + bool active_tab_changed() const { return old_contents != new_contents; } // TODO(sangwoo.ko) Do we need something to indicate that the change @@ -172,9 +173,8 @@ // TabStripModel before the |change| and after the |change| are applied. // When only selection/activation was changed without any change about // WebContents, |change| can be empty. - virtual void OnTabStripModelChanged( - const base::Optional<TabStripModelChange>& change, - const TabStripSelectionChange& selection); + virtual void OnTabStripModelChanged(const TabStripModelChange& change, + const TabStripSelectionChange& selection); // A new WebContents was inserted into the TabStripModel at the // specified index. |foreground| is whether or not it was opened in the
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc index f2ee0cd..f401c3c 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -377,48 +377,46 @@ // TabStripModelObserver implementation: void OnTabStripModelChanged( - const base::Optional<TabStripModelChange>& change, + const TabStripModelChange& change, const TabStripSelectionChange& selection) override { - if (change) { - switch (change->type()) { - case TabStripModelChange::kInserted: { - for (const auto& delta : change->deltas()) { - PushInsertState(delta.insert.contents, delta.insert.index, - selection.new_contents == delta.insert.contents); - } - break; + switch (change.type()) { + case TabStripModelChange::kInserted: { + for (const auto& delta : change.deltas()) { + PushInsertState(delta.insert.contents, delta.insert.index, + selection.new_contents == delta.insert.contents); } - case TabStripModelChange::kRemoved: { - for (const auto& delta : change->deltas()) { - if (delta.remove.will_be_deleted) - PushCloseState(delta.remove.contents, delta.remove.index); - - PushDetachState(delta.remove.contents, delta.remove.index, - selection.old_contents == delta.remove.contents); - } - break; - } - case TabStripModelChange::kReplaced: { - for (const auto& delta : change->deltas()) { - PushReplaceState(delta.replace.old_contents, - delta.replace.new_contents, delta.replace.index); - } - break; - } - case TabStripModelChange::kMoved: { - for (const auto& delta : change->deltas()) { - PushMoveState(delta.move.contents, delta.move.from_index, - delta.move.to_index); - } - // Selection change triggered by move shouldn't be counted as - // exsiting tests don't expect selection change in this case. - // TODO(sangwoo.ko): Update the tests in this class to not use the - // deprecated callbacks. https://crbug.com/842194 - return; - } - default: - NOTREACHED(); + break; } + case TabStripModelChange::kRemoved: { + for (const auto& delta : change.deltas()) { + if (delta.remove.will_be_deleted) + PushCloseState(delta.remove.contents, delta.remove.index); + + PushDetachState(delta.remove.contents, delta.remove.index, + selection.old_contents == delta.remove.contents); + } + break; + } + case TabStripModelChange::kReplaced: { + for (const auto& delta : change.deltas()) { + PushReplaceState(delta.replace.old_contents, + delta.replace.new_contents, delta.replace.index); + } + break; + } + case TabStripModelChange::kMoved: { + for (const auto& delta : change.deltas()) { + PushMoveState(delta.move.contents, delta.move.from_index, + delta.move.to_index); + } + // Selection change triggered by move shouldn't be counted as + // exsiting tests don't expect selection change in this case. + // TODO(sangwoo.ko): Update the tests in this class to not use the + // deprecated callbacks. https://crbug.com/842194 + return; + } + default: + break; } if (selection.active_tab_changed()) {
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc index 3ed6da6..4206451 100644 --- a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc +++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
@@ -16,7 +16,7 @@ #include "chrome/browser/media/router/media_router_factory.h" #include "chrome/browser/media/router/mojo/media_router_mojo_impl.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/media_router/cloud_services_dialog.h" #include "chrome/browser/ui/singleton_tabs.h" @@ -27,10 +27,10 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" -#include "components/signin/core/browser/signin_manager.h" #include "components/strings/grit/components_strings.h" #include "components/vector_icons/vector_icons.h" #include "extensions/common/constants.h" +#include "services/identity/public/cpp/identity_manager.h" #include "ui/base/models/menu_model_delegate.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/paint_vector_icon.h" @@ -136,9 +136,9 @@ if (command_id == IDC_MEDIA_ROUTER_CLOUD_SERVICES_TOGGLE) { // Cloud services preference is not set or used if the user is not signed // in. - SigninManagerBase* signin_manager = - SigninManagerFactory::GetForProfile(browser_->profile()); - return signin_manager && signin_manager->IsAuthenticated(); + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(browser_->profile()); + return identity_manager && identity_manager->HasPrimaryAccount(); } return true; }
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc index cacfe65..747d23fb 100644 --- a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc +++ b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/media/router/media_router_factory.h" #include "chrome/browser/media/router/test/mock_media_router.h" #include "chrome/browser/signin/fake_signin_manager_builder.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/extensions/browser_action_test_util.h" #include "chrome/browser/ui/media_router/media_router_ui_service.h" @@ -24,6 +25,8 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/browser_with_test_window_test.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" @@ -74,8 +77,6 @@ extensions::extension_action_test_util::CreateToolbarModelForProfile( profile()); - signin_manager_ = - SigninManagerFactory::GetInstance()->GetForProfile(profile()); browser_action_test_util_ = BrowserActionTestUtil::Create(browser(), false); action_ = std::make_unique<MediaRouterAction>( browser(), browser_action_test_util_->GetToolbarActionsBar()); @@ -97,13 +98,14 @@ return {{media_router::MediaRouterFactory::GetInstance(), &media_router::MockMediaRouter::Create}, {media_router::MediaRouterUIServiceFactory::GetInstance(), - &BuildUIService}}; + &BuildUIService}, + {SigninManagerFactory::GetInstance(), &BuildFakeSigninManagerBase}}; } protected: std::unique_ptr<BrowserActionTestUtil> browser_action_test_util_; std::unique_ptr<MediaRouterAction> action_; - SigninManagerBase* signin_manager_ = nullptr; + ToolbarActionsModel* toolbar_actions_model_ = nullptr; MockMediaRouterContextualMenuObserver observer_; @@ -146,7 +148,9 @@ } // Set up an authenticated account. - signin_manager_->SetAuthenticatedAccountInfo("foo@bar.com", "password"); + (void)identity::SetPrimaryAccount( + SigninManagerFactory::GetInstance()->GetForProfile(profile()), + IdentityManagerFactory::GetForProfile(profile()), "foo@bar.com"); // Run the same checks as before. All existing menu items should be now // enabled and visible. @@ -205,7 +209,9 @@ // Set up an authenticated account such that the cloud services menu item is // surfaced. Whether or not it is surfaced is tested in the "Basic" test. - signin_manager_->SetAuthenticatedAccountInfo("foo@bar.com", "password"); + (void)identity::SetPrimaryAccount( + SigninManagerFactory::GetInstance()->GetForProfile(profile()), + IdentityManagerFactory::GetForProfile(profile()), "foo@bar.com"); // Set this preference so that the cloud services can be enabled without // showing the opt-in dialog.
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc index 40ec0cda..a86c731 100644 --- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc +++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -22,7 +22,6 @@ #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/insets.h" @@ -280,8 +279,7 @@ } bool CardUnmaskPromptViews::ShouldShowCloseButton() const { - // Material UI has no [X] in the corner of this dialog. - return !ui::MaterialDesignController::IsSecondaryUiMaterial(); + return false; } bool CardUnmaskPromptViews::Cancel() {
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc index 85194a5..ef4c3a7 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_bubble_views.cc
@@ -17,7 +17,6 @@ #include "components/autofill/core/browser/ui/local_card_migration_bubble_controller.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/insets.h" @@ -80,9 +79,7 @@ } int LocalCardMigrationBubbleViews::GetDialogButtons() const { - return ui::MaterialDesignController::IsSecondaryUiMaterial() - ? ui::DIALOG_BUTTON_OK - : ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; + return ui::DIALOG_BUTTON_OK; } base::string16 LocalCardMigrationBubbleViews::GetDialogButtonLabel( @@ -116,7 +113,7 @@ } bool LocalCardMigrationBubbleViews::ShouldShowCloseButton() const { - return ui::MaterialDesignController::IsSecondaryUiMaterial(); + return true; } void LocalCardMigrationBubbleViews::WindowClosing() { @@ -138,4 +135,4 @@ AddChildView(explanatory_message); } -} // namespace autofill \ No newline at end of file +} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc index 21e8bb34..7a54a95 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -17,7 +17,6 @@ #include "components/autofill/core/browser/ui/save_card_bubble_controller.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/geometry/insets.h" @@ -120,10 +119,7 @@ } int SaveCardBubbleViews::GetDialogButtons() const { - // Material UI has no "No thanks" button in favor of an [X]. - return ui::MaterialDesignController::IsSecondaryUiMaterial() - ? ui::DIALOG_BUTTON_OK - : ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; + return ui::DIALOG_BUTTON_OK; } gfx::Size SaveCardBubbleViews::CalculatePreferredSize() const { @@ -183,8 +179,7 @@ } bool SaveCardBubbleViews::ShouldShowCloseButton() const { - // The [X] is shown for Material UI. - return ui::MaterialDesignController::IsSecondaryUiMaterial(); + return true; } base::string16 SaveCardBubbleViews::GetWindowTitle() const {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc index ece5f03..85eb408 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -26,7 +26,6 @@ #include "components/user_prefs/user_prefs.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/events/event.h" #include "ui/views/background.h" #include "ui/views/controls/button/md_text_button.h" @@ -43,13 +42,6 @@ using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; -namespace { - -// Background color of text field when URL is invalid. -const SkColor kErrorColor = SkColorSetRGB(0xFF, 0xBC, 0xBC); - -} // namespace - BookmarkEditorView::BookmarkEditorView( Profile* profile, const BookmarkNode* parent, @@ -454,12 +446,7 @@ void BookmarkEditorView::UserInputChanged() { if (details_.GetNodeType() != BookmarkNode::FOLDER) { const GURL url(GetInputURL()); - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) - url_tf_->SetInvalid(!url.is_valid()); - else if (!url.is_valid()) - url_tf_->SetBackgroundColor(kErrorColor); - else - url_tf_->UseDefaultBackgroundColor(); + url_tf_->SetInvalid(!url.is_valid()); } DialogModelChanged(); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index e777a3c..f34eb83 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -102,6 +102,33 @@ return !MD::IsRefreshUi(); } +bool BrowserNonClientFrameView::HasVisibleBackgroundTabShapes() const { + DCHECK(browser_view()->IsTabStripVisible()); + + // Pre-refresh, background tab shapes are always visible. + if (!MD::IsRefreshUi()) + return true; + + // When custom imagery is involved in drawing the tabstrip, assume tab shapes + // are visible if the tabs use a custom image for a background directly, or if + // the frame image has been tinted visibly. If the tabs use the same image as + // the frame, just shifted to look as if it aligns, this will report that + // shapes are visible when they aren't. To detect this, we'd need to do some + // sort of aligned image comparison, which seems harder than it's worth. + bool has_custom_image; + const int fill_id = + browser_view()->tabstrip()->GetBackgroundResourceId(&has_custom_image); + if (has_custom_image) { + return GetThemeProvider()->HasCustomImage(fill_id) || + color_utils::IsHSLShiftMeaningful(GetThemeProvider()->GetTint( + ThemeProperties::TINT_BACKGROUND_TAB)); + } + + // Background tab shapes are visible iff the tab color differs from the frame + // color. + return GetTabBackgroundColor(TAB_INACTIVE) != GetFrameColor(); +} + gfx::ImageSkia BrowserNonClientFrameView::GetIncognitoAvatarIcon() const { const SkColor icon_color = color_utils::PickContrastingColor( SK_ColorWHITE, gfx::kChromeIconGrey, GetFrameColor());
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h index c58a01d..ef4aaff 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -78,6 +78,10 @@ // Returns whether the content is painted with a client edge or not. virtual bool HasClientEdge() const; + // Returns whether the shapes of background tabs are visible against the + // frame. + virtual bool HasVisibleBackgroundTabShapes() const; + // Retrieves the icon to use in the frame to indicate an incognito window. gfx::ImageSkia GetIncognitoAvatarIcon() const;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index c6695a3..9a8c3f1 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1247,30 +1247,22 @@ LocationBarView* location_bar = GetLocationBarView(); PageActionIconView* card_view = location_bar->save_credit_card_icon_view(); - views::View* anchor_view = location_bar; - if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) { - if (card_view && card_view->visible()) - anchor_view = card_view; - else - anchor_view = toolbar_button_provider()->GetAppMenuButton(); - } - autofill::BubbleType bubble_type = controller->GetBubbleType(); autofill::SaveCardBubbleViews* bubble = nullptr; switch (bubble_type) { case autofill::BubbleType::LOCAL_SAVE: case autofill::BubbleType::UPLOAD_SAVE: - bubble = new autofill::SaveCardOfferBubbleViews(anchor_view, gfx::Point(), - web_contents, controller); + bubble = new autofill::SaveCardOfferBubbleViews( + location_bar, gfx::Point(), web_contents, controller); break; case autofill::BubbleType::SIGN_IN_PROMO: bubble = new autofill::SaveCardSignInPromoBubbleViews( - anchor_view, gfx::Point(), web_contents, controller); + location_bar, gfx::Point(), web_contents, controller); break; case autofill::BubbleType::MANAGE_CARDS: bubble = new autofill::SaveCardManageCardsBubbleViews( - anchor_view, gfx::Point(), web_contents, controller); + location_bar, gfx::Point(), web_contents, controller); break; case autofill::BubbleType::INACTIVE: break; @@ -1296,16 +1288,8 @@ PageActionIconView* card_view = location_bar->local_card_migration_icon_view(); - views::View* anchor_view = location_bar; - if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) { - if (card_view && card_view->visible()) - anchor_view = card_view; - else - anchor_view = toolbar_button_provider()->GetAppMenuButton(); - } - autofill::LocalCardMigrationBubbleViews* bubble = - new autofill::LocalCardMigrationBubbleViews(anchor_view, gfx::Point(), + new autofill::LocalCardMigrationBubbleViews(location_bar, gfx::Point(), web_contents, controller); views::Widget* bubble_widget = views::BubbleDialogDelegateView::CreateBubble(bubble);
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index 1ea2e43b..8be5035 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -171,6 +171,23 @@ BrowserNonClientFrameView::HasClientEdge(); } +bool GlassBrowserFrameView::HasVisibleBackgroundTabShapes() const { + // Pre-Win 8, tabs never match the glass frame appearance. + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return true; + + // Enabling high contrast mode disables the custom-drawn titlebar (so the + // system-drawn frame will respect the native frame colors) and enables the + // IncreasedContrastThemeSupplier (which does not respect the native frame + // colors). + // TODO(pkasting): https://crbug.com/831769 Change the architecture of the + // high contrast support to respect system colors, then remove this. + if (ui::NativeTheme::GetInstanceForNativeUi()->UsesHighContrastColors()) + return true; + + return BrowserNonClientFrameView::HasVisibleBackgroundTabShapes(); +} + void GlassBrowserFrameView::UpdateThrobber(bool running) { if (ShowCustomIcon()) window_icon_->Update();
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index 5ccd6eb..dc098a1 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -39,6 +39,7 @@ int GetTopInset(bool restored) const override; int GetThemeBackgroundXInset() const override; bool HasClientEdge() const override; + bool HasVisibleBackgroundTabShapes() const override; void UpdateThrobber(bool running) override; gfx::Size GetMinimumSize() const override; int GetTabStripLeftInset() const override;
diff --git a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc index 07a5f07..e7b6c45 100644 --- a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc +++ b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
@@ -38,11 +38,12 @@ // static std::unique_ptr<views::LayoutProvider> ChromeLayoutProvider::CreateLayoutProvider() { + // TODO(pbos): Consolidate HarmonyLayoutProvider into ChromeLayoutProvider as + // it is no longer active, or wait until Refresh is always on then consolidate + // all three. if (ui::MaterialDesignController::IsRefreshUi()) return std::make_unique<MaterialRefreshLayoutProvider>(); - return ui::MaterialDesignController::IsSecondaryUiMaterial() - ? std::make_unique<HarmonyLayoutProvider>() - : std::make_unique<ChromeLayoutProvider>(); + return std::make_unique<HarmonyLayoutProvider>(); } gfx::Insets ChromeLayoutProvider::GetInsetsMetric(int metric) const {
diff --git a/chrome/browser/ui/views/hover_button.cc b/chrome/browser/ui/views/hover_button.cc index 73e6301e..c7ac2da 100644 --- a/chrome/browser/ui/views/hover_button.cc +++ b/chrome/browser/ui/views/hover_button.cc
@@ -9,7 +9,6 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h" #include "chrome/browser/ui/views/harmony/chrome_typography.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/animation/ink_drop_highlight.h" @@ -80,9 +79,6 @@ SetBorder(CreateBorderWithVerticalSpacing(vert_spacing)); SetInkDropMode(views::InkDropHostView::InkDropMode::ON); - // Don't show the ripple on non-MD. - if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) - set_ink_drop_visible_opacity(0); } HoverButton::HoverButton(views::ButtonListener* button_listener,
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc index 1b095f8..9c611de 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc +++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/ui/content_settings/content_setting_image_model.h" #include "chrome/browser/ui/views/content_setting_bubble_contents.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/theme_provider.h" #include "ui/events/event_utils.h" #include "ui/gfx/color_palette.h" @@ -181,9 +180,7 @@ content::WebContents* web_contents = delegate_->GetContentSettingWebContents(); if (web_contents && !bubble_view_) { - views::View* anchor = this; - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) - anchor = parent(); + views::View* const anchor = parent(); bubble_view_ = new ContentSettingBubbleContents( content_setting_image_model_->CreateBubbleModel( delegate_->GetContentSettingBubbleModelDelegate(), web_contents,
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc index eea4e38..eca4ff4 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
@@ -14,7 +14,6 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/render_view_host.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/gfx/geometry/rect.h" #include "ui/views/accessibility/view_accessibility.h" @@ -82,16 +81,7 @@ void LocationBarBubbleDelegateView::ShowForReason(DisplayReason reason) { if (reason == USER_GESTURE) { -#if defined(OS_MACOSX) - // In the USER_GESTURE case, the icon will be in an active state so the - // bubble doesn't need an arrow (except on non-MD MacViews). - const bool hide_arrow = - ui::MaterialDesignController::IsSecondaryUiMaterial(); -#else - const bool hide_arrow = true; -#endif - if (hide_arrow) - SetArrowPaintType(views::BubbleBorder::PAINT_TRANSPARENT); + SetArrowPaintType(views::BubbleBorder::PAINT_TRANSPARENT); GetWidget()->Show(); } else { GetWidget()->ShowInactive();
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 07333fd..ba7286e1 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -360,9 +360,7 @@ } views::View* LocationBarView::GetSecurityBubbleAnchorView() { - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) - return this; - return location_icon_view()->GetImageView(); + return this; } bool LocationBarView::ShowPageInfoDialog(WebContents* contents) {
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc index 7ddca684..6f92c7e6 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -34,7 +34,6 @@ #include "extensions/browser/extension_zoom_request_client.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_features.h" #include "ui/gfx/favicon_size.h" @@ -130,13 +129,8 @@ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); if (!is_fullscreen || browser_view->immersive_mode_controller()->IsRevealed()) { - PageActionIconContainerView* container = - browser_view->toolbar_button_provider() - ->GetPageActionIconContainerView(); - return ui::MaterialDesignController::IsSecondaryUiMaterial() - ? static_cast<views::View*>(container) - : static_cast<views::View*>(container->GetPageActionIconView( - PageActionIconType::kZoom)); + return browser_view->toolbar_button_provider() + ->GetPageActionIconContainerView(); } return nullptr; #else // OS_MACOSX && !MAC_VIEWS_BROWSER
diff --git a/chrome/browser/ui/views/page_info/chosen_object_view.cc b/chrome/browser/ui/views/page_info/chosen_object_view.cc index 9e65981..8eda458 100644 --- a/chrome/browser/ui/views/page_info/chosen_object_view.cc +++ b/chrome/browser/ui/views/page_info/chosen_object_view.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h" #include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_utils.h" #include "ui/resources/grit/ui_resources.h" @@ -74,23 +73,11 @@ PageInfoUI::GetChosenObjectIcon(*info_, false, label->enabled_color())); layout->AddView(label); // Create the delete button. - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - delete_button_ = views::CreateVectorImageButton(this); - views::SetImageFromVectorIcon( - delete_button_, vector_icons::kCloseRoundedIcon, - views::style::GetColor(*this, CONTEXT_BODY_TEXT_LARGE, - views::style::STYLE_PRIMARY)); - - } else { - delete_button_ = new views::ImageButton(this); - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - delete_button_->SetImage(views::ImageButton::STATE_NORMAL, - rb.GetImageSkiaNamed(IDR_CLOSE_2)); - delete_button_->SetImage(views::ImageButton::STATE_HOVERED, - rb.GetImageSkiaNamed(IDR_CLOSE_2_H)); - delete_button_->SetImage(views::ImageButton::STATE_PRESSED, - rb.GetImageSkiaNamed(IDR_CLOSE_2_P)); - } + delete_button_ = views::CreateVectorImageButton(this); + views::SetImageFromVectorIcon( + delete_button_, vector_icons::kCloseRoundedIcon, + views::style::GetColor(*this, CONTEXT_BODY_TEXT_LARGE, + views::style::STYLE_PRIMARY)); delete_button_->SetFocusForPlatform(); delete_button_->set_request_focus_on_press(true); delete_button_->SetTooltipText(
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index 5c9f427..55ee18e6 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -43,7 +43,6 @@ #include "content/public/browser/browser_thread.h" #include "extensions/common/constants.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_features.h" @@ -90,10 +89,6 @@ constexpr int kMinBubbleWidth = 320; constexpr int kMaxBubbleWidth = 1000; -bool UseHarmonyStyle() { - return ui::MaterialDesignController::IsSecondaryUiMaterial(); -} - SkColor GetRelatedTextColor() { views::Label label; return views::style::GetColor(label, views::style::CONTEXT_LABEL, @@ -110,67 +105,6 @@ column_set->AddPaddingColumn(views::GridLayout::kFixedSize, margin); } -// Creates a section containing a title, icon, and link. Used to display Cookies -// and Certificate information. Hovering over the |subtitle_text| will show the -// |tooltip_text|. -// *----------------------------------------------* -// | Icon | Title |title_resource_id| string | -// |----------------------------------------------| -// | | Link |subtitle_text| | -// *----------------------------------------------* -views::View* CreateMoreInfoLinkSection(views::LinkListener* listener, - const gfx::ImageSkia& image_icon, - int title_resource_id, - const base::string16& subtitle_text, - int click_target_id, - const base::string16& tooltip_text, - views::Link** link) { - *link = new views::Link(subtitle_text); - (*link)->set_id(click_target_id); - (*link)->set_listener(listener); - (*link)->SetUnderline(false); - (*link)->SetTooltipText(tooltip_text); - - views::View* new_view = new views::View(); - views::GridLayout* layout = - new_view->SetLayoutManager(std::make_unique<views::GridLayout>(new_view)); - ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - const int side_margin = - provider->GetInsetsMetric(views::INSETS_DIALOG_SUBSECTION).left(); - const int vert_spacing = - provider->GetDistanceMetric(DISTANCE_CONTROL_LIST_VERTICAL) / 2; - - const int column = 0; - views::ColumnSet* column_set = layout->AddColumnSet(column); - column_set->AddPaddingColumn(views::GridLayout::kFixedSize, side_margin); - column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, - views::GridLayout::kFixedSize, views::GridLayout::FIXED, - PageInfoBubbleView::kIconColumnWidth, 0); - column_set->AddPaddingColumn( - views::GridLayout::kFixedSize, - provider->GetDistanceMetric(views::DISTANCE_RELATED_LABEL_HORIZONTAL)); - column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, - views::GridLayout::kFixedSize, - views::GridLayout::USE_PREF, 0, 0); - column_set->AddPaddingColumn(views::GridLayout::kFixedSize, side_margin); - - layout->StartRowWithPadding(1.0, column, views::GridLayout::kFixedSize, - vert_spacing); - views::ImageView* icon = new NonAccessibleImageView(); - icon->SetImage(image_icon); - layout->AddView(icon); - - views::Label* title_label = new views::Label( - l10n_util::GetStringUTF16(title_resource_id), CONTEXT_BODY_TEXT_LARGE); - layout->AddView(title_label); - - layout->StartRow(1.0, column); - layout->SkipColumns(1); - layout->AddView(*link); - layout->AddPaddingRow(views::GridLayout::kFixedSize, vert_spacing); - return new_view; -} - // Formats strings and returns the |gfx::Range| of the newly inserted string. gfx::Range GetRangeForFormatString(int string_id, const base::string16& insert_string, @@ -215,25 +149,11 @@ PageInfoBubbleView* listener) { const base::string16& tooltip = l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_TOOLTIP); - if (UseHarmonyStyle()) { - return CreateMoreInfoButton( - listener, PageInfoUI::GetSiteSettingsIcon(GetRelatedTextColor()), - IDS_PAGE_INFO_SITE_SETTINGS_LINK, base::string16(), - PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_SITE_SETTINGS, - tooltip); - } - views::Link* site_settings_link = new views::Link( - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK)); - site_settings_link->set_id( - PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_SITE_SETTINGS); - site_settings_link->SetTooltipText(tooltip); - site_settings_link->set_listener(listener); - site_settings_link->SetUnderline(false); - auto link_section = std::make_unique<views::View>(); - link_section->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::kHorizontal, gfx::Insets(0, side_margin))); - link_section->AddChildView(site_settings_link); - return link_section; + return CreateMoreInfoButton( + listener, PageInfoUI::GetSiteSettingsIcon(GetRelatedTextColor()), + IDS_PAGE_INFO_SITE_SETTINGS_LINK, base::string16(), + PageInfoBubbleView::VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_SITE_SETTINGS, + tooltip); } } // namespace @@ -510,7 +430,7 @@ bool InternalPageInfoBubbleView::ShouldShowCloseButton() const { // TODO(patricialor): When Harmony is default, also remove |bubble_icon_| and // supporting code. - return ui::MaterialDesignController::IsSecondaryUiMaterial(); + return true; } gfx::ImageSkia InternalPageInfoBubbleView::GetWindowIcon() { @@ -566,7 +486,6 @@ profile_(profile), header_(nullptr), site_settings_view_(nullptr), - cookie_link_legacy_(nullptr), cookie_button_(nullptr), weak_factory_(this) { // Capture the default bubble margin, and move it to the Layout classes. This @@ -582,8 +501,7 @@ // assuming that the "Cookies" & "Site settings" buttons will always be shown. const int hover_list_spacing = layout_provider->GetDistanceMetric(DISTANCE_CONTENT_LIST_VERTICAL_MULTI); - const int bottom_margin = - UseHarmonyStyle() ? hover_list_spacing : margins().bottom(); + const int bottom_margin = hover_list_spacing; set_margins(gfx::Insets(margins().top(), 0, bottom_margin, 0)); views::GridLayout* layout = @@ -604,21 +522,14 @@ layout->StartRow(views::GridLayout::kFixedSize, kColumnId); layout->AddView(new views::Separator()); - // The views inside |site_settings_view_| have their own padding, so subtract - // that from the actual padding needed to get the correct value. - const int vertical_spacing = - layout_provider->GetDistanceMetric( - views::DISTANCE_UNRELATED_CONTROL_VERTICAL) - - layout_provider->GetDistanceMetric(DISTANCE_CONTROL_LIST_VERTICAL) / 2; - layout->StartRowWithPadding( - views::GridLayout::kFixedSize, kColumnId, views::GridLayout::kFixedSize, - UseHarmonyStyle() ? hover_list_spacing : vertical_spacing); + layout->StartRowWithPadding(views::GridLayout::kFixedSize, kColumnId, + views::GridLayout::kFixedSize, + hover_list_spacing); site_settings_view_ = CreateSiteSettingsView(); layout->AddView(site_settings_view_); layout->StartRowWithPadding(views::GridLayout::kFixedSize, kColumnId, - views::GridLayout::kFixedSize, - UseHarmonyStyle() ? 0 : vertical_spacing); + views::GridLayout::kFixedSize, 0); layout->AddView(CreateSiteSettingsLink(side_margin, this).release()); views::BubbleDialogDelegateView::CreateBubble(this); @@ -702,19 +613,13 @@ } // Get the string to display the number of cookies. - base::string16 num_cookies_text; - if (UseHarmonyStyle()) { - num_cookies_text = l10n_util::GetPluralStringFUTF16( - IDS_PAGE_INFO_NUM_COOKIES_PARENTHESIZED, total_allowed); - } else { - num_cookies_text = l10n_util::GetPluralStringFUTF16( - IDS_PAGE_INFO_NUM_COOKIES, total_allowed); - } + const base::string16 num_cookies_text = l10n_util::GetPluralStringFUTF16( + IDS_PAGE_INFO_NUM_COOKIES_PARENTHESIZED, total_allowed); - // Create the cookie link / button if it doesn't yet exist. This method gets - // called each time site data is updated, so if it *does* already exist, skip - // this part and just update the text. - if (cookie_link_legacy_ == nullptr && cookie_button_ == nullptr) { + // Create the cookie button if it doesn't yet exist. This method gets called + // each time site data is updated, so if it *does* already exist, skip this + // part and just update the text. + if (cookie_button_ == nullptr) { // Get the icon. PageInfoUI::PermissionInfo info; info.type = CONTENT_SETTINGS_TYPE_COOKIES; @@ -728,31 +633,19 @@ const base::string16& tooltip = l10n_util::GetStringUTF16(IDS_PAGE_INFO_COOKIES_TOOLTIP); - if (UseHarmonyStyle()) { - cookie_button_ = - CreateMoreInfoButton( - this, icon, IDS_PAGE_INFO_COOKIES_BUTTON_TEXT, num_cookies_text, - VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_COOKIE_DIALOG, tooltip) - .release(); - site_settings_view_->AddChildView(cookie_button_); - } else { - site_settings_view_->AddChildView(CreateMoreInfoLinkSection( - this, icon, IDS_PAGE_INFO_COOKIES, num_cookies_text, - VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_COOKIE_DIALOG, tooltip, - &cookie_link_legacy_)); - } + cookie_button_ = + CreateMoreInfoButton( + this, icon, IDS_PAGE_INFO_COOKIES_BUTTON_TEXT, num_cookies_text, + VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_COOKIE_DIALOG, tooltip) + .release(); + site_settings_view_->AddChildView(cookie_button_); } // Update the text displaying the number of allowed cookies. - DCHECK((cookie_link_legacy_ == nullptr) != (cookie_button_ == nullptr)); - if (UseHarmonyStyle()) { - base::string16 button_text; - gfx::Range styled_range = GetRangeForFormatString( - IDS_PAGE_INFO_COOKIES_BUTTON_TEXT, num_cookies_text, &button_text); - cookie_button_->SetTitleTextWithHintRange(button_text, styled_range); - } else { - cookie_link_legacy_->SetText(num_cookies_text); - } + base::string16 button_text; + gfx::Range styled_range = GetRangeForFormatString( + IDS_PAGE_INFO_COOKIES_BUTTON_TEXT, num_cookies_text, &button_text); + cookie_button_->SetTitleTextWithHintRange(button_text, styled_range); Layout(); SizeToContents(); @@ -846,24 +739,22 @@ selector_rows_.push_back(std::move(selector)); } - // In Harmony, ensure most comboboxes are the same width by setting them all - // to the widest combobox size, provided it does not exceed a maximum width. + // Ensure most comboboxes are the same width by setting them all to the widest + // combobox size, provided it does not exceed a maximum width. // For selected options that are over the maximum width, allow them to assume // their full width. If the combobox selection is changed, this may make the // widths inconsistent again, but that is OK since the widths will be updated // on the next time the bubble is opened. - if (UseHarmonyStyle()) { - const int maximum_width = ChromeLayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_BUTTON_MAX_LINKABLE_WIDTH); - int combobox_width = 0; - for (const auto& selector : selector_rows_) { - int curr_width = selector->GetComboboxWidth(); - if (maximum_width >= curr_width) - combobox_width = std::max(combobox_width, curr_width); + const int maximum_width = ChromeLayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_BUTTON_MAX_LINKABLE_WIDTH); + int combobox_width = 0; + for (const auto& selector : selector_rows_) { + int curr_width = selector->GetComboboxWidth(); + if (maximum_width >= curr_width) + combobox_width = std::max(combobox_width, curr_width); } for (const auto& selector : selector_rows_) selector->SetMinComboboxWidth(combobox_width); - } for (auto& object : chosen_object_info_list) { // Since chosen objects are presented after permissions in the same list, @@ -890,7 +781,6 @@ // Set the bubble title, update the title label text, then apply color. set_window_title(security_description->summary); GetBubbleFrameView()->UpdateWindowTitle(); - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { int text_style = views::style::STYLE_PRIMARY; switch (security_description->summary_style) { case SecuritySummaryColor::RED: @@ -903,7 +793,6 @@ static_cast<views::Label*>(GetBubbleFrameView()->title()) ->SetEnabledColor(views::style::GetColor( *this, views::style::CONTEXT_DIALOG_TITLE, text_style)); - } if (identity_info.certificate) { certificate_ = identity_info.certificate; @@ -930,7 +819,6 @@ // Add the Certificate Section. const gfx::ImageSkia icon = PageInfoUI::GetCertificateIcon(GetRelatedTextColor()); - if (UseHarmonyStyle()) { const base::string16 secondary_text = l10n_util::GetStringUTF16( valid_identity ? IDS_PAGE_INFO_CERTIFICATE_VALID_PARENTHESIZED : IDS_PAGE_INFO_CERTIFICATE_INVALID_PARENTHESIZED); @@ -939,16 +827,6 @@ VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_CERTIFICATE_VIEWER, tooltip); certificate_button->set_auto_compute_tooltip(false); site_settings_view_->AddChildView(certificate_button.release()); - } else { - const base::string16 link_title = l10n_util::GetStringUTF16( - valid_identity ? IDS_PAGE_INFO_CERTIFICATE_VALID_LINK - : IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK); - views::Link* certificate_viewer_link = nullptr; - site_settings_view_->AddChildView(CreateMoreInfoLinkSection( - this, icon, IDS_PAGE_INFO_CERTIFICATE, link_title, - VIEW_ID_PAGE_INFO_LINK_OR_BUTTON_CERTIFICATE_VIEWER, tooltip, - &certificate_viewer_link)); - } } if (identity_info.show_change_password_buttons) {
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h index 123b313..36c92711 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -164,9 +164,7 @@ // The view that contains the certificate, cookie, and permissions sections. views::View* site_settings_view_; - // The link that opens the "Cookies" dialog. Non-harmony mode only. - views::Link* cookie_link_legacy_; - // The bubble that opens the "Cookies" dialog. Harmony mode only. + // The button that opens the "Cookies" dialog. HoverButton* cookie_button_; // The view that contains the "Permissions" table of the bubble.
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc index b37448c..d94af26 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
@@ -27,7 +27,6 @@ #include "ppapi/buildflags/buildflags.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/ui_base_features.h" #include "ui/events/event_utils.h" #include "ui/views/controls/button/menu_button.h" @@ -78,16 +77,12 @@ // Returns the number of cookies shown on the link or button to open the // collected cookies dialog. This should always be shown. base::string16 GetCookiesLinkText() { - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { EXPECT_TRUE(view_->cookie_button_); ui::AXNodeData data; view_->cookie_button_->GetAccessibleNodeData(&data); std::string name; data.GetStringAttribute(ax::mojom::StringAttribute::kName, &name); return base::ASCIIToUTF16(name); - } - EXPECT_TRUE(view_->cookie_link_legacy_); - return view_->cookie_link_legacy_->text(); } // Returns the permission label text of the |index|th permission selector row. @@ -250,7 +245,6 @@ // "set", so there is always one option checked in the resulting MenuModel. // This test creates settings that are left at their defaults, leading to zero // checked options, and checks that the text on the MenuButtons is right. - const bool is_md = ui::MaterialDesignController::IsSecondaryUiMaterial(); PermissionInfoList list(1); list.back().type = CONTENT_SETTINGS_TYPE_GEOLOCATION; @@ -281,31 +275,14 @@ // Simulate a user selection via the UI. Note this will also cover logic in // PageInfo to update the pref. - if (is_md) { - // Under MD, the changed setting is always read from the combobox selected - // index when changed in the UI. PermissionSelectorRow::PermissionChanged() - // ignores the argument, except to detect whether it is the default. - api_->SimulateUserSelectingComboboxItemAt(0, 1); - } else { - list.back().setting = CONTENT_SETTING_ALLOW; - api_->GetPermissionSelectorAt(0)->PermissionChanged(list.back()); - } + api_->SimulateUserSelectingComboboxItemAt(0, 1); EXPECT_EQ(num_expected_children, api_->permissions_view()->child_count()); EXPECT_EQ(base::ASCIIToUTF16("Allow"), api_->GetPermissionButtonTextAt(0)); // Setting to the default via the UI should keep the button around. - if (is_md) { - api_->SimulateUserSelectingComboboxItemAt(0, 0); - // Under MD, PermissionMenuModel gets strings using PageInfoUI:: - // PermissionActionToUIString(..) rather than directly from the - // ResourceBundle. - EXPECT_EQ(base::ASCIIToUTF16("Ask (default)"), - api_->GetPermissionButtonTextAt(0)); - } else { - list.back().setting = CONTENT_SETTING_ASK; - api_->GetPermissionSelectorAt(0)->PermissionChanged(list.back()); - EXPECT_EQ(base::ASCIIToUTF16("Ask"), api_->GetPermissionButtonTextAt(0)); - } + api_->SimulateUserSelectingComboboxItemAt(0, 0); + EXPECT_EQ(base::ASCIIToUTF16("Ask (default)"), + api_->GetPermissionButtonTextAt(0)); EXPECT_EQ(num_expected_children, api_->permissions_view()->child_count()); // However, since the setting is now default, recreating the dialog with those @@ -364,8 +341,6 @@ // "set", so there is always one option checked in the resulting MenuModel. // This test creates settings that are left at their defaults, leading to zero // checked options, and checks that the text on the MenuButtons is right. - const bool is_md = ui::MaterialDesignController::IsSecondaryUiMaterial(); - PermissionInfoList list(1); list.back().type = CONTENT_SETTINGS_TYPE_USB_GUARD; list.back().source = content_settings::SETTING_SOURCE_USER; @@ -384,31 +359,14 @@ // Simulate a user selection via the UI. Note this will also cover logic in // PageInfo to update the pref. - if (is_md) { - // Under MD, the changed setting is always read from the combobox selected - // index when changed in the UI. PermissionSelectorRow::PermissionChanged() - // ignores the argument, except to detect whether it is the default. - api_->SimulateUserSelectingComboboxItemAt(0, 2); - } else { - list.back().setting = CONTENT_SETTING_ASK; - api_->GetPermissionSelectorAt(0)->PermissionChanged(list.back()); - } + api_->SimulateUserSelectingComboboxItemAt(0, 2); EXPECT_EQ(num_expected_children, api_->permissions_view()->child_count()); EXPECT_EQ(base::ASCIIToUTF16("Ask"), api_->GetPermissionButtonTextAt(0)); // Setting to the default via the UI should keep the button around. - if (is_md) { api_->SimulateUserSelectingComboboxItemAt(0, 0); - // Under MD, PermissionMenuModel gets strings using PageInfoUI:: - // PermissionActionToUIString(..) rather than directly from the - // ResourceBundle. EXPECT_EQ(base::ASCIIToUTF16("Ask (default)"), api_->GetPermissionButtonTextAt(0)); - } else { - list.back().setting = CONTENT_SETTING_ASK; - api_->GetPermissionSelectorAt(0)->PermissionChanged(list.back()); - EXPECT_EQ(base::ASCIIToUTF16("Ask"), api_->GetPermissionButtonTextAt(0)); - } EXPECT_EQ(num_expected_children, api_->permissions_view()->child_count()); // However, since the setting is now default, recreating the dialog with those
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.cc b/chrome/browser/ui/views/page_info/permission_selector_row.cc index c4a535e..d0db13c 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row.cc +++ b/chrome/browser/ui/views/page_info/permission_selector_row.cc
@@ -16,7 +16,6 @@ #include "components/strings/grit/components_strings.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/models/combobox_model.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/image/image.h" @@ -42,7 +41,7 @@ const int list_item_padding = ChromeLayoutProvider::Get()->GetDistanceMetric( DISTANCE_CONTROL_LIST_VERTICAL) / 2; - if (!ui::MaterialDesignController::IsSecondaryUiMaterial() || !has_reason) + if (!has_reason) return list_item_padding; const int combobox_height = @@ -241,10 +240,8 @@ set_listener(this); SetEnabled(enabled); UpdateSelectedIndex(use_default); - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - set_size_to_largest_label(false); - ModelChanged(); - } + set_size_to_largest_label(false); + ModelChanged(); } PermissionCombobox::~PermissionCombobox() {} @@ -304,18 +301,8 @@ base::Bind(&PermissionSelectorRow::PermissionChanged, base::Unretained(this)))); -// Create the permission menu button. -#if defined(OS_MACOSX) - bool use_real_combobox = true; -#else - bool use_real_combobox = - ui::MaterialDesignController::IsSecondaryUiMaterial(); -#endif - if (use_real_combobox) { - InitializeComboboxView(layout, permission); - } else { - InitializeMenuButtonView(layout, permission); - } + // Create the permission menu button. + InitializeComboboxView(layout, permission); // Show the permission decision reason, if it was not the user. base::string16 reason = @@ -337,15 +324,13 @@ DCHECK(column_set); // Secondary labels in Harmony may not overlap into space shared with the // combobox column. - const int column_span = - ui::MaterialDesignController::IsSecondaryUiMaterial() ? 1 : 3; + const int column_span = 1; - // In Harmony, long labels that cannot fit in the existing space under the - // permission label should be allowed to use up to |kMaxSecondaryLabelWidth| - // for display. + // Long labels that cannot fit in the existing space under the permission + // label should be allowed to use up to |kMaxSecondaryLabelWidth| for + // display. constexpr int kMaxSecondaryLabelWidth = 140; - if (ui::MaterialDesignController::IsSecondaryUiMaterial() && - preferred_width > kMaxSecondaryLabelWidth) { + if (preferred_width > kMaxSecondaryLabelWidth) { layout->AddView(secondary_label, column_span, 1.0, views::GridLayout::LEADING, views::GridLayout::CENTER, kMaxSecondaryLabelWidth, 0); @@ -384,23 +369,6 @@ observer_list_.AddObserver(observer); } -void PermissionSelectorRow::InitializeMenuButtonView( - views::GridLayout* layout, - const PageInfoUI::PermissionInfo& permission) { - bool button_enabled = - permission.source == content_settings::SETTING_SOURCE_USER; - menu_button_ = new internal::PermissionMenuButton( - PageInfoUI::PermissionActionToUIString( - profile_, permission.type, permission.setting, - permission.default_setting, permission.source), - menu_model_.get(), button_enabled); - menu_button_->SetEnabled(button_enabled); - menu_button_->SetTooltipText(l10n_util::GetStringFUTF16( - IDS_PAGE_INFO_SELECTOR_TOOLTIP, - PageInfoUI::PermissionTypeToUIString(permission.type))); - layout->AddView(menu_button_); -} - void PermissionSelectorRow::InitializeComboboxView( views::GridLayout* layout, const PageInfoUI::PermissionInfo& permission) {
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.h b/chrome/browser/ui/views/page_info/permission_selector_row.h index 17ff487..2c9b6e8 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row.h +++ b/chrome/browser/ui/views/page_info/permission_selector_row.h
@@ -67,8 +67,6 @@ private: friend class test::PageInfoBubbleViewTestApi; - void InitializeMenuButtonView(views::GridLayout* layout, - const PageInfoUI::PermissionInfo& permission); void InitializeComboboxView(views::GridLayout* layout, const PageInfoUI::PermissionInfo& permission);
diff --git a/chrome/browser/ui/views/passwords/password_bubble_view_base.cc b/chrome/browser/ui/views/passwords/password_bubble_view_base.cc index 59c97b8d..0c8e4827b 100644 --- a/chrome/browser/ui/views/passwords/password_bubble_view_base.cc +++ b/chrome/browser/ui/views/passwords/password_bubble_view_base.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/ui/views/passwords/password_items_view.h" #include "chrome/browser/ui/views/passwords/password_pending_view.h" #include "chrome/browser/ui/views/passwords/password_save_confirmation_view.h" -#include "ui/base/material_design/material_design_controller.h" #if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER) #include "chrome/browser/ui/views/frame/browser_view.h" @@ -36,15 +35,8 @@ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); bool is_fullscreen = browser_view->IsFullscreen(); - views::View* anchor_view = nullptr; - if (!is_fullscreen) { - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { - anchor_view = browser_view->GetLocationBarView(); - } else { - anchor_view = - browser_view->GetLocationBarView()->manage_passwords_icon_view(); - } - } + views::View* const anchor_view = + is_fullscreen ? nullptr : browser_view->GetLocationBarView(); PasswordBubbleViewBase* bubble = CreateBubble(web_contents, anchor_view, gfx::Point(), reason);
diff --git a/chrome/browser/ui/views/payments/modifiers_browsertest.cc b/chrome/browser/ui/views/payments/modifiers_browsertest.cc index f15f6f8..92df460 100644 --- a/chrome/browser/ui/views/payments/modifiers_browsertest.cc +++ b/chrome/browser/ui/views/payments/modifiers_browsertest.cc
@@ -93,7 +93,7 @@ card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); AddCreditCard(card); - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { " @@ -130,7 +130,7 @@ card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); AddCreditCard(card); - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { " @@ -167,7 +167,7 @@ card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); AddCreditCard(card); - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { " @@ -204,7 +204,7 @@ card.set_card_type(autofill::CreditCard::CardType::CARD_TYPE_CREDIT); AddCreditCard(card); - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { " @@ -263,7 +263,7 @@ card.set_billing_address_id(profile.guid()); AddCreditCard(card); - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { " @@ -300,7 +300,7 @@ card.set_billing_address_id(profile.guid()); AddCreditCard(card); - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { document.getElementById('no_total').click(); })();";
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_browsertest.cc index 379a722a..1c74e3b0 100644 --- a/chrome/browser/ui/views/payments/payment_request_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_browsertest.cc
@@ -234,7 +234,7 @@ PaymentRequestPaymentMethodIdentifierTest() {} void InvokePaymentRequestWithJs(const std::string& js) { - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), js));
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc b/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc index 7e07dd6..7662e41 100644 --- a/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc +++ b/chrome/browser/ui/views/payments/payment_request_browsertest_base.cc
@@ -254,7 +254,7 @@ } void PaymentRequestBrowserTestBase::InvokePaymentRequestUI() { - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = @@ -767,6 +767,12 @@ std::move(event_sequence)); } +void PaymentRequestBrowserTestBase::ResetEventWaiterForDialogOpened() { + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::DIALOG_OPENED}); +} + void PaymentRequestBrowserTestBase::WaitForObservedEvent() { event_waiter_->Wait(); }
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h index 5377b9f..c270a2d6 100644 --- a/chrome/browser/ui/views/payments/payment_request_browsertest_base.h +++ b/chrome/browser/ui/views/payments/payment_request_browsertest_base.h
@@ -253,6 +253,8 @@ // Resets the event waiter for a given |event| or |event_sequence|. void ResetEventWaiter(DialogEvent event); void ResetEventWaiterForSequence(std::list<DialogEvent> event_sequence); + // Resets the event waiter for the events that trigger when opening a dialog. + void ResetEventWaiterForDialogOpened(); // Wait for the event(s) passed to ResetEventWaiter*() to occur. void WaitForObservedEvent();
diff --git a/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc index 79f0a2e0..199b31a7 100644 --- a/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_can_make_payment_metrics_browsertest.cc
@@ -39,6 +39,8 @@ // the Payment Request is shown. ResetEventWaiterForSequence({DialogEvent::CAN_MAKE_PAYMENT_CALLED, DialogEvent::CAN_MAKE_PAYMENT_RETURNED, + DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::DIALOG_OPENED}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "queryShow();")); WaitForObservedEvent(); @@ -388,7 +390,7 @@ // Start the Payment Request, CanMakePayment should not be called in this // test. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -430,7 +432,7 @@ // Start the Payment Request, CanMakePayment should not be called in this // test. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -478,7 +480,7 @@ // Start the Payment Request, CanMakePayment should not be called in this // test. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent();
diff --git a/chrome/browser/ui/views/payments/payment_request_completion_status_metrics_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_completion_status_metrics_browsertest.cc index d9dc0a4..13d7c2e 100644 --- a/chrome/browser/ui/views/payments/payment_request_completion_status_metrics_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_completion_status_metrics_browsertest.cc
@@ -43,6 +43,8 @@ // Payment Request is shown. ResetEventWaiterForSequence({DialogEvent::CAN_MAKE_PAYMENT_CALLED, DialogEvent::CAN_MAKE_PAYMENT_RETURNED, + DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::DIALOG_OPENED}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "queryShow();")); WaitForObservedEvent(); @@ -80,7 +82,7 @@ base::HistogramTester histogram_tester; // Start the Payment Request. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -125,7 +127,7 @@ base::HistogramTester histogram_tester; // Start the Payment Request. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -172,7 +174,7 @@ base::HistogramTester histogram_tester; // Start the Payment Request. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -220,7 +222,7 @@ base::HistogramTester histogram_tester; // Start the Payment Request. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -262,7 +264,7 @@ base::HistogramTester histogram_tester; // Start the Payment Request. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -304,7 +306,7 @@ base::HistogramTester histogram_tester; // Start the Payment Request. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent(); @@ -348,7 +350,7 @@ base::HistogramTester histogram_tester; // Start the Payment Request. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "noQueryShow();")); WaitForObservedEvent();
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc index 6518308c..5d4f784a 100644 --- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc +++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -83,6 +83,11 @@ if (!request->state()->is_get_all_instruments_finished()) { request->state()->AddObserver(this); ShowProcessingSpinner(); + } else if (observer_for_testing_) { + // When testing, signal that the processing spinner events have passed, even + // though the UI does not need to show it. + observer_for_testing_->OnProcessingSpinnerShown(); + observer_for_testing_->OnProcessingSpinnerHidden(); } ShowInitialPaymentSheet(); @@ -212,13 +217,16 @@ void PaymentRequestDialogView::OnGetAllPaymentInstrumentsFinished() { HideProcessingSpinner(); - if (observer_for_testing_) { - // The OnGetAllPaymentInstrumentsFinished() method is called if the payment - // instruments were retrieved asynchronously. This method hides the - // "Processing" spinner, so the UI is now ready for interaction. Any test - // that opens UI can now interact with it. The OnDialogOpened() call - // notifies the tests of this event. - observer_for_testing_->OnDialogOpened(); + if (request_->state()->are_requested_methods_supported()) { + request_->RecordDialogShownEventInJourneyLogger(); + if (observer_for_testing_) { + // The OnGetAllPaymentInstrumentsFinished() method is called if the + // payment instruments were retrieved asynchronously. This method hides + // the "Processing" spinner, so the UI is now ready for interaction. Any + // test that opens UI can now interact with it. The OnDialogOpened() call + // notifies the tests of this event. + observer_for_testing_->OnDialogOpened(); + } } } @@ -385,14 +393,16 @@ request_->spec(), request_->state(), this), &controller_map_), /* animate = */ false); - if (observer_for_testing_ && - request_->state()->is_get_all_instruments_finished()) { - // The is_get_all_instruments_finished() method returns true if all payment - // instruments were retrieved synchronously. There's no "Processing" spinner - // to hide, so the UI is ready instantly. Any test that opens UI can now - // interact with it. The OnDialogOpened() call notifies the tests of this - // event. - observer_for_testing_->OnDialogOpened(); + if (request_->state()->is_get_all_instruments_finished() && + request_->state()->are_requested_methods_supported()) { + request_->RecordDialogShownEventInJourneyLogger(); + if (observer_for_testing_) { + // The is_get_all_instruments_finished() method returns true if all + // payment instruments were retrieved synchronously. Any test that opens + // UI can now interact with it. The OnDialogOpened() call notifies the + // tests of this event. + observer_for_testing_->OnDialogOpened(); + } } }
diff --git a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc index 5964dc5..81074898 100644 --- a/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_journey_logger_browsertest.cc
@@ -97,7 +97,9 @@ NavigateTo("/payment_request_bobpay_test.html"); base::HistogramTester histogram_tester; - ResetEventWaiter(DialogEvent::NOT_SUPPORTED_ERROR); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::NOT_SUPPORTED_ERROR}); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { document.getElementById('buy').click(); })();"; @@ -1045,7 +1047,7 @@ browser()->tab_strip_model()->GetActiveWebContents(); GURL iframe_url = https_server()->GetURL("b.com", "/payment_request_iframe.html"); - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); EXPECT_TRUE(content::NavigateIframeToURL(tab, "test", iframe_url)); WaitForObservedEvent();
diff --git a/chrome/browser/ui/views/payments/payment_request_no_update_with_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_no_update_with_browsertest.cc index 17212d8..69e0051 100644 --- a/chrome/browser/ui/views/payments/payment_request_no_update_with_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_no_update_with_browsertest.cc
@@ -18,7 +18,7 @@ void RunJavaScriptFunctionToOpenPaymentRequestUI( const std::string& function_name) { - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(content::ExecuteScript(web_contents, function_name + "();"));
diff --git a/chrome/browser/ui/views/payments/payment_request_payment_app_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_payment_app_browsertest.cc index ce79c34..8f7889f 100644 --- a/chrome/browser/ui/views/payments/payment_request_payment_app_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_payment_app_browsertest.cc
@@ -172,7 +172,9 @@ // SetDownloaderAndIgnorePortInAppScopeForTesting again. SetDownloaderAndIgnorePortInAppScopeForTesting(); - ResetEventWaiter(DialogEvent::NOT_SUPPORTED_ERROR); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::NOT_SUPPORTED_ERROR}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); WaitForObservedEvent(); ExpectBodyContains({"NotSupportedError"}); @@ -195,7 +197,9 @@ // SetDownloaderAndIgnorePortInAppScopeForTesting again. SetDownloaderAndIgnorePortInAppScopeForTesting(); - ResetEventWaiter(DialogEvent::NOT_SUPPORTED_ERROR); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::NOT_SUPPORTED_ERROR}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); WaitForObservedEvent(); ExpectBodyContains({"NotSupportedError"}); @@ -332,7 +336,9 @@ // SetDownloaderAndIgnorePortInAppScopeForTesting again. SetDownloaderAndIgnorePortInAppScopeForTesting(); - ResetEventWaiter(DialogEvent::NOT_SUPPORTED_ERROR); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::NOT_SUPPORTED_ERROR}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); WaitForObservedEvent(); ExpectBodyContains({"NotSupportedError"}); @@ -355,7 +361,9 @@ // SetDownloaderAndIgnorePortInAppScopeForTesting again. SetDownloaderAndIgnorePortInAppScopeForTesting(); - ResetEventWaiter(DialogEvent::NOT_SUPPORTED_ERROR); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::NOT_SUPPORTED_ERROR}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); WaitForObservedEvent(); ExpectBodyContains({"NotSupportedError"}); @@ -382,7 +390,9 @@ // SetDownloaderAndIgnorePortInAppScopeForTesting again. SetDownloaderAndIgnorePortInAppScopeForTesting(); - ResetEventWaiter(DialogEvent::NOT_SUPPORTED_ERROR); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::NOT_SUPPORTED_ERROR}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); WaitForObservedEvent(); ExpectBodyContains({"NotSupportedError"}); @@ -405,7 +415,9 @@ // SetDownloaderAndIgnorePortInAppScopeForTesting again. SetDownloaderAndIgnorePortInAppScopeForTesting(); - ResetEventWaiter(DialogEvent::NOT_SUPPORTED_ERROR); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::NOT_SUPPORTED_ERROR}); ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); WaitForObservedEvent(); ExpectBodyContains({"NotSupportedError"}); @@ -462,7 +474,9 @@ // Since the skip UI flow is available, the request will complete without // interaction besides hitting "pay" on the website. ResetEventWaiterForSequence( - {DialogEvent::DIALOG_OPENED, DialogEvent::DIALOG_CLOSED}); + {DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::DIALOG_OPENED, + DialogEvent::PROCESSING_SPINNER_SHOWN, DialogEvent::DIALOG_CLOSED}); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { document.getElementById('buy').click(); })();"; @@ -522,7 +536,7 @@ // Since the skip UI flow is not available because the payer's email is // requested, the request will complete only after clicking on the Pay // button in the dialog. - ResetEventWaiter(DialogEvent::DIALOG_OPENED); + ResetEventWaiterForDialogOpened(); content::WebContents* web_contents = GetActiveWebContents(); const std::string click_buy_button_js = "(function() { "
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc index c13f37f..63f572a 100644 --- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -38,7 +38,6 @@ #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" @@ -981,9 +980,8 @@ views::StyledLabel::RangeStyleInfo link_style = views::StyledLabel::RangeStyleInfo::CreateForLink(); - // This is the harmony color, so not needed when MD is default. - if (ui::MaterialDesignController::IsSecondaryUiMaterial()) - link_style.override_color = gfx::kGoogleBlue700; + // TODO(pbos): Investigate whether this override is necessary. + link_style.override_color = gfx::kGoogleBlue700; data_source_label->AddStyleRange( gfx::Range(link_begin, link_begin + link_length), link_style);
diff --git a/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc b/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc index 17546dd..30dc1a8 100644 --- a/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc +++ b/chrome/browser/ui/views/payments/test_chrome_payment_request_delegate.cc
@@ -24,9 +24,8 @@ is_browser_window_active_(is_browser_window_active) {} void TestChromePaymentRequestDelegate::ShowDialog(PaymentRequest* request) { - hidden_dialog_ = - std::make_unique<PaymentRequestDialogView>(request, observer_); - MaybeShowHiddenDialog(request); + shown_dialog_ = new PaymentRequestDialogView(request, observer_); + shown_dialog_->ShowDialog(); } bool TestChromePaymentRequestDelegate::IsIncognito() const {
diff --git a/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc b/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc index 152d0d2..1cbd0e6c 100644 --- a/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc
@@ -19,7 +19,6 @@ #include "content/public/browser/render_process_host.h" #include "content/public/common/result_codes.h" #include "content/public/test/browser_test_utils.h" -#include "ui/base/material_design/material_design_controller.h" #include "ui/views/controls/button/blue_button.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/widget/widget.h" @@ -82,10 +81,6 @@ views::View* GetFocusedView() { return GetFocusManager()->GetFocusedView(); } const char* ActionButtonClassName() { -#if defined(OS_CHROMEOS) - if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) - return views::BlueButton::kViewClassName; -#endif return views::LabelButton::kViewClassName; }
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 012daf29..3f5f33e 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -386,6 +386,10 @@ immersive_reveal_lock_.reset(); } +bool BrowserTabStripController::HasVisibleBackgroundTabShapes() const { + return GetFrameView()->HasVisibleBackgroundTabShapes(); +} + SkColor BrowserTabStripController::GetFrameColor() const { return GetFrameView()->GetFrameColor(); }
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index 7dcc9c0..db4e708 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -76,6 +76,7 @@ bool ShouldDrawStrokes() const override; void OnStartedDraggingTabs() override; void OnStoppedDraggingTabs() override; + bool HasVisibleBackgroundTabShapes() const override; SkColor GetFrameColor() const override; SkColor GetToolbarTopSeparatorColor() const override; SkColor GetTabSeparatorColor() const override;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc index 06323d5..d1c60e2 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -150,6 +150,10 @@ void FakeBaseTabStripController::OnStoppedDraggingTabs() { } +bool FakeBaseTabStripController::HasVisibleBackgroundTabShapes() const { + return false; +} + SkColor FakeBaseTabStripController::GetFrameColor() const { return gfx::kPlaceholderColor; }
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h index f7acb66..305dcdc0 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -52,6 +52,7 @@ bool ShouldDrawStrokes() const override; void OnStartedDraggingTabs() override; void OnStoppedDraggingTabs() override; + bool HasVisibleBackgroundTabShapes() const override; SkColor GetFrameColor() const override; SkColor GetToolbarTopSeparatorColor() const override; SkColor GetTabSeparatorColor() const override;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index f618f280..34b35c69 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -536,8 +536,6 @@ title_animation_.SetContainer(animation_container_.get()); hover_controller_.SetAnimationContainer(animation_container_.get()); - - UpdateOpacities(); } Tab::~Tab() { @@ -852,7 +850,8 @@ void Tab::OnMouseEntered(const ui::MouseEvent& event) { mouse_hovered_ = true; - hover_controller_.SetSubtleOpacityScale(radial_highlight_opacity_); + hover_controller_.SetSubtleOpacityScale( + controller_->GetHoverOpacityForRadialHighlight()); hover_controller_.Show(GlowHoverController::SUBTLE); Layout(); } @@ -968,7 +967,6 @@ void Tab::OnThemeChanged() { OnButtonColorMaybeChanged(); - UpdateOpacities(); } void Tab::SetClosing(bool closing) { @@ -1672,10 +1670,9 @@ // narrow tabs will still stand out on the high end. const float range_start = float{GetStandardWidth()}; const float range_end = float{GetMinimumInactiveWidth()}; - const float value_in_range = float{bounds().width()}; + const float value_in_range = float{width()}; const float t = (value_in_range - range_start) / (range_end - range_start); - const float opacity = gfx::Tween::FloatValueBetween( - t * t, hover_opacity_min_, hover_opacity_max_); + const float opacity = controller_->GetHoverOpacityForTab(t * t); return is_selected ? (kSelectedTabThrobScale * opacity) : opacity; }; @@ -1710,45 +1707,6 @@ } } -void Tab::UpdateOpacities() { - // The contrast ratio for the hover effect on standard-width tabs. - // In the default Refresh color scheme, this corresponds to a hover - // opacity of 0.4. - constexpr float kDesiredContrastHoveredStandardWidthTab = 1.11f; - - // The contrast ratio for the hover effect on min-width tabs. - // In the default Refresh color scheme, this corresponds to a hover - // opacity of 0.65. - constexpr float kDesiredContrastHoveredMinWidthTab = 1.19f; - - // The contrast ratio for the radial gradient effect on hovered tabs. - // In the default Refresh color scheme, this corresponds to a hover - // opacity of 0.45. - constexpr float kDesiredContrastRadialGradient = 1.13728f; - - const SkColor active_tab_bg_color = - controller_->GetTabBackgroundColor(TAB_ACTIVE); - const SkColor inactive_tab_bg_color = - controller_->GetTabBackgroundColor(TAB_INACTIVE); - - const SkAlpha hover_base_alpha_wide = - color_utils::GetBlendValueWithMinimumContrast( - inactive_tab_bg_color, active_tab_bg_color, inactive_tab_bg_color, - kDesiredContrastHoveredStandardWidthTab); - const SkAlpha hover_base_alpha_narrow = - color_utils::GetBlendValueWithMinimumContrast( - inactive_tab_bg_color, active_tab_bg_color, inactive_tab_bg_color, - kDesiredContrastHoveredMinWidthTab); - const SkAlpha radial_highlight_alpha = - color_utils::GetBlendValueWithMinimumContrast( - inactive_tab_bg_color, active_tab_bg_color, inactive_tab_bg_color, - kDesiredContrastRadialGradient); - - hover_opacity_min_ = hover_base_alpha_wide / 255.0f; - hover_opacity_max_ = hover_base_alpha_narrow / 255.0f; - radial_highlight_opacity_ = radial_highlight_alpha / 255.0f; -} - void Tab::UpdateButtonIconColors(SkColor title_color) { // These ratios are calculated from the default colors specified in the // Material Refresh design document. Active/inactive are the contrast ratios
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h index b893797..0c4999d2 100644 --- a/chrome/browser/ui/views/tabs/tab.h +++ b/chrome/browser/ui/views/tabs/tab.h
@@ -310,9 +310,6 @@ // state; it is the responsibility of the caller to request a paint. void UpdateTabIconNeedsAttentionBlocked(); - // Computes and stores opacities derived from contrast ratios. - void UpdateOpacities(); - // Generate and update close button and alert icon colors for proper contrast. void UpdateButtonIconColors(SkColor title_color); @@ -389,11 +386,6 @@ // the view bounds. bool mouse_hovered_ = false; - // These computed values are stored for fast use during mouse moves & hover. - float hover_opacity_min_; - float hover_opacity_max_; - float radial_highlight_opacity_; - class BackgroundCache { public: BackgroundCache();
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index b2d1753..0c0721d9 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -169,6 +169,14 @@ // Returns the accessible tab name for this tab. virtual base::string16 GetAccessibleTabName(const Tab* tab) const = 0; + // Returns opacity for hover effect on a tab with |range_parameter| between + // 0 and 1, where 0 gives the minimum opacity suitable for wider tabs and 1 + // gives maximum opacity suitable for narrower tabs. + virtual float GetHoverOpacityForTab(float range_parameter) const = 0; + + // Returns opacity for use on tab hover radial highlight. + virtual float GetHoverOpacityForRadialHighlight() const = 0; + protected: virtual ~TabController() {} };
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 4cfe393..efb69739 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -54,6 +54,7 @@ #include "ui/display/screen.h" #include "ui/gfx/animation/animation_container.h" #include "ui/gfx/animation/throb_animation.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size.h" @@ -318,6 +319,7 @@ for (int i = 0; i < tab_count(); ++i) tab_at(i)->FrameColorsChanged(); new_tab_button_->FrameColorsChanged(); + UpdateOpacities(); SchedulePaint(); } @@ -343,10 +345,10 @@ // draggability. This region starts 1 DIP above the top of the separator. const int drag_handle_extension = (height() - Tab::GetTabSeparatorHeight()) / 2 - 1; - // TODO(pkasting): https://crbug.com/862276 Set this condition false when tab - // shapes are visible. - const bool extend_drag_handle = - MD::IsRefreshUi() && !SizeTabButtonToTopOfTabStrip(); + + // Disable drag handle extension when tab shapes are visible. + bool extend_drag_handle = !SizeTabButtonToTopOfTabStrip() && + !controller_->HasVisibleBackgroundTabShapes(); // A hit on the tab is not in the caption unless it is in the thin strip // mentioned above. @@ -1183,6 +1185,15 @@ } } +float TabStrip::GetHoverOpacityForTab(float range_parameter) const { + return gfx::Tween::FloatValueBetween(range_parameter, hover_opacity_min_, + hover_opacity_max_); +} + +float TabStrip::GetHoverOpacityForRadialHighlight() const { + return radial_highlight_opacity_; +} + /////////////////////////////////////////////////////////////////////////////// // TabStrip, views::View overrides: @@ -1495,6 +1506,8 @@ drop_indicator_width = drop_image->width(); drop_indicator_height = drop_image->height(); } + + UpdateOpacities(); } void TabStrip::StartInsertTabAnimation(int model_index) { @@ -2047,6 +2060,48 @@ } } +void TabStrip::UpdateOpacities() { + // There may be no controller in unit tests, and call to GetTabBackgroundColor + // below requires one, so bail early if it is absent. + if (!controller_) + return; + + // The contrast ratio for the hover effect on standard-width tabs. + // In the default Refresh color scheme, this corresponds to a hover + // opacity of 0.4. + constexpr float kDesiredContrastHoveredStandardWidthTab = 1.11f; + + // The contrast ratio for the hover effect on min-width tabs. + // In the default Refresh color scheme, this corresponds to a hover + // opacity of 0.65. + constexpr float kDesiredContrastHoveredMinWidthTab = 1.19f; + + // The contrast ratio for the radial gradient effect on hovered tabs. + // In the default Refresh color scheme, this corresponds to a hover + // opacity of 0.45. + constexpr float kDesiredContrastRadialGradient = 1.13728f; + + const SkColor active_tab_bg_color = GetTabBackgroundColor(TAB_ACTIVE); + const SkColor inactive_tab_bg_color = GetTabBackgroundColor(TAB_INACTIVE); + + const SkAlpha hover_base_alpha_wide = + color_utils::GetBlendValueWithMinimumContrast( + inactive_tab_bg_color, active_tab_bg_color, inactive_tab_bg_color, + kDesiredContrastHoveredStandardWidthTab); + const SkAlpha hover_base_alpha_narrow = + color_utils::GetBlendValueWithMinimumContrast( + inactive_tab_bg_color, active_tab_bg_color, inactive_tab_bg_color, + kDesiredContrastHoveredMinWidthTab); + const SkAlpha radial_highlight_alpha = + color_utils::GetBlendValueWithMinimumContrast( + inactive_tab_bg_color, active_tab_bg_color, inactive_tab_bg_color, + kDesiredContrastRadialGradient); + + hover_opacity_min_ = hover_base_alpha_wide / 255.0f; + hover_opacity_max_ = hover_base_alpha_narrow / 255.0f; + radial_highlight_opacity_ = radial_highlight_alpha / 255.0f; +} + void TabStrip::ResizeLayoutTabs() { // We've been called back after the TabStrip has been emptied out (probably // just prior to the window being destroyed). We need to do nothing here or
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index de720eb..fe46944 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -262,6 +262,8 @@ base::string16 GetAccessibleTabName(const Tab* tab) const override; int GetBackgroundResourceId(bool* has_custom_image) const override; gfx::Rect GetTabAnimationTargetBounds(const Tab* tab) override; + float GetHoverOpacityForTab(float range_parameter) const override; + float GetHoverOpacityForRadialHighlight() const override; // MouseWatcherListener: void MouseMovedOutOfHost() override; @@ -454,6 +456,9 @@ void UpdateStackedLayoutFromMouseEvent(views::View* source, const ui::MouseEvent& event); + // Computes and stores tab hover opacities derived from contrast ratios. + void UpdateOpacities(); + // -- Tab Resize Layout ----------------------------------------------------- // Returns the current width of each tab. If the space for tabs is not evenly @@ -674,6 +679,17 @@ // updated to account for tab insertions/removals/moves. ui::ListSelectionModel selected_tabs_; + // When tabs are hovered, a radial highlight is shown and the tab opacity is + // adjusted using some value between |hover_opacity_min_| and + // |hover_opacity_max_| (depending on tab width). All these opacities depend + // on contrast ratios and are updated when colors or active state changes, + // so for efficiency's sake they are computed and stored once here instead + // of with each tab. Note: these defaults will be overwritten at construction + // except in cases where a unit test provides no controller_. + float hover_opacity_min_ = 1.0f; + float hover_opacity_max_ = 1.0f; + float radial_highlight_opacity_ = 1.0f; + DISALLOW_COPY_AND_ASSIGN(TabStrip); };
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index 5bfb282c4..586cf72 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -119,6 +119,10 @@ // from this tabstrip but the user is still dragging the tabs. virtual void OnStoppedDraggingTabs() = 0; + // Returns whether the shapes of background tabs are visible against the + // frame. + virtual bool HasVisibleBackgroundTabShapes() const = 0; + // Returns the color of the browser frame, which is also the color of the // tabstrip background. virtual SkColor GetFrameColor() const = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index 44eba68c..bdc135e2 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -102,6 +102,10 @@ base::string16 GetAccessibleTabName(const Tab* tab) const override { return base::string16(); } + float GetHoverOpacityForTab(float range_parameter) const override { + return 1.0f; + } + float GetHoverOpacityForRadialHighlight() const override { return 1.0f; } private: ui::ListSelectionModel selection_model_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 6fe7e1b..3ffa012 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -308,14 +308,8 @@ const GURL& url, bool already_bookmarked, bookmarks::BookmarkBubbleObserver* observer) { - views::View* anchor_view = location_bar(); + views::View* const anchor_view = location_bar(); PageActionIconView* const star_view = location_bar()->star_view(); - if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) { - if (star_view && star_view->visible()) - anchor_view = star_view; - else - anchor_view = app_menu_button_; - } std::unique_ptr<BubbleSyncPromoDelegate> delegate; delegate.reset(new BookmarkBubbleSignInDelegate(browser_)); @@ -331,15 +325,9 @@ translate::TranslateStep step, translate::TranslateErrors::Type error_type, bool is_user_gesture) { - views::View* anchor_view = location_bar(); + views::View* const anchor_view = location_bar(); PageActionIconView* translate_icon_view = location_bar()->translate_icon_view(); - if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) { - if (translate_icon_view && translate_icon_view->visible()) - anchor_view = translate_icon_view; - else - anchor_view = app_menu_button_; - } views::Widget* bubble_widget = TranslateBubbleView::ShowBubble( anchor_view, gfx::Point(), web_contents, step, error_type,
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index c1c363aa..40c22874 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -247,6 +247,8 @@ "sample_queue.h", "service/browser_xr_runtime.cc", "service/browser_xr_runtime.h", + "service/isolated_device_provider.cc", + "service/isolated_device_provider.h", "service/vr_service_impl.cc", "service/vr_service_impl.h", "service/xr_device_impl.cc",
diff --git a/chrome/browser/vr/service/isolated_device_provider.cc b/chrome/browser/vr/service/isolated_device_provider.cc new file mode 100644 index 0000000..2ca3095 --- /dev/null +++ b/chrome/browser/vr/service/isolated_device_provider.cc
@@ -0,0 +1,77 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/vr/service/isolated_device_provider.h" +#include "content/public/common/service_manager_connection.h" +#include "device/vr/buildflags/buildflags.h" +#include "device/vr/isolated_gamepad_data_fetcher.h" +#include "services/service_manager/public/cpp/connector.h" + +namespace vr { + +void IsolatedVRDeviceProvider::Initialize( + base::RepeatingCallback<void(device::mojom::XRDeviceId, + device::mojom::VRDisplayInfoPtr, + device::mojom::XRRuntimePtr)> + add_device_callback, + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + remove_device_callback, + base::OnceClosure initialization_complete) { + content::ServiceManagerConnection* connection = + content::ServiceManagerConnection::GetForProcess(); + connection->GetConnector()->BindInterface( + device::mojom::kVrIsolatedServiceName, + mojo::MakeRequest(&device_provider_)); + + device::mojom::IsolatedXRRuntimeProviderClientPtr client; + binding_.Bind(mojo::MakeRequest(&client)); + device_provider_->RequestDevices(std::move(client)); + + add_device_callback_ = std::move(add_device_callback); + remove_device_callback_ = std::move(remove_device_callback); + initialization_complete_ = std::move(initialization_complete); +} + +bool IsolatedVRDeviceProvider::Initialized() { + return initialized_; +} + +void IsolatedVRDeviceProvider::OnDeviceAdded( + device::mojom::XRRuntimePtr device, + device::mojom::IsolatedXRGamepadProviderFactoryPtr gamepad_factory, + device::mojom::VRDisplayInfoPtr display_info) { + device::mojom::XRDeviceId id = display_info->id; + add_device_callback_.Run(id, std::move(display_info), std::move(device)); + +#if BUILDFLAG(ENABLE_OPENVR) || BUILDFLAG(ENABLE_OCULUS_VR) + registered_gamepads_.insert(id); + device::IsolatedGamepadDataFetcher::Factory::AddGamepad( + id, std::move(gamepad_factory)); +#endif +} + +void IsolatedVRDeviceProvider::OnDeviceRemoved(device::mojom::XRDeviceId id) { + remove_device_callback_.Run(id); + +#if BUILDFLAG(ENABLE_OPENVR) || BUILDFLAG(ENABLE_OCULUS_VR) + device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(id); +#endif +} + +void IsolatedVRDeviceProvider::OnDevicesEnumerated() { + initialized_ = true; + std::move(initialization_complete_).Run(); +} + +IsolatedVRDeviceProvider::IsolatedVRDeviceProvider() : binding_(this) {} + +IsolatedVRDeviceProvider::~IsolatedVRDeviceProvider() { +#if BUILDFLAG(ENABLE_OPENVR) || BUILDFLAG(ENABLE_OCULUS_VR) + for (auto gamepad_id : registered_gamepads_) { + device::IsolatedGamepadDataFetcher::Factory::RemoveGamepad(gamepad_id); + } +#endif +} + +} // namespace vr
diff --git a/chrome/browser/vr/service/isolated_device_provider.h b/chrome/browser/vr/service/isolated_device_provider.h new file mode 100644 index 0000000..ad059d19 --- /dev/null +++ b/chrome/browser/vr/service/isolated_device_provider.h
@@ -0,0 +1,59 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VR_SERVICE_ISOLATED_DEVICE_PROVIDER_H_ +#define CHROME_BROWSER_VR_SERVICE_ISOLATED_DEVICE_PROVIDER_H_ + +#include "device/vr/public/mojom/isolated_xr_service.mojom.h" +#include "device/vr/vr_device.h" +#include "device/vr/vr_device_provider.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace vr { + +class IsolatedVRDeviceProvider + : public device::VRDeviceProvider, + public device::mojom::IsolatedXRRuntimeProviderClient { + public: + IsolatedVRDeviceProvider(); + ~IsolatedVRDeviceProvider() override; + + // If the VR API requires initialization that should happen here. + void Initialize(base::RepeatingCallback<void(device::mojom::XRDeviceId, + device::mojom::VRDisplayInfoPtr, + device::mojom::XRRuntimePtr)> + add_device_callback, + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + remove_device_callback, + base::OnceClosure initialization_complete) override; + + // Returns true if initialization is complete. + bool Initialized() override; + + private: + // IsolatedXRRuntimeProviderClient + void OnDeviceAdded( + device::mojom::XRRuntimePtr device, + device::mojom::IsolatedXRGamepadProviderFactoryPtr gamepad_factory, + device::mojom::VRDisplayInfoPtr display_info) override; + void OnDeviceRemoved(device::mojom::XRDeviceId id) override; + void OnDevicesEnumerated() override; + + bool initialized_ = false; + device::mojom::IsolatedXRRuntimeProviderPtr device_provider_; + + base::RepeatingCallback<void(device::mojom::XRDeviceId, + device::mojom::VRDisplayInfoPtr, + device::mojom::XRRuntimePtr)> + add_device_callback_; + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + remove_device_callback_; + base::OnceClosure initialization_complete_; + std::set<device::mojom::XRDeviceId> registered_gamepads_; + mojo::Binding<device::mojom::IsolatedXRRuntimeProviderClient> binding_; +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_SERVICE_ISOLATED_DEVICE_PROVIDER_H_
diff --git a/chrome/browser/vr/service/xr_runtime_manager.cc b/chrome/browser/vr/service/xr_runtime_manager.cc index 4d92e1d..f4cca662 100644 --- a/chrome/browser/vr/service/xr_runtime_manager.cc +++ b/chrome/browser/vr/service/xr_runtime_manager.cc
@@ -27,6 +27,12 @@ #include "device/vr/android/gvr/gvr_device_provider.h" #endif +#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) +// We are hosting Oculus and OpenVR in a separate process +#include "chrome/browser/vr/service/isolated_device_provider.h" +#else +// We are hosting Oculus and OpenVR in the browser process if enabled. + #if BUILDFLAG(ENABLE_OPENVR) #include "device/vr/openvr/openvr_device_provider.h" #endif @@ -35,6 +41,8 @@ #include "device/vr/oculus/oculus_device_provider.h" #endif +#endif // BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) + namespace vr { namespace { @@ -56,6 +64,9 @@ providers.emplace_back(std::make_unique<device::GvrDeviceProvider>()); #endif +#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) + providers.emplace_back(std::make_unique<vr::IsolatedVRDeviceProvider>()); +#else #if BUILDFLAG(ENABLE_OPENVR) if (base::FeatureList::IsEnabled(features::kOpenVR)) providers.emplace_back(std::make_unique<device::OpenVRDeviceProvider>()); @@ -70,6 +81,7 @@ providers.emplace_back( std::make_unique<device::OculusVRDeviceProvider>()); #endif +#endif // ENABLE_ISOLATED_XR_SERVICE if (base::FeatureList::IsEnabled(features::kWebXrOrientationSensorDevice)) { content::ServiceManagerConnection* connection = @@ -90,19 +102,19 @@ BrowserXRRuntime* XRRuntimeManager::GetImmersiveRuntime() { #if defined(OS_ANDROID) - auto* gvr = GetRuntime(device::VRDeviceId::GVR_DEVICE_ID); + auto* gvr = GetRuntime(device::mojom::XRDeviceId::GVR_DEVICE_ID); if (gvr) return gvr; #endif #if BUILDFLAG(ENABLE_OPENVR) - auto* openvr = GetRuntime(device::VRDeviceId::OPENVR_DEVICE_ID); + auto* openvr = GetRuntime(device::mojom::XRDeviceId::OPENVR_DEVICE_ID); if (openvr) return openvr; #endif #if BUILDFLAG(ENABLE_OCULUS_VR) - auto* oculus = GetRuntime(device::VRDeviceId::OCULUS_DEVICE_ID); + auto* oculus = GetRuntime(device::mojom::XRDeviceId::OCULUS_DEVICE_ID); if (oculus) return oculus; #endif @@ -110,8 +122,8 @@ return nullptr; } -BrowserXRRuntime* XRRuntimeManager::GetRuntime(device::VRDeviceId id) { - auto it = runtimes_.find(static_cast<unsigned int>(id)); +BrowserXRRuntime* XRRuntimeManager::GetRuntime(device::mojom::XRDeviceId id) { + auto it = runtimes_.find(id); if (it == runtimes_.end()) return nullptr; @@ -124,12 +136,12 @@ if (options->immersive && !options->provide_passthrough_camera) { return GetImmersiveRuntime(); } else if (options->provide_passthrough_camera && !options->immersive) { - return GetRuntime(device::VRDeviceId::ARCORE_DEVICE_ID); + return GetRuntime(device::mojom::XRDeviceId::ARCORE_DEVICE_ID); } else if (!options->provide_passthrough_camera && !options->immersive) { // Non immersive session. // Try the orientation provider if it exists. auto* orientation_runtime = - GetRuntime(device::VRDeviceId::ORIENTATION_DEVICE_ID); + GetRuntime(device::mojom::XRDeviceId::ORIENTATION_DEVICE_ID); if (orientation_runtime) { return orientation_runtime; } @@ -180,7 +192,7 @@ } } -void XRRuntimeManager::AddRuntime(unsigned int id, +void XRRuntimeManager::AddRuntime(device::mojom::XRDeviceId id, device::mojom::VRDisplayInfoPtr info, device::mojom::XRRuntimePtr runtime) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -192,7 +204,7 @@ service->ConnectRuntime(runtimes_[id].get()); } -void XRRuntimeManager::RemoveRuntime(unsigned int id) { +void XRRuntimeManager::RemoveRuntime(device::mojom::XRDeviceId id) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auto it = runtimes_.find(id); DCHECK(it != runtimes_.end()); @@ -207,7 +219,7 @@ } void XRRuntimeManager::RecordVrStartupHistograms() { -#if BUILDFLAG(ENABLE_OPENVR) +#if BUILDFLAG(ENABLE_OPENVR) && !BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) device::OpenVRDeviceProvider::RecordRuntimeAvailability(); #endif } @@ -253,7 +265,8 @@ if (id == 0) return nullptr; - DeviceRuntimeMap::iterator iter = runtimes_.find(id); + DeviceRuntimeMap::iterator iter = + runtimes_.find(static_cast<device::mojom::XRDeviceId>(id)); if (iter == runtimes_.end()) return nullptr;
diff --git a/chrome/browser/vr/service/xr_runtime_manager.h b/chrome/browser/vr/service/xr_runtime_manager.h index a59a4cd..3d1832705 100644 --- a/chrome/browser/vr/service/xr_runtime_manager.h +++ b/chrome/browser/vr/service/xr_runtime_manager.h
@@ -59,6 +59,7 @@ // Used by tests to supply providers. explicit XRRuntimeManager(ProviderList providers); // Used by tests to check on device state. + // TODO: Use XRDeviceId as appropriate. device::mojom::XRRuntime* GetRuntimeForTest(unsigned int id); size_t NumberOfConnectedServices(); @@ -68,19 +69,19 @@ void OnProviderInitialized(); bool AreAllProvidersInitialized(); - void AddRuntime(unsigned int id, + void AddRuntime(device::mojom::XRDeviceId id, device::mojom::VRDisplayInfoPtr info, device::mojom::XRRuntimePtr runtime); - void RemoveRuntime(unsigned int id); + void RemoveRuntime(device::mojom::XRDeviceId id); - BrowserXRRuntime* GetRuntime(device::VRDeviceId id); + BrowserXRRuntime* GetRuntime(device::mojom::XRDeviceId id); ProviderList providers_; // VRDevices are owned by their providers, each correspond to a // BrowserXRRuntime that is owned by XRRuntimeManager. using DeviceRuntimeMap = base::small_map< - std::map<unsigned int, std::unique_ptr<BrowserXRRuntime>>>; + std::map<device::mojom::XRDeviceId, std::unique_ptr<BrowserXRRuntime>>>; DeviceRuntimeMap runtimes_; bool providers_initialized_ = false;
diff --git a/chrome/browser/vr/service/xr_runtime_manager_unittest.cc b/chrome/browser/vr/service/xr_runtime_manager_unittest.cc index 4452f459..4fa4963e 100644 --- a/chrome/browser/vr/service/xr_runtime_manager_unittest.cc +++ b/chrome/browser/vr/service/xr_runtime_manager_unittest.cc
@@ -136,8 +136,8 @@ auto service = BindService(); EXPECT_EQ(1u, ServiceCount()); EXPECT_TRUE(Provider()->Initialized()); - device::FakeVRDevice* device = new device::FakeVRDevice( - static_cast<int>(device::VRDeviceId::ARCORE_DEVICE_ID)); + device::FakeVRDevice* device = + new device::FakeVRDevice(device::mojom::XRDeviceId::ARCORE_DEVICE_ID); Provider()->AddDevice(base::WrapUnique(device)); device::mojom::XRSessionOptions options = {};
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index 336f4eae0..54f5379 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -19,6 +19,8 @@ # those might be similar enough to merge. "web_app_icon_downloader.cc", "web_app_icon_downloader.h", + "web_app_icon_generator.cc", + "web_app_icon_generator.h", "web_app_shortcut.cc", "web_app_shortcut.h", "web_app_shortcut_chromeos.cc", @@ -49,6 +51,7 @@ sources = [ "web_app_helpers_unittest.cc", "web_app_icon_downloader_unittest.cc", + "web_app_icon_generator_unittest.cc", "web_app_shortcut_mac_unittest.mm", "web_app_shortcut_unittest.cc", ]
diff --git a/chrome/browser/web_applications/components/pending_app_manager.h b/chrome/browser/web_applications/components/pending_app_manager.h index 94191403..d69959d 100644 --- a/chrome/browser/web_applications/components/pending_app_manager.h +++ b/chrome/browser/web_applications/components/pending_app_manager.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_PENDING_APP_MANAGER_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_PENDING_APP_MANAGER_H_ +#include <string> #include <vector> #include "base/callback_forward.h" @@ -21,7 +22,7 @@ // should wait for the update request to finish before uninstalling the app. class PendingAppManager { public: - using InstallCallback = base::OnceCallback<void(bool)>; + using InstallCallback = base::OnceCallback<void(const std::string&)>; // How the app will be launched after installation. enum class LaunchContainer { @@ -47,7 +48,9 @@ // Queues an installation operation with the highest priority. Essentially // installing the app immediately if there are no ongoing operations or - // installing the app right after the current operation finishes. + // installing the app right after the current operation finishes. Runs its + // callback with the id of the installed app or an empty string if the + // installation fails. // // Fails if the same operation has been queued before. Should only be used in // response to a user action e.g. the user clicked an install button.
diff --git a/chrome/browser/web_applications/components/web_app_icon_generator.cc b/chrome/browser/web_applications/components/web_app_icon_generator.cc new file mode 100644 index 0000000..ff330a7b --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_icon_generator.cc
@@ -0,0 +1,221 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/components/web_app_icon_generator.h" + +#include <cctype> +#include <string> +#include <utility> + +#include "base/macros.h" +#include "build/build_config.h" +#include "chrome/grit/platform_locale_settings.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "skia/ext/image_operations.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/color_analysis.h" +#include "ui/gfx/color_utils.h" +#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/image/canvas_image_source.h" +#include "ui/gfx/image/image.h" + +namespace web_app { + +namespace { + +// Generates a square container icon of |output_size| by drawing the given +// |letter| into a rounded background of |color|. +class GeneratedIconImageSource : public gfx::CanvasImageSource { + public: + explicit GeneratedIconImageSource(char letter, SkColor color, int output_size) + : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false), + letter_(letter), + color_(color), + output_size_(output_size) {} + ~GeneratedIconImageSource() override {} + + private: + // gfx::CanvasImageSource overrides: + void Draw(gfx::Canvas* canvas) override { + const uint8_t kLumaThreshold = 190; + const int icon_size = output_size_ * 3 / 4; + const int icon_inset = output_size_ / 8; + const size_t border_radius = output_size_ / 16; + const size_t font_size = output_size_ * 7 / 16; + + std::string font_name = + l10n_util::GetStringUTF8(IDS_SANS_SERIF_FONT_FAMILY); +#if defined(OS_CHROMEOS) + const std::string kChromeOSFontFamily = "Noto Sans"; + font_name = kChromeOSFontFamily; +#endif + + // Draw a rounded rect of the given |color|. + cc::PaintFlags background_flags; + background_flags.setAntiAlias(true); + background_flags.setColor(color_); + + gfx::Rect icon_rect(icon_inset, icon_inset, icon_size, icon_size); + canvas->DrawRoundRect(icon_rect, border_radius, background_flags); + + // The text rect's size needs to be odd to center the text correctly. + gfx::Rect text_rect(icon_inset, icon_inset, icon_size + 1, icon_size + 1); + // Draw the letter onto the rounded rect. The letter's color depends on the + // luma of |color|. + const uint8_t luma = color_utils::GetLuma(color_); + canvas->DrawStringRectWithFlags( + base::string16(1, std::toupper(letter_)), + gfx::FontList(gfx::Font(font_name, font_size)), + (luma > kLumaThreshold) ? SK_ColorBLACK : SK_ColorWHITE, text_rect, + gfx::Canvas::TEXT_ALIGN_CENTER); + } + + char letter_; + + SkColor color_; + + int output_size_; + + DISALLOW_COPY_AND_ASSIGN(GeneratedIconImageSource); +}; + +// Adds a square container icon of |output_size| and 2 * |output_size| pixels +// to |bitmaps| by drawing the given |letter| into a rounded background of +// |color|. For each size, if an icon of the requested size already exists in +// |bitmaps|, nothing will happen. +void GenerateIcon(std::map<int, BitmapAndSource>* bitmaps, + int output_size, + SkColor color, + char letter) { + // Do nothing if there is already an icon of |output_size|. + if (bitmaps->count(output_size)) + return; + + (*bitmaps)[output_size].bitmap = GenerateBitmap(output_size, color, letter); +} + +void GenerateIcons(std::set<int> generate_sizes, + const GURL& app_url, + SkColor generated_icon_color, + std::map<int, BitmapAndSource>* bitmap_map) { + // The letter that will be painted on the generated icon. + char icon_letter = ' '; + std::string domain_and_registry( + net::registry_controlled_domains::GetDomainAndRegistry( + app_url, + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)); + if (!domain_and_registry.empty()) { + icon_letter = domain_and_registry[0]; + } else if (app_url.has_host()) { + icon_letter = app_url.host_piece()[0]; + } + + // If no color has been specified, use a dark gray so it will stand out on the + // black shelf. + if (generated_icon_color == SK_ColorTRANSPARENT) + generated_icon_color = SK_ColorDKGRAY; + + for (int size : generate_sizes) { + GenerateIcon(bitmap_map, size, generated_icon_color, icon_letter); + } +} + +} // namespace + +BitmapAndSource::BitmapAndSource() {} + +BitmapAndSource::BitmapAndSource(const GURL& source_url_p, + const SkBitmap& bitmap_p) + : source_url(source_url_p), bitmap(bitmap_p) {} + +BitmapAndSource::~BitmapAndSource() {} + +std::map<int, BitmapAndSource> ConstrainBitmapsToSizes( + const std::vector<BitmapAndSource>& bitmaps, + const std::set<int>& sizes) { + std::map<int, BitmapAndSource> output_bitmaps; + std::map<int, BitmapAndSource> ordered_bitmaps; + for (const BitmapAndSource& bitmap_and_source : bitmaps) { + const SkBitmap& bitmap = bitmap_and_source.bitmap; + DCHECK(bitmap.width() == bitmap.height()); + ordered_bitmaps[bitmap.width()] = bitmap_and_source; + } + + if (ordered_bitmaps.size() > 0) { + for (const auto& size : sizes) { + // Find the closest not-smaller bitmap, or failing that use the largest + // icon available. + auto bitmaps_it = ordered_bitmaps.lower_bound(size); + if (bitmaps_it != ordered_bitmaps.end()) + output_bitmaps[size] = bitmaps_it->second; + else + output_bitmaps[size] = ordered_bitmaps.rbegin()->second; + + // Resize the bitmap if it does not exactly match the desired size. + if (output_bitmaps[size].bitmap.width() != size) { + output_bitmaps[size].bitmap = skia::ImageOperations::Resize( + output_bitmaps[size].bitmap, skia::ImageOperations::RESIZE_LANCZOS3, + size, size); + } + } + } + + return output_bitmaps; +} + +SkBitmap GenerateBitmap(int output_size, SkColor color, char letter) { + gfx::ImageSkia icon_image( + std::make_unique<GeneratedIconImageSource>(letter, color, output_size), + gfx::Size(output_size, output_size)); + SkBitmap dst; + if (dst.tryAllocPixels(icon_image.bitmap()->info())) { + icon_image.bitmap()->readPixels(dst.info(), dst.getPixels(), dst.rowBytes(), + 0, 0); + } + return dst; +} + +std::map<int, BitmapAndSource> ResizeIconsAndGenerateMissing( + const std::vector<BitmapAndSource>& icons, + const std::set<int>& sizes_to_generate, + const GURL& app_url, + SkColor* generated_icon_color) { + DCHECK(generated_icon_color); + + // Resize provided icons to make sure we have versions for each size in + // |sizes_to_generate|. + std::map<int, BitmapAndSource> resized_bitmaps( + ConstrainBitmapsToSizes(icons, sizes_to_generate)); + + // Also add all provided icon sizes. + for (const BitmapAndSource& icon : icons) { + if (resized_bitmaps.find(icon.bitmap.width()) == resized_bitmaps.end()) + resized_bitmaps.insert(std::make_pair(icon.bitmap.width(), icon)); + } + + // Determine the color that will be used for the icon's background. For this + // the dominant color of the first icon found is used. + if (resized_bitmaps.size()) { + color_utils::GridSampler sampler; + *generated_icon_color = color_utils::CalculateKMeanColorOfBitmap( + resized_bitmaps.begin()->second.bitmap); + } + + // Work out what icons we need to generate here. Icons are only generated if + // there is no icon in the required size. + std::set<int> generate_sizes; + for (int size : sizes_to_generate) { + if (resized_bitmaps.find(size) == resized_bitmaps.end()) + generate_sizes.insert(size); + } + GenerateIcons(generate_sizes, app_url, *generated_icon_color, + &resized_bitmaps); + + return resized_bitmaps; +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_icon_generator.h b/chrome/browser/web_applications/components/web_app_icon_generator.h new file mode 100644 index 0000000..11c8f72 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_icon_generator.h
@@ -0,0 +1,51 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_ICON_GENERATOR_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_ICON_GENERATOR_H_ + +#include <map> +#include <set> +#include <vector> + +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" +#include "url/gurl.h" + +namespace web_app { + +struct BitmapAndSource { + BitmapAndSource(); + BitmapAndSource(const GURL& source_url_p, const SkBitmap& bitmap_p); + ~BitmapAndSource(); + + GURL source_url; + SkBitmap bitmap; +}; + +// This finds the closest not-smaller bitmap in |bitmaps| for each size in +// |sizes| and resizes it to that size. This returns a map of sizes to bitmaps +// which contains only bitmaps of a size in |sizes| and at most one bitmap of +// each size. +std::map<int, BitmapAndSource> ConstrainBitmapsToSizes( + const std::vector<BitmapAndSource>& bitmaps, + const std::set<int>& sizes); + +// Generates a square container icon of |output_size| by drawing the given +// |letter| into a rounded background of |color|. +SkBitmap GenerateBitmap(int output_size, SkColor color, char letter); + +// Resize icons to the accepted sizes, and generate any that are missing. +// Note that |app_url| is the launch URL for the app. +// Output: |generated_icon_color| is the color to use if an icon needs to be +// generated for the web app. +std::map<int, BitmapAndSource> ResizeIconsAndGenerateMissing( + const std::vector<BitmapAndSource>& icons, + const std::set<int>& sizes_to_generate, + const GURL& app_url, + SkColor* generated_icon_color); + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_ICON_GENERATOR_H_
diff --git a/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc b/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc new file mode 100644 index 0000000..04b10922 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc
@@ -0,0 +1,422 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/components/web_app_icon_generator.h" + +#include <vector> + +#include "base/stl_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_app { + +namespace { + +const char kAppIconURL1[] = "http://foo.com/1.png"; +const char kAppIconURL2[] = "http://foo.com/2.png"; +const char kAppIconURL3[] = "http://foo.com/3.png"; + +// These sizes match extension_misc::ExtensionIcons enum. +const int kIconSizeTiny = 16; +const int kIconSizeSmall = 32; +const int kIconSizeMedium = 48; +const int kIconSizeLarge = 128; +const int kIconSizeGigantor = 512; + +const int kIconSizeSmallBetweenMediumAndLarge = 63; +const int kIconSizeLargeBetweenMediumAndLarge = 96; + +SkBitmap CreateSquareBitmapWithColor(int size, SkColor color) { + SkBitmap bitmap; + bitmap.allocN32Pixels(size, size); + bitmap.eraseColor(color); + return bitmap; +} + +web_app::BitmapAndSource CreateSquareBitmapAndSourceWithColor(int size, + SkColor color) { + return web_app::BitmapAndSource(GURL(), + CreateSquareBitmapWithColor(size, color)); +} + +struct IconInfo { + IconInfo() : width(0), height(0) {} + ~IconInfo() = default; + + GURL url; + int width; + int height; + SkBitmap data; +}; + +IconInfo CreateIconInfoWithBitmap(int size, SkColor color) { + IconInfo icon_info; + icon_info.width = size; + icon_info.height = size; + icon_info.data = CreateSquareBitmapWithColor(size, color); + return icon_info; +} + +std::set<int> TestSizesToGenerate() { + const int kIconSizesToGenerate[] = { + kIconSizeSmall, kIconSizeMedium, kIconSizeLarge, + }; + return std::set<int>(kIconSizesToGenerate, + kIconSizesToGenerate + base::size(kIconSizesToGenerate)); +} + +void ValidateAllIconsWithURLsArePresent( + const std::vector<IconInfo>& icons_to_check, + const std::map<int, BitmapAndSource>& size_map) { + EXPECT_EQ(icons_to_check.size(), size_map.size()); + + // Check that every icon with URL has a mapped icon. + for (const auto& icon : icons_to_check) { + if (!icon.url.is_empty()) { + bool found = false; + if (base::ContainsKey(size_map, icon.width)) { + const BitmapAndSource& mapped_icon = size_map.at(icon.width); + if (mapped_icon.source_url == icon.url && + mapped_icon.bitmap.width() == icon.width) { + found = true; + } + } + EXPECT_TRUE(found); + } + } +} + +std::vector<web_app::BitmapAndSource>::const_iterator +FindLargestBitmapAndSourceVector( + const std::vector<web_app::BitmapAndSource>& bitmap_vector) { + auto result = bitmap_vector.end(); + int largest = -1; + for (std::vector<web_app::BitmapAndSource>::const_iterator it = + bitmap_vector.begin(); + it != bitmap_vector.end(); ++it) { + if (it->bitmap.width() > largest) { + result = it; + } + } + return result; +} + +std::vector<web_app::BitmapAndSource>::const_iterator +FindMatchingBitmapAndSourceVector( + const std::vector<web_app::BitmapAndSource>& bitmap_vector, + int size) { + for (std::vector<web_app::BitmapAndSource>::const_iterator it = + bitmap_vector.begin(); + it != bitmap_vector.end(); ++it) { + if (it->bitmap.width() == size) { + return it; + } + } + return bitmap_vector.end(); +} + +std::vector<web_app::BitmapAndSource>::const_iterator +FindEqualOrLargerBitmapAndSourceVector( + const std::vector<web_app::BitmapAndSource>& bitmap_vector, + int size) { + for (std::vector<web_app::BitmapAndSource>::const_iterator it = + bitmap_vector.begin(); + it != bitmap_vector.end(); ++it) { + if (it->bitmap.width() >= size) { + return it; + } + } + return bitmap_vector.end(); +} + +void ValidateIconsGeneratedAndResizedCorrectly( + std::vector<web_app::BitmapAndSource> downloaded, + std::map<int, web_app::BitmapAndSource> size_map, + std::set<int> sizes_to_generate, + int expected_generated, + int expected_resized) { + GURL empty_url(""); + int number_generated = 0; + int number_resized = 0; + + auto icon_largest = FindLargestBitmapAndSourceVector(downloaded); + for (const auto& size : sizes_to_generate) { + auto icon_downloaded = FindMatchingBitmapAndSourceVector(downloaded, size); + auto icon_larger = FindEqualOrLargerBitmapAndSourceVector(downloaded, size); + if (icon_downloaded == downloaded.end()) { + auto icon_resized = size_map.find(size); + if (icon_largest == downloaded.end()) { + // There are no downloaded icons. Expect an icon to be generated. + EXPECT_NE(size_map.end(), icon_resized); + EXPECT_EQ(size, icon_resized->second.bitmap.width()); + EXPECT_EQ(size, icon_resized->second.bitmap.height()); + EXPECT_EQ(size, icon_resized->second.bitmap.height()); + EXPECT_EQ(empty_url, icon_resized->second.source_url); + ++number_generated; + } else { + // If there is a larger downloaded icon, it should be resized. Otherwise + // the largest downloaded icon should be resized. + auto icon_to_resize = icon_largest; + if (icon_larger != downloaded.end()) + icon_to_resize = icon_larger; + EXPECT_NE(size_map.end(), icon_resized); + EXPECT_EQ(size, icon_resized->second.bitmap.width()); + EXPECT_EQ(size, icon_resized->second.bitmap.height()); + EXPECT_EQ(size, icon_resized->second.bitmap.height()); + EXPECT_EQ(icon_to_resize->source_url, icon_resized->second.source_url); + ++number_resized; + } + } else { + // There is an icon of exactly this size downloaded. Expect no icon to be + // generated, and the existing downloaded icon to be used. + auto icon_resized = size_map.find(size); + EXPECT_NE(size_map.end(), icon_resized); + EXPECT_EQ(size, icon_resized->second.bitmap.width()); + EXPECT_EQ(size, icon_resized->second.bitmap.height()); + EXPECT_EQ(size, icon_downloaded->bitmap.width()); + EXPECT_EQ(size, icon_downloaded->bitmap.height()); + EXPECT_EQ(icon_downloaded->source_url, icon_resized->second.source_url); + } + } + EXPECT_EQ(expected_generated, number_generated); + EXPECT_EQ(expected_resized, number_resized); +} + +void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) { + // Obtain pixel lock to access pixels. + EXPECT_EQ(color, bitmap.getColor(0, 0)); + EXPECT_EQ(size, bitmap.width()); + EXPECT_EQ(size, bitmap.height()); +} + +void TestIconGeneration(int icon_size, + int expected_generated, + int expected_resized) { + std::vector<BitmapAndSource> downloaded; + + // Add an icon with a URL and bitmap. 'Download' it. + IconInfo icon_info = CreateIconInfoWithBitmap(icon_size, SK_ColorRED); + icon_info.url = GURL(kAppIconURL1); + downloaded.push_back(BitmapAndSource(icon_info.url, icon_info.data)); + + // Now run the resizing/generation and validation. + SkColor generated_icon_color; + std::map<int, web_app::BitmapAndSource> size_map = + ResizeIconsAndGenerateMissing(downloaded, TestSizesToGenerate(), GURL(), + &generated_icon_color); + + ValidateIconsGeneratedAndResizedCorrectly( + downloaded, size_map, TestSizesToGenerate(), expected_generated, + expected_resized); +} + +} // namespace + +TEST(WebAppIconGeneratorTest, ConstrainBitmapsToSizes) { + std::set<int> desired_sizes; + desired_sizes.insert(16); + desired_sizes.insert(32); + desired_sizes.insert(48); + desired_sizes.insert(96); + desired_sizes.insert(128); + desired_sizes.insert(256); + + { + std::vector<web_app::BitmapAndSource> bitmaps; + bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(16, SK_ColorRED)); + bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(32, SK_ColorGREEN)); + bitmaps.push_back( + CreateSquareBitmapAndSourceWithColor(144, SK_ColorYELLOW)); + + std::map<int, web_app::BitmapAndSource> results( + ConstrainBitmapsToSizes(bitmaps, desired_sizes)); + + EXPECT_EQ(6u, results.size()); + ValidateBitmapSizeAndColor(results[16].bitmap, 16, SK_ColorRED); + ValidateBitmapSizeAndColor(results[32].bitmap, 32, SK_ColorGREEN); + ValidateBitmapSizeAndColor(results[48].bitmap, 48, SK_ColorYELLOW); + ValidateBitmapSizeAndColor(results[96].bitmap, 96, SK_ColorYELLOW); + ValidateBitmapSizeAndColor(results[128].bitmap, 128, SK_ColorYELLOW); + ValidateBitmapSizeAndColor(results[256].bitmap, 256, SK_ColorYELLOW); + } + { + std::vector<web_app::BitmapAndSource> bitmaps; + bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(512, SK_ColorRED)); + bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(18, SK_ColorGREEN)); + bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(33, SK_ColorBLUE)); + bitmaps.push_back(CreateSquareBitmapAndSourceWithColor(17, SK_ColorYELLOW)); + + std::map<int, web_app::BitmapAndSource> results( + ConstrainBitmapsToSizes(bitmaps, desired_sizes)); + + EXPECT_EQ(6u, results.size()); + ValidateBitmapSizeAndColor(results[16].bitmap, 16, SK_ColorYELLOW); + ValidateBitmapSizeAndColor(results[32].bitmap, 32, SK_ColorBLUE); + ValidateBitmapSizeAndColor(results[48].bitmap, 48, SK_ColorRED); + ValidateBitmapSizeAndColor(results[96].bitmap, 96, SK_ColorRED); + ValidateBitmapSizeAndColor(results[128].bitmap, 128, SK_ColorRED); + ValidateBitmapSizeAndColor(results[256].bitmap, 256, SK_ColorRED); + } +} + +TEST(WebAppIconGeneratorTest, LinkedAppIconsAreNotChanged) { + std::vector<IconInfo> icons_info; + + IconInfo icon_info; + icon_info.url = GURL(kAppIconURL3); + + icon_info.width = kIconSizeMedium; + icons_info.push_back(icon_info); + + icon_info.width = kIconSizeSmall; + icons_info.push_back(icon_info); + + icon_info.width = kIconSizeLarge; + icons_info.push_back(icon_info); + + // 'Download' one of the icons without a size or bitmap. + std::vector<BitmapAndSource> downloaded; + downloaded.push_back(BitmapAndSource( + GURL(kAppIconURL3), + CreateSquareBitmapWithColor(kIconSizeLarge, SK_ColorBLACK))); + + const auto& sizes = TestSizesToGenerate(); + + // Now run the resizing and generation into a new web icons info. + SkColor generated_icon_color; + std::map<int, web_app::BitmapAndSource> size_map = + ResizeIconsAndGenerateMissing(downloaded, sizes, GURL(), + &generated_icon_color); + EXPECT_EQ(sizes.size(), size_map.size()); + + // Now check that the linked app icons (i.e. those with URLs) are matching. + ValidateAllIconsWithURLsArePresent(icons_info, size_map); +} + +TEST(WebAppIconGeneratorTest, IconsResizedFromOddSizes) { + std::vector<BitmapAndSource> downloaded; + + // Add three icons with a URL and bitmap. 'Download' each of them. + IconInfo icon_info = CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED); + icon_info.url = GURL(kAppIconURL1); + downloaded.push_back(web_app::BitmapAndSource(icon_info.url, icon_info.data)); + + icon_info = CreateIconInfoWithBitmap(kIconSizeSmallBetweenMediumAndLarge, + SK_ColorRED); + icon_info.url = GURL(kAppIconURL2); + downloaded.push_back(web_app::BitmapAndSource(icon_info.url, icon_info.data)); + + icon_info = CreateIconInfoWithBitmap(kIconSizeLargeBetweenMediumAndLarge, + SK_ColorRED); + icon_info.url = GURL(kAppIconURL3); + downloaded.push_back(web_app::BitmapAndSource(icon_info.url, icon_info.data)); + + // Now run the resizing and generation. + SkColor generated_icon_color; + std::map<int, web_app::BitmapAndSource> size_map = + ResizeIconsAndGenerateMissing(downloaded, TestSizesToGenerate(), GURL(), + &generated_icon_color); + + // No icons should be generated. The LARGE and MEDIUM sizes should be resized. + ValidateIconsGeneratedAndResizedCorrectly(downloaded, size_map, + TestSizesToGenerate(), 0, 2); +} + +TEST(WebAppIconGeneratorTest, IconsResizedFromLarger) { + std::vector<web_app::BitmapAndSource> downloaded; + + // Add three icons with a URL and bitmap. 'Download' two of them and pretend + // the third failed to download. + IconInfo icon_info = CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED); + icon_info.url = GURL(kAppIconURL1); + downloaded.push_back(web_app::BitmapAndSource(icon_info.url, icon_info.data)); + + icon_info = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorBLUE); + icon_info.url = GURL(kAppIconURL2); + + icon_info = CreateIconInfoWithBitmap(kIconSizeGigantor, SK_ColorBLACK); + icon_info.url = GURL(kAppIconURL3); + downloaded.push_back(web_app::BitmapAndSource(icon_info.url, icon_info.data)); + + // Now run the resizing and generation. + SkColor generated_icon_color; + std::map<int, web_app::BitmapAndSource> size_map = + ResizeIconsAndGenerateMissing(downloaded, TestSizesToGenerate(), GURL(), + &generated_icon_color); + + // Expect icon for MEDIUM and LARGE to be resized from the gigantor icon + // as it was not downloaded. + ValidateIconsGeneratedAndResizedCorrectly(downloaded, size_map, + TestSizesToGenerate(), 0, 2); +} + +TEST(WebAppIconGeneratorTest, AllIconsGeneratedWhenNotDownloaded) { + std::vector<web_app::BitmapAndSource> downloaded; + + // Add three icons with a URL and bitmap. 'Download' none of them. + IconInfo icon_info = CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED); + icon_info.url = GURL(kAppIconURL1); + + icon_info = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorBLUE); + icon_info.url = GURL(kAppIconURL2); + + icon_info = CreateIconInfoWithBitmap(kIconSizeGigantor, SK_ColorBLACK); + icon_info.url = GURL(kAppIconURL3); + + // Now run the resizing and generation. + SkColor generated_icon_color; + std::map<int, web_app::BitmapAndSource> size_map = + ResizeIconsAndGenerateMissing(downloaded, TestSizesToGenerate(), GURL(), + &generated_icon_color); + + // Expect all icons to be generated. + ValidateIconsGeneratedAndResizedCorrectly(downloaded, size_map, + TestSizesToGenerate(), 3, 0); +} + +TEST(WebAppIconGeneratorTest, IconResizedFromLargerAndSmaller) { + std::vector<web_app::BitmapAndSource> downloaded; + + // Pretend the huge icon wasn't downloaded but two smaller ones were. + IconInfo icon_info = CreateIconInfoWithBitmap(kIconSizeTiny, SK_ColorRED); + icon_info.url = GURL(kAppIconURL1); + downloaded.push_back(web_app::BitmapAndSource(icon_info.url, icon_info.data)); + + icon_info = CreateIconInfoWithBitmap(kIconSizeMedium, SK_ColorBLUE); + icon_info.url = GURL(kAppIconURL2); + downloaded.push_back(web_app::BitmapAndSource(icon_info.url, icon_info.data)); + + icon_info = CreateIconInfoWithBitmap(kIconSizeGigantor, SK_ColorBLACK); + icon_info.url = GURL(kAppIconURL3); + + // Now run the resizing and generation. + SkColor generated_icon_color; + std::map<int, web_app::BitmapAndSource> size_map = + ResizeIconsAndGenerateMissing(downloaded, TestSizesToGenerate(), GURL(), + &generated_icon_color); + + // Expect no icons to be generated, but the LARGE and SMALL icons to be + // resized from the MEDIUM icon. + ValidateIconsGeneratedAndResizedCorrectly(downloaded, size_map, + TestSizesToGenerate(), 0, 2); + + // Verify specifically that the LARGE icons was resized from the medium icon. + const auto it = size_map.find(kIconSizeLarge); + EXPECT_NE(size_map.end(), it); + EXPECT_EQ(GURL(kAppIconURL2), it->second.source_url); +} + +TEST(WebAppIconGeneratorTest, IconsResizedWhenOnlyATinyOneIsProvided) { + // When only a tiny icon is downloaded (smaller than the three desired + // sizes), 3 icons should be resized. + TestIconGeneration(kIconSizeTiny, 0, 3); +} + +TEST(WebAppIconGeneratorTest, IconsResizedWhenOnlyAGigantorOneIsProvided) { + // When an enormous icon is provided, each desired icon size should be resized + // from it, and no icons should be generated. + TestIconGeneration(kIconSizeGigantor, 0, 3); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc index 69317aa..2521c2b2 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
@@ -14,6 +14,16 @@ namespace extensions { +BookmarkAppInstallationTask::Result::Result(ResultCode code, + const std::string& app_id) + : code(code), app_id(app_id) { + DCHECK_EQ(code == ResultCode::kSuccess, !app_id.empty()); +} + +BookmarkAppInstallationTask::Result::Result(Result&&) = default; + +BookmarkAppInstallationTask::Result::~Result() = default; + BookmarkAppInstallationTask::~BookmarkAppInstallationTask() = default; void BookmarkAppInstallationTask::SetDataRetrieverForTesting(
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h index ed515370..837c6aa 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_INSTALLATION_TASK_H_ #include <memory> +#include <string> #include "base/callback_forward.h" #include "base/macros.h" @@ -21,12 +22,24 @@ // or WebApplicationInfo. Can only be called from the UI thread. class BookmarkAppInstallationTask { public: - enum class Result { + enum class ResultCode { kSuccess, kGetWebApplicationInfoFailed, kInstallationFailed, }; + struct Result { + Result(ResultCode code, const std::string& app_id); + Result(Result&&); + ~Result(); + + const ResultCode code; + // Empty unless |code| is ResultCode::kSuccess. + std::string app_id; + + DISALLOW_COPY_AND_ASSIGN(Result); + }; + using ResultCallback = base::OnceCallback<void(Result)>; virtual ~BookmarkAppInstallationTask();
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc index a871b404..e90e157 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task_unittest.cc
@@ -23,11 +23,15 @@ #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/web_contents_tester.h" +#include "extensions/common/extension_id.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/manifest/manifest.h" namespace extensions { +using Result = BookmarkAppInstallationTask::Result; +using ResultCode = BookmarkAppInstallationTask::ResultCode; + namespace { const char kWebAppUrl[] = "https://foo.example"; @@ -40,9 +44,8 @@ BookmarkAppInstallationTaskTest() = default; ~BookmarkAppInstallationTaskTest() override = default; - void OnInstallationTaskResult(base::OnceClosure quit_closure, - BookmarkAppInstallationTask::Result result) { - app_installation_result_ = result; + void OnInstallationTaskResult(base::OnceClosure quit_closure, Result result) { + app_installation_result_ = std::make_unique<Result>(std::move(result)); std::move(quit_closure).Run(); } @@ -59,16 +62,15 @@ protected: bool app_installed() { - return app_installation_result_.value() == - BookmarkAppInstallationTask::Result::kSuccess; + bool app_installed = app_installation_result_->code == ResultCode::kSuccess; + EXPECT_NE(app_installed, app_installation_result_->app_id.empty()); + return app_installed; } - BookmarkAppInstallationTask::Result app_installation_result() { - return app_installation_result_.value(); - } + const Result& app_installation_result() { return *app_installation_result_; } private: - base::Optional<BookmarkAppInstallationTask::Result> app_installation_result_; + std::unique_ptr<Result> app_installation_result_; DISALLOW_COPY_AND_ASSIGN(BookmarkAppInstallationTaskTest); }; @@ -115,13 +117,14 @@ ResultCallback callback) override { web_app_info_ = web_app_info; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), succeeds_)); + FROM_HERE, base::BindOnce(std::move(callback), + succeeds_ ? "12345" : std::string())); } const WebApplicationInfo& web_app_info() { return web_app_info_.value(); } private: - bool succeeds_; + const bool succeeds_; base::Optional<WebApplicationInfo> web_app_info_; DISALLOW_COPY_AND_ASSIGN(TestInstaller); @@ -156,8 +159,9 @@ run_loop.Run(); EXPECT_FALSE(app_installed()); - EXPECT_EQ(BookmarkAppInstallationTask::Result::kGetWebApplicationInfoFailed, - app_installation_result()); + EXPECT_EQ( + BookmarkAppInstallationTask::ResultCode::kGetWebApplicationInfoFailed, + app_installation_result().code); } TEST_F(BookmarkAppInstallationTaskTest, ShortcutFromContents_NoManifest) { @@ -208,8 +212,8 @@ run_loop.Run(); EXPECT_FALSE(app_installed()); - EXPECT_EQ(BookmarkAppInstallationTask::Result::kInstallationFailed, - app_installation_result()); + EXPECT_EQ(BookmarkAppInstallationTask::ResultCode::kInstallationFailed, + app_installation_result().code); } } // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installer.cc b/chrome/browser/web_applications/extensions/bookmark_app_installer.cc index 7a504a8..7f911b4 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installer.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_installer.cc
@@ -10,7 +10,10 @@ #include "base/callback.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/web_application_info.h" +#include "extensions/common/extension.h" +#include "url/gurl.h" namespace extensions { @@ -22,9 +25,9 @@ void BookmarkAppInstaller::Install(const WebApplicationInfo& web_app_info, ResultCallback callback) { - crx_installer_->set_installer_callback( - base::BindOnce(&BookmarkAppInstaller::OnInstall, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + crx_installer_->set_installer_callback(base::BindOnce( + &BookmarkAppInstaller::OnInstall, weak_ptr_factory_.GetWeakPtr(), + std::move(callback), web_app_info.app_url)); crx_installer_->InstallWebApp(web_app_info); } @@ -35,11 +38,18 @@ void BookmarkAppInstaller::OnInstall( ResultCallback callback, + const GURL& app_url, const base::Optional<CrxInstallError>& error) { - // TODO(crbug.com/864904): Finish the installation i.e. set launch container. + if (error) { + std::move(callback).Run(std::string()); + return; + } - const bool installation_succeeded = !error; - std::move(callback).Run(installation_succeeded); + auto* installed_extension = crx_installer_->extension(); + DCHECK(installed_extension); + DCHECK_EQ(AppLaunchInfo::GetLaunchWebURL(installed_extension), app_url); + + std::move(callback).Run(installed_extension->id()); } } // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installer.h b/chrome/browser/web_applications/extensions/bookmark_app_installer.h index 32aa0b7..a9334c4 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installer.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_installer.h
@@ -10,7 +10,9 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "extensions/common/extension_id.h" +class GURL; class Profile; struct WebApplicationInfo; @@ -24,7 +26,7 @@ // App in the system. class BookmarkAppInstaller { public: - using ResultCallback = base::OnceCallback<void(bool)>; + using ResultCallback = base::OnceCallback<void(const ExtensionId&)>; // Constructs a BookmarkAppInstaller that will install the Bookmark App in // |profile|. @@ -40,6 +42,7 @@ private: void OnInstall(ResultCallback callback, + const GURL& app_url, const base::Optional<CrxInstallError>& error); scoped_refptr<CrxInstaller> crx_installer_;
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installer_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_installer_unittest.cc index 73b42b6..915b6b2f 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installer_unittest.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_installer_unittest.cc
@@ -18,6 +18,7 @@ #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "extensions/browser/install/crx_install_error.h" +#include "extensions/common/extension_id.h" namespace extensions { @@ -82,8 +83,9 @@ false /* autoupdate_enabled */); } - void InstallCallback(base::OnceClosure quit_closure, bool app_installed) { - app_installed_ = app_installed; + void InstallCallback(base::OnceClosure quit_closure, + const ExtensionId& extension_id) { + app_installed_ = !extension_id.empty(); std::move(quit_closure).Run(); }
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.cc b/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.cc index e71f589..e2f117b6 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.h" #include <memory> +#include <string> #include <utility> #include <vector> @@ -41,7 +42,8 @@ std::unique_ptr<WebApplicationInfo> web_app_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!web_app_info) { - std::move(result_callback).Run(Result::kGetWebApplicationInfoFailed); + std::move(result_callback) + .Run(Result(ResultCode::kGetWebApplicationInfoFailed, std::string())); return; } @@ -76,9 +78,10 @@ void BookmarkAppShortcutInstallationTask::OnInstalled( ResultCallback result_callback, - bool success) { - std::move(result_callback) - .Run(success ? Result::kSuccess : Result::kInstallationFailed); + const std::string& app_id) { + ResultCode code = + app_id.empty() ? ResultCode::kInstallationFailed : ResultCode::kSuccess; + std::move(result_callback).Run(Result(code, app_id)); } } // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.h b/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.h index 1e9902a..88646e9 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_shortcut_installation_task.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_SHORTCUT_INSTALLATION_TASK_H_ #include <memory> +#include <string> #include <vector> #include "base/callback.h" @@ -40,7 +41,7 @@ void OnGetIcons(ResultCallback result_callback, std::unique_ptr<WebApplicationInfo> web_app_info, std::vector<WebApplicationInfo::IconInfo> icons); - void OnInstalled(ResultCallback result_callback, bool success); + void OnInstalled(ResultCallback result_callback, const std::string& app_id); base::WeakPtrFactory<BookmarkAppShortcutInstallationTask> weak_ptr_factory_{ this};
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc index 4bef8222..7fbb915 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h" #include <memory> +#include <string> #include <utility> #include <vector> @@ -43,7 +44,7 @@ InstallCallback callback) { // The app is already being installed. if (current_install_info_ && *current_install_info_ == app_to_install) { - std::move(callback).Run(false); + std::move(callback).Run(std::string()); return; } @@ -82,7 +83,7 @@ } if (validated_url != current_install_info_->url) { - std::move(current_install_callback_).Run(false); + std::move(current_install_callback_).Run(std::string()); return; } @@ -114,7 +115,7 @@ web_contents_.reset(); current_install_info_.reset(); - std::move(current_install_callback_).Run(false); + std::move(current_install_callback_).Run(std::string()); } void PendingBookmarkAppManager::OnInstalled( @@ -123,8 +124,7 @@ // queued installation requests. web_contents_.reset(); current_install_info_.reset(); - std::move(current_install_callback_) - .Run(result == BookmarkAppInstallationTask::Result::kSuccess); + std::move(current_install_callback_).Run(result.app_id); } } // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc index cf38470..b808e8f 100644 --- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc +++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h" #include <memory> +#include <string> #include <utility> #include "base/bind.h" @@ -39,8 +40,12 @@ content::WebContents* web_contents, BookmarkAppInstallationTask::ResultCallback callback) override { std::move(callback).Run( - succeeds_ ? BookmarkAppInstallationTask::Result::kSuccess - : BookmarkAppInstallationTask::Result::kInstallationFailed); + succeeds_ + ? BookmarkAppInstallationTask::Result( + BookmarkAppInstallationTask::ResultCode::kSuccess, "12345") + : BookmarkAppInstallationTask::Result( + BookmarkAppInstallationTask::ResultCode::kInstallationFailed, + std::string())); } private: @@ -85,8 +90,8 @@ false); } - void InstallCallback(bool succeeded) { - install_succeeded_ = succeeded; + void InstallCallback(const std::string& app_id) { + install_succeeded_ = !app_id.empty(); } protected:
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index 1db083d..1d8101b 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json
@@ -51,8 +51,8 @@ "channel": "trunk", "extension_types": ["platform_app"], "whitelist": [ - "D8524F339305807AB2439035774F746F739D0983" // Test platform app - // TODO(crbug.com/819404): Whitelist the Highlights app. + "46578A13607D38F1DC8E280C4F499FB0A2F9565C", // http://crbug.com/819404 + "898FB5A39687D210766B8998BA4530B99C9E6586" // http://crbug.com/819404 ] }, "autofillPrivate": {
diff --git a/chrome/common/google_url_loader_throttle.cc b/chrome/common/google_url_loader_throttle.cc index 6fd22cf..9855d649 100644 --- a/chrome/common/google_url_loader_throttle.cc +++ b/chrome/common/google_url_loader_throttle.cc
@@ -9,15 +9,15 @@ GoogleURLLoaderThrottle::GoogleURLLoaderThrottle( bool is_off_the_record, - bool is_signed_in, bool force_safe_search, int32_t youtube_restrict, - const std::string& allowed_domains_for_apps) + const std::string& allowed_domains_for_apps, + const std::string& variation_ids_header) : is_off_the_record_(is_off_the_record), - is_signed_in_(is_signed_in), force_safe_search_(force_safe_search), youtube_restrict_(youtube_restrict), - allowed_domains_for_apps_(allowed_domains_for_apps) {} + allowed_domains_for_apps_(allowed_domains_for_apps), + variation_ids_header_(variation_ids_header) {} GoogleURLLoaderThrottle::~GoogleURLLoaderThrottle() {} @@ -26,12 +26,12 @@ void GoogleURLLoaderThrottle::WillStartRequest( network::ResourceRequest* request, bool* defer) { - variations::AppendVariationHeaders( - request->url, - is_off_the_record_ ? variations::InIncognito::kYes - : variations::InIncognito::kNo, - is_signed_in_ ? variations::SignedIn::kYes : variations::SignedIn::kNo, - &request->headers); + if (!is_off_the_record_ && + variations::ShouldAppendVariationHeaders(request->url) && + !variation_ids_header_.empty()) { + request->headers.SetHeaderIfMissing(variations::kClientDataHeader, + variation_ids_header_); + } if (force_safe_search_) { GURL new_url; @@ -61,9 +61,6 @@ const network::ResourceResponseHead& response_head, bool* defer, std::vector<std::string>* to_be_removed_headers) { - if (!variations::internal::ShouldAppendVariationHeaders( - redirect_info.new_url)) { - const char kClientData[] = "X-Client-Data"; - to_be_removed_headers->push_back(kClientData); - } + if (!variations::ShouldAppendVariationHeaders(redirect_info.new_url)) + to_be_removed_headers->push_back(variations::kClientDataHeader); }
diff --git a/chrome/common/google_url_loader_throttle.h b/chrome/common/google_url_loader_throttle.h index 5c9d530..2765148 100644 --- a/chrome/common/google_url_loader_throttle.h +++ b/chrome/common/google_url_loader_throttle.h
@@ -15,10 +15,10 @@ public base::SupportsWeakPtr<GoogleURLLoaderThrottle> { public: GoogleURLLoaderThrottle(bool is_off_the_record, - bool is_signed_in, bool force_safe_search, int32_t youtube_restrict, - const std::string& allowed_domains_for_apps); + const std::string& allowed_domains_for_apps, + const std::string& variation_ids_header); ~GoogleURLLoaderThrottle() override; private: @@ -33,10 +33,10 @@ std::vector<std::string>* to_be_removed_headers) override; bool is_off_the_record_; - bool is_signed_in_; bool force_safe_search_; int32_t youtube_restrict_; std::string allowed_domains_for_apps_; + std::string variation_ids_header_; }; #endif // CHROME_COMMON_GOOGLE_URL_LOADER_THROTTLE_H_
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.cc b/chrome/common/media_router/providers/cast/cast_media_source.cc index 8f97a0d..3a978ec3 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source.cc +++ b/chrome/common/media_router/providers/cast/cast_media_source.cc
@@ -7,7 +7,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" #include "chrome/common/media_router/media_source_helper.h" #include "net/base/url_util.h" #include "url/gurl.h" @@ -70,16 +69,10 @@ std::unique_ptr<CastMediaSource> CastMediaSourceForDesktopMirroring( const MediaSource::Id& source_id) { -// Desktop audio mirroring is only supported on some platforms. -#if defined(OS_WIN) || defined(OS_CHROMEOS) - return std::make_unique<CastMediaSource>( - source_id, - std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId), - CastAppInfo(kCastStreamingAudioAppId)})); -#else + // TODO(https://crbug.com/849335): Add back audio-only devices for desktop + // mirroring when proper support is implemented. return std::make_unique<CastMediaSource>( source_id, std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId)})); -#endif } std::unique_ptr<CastMediaSource> CreateFromURLParams(
diff --git a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc index 54181fdc..5ab5eaa 100644 --- a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc +++ b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
@@ -63,8 +63,8 @@ ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); ASSERT_EQ(2u, source->app_infos().size()); - EXPECT_EQ("0F5096E8", source->app_infos()[0].app_id); - EXPECT_EQ("85CDB22F", source->app_infos()[1].app_id); + EXPECT_EQ(kCastStreamingAppId, source->app_infos()[0].app_id); + EXPECT_EQ(kCastStreamingAudioAppId, source->app_infos()[1].app_id); EXPECT_TRUE(source->client_id().empty()); EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout()); } @@ -75,8 +75,19 @@ ASSERT_TRUE(source); EXPECT_EQ(source_id, source->source_id()); ASSERT_EQ(2u, source->app_infos().size()); - EXPECT_EQ("0F5096E8", source->app_infos()[0].app_id); - EXPECT_EQ("85CDB22F", source->app_infos()[1].app_id); + EXPECT_EQ(kCastStreamingAppId, source->app_infos()[0].app_id); + EXPECT_EQ(kCastStreamingAudioAppId, source->app_infos()[1].app_id); + EXPECT_TRUE(source->client_id().empty()); + EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout()); +} + +TEST(CastMediaSourceTest, FromDesktopUrn) { + MediaSource::Id source_id("urn:x-org.chromium.media:source:desktop"); + std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id); + ASSERT_TRUE(source); + EXPECT_EQ(source_id, source->source_id()); + ASSERT_EQ(1u, source->app_infos().size()); + EXPECT_EQ(kCastStreamingAppId, source->app_infos()[0].app_id); EXPECT_TRUE(source->client_id().empty()); EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout()); }
diff --git a/chrome/common/renderer_configuration.mojom b/chrome/common/renderer_configuration.mojom index f95d1b7..1daffe6 100644 --- a/chrome/common/renderer_configuration.mojom +++ b/chrome/common/renderer_configuration.mojom
@@ -12,10 +12,10 @@ SetInitialConfiguration(bool is_incognito_process); // Update renderer configuration with settings that can change. - SetConfiguration(bool is_signed_in, - bool force_safe_search, + SetConfiguration(bool force_safe_search, int32 youtube_restrict, - string allowed_domains_for_apps); + string allowed_domains_for_apps, + string variation_ids_header); // Set the content setting rules stored by the renderer. SetContentSettingRules(
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc index 1d3f354..8832d25 100644 --- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -520,75 +520,114 @@ ExpectAutomaticGenerationAvailable("first_password", true); } -TEST_F(PasswordGenerationAgentTest, MaximumOfferSize) { - for (size_t maximum_offer_size : {0, 5}) { - SCOPED_TRACE(testing::Message() - << "maximum_offer_size = " << maximum_offer_size); - password_generation_->set_maximum_offer_size_for_testing( - maximum_offer_size); - EXPECT_EQ(maximum_offer_size, password_generation_->maximum_offer_size()); +TEST_F(PasswordGenerationAgentTest, MaximumCharsForGenerationOffer) { + base::HistogramTester histogram_tester; - base::HistogramTester histogram_tester; + LoadHTMLWithUserGesture(kAccountCreationFormHTML); + SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML); + SetAccountCreationFormsDetectedMessage(password_generation_, + GetMainFrame()->GetDocument(), 0, 1); + // There should now be a message to show the UI. + ExpectAutomaticGenerationAvailable("first_password", true); - LoadHTMLWithUserGesture(kAccountCreationFormHTML); - SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML); - SetAccountCreationFormsDetectedMessage(password_generation_, - GetMainFrame()->GetDocument(), 0, 1); - // There should now be a message to show the UI. - ExpectAutomaticGenerationAvailable("first_password", true); + WebDocument document = GetMainFrame()->GetDocument(); + WebElement element = + document.GetElementById(WebString::FromUTF8("first_password")); + ASSERT_FALSE(element.IsNull()); + WebInputElement first_password_element = element.To<WebInputElement>(); - WebDocument document = GetMainFrame()->GetDocument(); - WebElement element = - document.GetElementById(WebString::FromUTF8("first_password")); - ASSERT_FALSE(element.IsNull()); - WebInputElement first_password_element = element.To<WebInputElement>(); + // Make a password just under maximum offer size. + SimulateUserInputChangeForElement( + &first_password_element, + std::string(PasswordGenerationAgent::kMaximumCharsForGenerationOffer, + 'a')); - // Make a password just under maximum offer size. - if (password_generation_->maximum_offer_size() > 0) { - SimulateUserInputChangeForElement( - &first_password_element, - std::string(password_generation_->maximum_offer_size(), 'a')); + // There should still be a message to show the UI. + EXPECT_TRUE(GetCalledAutomaticGenerationStatusChangedTrue()); + fake_pw_client_.reset_called_automatic_generation_status_changed_true(); + fake_pw_client_.reset_called_password_generation_rejected_by_typing(); - // There should still be a message to show the UI. - EXPECT_TRUE(GetCalledAutomaticGenerationStatusChangedTrue()); - fake_pw_client_.reset_called_automatic_generation_status_changed_true(); - fake_pw_client_.reset_called_password_generation_rejected_by_typing(); - } + // Simulate a user typing a password just over maximum offer size. + SimulateUserTypingASCIICharacter('a', true); + // There should now be a message that generation was rejected. + fake_pw_client_.Flush(); + EXPECT_TRUE(fake_pw_client_.called_password_generation_rejected_by_typing()); + fake_pw_client_.reset_called_password_generation_rejected_by_typing(); - // Simulate a user typing a password just over maximum offer size. - SimulateUserTypingASCIICharacter('a', true); - // There should now be a message that generation was rejected. - fake_pw_client_.Flush(); - EXPECT_TRUE( - fake_pw_client_.called_password_generation_rejected_by_typing()); - fake_pw_client_.reset_called_show_manual_pw_generation_popup(); + // Simulate the user deleting characters. The generation popup should be + // shown again. + SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); + // There should now be a message to show the UI. + EXPECT_TRUE(GetCalledAutomaticGenerationStatusChangedTrue()); + fake_pw_client_.reset_called_automatic_generation_status_changed_true(); - // Simulate the user deleting characters. The generation popup should be - // shown again. - SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); - // There should now be a message to show the UI. - EXPECT_TRUE(GetCalledAutomaticGenerationStatusChangedTrue()); - fake_pw_client_.reset_called_automatic_generation_status_changed_true(); + // Change focus. Bubble should be hidden, but that is handled by + // AutofilAgent, so no messages are sent. + ExecuteJavaScriptForTests("document.getElementById('username').focus();"); + EXPECT_FALSE(GetCalledAutomaticGenerationStatusChangedTrue()); - // Change focus. Bubble should be hidden, but that is handled by - // AutofilAgent, so no messages are sent. - ExecuteJavaScriptForTests("document.getElementById('username').focus();"); - EXPECT_FALSE(GetCalledAutomaticGenerationStatusChangedTrue()); + // Focusing the password field will bring up the generation UI again. + ExecuteJavaScriptForTests( + "document.getElementById('first_password').focus();"); + EXPECT_TRUE(GetCalledAutomaticGenerationStatusChangedTrue()); + fake_pw_client_.reset_called_automatic_generation_status_changed_true(); - // Focusing the password field will bring up the generation UI again. - ExecuteJavaScriptForTests( - "document.getElementById('first_password').focus();"); - EXPECT_TRUE(GetCalledAutomaticGenerationStatusChangedTrue()); - fake_pw_client_.reset_called_automatic_generation_status_changed_true(); + // Loading a different page triggers UMA stat upload. Verify that only one + // display event is sent. + LoadHTMLWithUserGesture(kSigninFormHTML); - // Loading a different page triggers UMA stat upload. Verify that only one - // display event is sent. - LoadHTMLWithUserGesture(kSigninFormHTML); + histogram_tester.ExpectBucketCount( + "PasswordGeneration.Event", + autofill::password_generation::GENERATION_POPUP_SHOWN, 1); +} - histogram_tester.ExpectBucketCount( - "PasswordGeneration.Event", - autofill::password_generation::GENERATION_POPUP_SHOWN, 1); - } +TEST_F(PasswordGenerationAgentTest, MinimumLengthForEditedPassword) { + LoadHTMLWithUserGesture(kAccountCreationFormHTML); + SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML); + SetAccountCreationFormsDetectedMessage(password_generation_, + GetMainFrame()->GetDocument(), 0, 1); + + // Generate a new password. + base::string16 password = base::ASCIIToUTF16("random_password"); + EXPECT_CALL(fake_pw_client_, + PresaveGeneratedPassword(testing::Field( + &autofill::PasswordForm::password_value, password))); + password_generation_->GeneratedPasswordAccepted(password); + fake_pw_client_.Flush(); + testing::Mock::VerifyAndClearExpectations(&fake_pw_client_); + + // Delete most of the password. + FocusField("first_password"); + size_t max_chars_to_delete = + password.length() - + PasswordGenerationAgent::kMinimumLengthForEditedPassword; + EXPECT_CALL(fake_pw_client_, PresaveGeneratedPassword(testing::_)) + .Times(testing::AtLeast(1)); + for (size_t i = 0; i < max_chars_to_delete; ++i) + SimulateUserTypingASCIICharacter(ui::VKEY_BACK, false); + fake_pw_client_.Flush(); + testing::Mock::VerifyAndClearExpectations(&fake_pw_client_); + EXPECT_FALSE(GetCalledAutomaticGenerationStatusChangedTrue()); + + // Delete one more character. The state should move to offering generation. + EXPECT_CALL(fake_pw_client_, PasswordNoLongerGenerated(testing::_)); + SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); + fake_pw_client_.Flush(); + testing::Mock::VerifyAndClearExpectations(&fake_pw_client_); + EXPECT_TRUE(GetCalledAutomaticGenerationStatusChangedTrue()); + + // The first password field is still non empty. The second one should be + // cleared. + WebDocument document = GetMainFrame()->GetDocument(); + WebElement element = + document.GetElementById(WebString::FromUTF8("first_password")); + ASSERT_FALSE(element.IsNull()); + WebInputElement first_password_element = element.To<WebInputElement>(); + element = document.GetElementById(WebString::FromUTF8("second_password")); + ASSERT_FALSE(element.IsNull()); + WebInputElement second_password_element = element.To<WebInputElement>(); + EXPECT_NE(base::string16(), first_password_element.Value().Utf16()); + EXPECT_EQ(base::string16(), second_password_element.Value().Utf16()); } TEST_F(PasswordGenerationAgentTest, DynamicFormTest) { @@ -876,7 +915,7 @@ const char* kTextFieldId = "username"; ExpectAutomaticGenerationAvailable(kGenerationElementId, true); - base::string16 password = base::ASCIIToUTF16("pwd"); + base::string16 password = base::ASCIIToUTF16("long_pwd"); EXPECT_CALL(fake_pw_client_, PresaveGeneratedPassword(testing::Field( &autofill::PasswordForm::password_value, password))); @@ -911,7 +950,7 @@ const char kGenerationElementId[] = "first_password"; ExpectAutomaticGenerationAvailable(kGenerationElementId, true); - base::string16 password = base::ASCIIToUTF16("pwd"); + base::string16 password = base::ASCIIToUTF16("long_pwd"); EXPECT_CALL(fake_pw_client_, PresaveGeneratedPassword(testing::Field( &autofill::PasswordForm::password_value, password)));
diff --git a/chrome/renderer/chrome_render_thread_observer.cc b/chrome/renderer/chrome_render_thread_observer.cc index e5cccd3..a23117de 100644 --- a/chrome/renderer/chrome_render_thread_observer.cc +++ b/chrome/renderer/chrome_render_thread_observer.cc
@@ -135,10 +135,10 @@ } // namespace bool ChromeRenderThreadObserver::is_incognito_process_ = false; -bool ChromeRenderThreadObserver::is_signed_in_ = false; bool ChromeRenderThreadObserver::force_safe_search_ = false; int32_t ChromeRenderThreadObserver::youtube_restrict_ = 0; std::string* ChromeRenderThreadObserver::allowed_domains_for_apps_ = nullptr; +std::string* ChromeRenderThreadObserver::variation_ids_header_ = nullptr; ChromeRenderThreadObserver::ChromeRenderThreadObserver() : visited_link_slave_(new visitedlink::VisitedLinkSlave), @@ -196,16 +196,18 @@ } void ChromeRenderThreadObserver::SetConfiguration( - bool is_signed_in, bool force_safe_search, int32_t youtube_restrict, - const std::string& allowed_domains_for_apps) { - is_signed_in_ = is_signed_in; + const std::string& allowed_domains_for_apps, + const std::string& variation_ids_header) { force_safe_search_ = force_safe_search; youtube_restrict_ = youtube_restrict; if (!allowed_domains_for_apps_) allowed_domains_for_apps_ = new std::string(); *allowed_domains_for_apps_ = allowed_domains_for_apps; + if (!variation_ids_header_) + variation_ids_header_ = new std::string(); + *variation_ids_header_ = variation_ids_header; } void ChromeRenderThreadObserver::SetContentSettingRules(
diff --git a/chrome/renderer/chrome_render_thread_observer.h b/chrome/renderer/chrome_render_thread_observer.h index 9af2d57..f999803 100644 --- a/chrome/renderer/chrome_render_thread_observer.h +++ b/chrome/renderer/chrome_render_thread_observer.h
@@ -35,12 +35,14 @@ ~ChromeRenderThreadObserver() override; static bool is_incognito_process() { return is_incognito_process_; } - static bool is_signed_in() { return is_signed_in_; } static bool force_safe_search() { return force_safe_search_; } static int32_t youtube_restrict() { return youtube_restrict_; } static const std::string& allowed_domains_for_apps() { return *allowed_domains_for_apps_; } + static const std::string& variation_ids_header() { + return *variation_ids_header_; + } // Returns a pointer to the content setting rules owned by // |ChromeRenderThreadObserver|. @@ -59,10 +61,10 @@ // chrome::mojom::RendererConfiguration: void SetInitialConfiguration(bool is_incognito_process) override; - void SetConfiguration(bool is_signed_in, - bool force_safe_search, + void SetConfiguration(bool force_safe_search, int32_t youtube_restrict, - const std::string& allowed_domains_for_apps) override; + const std::string& allowed_domains_for_apps, + const std::string& variation_ids_header) override; void SetContentSettingRules( const RendererContentSettingRules& rules) override; void SetFieldTrialGroup(const std::string& trial_name, @@ -72,10 +74,10 @@ chrome::mojom::RendererConfigurationAssociatedRequest request); static bool is_incognito_process_; - static bool is_signed_in_; static bool force_safe_search_; static int32_t youtube_restrict_; static std::string* allowed_domains_for_apps_; + static std::string* variation_ids_header_; std::unique_ptr<content::ResourceDispatcherDelegate> resource_delegate_; RendererContentSettingRules content_setting_rules_;
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc index 7874b84e..3c38ef8 100644 --- a/chrome/renderer/url_loader_throttle_provider_impl.cc +++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -245,10 +245,10 @@ throttles.push_back(std::make_unique<GoogleURLLoaderThrottle>( ChromeRenderThreadObserver::is_incognito_process(), - ChromeRenderThreadObserver::is_signed_in(), ChromeRenderThreadObserver::force_safe_search(), ChromeRenderThreadObserver::youtube_restrict(), - ChromeRenderThreadObserver::allowed_domains_for_apps())); + ChromeRenderThreadObserver::allowed_domains_for_apps(), + ChromeRenderThreadObserver::variation_ids_header())); return throttles; }
diff --git a/chrome/services/isolated_xr_device/BUILD.gn b/chrome/services/isolated_xr_device/BUILD.gn new file mode 100644 index 0000000..e371a3f --- /dev/null +++ b/chrome/services/isolated_xr_device/BUILD.gn
@@ -0,0 +1,28 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//services/service_manager/public/cpp/service.gni") +import("//services/service_manager/public/service_manifest.gni") + +source_set("lib") { + sources = [ + "xr_device_service.cc", + "xr_device_service.h", + "xr_runtime_provider.cc", + "xr_runtime_provider.h", + ] + + deps = [ + "//base", + "//device/vr:vr", + "//device/vr/public/mojom", + "//services/service_manager/public/cpp", + "//services/service_manager/public/mojom", + ] +} + +service_manifest("manifest") { + name = "xr_device_service" + source = "manifest.json" +}
diff --git a/chrome/services/isolated_xr_device/DEPS b/chrome/services/isolated_xr_device/DEPS new file mode 100644 index 0000000..a210e73d --- /dev/null +++ b/chrome/services/isolated_xr_device/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+device/vr", + "+mojo/public", + "+services/service_manager/public" +] \ No newline at end of file
diff --git a/chrome/services/isolated_xr_device/OWNERS b/chrome/services/isolated_xr_device/OWNERS new file mode 100644 index 0000000..b19eacaf --- /dev/null +++ b/chrome/services/isolated_xr_device/OWNERS
@@ -0,0 +1,6 @@ +billorr@chromium.org +mthiesse@chromium.org +ddorwin@chromium.org + +per-file manifest.json=set noparent +per-file manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/chrome/services/isolated_xr_device/manifest.json b/chrome/services/isolated_xr_device/manifest.json new file mode 100644 index 0000000..5346733 --- /dev/null +++ b/chrome/services/isolated_xr_device/manifest.json
@@ -0,0 +1,14 @@ +{ + "name": "xr_device_service", + "display_name": "XR Isolated Device Service", + "sandbox_type": "none", + "interface_provider_specs": { + "service_manager:connector": { + "provides": { + "xr_device_provider": [ "device.mojom.IsolatedXRRuntimeProvider" ] + }, + "requires": { + } + } + } +} \ No newline at end of file
diff --git a/chrome/services/isolated_xr_device/xr_device_service.cc b/chrome/services/isolated_xr_device/xr_device_service.cc new file mode 100644 index 0000000..45e9138 --- /dev/null +++ b/chrome/services/isolated_xr_device/xr_device_service.cc
@@ -0,0 +1,46 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/services/isolated_xr_device/xr_device_service.h" + +#include "base/bind.h" +#include "chrome/services/isolated_xr_device/xr_runtime_provider.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "services/service_manager/public/cpp/service_context.h" + +namespace device { + +std::unique_ptr<service_manager::Service> +XrDeviceService::CreateXrDeviceService() { + return std::make_unique<XrDeviceService>(); +} + +void XrDeviceService::OnDeviceProviderRequest( + device::mojom::IsolatedXRRuntimeProviderRequest request) { + mojo::MakeStrongBinding( + std::make_unique<IsolatedXRRuntimeProvider>(ref_factory_->CreateRef()), + std::move(request)); +} + +XrDeviceService::XrDeviceService() { + // Register device provider here. + registry_.AddInterface(base::BindRepeating( + &XrDeviceService::OnDeviceProviderRequest, base::Unretained(this))); +} + +XrDeviceService::~XrDeviceService() {} + +void XrDeviceService::OnStart() { + ref_factory_ = std::make_unique<service_manager::ServiceContextRefFactory>( + context()->CreateQuitClosure()); +} + +void XrDeviceService::OnBindInterface( + const service_manager::BindSourceInfo& source_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + registry_.BindInterface(interface_name, std::move(interface_pipe)); +} + +} // namespace device
diff --git a/chrome/services/isolated_xr_device/xr_device_service.h b/chrome/services/isolated_xr_device/xr_device_service.h new file mode 100644 index 0000000..fe8cb8ab --- /dev/null +++ b/chrome/services/isolated_xr_device/xr_device_service.h
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_DEVICE_SERVICE_H_ +#define CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_DEVICE_SERVICE_H_ + +#include "device/vr/public/mojom/isolated_xr_service.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/cpp/service_context.h" +#include "services/service_manager/public/cpp/service_context_ref.h" + +namespace device { + +class XrDeviceService : public service_manager::Service { + public: + static std::unique_ptr<service_manager::Service> CreateXrDeviceService(); + + XrDeviceService(); + ~XrDeviceService() override; + void OnDeviceProviderRequest( + device::mojom::IsolatedXRRuntimeProviderRequest request); + + private: + // service_manager::Service + void OnStart() override; + void OnBindInterface(const service_manager::BindSourceInfo& source_info, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override; + + service_manager::BinderRegistry registry_; + + std::unique_ptr<service_manager::ServiceContextRefFactory> ref_factory_; + + DISALLOW_COPY_AND_ASSIGN(XrDeviceService); +}; + +} // namespace device + +#endif // CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_DEVICE_SERVICE_H_
diff --git a/chrome/services/isolated_xr_device/xr_runtime_provider.cc b/chrome/services/isolated_xr_device/xr_runtime_provider.cc new file mode 100644 index 0000000..0298898e --- /dev/null +++ b/chrome/services/isolated_xr_device/xr_runtime_provider.cc
@@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/services/isolated_xr_device/xr_runtime_provider.h" +#include "chrome/common/chrome_features.h" +#include "device/vr/buildflags/buildflags.h" + +#if BUILDFLAG(ENABLE_OPENVR) +#include "device/vr/openvr/openvr_device.h" +#endif + +#if BUILDFLAG(ENABLE_OCULUS_VR) +#include "device/vr/oculus/oculus_device.h" +#endif + +void IsolatedXRRuntimeProvider::RequestDevices( + device::mojom::IsolatedXRRuntimeProviderClientPtr client) { +#if BUILDFLAG(ENABLE_OCULUS_VR) + if (base::FeatureList::IsEnabled(features::kOculusVR)) { + oculus_device_ = std::make_unique<device::OculusDevice>(); + if (!oculus_device_->IsInitialized()) { + oculus_device_ = nullptr; + } else { + client->OnDeviceAdded(oculus_device_->BindXRRuntimePtr(), + oculus_device_->BindGamepadFactory(), + oculus_device_->GetVRDisplayInfo()); + } + } +#endif + +#if BUILDFLAG(ENABLE_OPENVR) + if (base::FeatureList::IsEnabled(features::kOpenVR)) { + openvr_device_ = std::make_unique<device::OpenVRDevice>(); + if (!openvr_device_->IsInitialized()) { + openvr_device_ = nullptr; + } else { + client->OnDeviceAdded(openvr_device_->BindXRRuntimePtr(), + openvr_device_->BindGamepadFactory(), + openvr_device_->GetVRDisplayInfo()); + } + } +#endif + + client->OnDevicesEnumerated(); + client_ = std::move(client); +} + +IsolatedXRRuntimeProvider::IsolatedXRRuntimeProvider( + std::unique_ptr<service_manager::ServiceContextRef> service_ref) + : service_ref_(std::move(service_ref)) {} + +IsolatedXRRuntimeProvider::~IsolatedXRRuntimeProvider() {}
diff --git a/chrome/services/isolated_xr_device/xr_runtime_provider.h b/chrome/services/isolated_xr_device/xr_runtime_provider.h new file mode 100644 index 0000000..a68f3bd --- /dev/null +++ b/chrome/services/isolated_xr_device/xr_runtime_provider.h
@@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_RUNTIME_PROVIDER_H_ +#define CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_RUNTIME_PROVIDER_H_ + +#include "device/vr/public/mojom/isolated_xr_service.mojom.h" +#include "services/service_manager/public/cpp/service_context.h" +#include "services/service_manager/public/cpp/service_context_ref.h" + +namespace device { +class OculusDevice; +class OpenVRDevice; +} // namespace device + +class IsolatedXRRuntimeProvider + : public device::mojom::IsolatedXRRuntimeProvider { + public: + IsolatedXRRuntimeProvider( + std::unique_ptr<service_manager::ServiceContextRef> service_ref); + ~IsolatedXRRuntimeProvider() final; + + void RequestDevices( + device::mojom::IsolatedXRRuntimeProviderClientPtr client) override; + + private: + const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; + + IsolatedXRRuntimeProvider(); + + std::unique_ptr<device::OculusDevice> oculus_device_; + std::unique_ptr<device::OpenVRDevice> openvr_device_; + + device::mojom::IsolatedXRRuntimeProviderClientPtr client_; +}; + +#endif // CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_RUNTIME_PROVIDER_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 95a5226..34ab935 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -205,10 +205,6 @@ "base/test_browser_window.cc", "base/test_browser_window.h", ] - if (enable_vr) { - # Add a dummy implementation of RegisterJni to satisfy the linker. - sources += [ "../browser/android/vr/register_jni_monochrome.cc" ] - } } else { public_deps += [ "//components/ukm:test_support", @@ -1091,7 +1087,7 @@ "//third_party/mocha/mocha.js", "//third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/simplejson/", "//third_party/tlslite/", "//ui/webui/resources/js/", @@ -1840,6 +1836,7 @@ "//ui/login:resources", "//url", ] + data_deps += [ "//ui/file_manager:unit_test_data" ] if (use_dbus) { deps += [ "//dbus:test_support" ] } @@ -2818,7 +2815,7 @@ "//third_party/accessibility-audit/axs_testing.js", "//third_party/chaijs/chai.js", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", "//third_party/zlib/google/test/data/", "//tools/metrics/histograms/enums.xml", @@ -4837,7 +4834,7 @@ "//third_party/mocha/mocha.js", "//third_party/polymer/v1_0/components-chromium/iron-test-helpers/mock-interactions.js", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", "//third_party/zlib/google/test/data/", "//tools/metrics/histograms/enums.xml", @@ -5499,9 +5496,8 @@ "//net/tools/testserver/", "//components/sync/tools/testserver/", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", - "$root_out_dir/pyproto/", "//testing/xvfb.py", ] @@ -5530,6 +5526,7 @@ "//chrome/common", "//chrome/renderer", "//components/sync", + "//components/sync/protocol:chromiumsync_pyproto", "//crypto:platform", "//testing/gmock", "//testing/gtest",
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc index b4e8d51..df8efa88 100644 --- a/chrome/test/base/testing_browser_process.cc +++ b/chrome/test/base/testing_browser_process.cc
@@ -26,12 +26,13 @@ #include "components/policy/core/browser/browser_policy_connector.h" #include "components/prefs/pref_service.h" #include "components/subresource_filter/content/browser/content_ruleset_service.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/notification_service.h" #include "extensions/buildflags/buildflags.h" #include "media/media_buildflags.h" #include "net/url_request/url_request_context_getter.h" #include "printing/buildflags/buildflags.h" -#include "services/network/public/cpp/network_connection_tracker.h" +#include "services/network/test/test_network_connection_tracker.h" #include "testing/gtest/include/gtest/gtest.h" #if BUILDFLAG(ENABLE_BACKGROUND_MODE) @@ -57,25 +58,6 @@ #include "components/keep_alive_registry/keep_alive_registry.h" #endif -namespace { - -class MockNetworkConnectionTracker : public network::NetworkConnectionTracker { - public: - MockNetworkConnectionTracker() : network::NetworkConnectionTracker() {} - ~MockNetworkConnectionTracker() override {} - - bool GetConnectionType(network::mojom::ConnectionType* type, - ConnectionTypeCallback callback) override { - *type = network::mojom::ConnectionType::CONNECTION_UNKNOWN; - return true; - } - - private: - DISALLOW_COPY_AND_ASSIGN(MockNetworkConnectionTracker); -}; - -} // namespace - // static TestingBrowserProcess* TestingBrowserProcess::GetGlobal() { return static_cast<TestingBrowserProcess*>(g_browser_process); @@ -103,7 +85,14 @@ io_thread_(nullptr), system_request_context_(nullptr), rappor_service_(nullptr), - platform_part_(new TestingBrowserProcessPlatformPart()) { + platform_part_(new TestingBrowserProcessPlatformPart()), + test_network_connection_tracker_( + new network::TestNetworkConnectionTracker( + true /* respond_synchronously */, + network::mojom::ConnectionType::CONNECTION_UNKNOWN)) { + content::SetNetworkConnectionTrackerForTesting( + test_network_connection_tracker_.get()); + #if BUILDFLAG(ENABLE_EXTENSIONS) extensions_browser_client_.reset( new extensions::ChromeExtensionsBrowserClient); @@ -131,6 +120,8 @@ tab_manager_.reset(); #endif + content::SetNetworkConnectionTrackerForTesting(nullptr); + // Destructors for some objects owned by TestingBrowserProcess will use // g_browser_process if it is not null, so it must be null before proceeding. DCHECK_EQ(static_cast<BrowserProcess*>(nullptr), g_browser_process); @@ -176,15 +167,6 @@ return shared_url_loader_factory_; } -network::NetworkConnectionTracker* -TestingBrowserProcess::network_connection_tracker() { - if (!network_connection_tracker_) { - network_connection_tracker_ = - std::make_unique<MockNetworkConnectionTracker>(); - } - return network_connection_tracker_.get(); -} - network::NetworkQualityTracker* TestingBrowserProcess::network_quality_tracker() { return nullptr; @@ -470,11 +452,6 @@ shared_url_loader_factory_ = shared_url_loader_factory; } -void TestingBrowserProcess::SetNetworkConnectionTracker( - std::unique_ptr<network::NetworkConnectionTracker> tracker) { - network_connection_tracker_ = std::move(tracker); -} - void TestingBrowserProcess::SetNotificationUIManager( std::unique_ptr<NotificationUIManager> notification_ui_manager) { notification_ui_manager_.swap(notification_ui_manager);
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h index c79a43e3..b0e50a8 100644 --- a/chrome/test/base/testing_browser_process.h +++ b/chrome/test/base/testing_browser_process.h
@@ -43,6 +43,10 @@ class GCMDriver; } +namespace network { +class TestNetworkConnectionTracker; +} + namespace policy { class PolicyService; } @@ -74,7 +78,6 @@ SystemNetworkContextManager* system_network_context_manager() override; scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory() override; - network::NetworkConnectionTracker* network_connection_tracker() override; network::NetworkQualityTracker* network_quality_tracker() override; WatchDogThread* watchdog_thread() override; ProfileManager* profile_manager() override; @@ -149,8 +152,6 @@ void SetSystemRequestContext(net::URLRequestContextGetter* context_getter); void SetSharedURLLoaderFactory( scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory); - void SetNetworkConnectionTracker( - std::unique_ptr<network::NetworkConnectionTracker> tracker); void SetNotificationUIManager( std::unique_ptr<NotificationUIManager> notification_ui_manager); void SetNotificationPlatformBridge( @@ -171,8 +172,6 @@ std::unique_ptr<policy::ChromeBrowserPolicyConnector> browser_policy_connector_; bool created_browser_policy_connector_ = false; - std::unique_ptr<network::NetworkConnectionTracker> - network_connection_tracker_; std::unique_ptr<ProfileManager> profile_manager_; std::unique_ptr<NotificationUIManager> notification_ui_manager_; std::unique_ptr<NotificationPlatformBridge> notification_platform_bridge_; @@ -212,6 +211,8 @@ rappor::RapporServiceImpl* rappor_service_; std::unique_ptr<BrowserProcessPlatformPart> platform_part_; + std::unique_ptr<network::TestNetworkConnectionTracker> + test_network_connection_tracker_; #if BUILDFLAG(ENABLE_EXTENSIONS) std::unique_ptr<MediaFileSystemRegistry> media_file_system_registry_;
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py index 4fbbc67..7fa5ead13d 100644 --- a/chrome/test/chromedriver/client/chromedriver.py +++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -356,9 +356,8 @@ return self.ExecuteCommand( Command.FIND_ELEMENTS, {'using': strategy, 'value': target}) - def SetTimeout(self, type, timeout): - return self.ExecuteCommand( - Command.SET_TIMEOUT, {'type' : type, 'ms': timeout}) + def SetTimeouts(self, params): + return self.ExecuteCommand(Command.SET_TIMEOUTS, params) def GetCurrentUrl(self): return self.ExecuteCommand(Command.GET_CURRENT_URL)
diff --git a/chrome/test/chromedriver/client/command_executor.py b/chrome/test/chromedriver/client/command_executor.py index f7ed3c1..ac1d0a9d 100644 --- a/chrome/test/chromedriver/client/command_executor.py +++ b/chrome/test/chromedriver/client/command_executor.py
@@ -101,7 +101,7 @@ _Method.POST, '/session/:sessionId/timeouts/implicit_wait') SET_SCRIPT_TIMEOUT = ( _Method.POST, '/session/:sessionId/timeouts/async_script') - SET_TIMEOUT = (_Method.POST, '/session/:sessionId/timeouts') + SET_TIMEOUTS = (_Method.POST, '/session/:sessionId/timeouts') GET_TIMEOUTS = (_Method.GET, '/session/:sessionId/timeouts') EXECUTE_SQL = (_Method.POST, '/session/:sessionId/execute_sql') GET_LOCATION = (_Method.GET, '/session/:sessionId/location')
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc index 9593115..0332454 100644 --- a/chrome/test/chromedriver/server/http_handler.cc +++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -100,7 +100,7 @@ WrapToCommand("GetTimeouts", base::Bind(&ExecuteGetTimeouts))), CommandMapping( kPost, "session/:sessionId/timeouts", - WrapToCommand("SetTimeout", base::Bind(&ExecuteSetTimeout))), + WrapToCommand("SetTimeouts", base::Bind(&ExecuteSetTimeouts))), CommandMapping(kPost, "session/:sessionId/url", WrapToCommand("Navigate", base::Bind(&ExecuteGet))), CommandMapping(
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc index 357517e..06858a6 100644 --- a/chrome/test/chromedriver/session_commands.cc +++ b/chrome/test/chromedriver/session_commands.cc
@@ -542,9 +542,11 @@ return Status(kOk); } -Status ExecuteSetTimeout(Session* session, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value) { +// Handles legacy format SetTimeout command. +// TODO(johnchen@chromium.org): Remove when we stop supporting legacy protocol. +Status ExecuteSetTimeoutLegacy(Session* session, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value) { double ms_double; if (!params.GetDouble("ms", &ms_double)) return Status(kUnknownError, "'ms' must be a double"); @@ -554,8 +556,6 @@ base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(static_cast<int>(ms_double)); - // TODO(frankf): implicit and script timeout should be cleared - // if negative timeout is specified. if (type == "implicit") { session->implicit_wait = timeout; } else if (type == "script") { @@ -570,6 +570,41 @@ return Status(kOk); } +Status ExecuteSetTimeoutsW3C(Session* session, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value) { + for (const auto& setting : params.DictItems()) { + int timeout_ms; + if (!setting.second.GetAsInteger(&timeout_ms) || timeout_ms < 0) + return Status(kInvalidArgument, "value must be a non-negative integer"); + base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(timeout_ms); + const std::string& type = setting.first; + if (type == "script") { + session->script_timeout = timeout; + } else if (type == "pageLoad") { + session->page_load_timeout = timeout; + } else if (type == "implicit") { + session->implicit_wait = timeout; + } else { + return Status(kInvalidArgument, "unknown type of timeout: " + type); + } + } + return Status(kOk); +} + +Status ExecuteSetTimeouts(Session* session, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value) { + // TODO(johnchen@chromium.org): Remove legacy version support when we stop + // supporting non-W3C protocol. At that time, we can delete the legacy + // function and merge the W3C function into this function. + if (params.HasKey("ms")) { + return ExecuteSetTimeoutLegacy(session, params, value); + } else { + return ExecuteSetTimeoutsW3C(session, params, value); + } +} + Status ExecuteGetTimeouts(Session* session, const base::DictionaryValue& params, std::unique_ptr<base::Value>* value) {
diff --git a/chrome/test/chromedriver/session_commands.h b/chrome/test/chromedriver/session_commands.h index 5a57c63..550d42e 100644 --- a/chrome/test/chromedriver/session_commands.h +++ b/chrome/test/chromedriver/session_commands.h
@@ -80,9 +80,9 @@ // Configure the amount of time that a particular type of operation can execute // for before they are aborted and a timeout error is returned to the client. -Status ExecuteSetTimeout(Session* session, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value); +Status ExecuteSetTimeouts(Session* session, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value); // Get the implicit, script and page load timeouts in milliseconds. Status ExecuteGetTimeouts(Session* session,
diff --git a/chrome/test/chromedriver/session_commands_unittest.cc b/chrome/test/chromedriver/session_commands_unittest.cc index 313d582..94351d7 100644 --- a/chrome/test/chromedriver/session_commands_unittest.cc +++ b/chrome/test/chromedriver/session_commands_unittest.cc
@@ -41,6 +41,41 @@ ASSERT_EQ(implicit, 0); } +TEST(SessionCommandsTest, ExecuteSetTimeouts) { + Session session("id"); + base::DictionaryValue params; + std::unique_ptr<base::Value> value; + + // W3C spec doesn't forbid passing in an empty object, so we should get kOk. + Status status = ExecuteSetTimeouts(&session, params, &value); + ASSERT_EQ(kOk, status.code()); + + params.SetInteger("pageLoad", 5000); + status = ExecuteSetTimeouts(&session, params, &value); + ASSERT_EQ(kOk, status.code()); + + params.SetInteger("script", 5000); + params.SetInteger("implicit", 5000); + status = ExecuteSetTimeouts(&session, params, &value); + ASSERT_EQ(kOk, status.code()); + + params.SetInteger("implicit", -5000); + status = ExecuteSetTimeouts(&session, params, &value); + ASSERT_EQ(kInvalidArgument, status.code()); + + params.Clear(); + params.SetInteger("unknown", 5000); + status = ExecuteSetTimeouts(&session, params, &value); + ASSERT_EQ(kInvalidArgument, status.code()); + + // Old pre-W3C format. + params.Clear(); + params.SetDouble("ms", 5000.0); + params.SetString("type", "page load"); + status = ExecuteSetTimeouts(&session, params, &value); + ASSERT_EQ(kOk, status.code()); +} + TEST(SessionCommandsTest, MergeCapabilities) { base::DictionaryValue primary; primary.SetString("strawberry", "velociraptor");
diff --git a/chrome/test/chromedriver/test/run_java_tests.py b/chrome/test/chromedriver/test/run_java_tests.py index 778a8d9..04a0ee73 100755 --- a/chrome/test/chromedriver/test/run_java_tests.py +++ b/chrome/test/chromedriver/test/run_java_tests.py
@@ -133,19 +133,13 @@ jvm_args += ['-agentlib:jdwp=transport=%s,server=y,suspend=y,' 'address=33081' % transport] - return _RunAntTest(java_tests_src_dir, test_filter, chromedriver_path, - chrome_path, log_path, android_package_key, - jvm_args, verbose, debug, sys_props) + return _RunAntTest(java_tests_src_dir, jvm_args, verbose, sys_props) -def _RunAntTest(java_tests_src_dir, test_filter, chromedriver_path, - chrome_path, log_path, android_package_key, - jvm_args, verbose, debug, sys_props): +def _RunAntTest(java_tests_src_dir, jvm_args, verbose, sys_props): """Runs a single Ant JUnit test suite and returns the |TestResult|s. Args: - test_dir: the directory to run the tests in. - test_class: the name of the JUnit test suite class to run. - class_path: the Java class path used when running the tests, colon delimited + java_tests_src_dir: the directory to run the tests in. sys_props: Java system properties to set when running the tests. jvm_args: Java VM command line args to use. verbose: whether the output should be verbose.
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 96be822..7812cc1c 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -485,7 +485,7 @@ self._driver.ExecuteScript, '{{{') def testExecuteAsyncScript(self): - self._driver.SetTimeout('script', 3000) + self._driver.SetTimeouts({'script': 3000}) self.assertRaises( chromedriver.ScriptTimeout, self._driver.ExecuteAsyncScript, @@ -1699,7 +1699,7 @@ # This test is unreliable on Windows, as FindElement can be called too # soon, before the child frame is fully loaded. This causes element not # found error. Add an implicit wait works around this issue. - self._driver.SetTimeout('implicit', 2000) + self._driver.SetTimeouts({'implicit': 2000}) self._driver.Load(self.GetHttpUrlForFile( '/chromedriver/cross_domain_iframe.html')) a_outer = self._driver.FindElement('tag name', 'a') @@ -1741,7 +1741,7 @@ # about 0.1 second on Linux and Windows, but takes half a second or longer # on Mac. So we use longer timeout on Mac, 0.5 second on others. timeout = 3000 if util.GetPlatformName() == 'mac' else 500 - self._driver.SetTimeout('page load', timeout) + self._driver.SetTimeouts({'pageLoad': timeout}) def tearDown(self): super(ChromeDriverPageLoadTimeoutTest, self).tearDown()
diff --git a/chrome/test/data/media/picture-in-picture/player_preload_none.html b/chrome/test/data/media/picture-in-picture/player_preload_none.html new file mode 100644 index 0000000..55c4002 --- /dev/null +++ b/chrome/test/data/media/picture-in-picture/player_preload_none.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<video preload=none poster='../../banners/image-512px.png'> + <source src='../bigbuck.webm' type='video/webm'> +</video> +<script> + const video = document.querySelector('video'); + + function play() { + video.play().then(() => { + window.domAutomationController.send(true); + }); + } + + function enterPictureInPicture() { + video.requestPictureInPicture().then(() => { + window.domAutomationController.send(true); + }); + } + + function changeSrcAndLoad() { + video.addEventListener('loadedmetadata', () => { + window.domAutomationController.send(true); + }, { once: true }); + + document.querySelector('source').src = '../bear-640x360-av-enc_av.webm'; + video.load(); + } + + function isInPictureInPicture() { + window.domAutomationController.send(document.pictureInPictureElement == video); + } +</script>
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 06e274ce..5ce9be6 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -1960,6 +1960,29 @@ }); /** + * Test fixture for the multidevice settings subpage. + * @constructor + * @extends {CrSettingsBrowserTest} + */ +function CrSettingsMultideviceSubpageTest() {} + +CrSettingsMultideviceSubpageTest.prototype = { + __proto__: CrSettingsBrowserTest.prototype, + + /** @override */ + browsePreload: 'chrome://settings/multidevice_page/multidevice_subpage.html', + + /** @override */ + extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ + 'multidevice_subpage_tests.js', + ]), +}; + +TEST_F('CrSettingsMultideviceSubpageTest', 'All', function() { + mocha.run(); +}); + +/** * Test fixture for the Linux for Chromebook (Crostini) page. * @constructor * @extends {CrSettingsBrowserTest}
diff --git a/chrome/test/data/webui/settings/multidevice_subpage_tests.js b/chrome/test/data/webui/settings/multidevice_subpage_tests.js new file mode 100644 index 0000000..31ef914 --- /dev/null +++ b/chrome/test/data/webui/settings/multidevice_subpage_tests.js
@@ -0,0 +1,77 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +suite('Multidevice', function() { + let multideviceSubpage = null; + // Although HOST_SET_MODES is effectively a constant, it cannot reference the + // enum settings.MultiDeviceSettingsMode from here so its initialization is + // deferred to the suiteSetup function. + let HOST_SET_MODES; + const HOST_DEVICE = { + name: 'Pixel XL', + }; + + function setPageContentData(newMode) { + multideviceSubpage.pageContentData = { + mode: newMode, + hostDevice: HOST_DEVICE, + }; + Polymer.dom.flush(); + } + + suiteSetup(function() { + HOST_SET_MODES = [ + settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, + settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, + settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, + ]; + }); + + setup(function() { + multideviceSubpage = document.createElement('settings-multidevice-subpage'); + + setPageContentData(settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED); + multideviceSubpage.prefs = { + multidevice: {sms_connect_enabled: {value: true}}, + multidevice_setup: {suite_enabled: {value: true}}, + }; + + document.body.appendChild(multideviceSubpage); + Polymer.dom.flush(); + }); + + teardown(function() { + multideviceSubpage.remove(); + }); + + test('individual features appear only if host is verified', function() { + for (const mode of HOST_SET_MODES) { + setPageContentData(mode); + assertEquals( + !!multideviceSubpage.$$('settings-multidevice-feature-item'), + mode == settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED); + } + }); + + test('clicking EasyUnlock item routes to screen lock page', function() { + multideviceSubpage.$$('#smart-lock-item').$.card.click(); + assertEquals(settings.getCurrentRoute(), settings.routes.LOCK_SCREEN); + }); + + test('AndroidMessages item shows correct input control', function() { + const inputControl = multideviceSubpage.$$('[slot=feature-controller]'); + + multideviceSubpage.androidMessagesRequiresSetup_ = true; + Polymer.dom.flush(); + assertTrue(!!inputControl.querySelector('paper-button')); + assertFalse( + !!inputControl.querySelector('settings-multidevice-feature-toggle')); + + multideviceSubpage.androidMessagesRequiresSetup_ = false; + Polymer.dom.flush(); + assertFalse(!!inputControl.querySelector('paper-button')); + assertTrue( + !!inputControl.querySelector('settings-multidevice-feature-toggle')); + }); +});
diff --git a/chrome/test/data/workers/fetch_from_service_worker.html b/chrome/test/data/workers/fetch_from_service_worker.html new file mode 100644 index 0000000..4dbb1d8 --- /dev/null +++ b/chrome/test/data/workers/fetch_from_service_worker.html
@@ -0,0 +1,32 @@ +<script> +let registration = null; + +self.onload = async () => { + registration = await navigator.serviceWorker.register( + 'fetch_from_service_worker.js'); + if (!registration) { + document.body.innerText = 'Registration failed'; + document.title = 'DONE'; + return; + } + registration = await navigator.serviceWorker.ready; + document.body.innerText = 'ready'; + document.title = 'DONE'; +} + +function fetch_from_service_worker(url) { + document.title = 'Fetching'; + document.innerText = ''; + if (!registration) { + document.innerText = 'Registration failed'; + document.title = 'DONE'; + return; + } + const channel = new MessageChannel(); + channel.port1.onmessage = e => { + document.body.innerText = e.data; + document.title = 'DONE'; + }; + registration.active.postMessage({url: url}, [channel.port2]); +} +</script>
diff --git a/chrome/test/data/workers/fetch_from_service_worker.js b/chrome/test/data/workers/fetch_from_service_worker.js new file mode 100644 index 0000000..eb789b3 --- /dev/null +++ b/chrome/test/data/workers/fetch_from_service_worker.js
@@ -0,0 +1,18 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +async function MessageHandler(e) { + const port = e.ports[0]; + const response = await fetch(e.data.url); + if (!response.ok) { + port.postMessage('bad response'); + return; + } + const text = await response.text(); + port.postMessage(text); +} + +self.addEventListener('message', e => { + e.waitUntil(MessageHandler(e)); +});
diff --git a/chrome/test/data/workers/fetch_from_shared_worker.html b/chrome/test/data/workers/fetch_from_shared_worker.html new file mode 100644 index 0000000..c7786eb2 --- /dev/null +++ b/chrome/test/data/workers/fetch_from_shared_worker.html
@@ -0,0 +1,14 @@ +<script> +const worker = new SharedWorker('fetch_from_shared_worker.js'); +worker.port.onmessage = e => { + document.body.innerText += e.data; + document.title = 'DONE'; +}; +worker.port.start(); + +function fetch_from_shared_worker(url) { + document.title = 'Fetching'; + document.body.innerText = ''; + worker.port.postMessage({url: url}); +} +</script>
diff --git a/chrome/test/data/workers/fetch_from_shared_worker.js b/chrome/test/data/workers/fetch_from_shared_worker.js new file mode 100644 index 0000000..1aa389e3 --- /dev/null +++ b/chrome/test/data/workers/fetch_from_shared_worker.js
@@ -0,0 +1,16 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +self.onconnect = e => { + const port = e.ports[0]; + port.onmessage = async e => { + const response = await fetch(e.data.url); + if (!response.ok) { + port.postMessage(`Bad response: ${responses.statusText}`); + return; + } + const text = await response.text(); + port.postMessage(text); + } +};
diff --git a/chrome/test/data/workers/fetch_from_worker.html b/chrome/test/data/workers/fetch_from_worker.html new file mode 100644 index 0000000..661d2d1 --- /dev/null +++ b/chrome/test/data/workers/fetch_from_worker.html
@@ -0,0 +1,13 @@ +<script> +const worker = new Worker('fetch_from_worker.js'); +worker.onmessage = e => { + document.body.innerText += e.data; + document.title = 'DONE'; +}; + +function fetch_from_worker(url) { + document.title = 'Fetching'; + document.body.innerText = ''; + worker.postMessage({url: url}); +} +</script>
diff --git a/chrome/test/data/workers/fetch_from_worker.js b/chrome/test/data/workers/fetch_from_worker.js new file mode 100644 index 0000000..998025f3 --- /dev/null +++ b/chrome/test/data/workers/fetch_from_worker.js
@@ -0,0 +1,13 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +self.onmessage = async e => { + const response = await fetch(e.data.url); + if (!response.ok) { + self.postMessage('bad response'); + return; + } + const text = await response.text(); + self.postMessage(text); +};
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn index 20b78f06..8ce1785 100644 --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/features.gni") import("//build/config/sysroot.gni") import("//chrome/common/features.gni") +import("//device/vr/buildflags/buildflags.gni") import("//extensions/buildflags/buildflags.gni") import("//printing/buildflags/buildflags.gni") import("//services/service_manager/public/service_manifest.gni") @@ -38,6 +39,7 @@ "//content/public/child", "//content/public/common", "//content/public/utility", + "//device/vr/buildflags", "//extensions/buildflags", "//ipc", "//media", @@ -204,6 +206,13 @@ deps += [ "//chrome/services/media_gallery_util:lib" ] } + if (enable_isolated_xr_service) { + deps += [ + "//chrome/services/isolated_xr_device:lib", + "//device/vr/public/mojom", + ] + } + if (enable_simple_browser_service) { deps += [ "//services/content/simple_browser",
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS index 92d397d..7ce7d8d 100644 --- a/chrome/utility/DEPS +++ b/chrome/utility/DEPS
@@ -5,6 +5,7 @@ "+chrome/services/cups_ipp_validator/public/mojom", "+chrome/services/file_util/file_util_service.h", "+chrome/services/file_util/public/mojom", + "+chrome/services/isolated_xr_device", "+chrome/services/media_gallery_util/media_gallery_util_service.h", "+chrome/services/media_gallery_util/public/mojom", # TODO(crbug.com/798782): remove dependency to pdf_to_emf_converter_factory.h @@ -29,6 +30,8 @@ "+components/wifi", "+content/public/child", "+content/public/utility", + "+device/vr/buildflags", + "+device/vr/public", "+extensions/common", "+extensions/buildflags", "+media",
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc index b97904e3..6a7b621 100644 --- a/chrome/utility/chrome_content_utility_client.cc +++ b/chrome/utility/chrome_content_utility_client.cc
@@ -22,6 +22,7 @@ #include "content/public/common/service_manager_connection.h" #include "content/public/common/simple_connection_filter.h" #include "content/public/utility/utility_thread.h" +#include "device/vr/buildflags/buildflags.h" #include "extensions/buildflags/buildflags.h" #include "services/service_manager/embedder/embedded_service_info.h" #include "services/service_manager/public/cpp/binder_registry.h" @@ -43,6 +44,10 @@ #include "chrome/services/util_win/util_win_service.h" #endif +#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) +#include "chrome/services/isolated_xr_device/xr_device_service.h" +#endif + #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/services/removable_storage_writer/public/mojom/constants.mojom.h" #include "chrome/services/removable_storage_writer/removable_storage_writer_service.h" @@ -185,6 +190,13 @@ return; } +#if BUILDFLAG(ENABLE_ISOLATED_XR_SERVICE) + service_manager::EmbeddedServiceInfo service_info; + service_info.factory = + base::BindRepeating(&device::XrDeviceService::CreateXrDeviceService); + services->emplace(device::mojom::kVrIsolatedServiceName, service_info); +#endif + #if BUILDFLAG(ENABLE_PRINTING) service_manager::EmbeddedServiceInfo pdf_compositor_info; pdf_compositor_info.factory = base::BindRepeating(
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc index 9457f12..8b574e9f 100644 --- a/chromecast/browser/cast_browser_main_parts.cc +++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -64,6 +64,7 @@ #include "gpu/command_buffer/service/gpu_switches.h" #include "media/base/media.h" #include "media/base/media_switches.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "ui/base/ui_base_switches.h" #include "ui/compositor/compositor_switches.h" #include "ui/gl/gl_switches.h" @@ -508,7 +509,7 @@ cast_browser_process_->pref_service(), content::BrowserContext::GetDefaultStoragePartition( cast_browser_process_->browser_context()) - ->GetURLRequestContext())); + ->GetURLLoaderFactoryForBrowserProcess())); cast_browser_process_->SetRemoteDebuggingServer( std::make_unique<RemoteDebuggingServer>( cast_browser_process_->browser_client()
diff --git a/chromecast/browser/cast_permission_manager.cc b/chromecast/browser/cast_permission_manager.cc index bb878a2d..3e61650 100644 --- a/chromecast/browser/cast_permission_manager.cc +++ b/chromecast/browser/cast_permission_manager.cc
@@ -65,8 +65,8 @@ int CastPermissionManager::SubscribePermissionStatusChange( content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { return content::PermissionController::kNoPendingOperation; }
diff --git a/chromecast/browser/cast_permission_manager.h b/chromecast/browser/cast_permission_manager.h index 82809fc..585f998 100644 --- a/chromecast/browser/cast_permission_manager.h +++ b/chromecast/browser/cast_permission_manager.h
@@ -46,8 +46,8 @@ const GURL& requesting_origin) override; int SubscribePermissionStatusChange( content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void UnsubscribePermissionStatusChange(int subscription_id) override;
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.cc b/chromecast/browser/metrics/cast_metrics_service_client.cc index a27d880f..b58217a 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.cc +++ b/chromecast/browser/metrics/cast_metrics_service_client.cc
@@ -36,6 +36,7 @@ #include "components/prefs/pref_service.h" #include "content/public/browser/histogram_fetcher.h" #include "content/public/common/content_switches.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #if defined(OS_LINUX) #include "chromecast/browser/metrics/external_metrics.h" @@ -243,7 +244,7 @@ ::metrics::MetricsLogUploader::MetricServiceType service_type, const ::metrics::MetricsLogUploader::UploadCallback& on_upload_complete) { return std::unique_ptr<::metrics::MetricsLogUploader>( - new ::metrics::NetMetricsLogUploader(request_context_, server_url, + new ::metrics::NetMetricsLogUploader(url_loader_factory_, server_url, insecure_server_url, mime_type, service_type, on_upload_complete)); } @@ -274,7 +275,7 @@ CastMetricsServiceClient::CastMetricsServiceClient( PrefService* pref_service, - net::URLRequestContextGetter* request_context) + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : pref_service_(pref_service), client_info_loaded_(false), #if defined(OS_LINUX) @@ -282,7 +283,7 @@ platform_metrics_(nullptr), #endif // defined(OS_LINUX) task_runner_(base::ThreadTaskRunnerHandle::Get()), - request_context_(request_context) { + url_loader_factory_(url_loader_factory) { } CastMetricsServiceClient::~CastMetricsServiceClient() {
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.h b/chromecast/browser/metrics/cast_metrics_service_client.h index 8d0d0d6..7b245e3 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.h +++ b/chromecast/browser/metrics/cast_metrics_service_client.h
@@ -30,9 +30,9 @@ class MetricsStateManager; } // namespace metrics -namespace net { -class URLRequestContextGetter; -} // namespace net +namespace network { +class SharedURLLoaderFactory; +} namespace chromecast { namespace metrics { @@ -42,8 +42,9 @@ class CastMetricsServiceClient : public ::metrics::MetricsServiceClient, public ::metrics::EnabledStateProvider { public: - CastMetricsServiceClient(PrefService* pref_service, - net::URLRequestContextGetter* request_context); + CastMetricsServiceClient( + PrefService* pref_service, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); ~CastMetricsServiceClient() override; static void RegisterPrefs(PrefRegistrySimple* registry); @@ -105,7 +106,7 @@ std::unique_ptr<::metrics::MetricsStateManager> metrics_state_manager_; std::unique_ptr<::metrics::MetricsService> metrics_service_; std::unique_ptr<::metrics::EnabledStateProvider> enabled_state_provider_; - net::URLRequestContextGetter* const request_context_; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; DISALLOW_COPY_AND_ASSIGN(CastMetricsServiceClient); };
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc index 0ac444f..4be99e7 100644 --- a/chromeos/chromeos_switches.cc +++ b/chromeos/chromeos_switches.cc
@@ -307,6 +307,10 @@ // Enables the Cast Receiver. const char kEnableCastReceiver[] = "enable-cast-receiver"; +// Enables the experimental chromevox developer option. +const char kEnableChromevoxDeveloperOption[] = + "enable-chromevox-developer-option"; + // Enables consumer kiosk mode for Chrome OS. const char kEnableConsumerKiosk[] = "enable-consumer-kiosk";
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h index 9080de02..0e5c6ef 100644 --- a/chromeos/chromeos_switches.h +++ b/chromeos/chromeos_switches.h
@@ -91,6 +91,7 @@ CHROMEOS_EXPORT extern const char kEnableArcOobeOptinNoSkip[]; CHROMEOS_EXPORT extern const char kEnableCaptivePortalRandomUrl[]; CHROMEOS_EXPORT extern const char kEnableCastReceiver[]; +CHROMEOS_EXPORT extern const char kEnableChromevoxDeveloperOption[]; CHROMEOS_EXPORT extern const char kEnableConsumerKiosk[]; CHROMEOS_EXPORT extern const char kEnableDataSaverPrompt[]; CHROMEOS_EXPORT extern const char kEnableDemoMode[];
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.cc b/chromeos/services/assistant/platform/audio_output_provider_impl.cc index b5e75bd..2e5fba90 100644 --- a/chromeos/services/assistant/platform/audio_output_provider_impl.cc +++ b/chromeos/services/assistant/platform/audio_output_provider_impl.cc
@@ -137,16 +137,16 @@ assistant_client::OutputStreamType focused_stream) {} float VolumeControlImpl::GetSystemVolume() { - return volume_; + return volume_ * 1.0 / 100.0; } void VolumeControlImpl::SetSystemVolume(float new_volume, bool user_initiated) { - volume_control_ptr_->SetVolume(new_volume, user_initiated); + volume_control_ptr_->SetVolume(new_volume * 100.0, user_initiated); } float VolumeControlImpl::GetAlarmVolume() { // TODO(muyuanli): implement. - return 100.0f; + return 1.0f; } void VolumeControlImpl::SetAlarmVolume(float new_volume, bool user_initiated) {
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc index 7669483c..48e2f92e 100644 --- a/components/autofill/content/renderer/password_generation_agent.cc +++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -10,9 +10,7 @@ #include "base/command_line.h" #include "base/logging.h" -#include "base/metrics/field_trial_params.h" #include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "components/autofill/content/renderer/form_autofill_util.h" #include "components/autofill/content/renderer/password_autofill_agent.h" @@ -168,23 +166,6 @@ } } -// Returns the number of characters the user may type while password generation -// is offered. Once the user has typed more than the given number, a password -// generation popup is removed. -// TODO(crbug.com/859472) Delete this function once we know a good value from -// the field trial. -size_t GetMaximumOfferSize() { - std::string string_value = base::GetFieldTrialParamValue( - "PasswordGenerationMaximumOfferSize", "maximum_offer_size"); - size_t parsed_value = 0; - if (!base::StringToSizeT(string_value, &parsed_value)) { - // This is the historic default value and remains in place for the time - // being. The hypothesis is, though, that 0 would be a better default. - return 5; - } - return parsed_value; -} - } // namespace PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData( @@ -212,8 +193,7 @@ base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kShowAutofillSignatures)), password_agent_(password_agent), - binding_(this), - maximum_offer_size_(GetMaximumOfferSize()) { + binding_(this) { LogBoolean(Logger::STRING_GENERATION_RENDERER_ENABLED, enabled_); registry->AddInterface(base::BindRepeating( &PasswordGenerationAgent::BindRequest, base::Unretained(this))); @@ -377,6 +357,9 @@ void PasswordGenerationAgent::GeneratedPasswordAccepted( const base::string16& password) { + // static cast is workaround for linker error. + DCHECK_LE(static_cast<size_t>(kMinimumLengthForEditedPassword), + password.size()); password_is_generated_ = true; password_edited_ = false; password_generation::LogPasswordGenerationEvent( @@ -591,7 +574,8 @@ } if (password_is_generated_) { - if (generation_element_.Value().IsEmpty()) { + if (generation_element_.Value().length() < + kMinimumLengthForEditedPassword) { PasswordNoLongerGenerated(); } else { generation_element_.SetShouldRevealPassword(true); @@ -600,11 +584,11 @@ return true; } - // Assume that if the password field has less than maximum_offer_size_ - // characters then the user is not finished typing their password and display - // the password suggestion. + // Assume that if the password field has less than + // |kMaximumCharsForGenerationOffer| characters then the user is not finished + // typing their password and display the password suggestion. if (!element->IsReadOnly() && element->IsEnabled() && - element->Value().length() <= maximum_offer_size_) { + element->Value().length() <= kMaximumCharsForGenerationOffer) { MaybeOfferAutomaticGeneration(); return true; } @@ -627,32 +611,34 @@ return false; } - if (element.Value().IsEmpty()) { - // The call may pop up a generation prompt. - MaybeOfferAutomaticGeneration(); - // Tell the browser that the state isn't "editing" anymore. The browser - // should hide the editing prompt if it wasn't replaced above. - if (password_is_generated_) { - // User generated a password and then deleted it. - PasswordNoLongerGenerated(); - } - } else if (password_is_generated_) { - password_edited_ = true; - // Mirror edits to any confirmation password fields. - CopyElementValueToOtherInputElements(&element, - &generation_form_data_->password_elements); - std::unique_ptr<PasswordForm> presaved_form(CreatePasswordFormToPresave()); - if (presaved_form) { - GetPasswordManagerClient()->PresaveGeneratedPassword(*presaved_form); - } - } else if (element.Value().length() > maximum_offer_size_) { + if (!password_is_generated_ && + element.Value().length() > kMaximumCharsForGenerationOffer) { // User has rejected the feature and has started typing a password. GenerationRejectedByTyping(); } else { - // Password isn't generated and there are fewer than maximum_offer_size_ - // characters typed, so keep offering the password. Note this function - // will just keep the previous popup if one is already showing. - MaybeOfferAutomaticGeneration(); + const bool leave_editing_state = + password_is_generated_ && + element.Value().length() < kMinimumLengthForEditedPassword; + if (!password_is_generated_ || leave_editing_state) { + // The call may pop up a generation prompt, replacing the editing prompt + // if it was previously shown. + MaybeOfferAutomaticGeneration(); + } + if (leave_editing_state) { + // Tell the browser that the state isn't "editing" anymore. The browser + // should hide the editing prompt if it wasn't replaced above. + PasswordNoLongerGenerated(); + } else if (password_is_generated_) { + password_edited_ = true; + // Mirror edits to any confirmation password fields. + CopyElementValueToOtherInputElements( + &element, &generation_form_data_->password_elements); + std::unique_ptr<PasswordForm> presaved_form( + CreatePasswordFormToPresave()); + if (presaved_form) { + GetPasswordManagerClient()->PresaveGeneratedPassword(*presaved_form); + } + } } return true; } @@ -712,8 +698,11 @@ password.SetAutofillState(WebAutofillState::kNotFilled); password_generation::LogPasswordGenerationEvent( password_generation::PASSWORD_DELETED); - CopyElementValueToOtherInputElements( - &generation_element_, &generation_form_data_->password_elements); + // Clear all other password fields. + for (WebInputElement& element : generation_form_data_->password_elements) { + if (generation_element_ != element) + element.SetAutofillValue(blink::WebString()); + } std::unique_ptr<PasswordForm> presaved_form(CreatePasswordFormToPresave()); if (presaved_form) GetPasswordManagerClient()->PasswordNoLongerGenerated(*presaved_form);
diff --git a/components/autofill/content/renderer/password_generation_agent.h b/components/autofill/content/renderer/password_generation_agent.h index 74a2a16b..a5f0a8b2 100644 --- a/components/autofill/content/renderer/password_generation_agent.h +++ b/components/autofill/content/renderer/password_generation_agent.h
@@ -35,6 +35,15 @@ class PasswordGenerationAgent : public content::RenderFrameObserver, public mojom::PasswordGenerationAgent { public: + // Maximum number of characters typed by user while the generation is still + // offered. When the (kMaximumCharsForGenerationOffer + 1)-th character is + // typed, the generation becomes unavailable. + static const size_t kMaximumCharsForGenerationOffer = 5; + + // User can edit the generated password. If the length falls below this value, + // the password is no longer considered generated. + static const size_t kMinimumLengthForEditedPassword = 4; + PasswordGenerationAgent(content::RenderFrame* render_frame, PasswordAutofillAgent* password_agent, blink::AssociatedInterfaceRegistry* registry); @@ -64,14 +73,7 @@ // Called right before PasswordAutofillAgent filled |password_element|. void OnFieldAutofilled(const blink::WebInputElement& password_element); - // The length that a password can be before the UI is hidden. - size_t maximum_offer_size() const { return maximum_offer_size_; } - #if defined(UNIT_TEST) - void set_maximum_offer_size_for_testing(size_t maximum_offer_size) { - maximum_offer_size_ = maximum_offer_size; - } - // This method requests the autofill::mojom::PasswordManagerClient which binds // requests the binding if it wasn't bound yet. void RequestPasswordManagerClientForTesting() { GetPasswordManagerClient(); } @@ -228,9 +230,6 @@ mojo::AssociatedBinding<mojom::PasswordGenerationAgent> binding_; - // The length that a password can be before the UI is hidden. - size_t maximum_offer_size_; - DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgent); };
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 0d3e6a5a..0dc8d8c 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -465,6 +465,7 @@ "webdata/autofill_profile_sync_bridge_unittest.cc", "webdata/autofill_profile_sync_difference_tracker_unittest.cc", "webdata/autofill_profile_syncable_service_unittest.cc", + "webdata/autofill_sync_bridge_util_unittest.cc", "webdata/autofill_table_unittest.cc", "webdata/autofill_wallet_metadata_sync_bridge_unittest.cc", "webdata/autofill_wallet_metadata_syncable_service_unittest.cc",
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/autofill_data_util.cc index 330cf8b..9bb74de 100644 --- a/components/autofill/core/browser/autofill_data_util.cc +++ b/components/autofill/core/browser/autofill_data_util.cc
@@ -16,6 +16,7 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/grit/components_scaled_resources.h" #include "components/strings/grit/components_strings.h" #include "third_party/icu/source/common/unicode/uscript.h" @@ -240,6 +241,13 @@ } // namespace +std::string TruncateUTF8(const std::string& data) { + std::string trimmed_value; + base::TruncateUTF8ToByteSize(data, AutofillTable::kMaxDataLength, + &trimmed_value); + return trimmed_value; +} + bool IsCreditCardExpirationType(ServerFieldType type) { return type == CREDIT_CARD_EXP_MONTH || type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
diff --git a/components/autofill/core/browser/autofill_data_util.h b/components/autofill/core/browser/autofill_data_util.h index 0e8ab97..ee3ede76 100644 --- a/components/autofill/core/browser/autofill_data_util.h +++ b/components/autofill/core/browser/autofill_data_util.h
@@ -23,6 +23,10 @@ base::string16 family; }; +// Truncates a string to the nearest UTF-8 character that will leave +// the string less than or equal to the specified byte size. +std::string TruncateUTF8(const std::string& data); + bool IsCreditCardExpirationType(ServerFieldType type); // Used to map Chrome card issuer networks to Payment Request API basic card
diff --git a/components/autofill/core/browser/autofill_profile_sync_util.cc b/components/autofill/core/browser/autofill_profile_sync_util.cc index f81dc6f..c7af768d 100644 --- a/components/autofill/core/browser/autofill_profile_sync_util.cc +++ b/components/autofill/core/browser/autofill_profile_sync_util.cc
@@ -7,6 +7,7 @@ #include "base/guid.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/country_names.h" #include "components/autofill/core/browser/field_types.h" @@ -16,19 +17,13 @@ using base::UTF16ToUTF8; using base::UTF8ToUTF16; +using autofill::data_util::TruncateUTF8; using sync_pb::AutofillProfileSpecifics; using syncer::EntityData; namespace autofill { namespace { -std::string TruncateUTF8(const std::string& data) { - std::string trimmed_value; - base::TruncateUTF8ToByteSize(data, AutofillTable::kMaxDataLength, - &trimmed_value); - return trimmed_value; -} - bool IsAutofillProfileSpecificsValid( const AutofillProfileSpecifics& specifics) { return base::IsValidGUID(specifics.guid());
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index 48721528..3abf1bc 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -36,6 +36,8 @@ namespace { +const int kValidityStateBitfield = 1984; + std::string GetRandomCardNumber() { const size_t length = 16; std::string value; @@ -332,6 +334,50 @@ return profile; } +AutofillProfile GetServerProfile() { + AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "id1"); + // Note: server profiles don't have email addresses and only have full names. + SetProfileInfo(&profile, "", "", "", "", "Google, Inc.", "123 Fake St.", + "Apt. 42", "Mountain View", "California", "94043", "US", + "1.800.555.1234"); + + profile.SetInfo(NAME_FULL, ASCIIToUTF16("John K. Doe"), "en"); + profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("CEDEX")); + profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + ASCIIToUTF16("Santa Clara")); + + profile.set_language_code("en"); + profile.SetValidityFromBitfieldValue(kValidityStateBitfield); + profile.set_use_count(7); + profile.set_use_date(base::Time::FromTimeT(54321)); + + profile.GenerateServerProfileIdentifier(); + + return profile; +} + +AutofillProfile GetServerProfile2() { + AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "id2"); + // Note: server profiles don't have email addresses. + SetProfileInfo(&profile, "", "", "", "", "Main, Inc.", "4323 Wrong St.", + "Apt. 1032", "Sunnyvale", "California", "10011", "US", + "+1 514-123-1234"); + + profile.SetInfo(NAME_FULL, ASCIIToUTF16("Jim S. Bristow"), "en"); + profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("XEDEC")); + profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + ASCIIToUTF16("Santa Monica")); + + profile.set_language_code("en"); + profile.SetValidityFromBitfieldValue(kValidityStateBitfield); + profile.set_use_count(14); + profile.set_use_date(base::Time::FromTimeT(98765)); + + profile.GenerateServerProfileIdentifier(); + + return profile; +} + CreditCard GetCreditCard() { CreditCard credit_card(base::GenerateGUID(), kEmptyOrigin); SetCreditCardInfo(&credit_card, "Test User", "4111111111111111" /* Visa */, @@ -363,6 +409,7 @@ test::SetCreditCardInfo(&credit_card, "Bonnie Parker", "2109" /* Mastercard */, "12", "2020", "1"); credit_card.SetNetworkForMaskedCard(kMasterCard); + credit_card.set_card_type(CreditCard::CARD_TYPE_CREDIT); return credit_card; } @@ -371,6 +418,7 @@ test::SetCreditCardInfo(&credit_card, "Justin Thyme", "8431" /* Amex */, "9", "2020", "1"); credit_card.SetNetworkForMaskedCard(kAmericanExpressCard); + credit_card.set_card_type(CreditCard::CARD_TYPE_PREPAID); return credit_card; }
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h index 38077c0..2ff459a 100644 --- a/components/autofill/core/browser/autofill_test_utils.h +++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -107,6 +107,12 @@ // Returns a verified profile full of dummy info, different to the above. AutofillProfile GetVerifiedProfile2(); +// Returns a server profile full of dummy info. +AutofillProfile GetServerProfile(); + +// Returns a server profile full of dummy info, different to the above. +AutofillProfile GetServerProfile2(); + // Returns a credit card full of dummy info. CreditCard GetCreditCard();
diff --git a/components/autofill/core/browser/form_field.cc b/components/autofill/core/browser/form_field.cc index c8d7bf1..3328e18 100644 --- a/components/autofill/core/browser/form_field.cc +++ b/components/autofill/core/browser/form_field.cc
@@ -70,7 +70,8 @@ ParseFormFieldsPass(PhoneField::Parse, processed_fields, &field_candidates); // Address pass. - ParseFormFieldsPass(AddressField::Parse, processed_fields, &field_candidates); + ParseFormFieldsPass(autofill::AddressField::Parse, processed_fields, + &field_candidates); // Credit card pass. ParseFormFieldsPass(CreditCardField::Parse, processed_fields,
diff --git a/components/autofill/core/browser/test_event_waiter.h b/components/autofill/core/browser/test_event_waiter.h index b7f7102..be100f8 100644 --- a/components/autofill/core/browser/test_event_waiter.h +++ b/components/autofill/core/browser/test_event_waiter.h
@@ -31,7 +31,7 @@ class EventWaiter { public: explicit EventWaiter( - std::list<Event> event_sequence, + std::list<Event> expected_event_sequence, base::TimeDelta timeout = base::TimeDelta::FromSeconds(0)); ~EventWaiter(); @@ -44,16 +44,16 @@ void OnEvent(Event event); private: - std::list<Event> events_; + std::list<Event> expected_events_; base::RunLoop run_loop_; DISALLOW_COPY_AND_ASSIGN(EventWaiter); }; template <typename Event> -EventWaiter<Event>::EventWaiter(std::list<Event> event_sequence, +EventWaiter<Event>::EventWaiter(std::list<Event> expected_event_sequence, base::TimeDelta timeout) - : events_(std::move(event_sequence)) { + : expected_events_(std::move(expected_event_sequence)) { if (!timeout.is_zero()) { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, run_loop_.QuitClosure(), timeout); @@ -65,23 +65,23 @@ template <typename Event> bool EventWaiter<Event>::Wait() { - if (events_.empty()) + if (expected_events_.empty()) return true; DCHECK(!run_loop_.running()); run_loop_.Run(); - return events_.empty(); + return expected_events_.empty(); } template <typename Event> -void EventWaiter<Event>::OnEvent(Event event) { - if (events_.empty()) +void EventWaiter<Event>::OnEvent(Event actual_event) { + if (expected_events_.empty()) return; - ASSERT_EQ(events_.front(), event); - events_.pop_front(); + ASSERT_EQ(expected_events_.front(), actual_event); + expected_events_.pop_front(); // Only quit the loop if no other events are expected. - if (events_.empty() && run_loop_.running()) + if (expected_events_.empty() && run_loop_.running()) run_loop_.Quit(); }
diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc b/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc index 4b7b7d7..2bd936a4 100644 --- a/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc +++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc
@@ -16,4 +16,32 @@ return CreditCard(CreditCard::MASKED_SERVER_CARD, server_id); } +sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForCard( + const std::string& specifics_id, + const std::string& billing_address_id) { + sync_pb::AutofillWalletSpecifics wallet_specifics; + wallet_specifics.set_type( + sync_pb::AutofillWalletSpecifics_WalletInfoType:: + AutofillWalletSpecifics_WalletInfoType_MASKED_CREDIT_CARD); + + sync_pb::WalletMaskedCreditCard* card_specifics = + wallet_specifics.mutable_masked_card(); + card_specifics->set_id(specifics_id); + card_specifics->set_billing_address_id(billing_address_id); + return wallet_specifics; +} + +sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForAddress( + const std::string& specifics_id) { + sync_pb::AutofillWalletSpecifics wallet_specifics; + wallet_specifics.set_type( + sync_pb::AutofillWalletSpecifics_WalletInfoType:: + AutofillWalletSpecifics_WalletInfoType_POSTAL_ADDRESS); + + sync_pb::WalletPostalAddress* profile_specifics = + wallet_specifics.mutable_address(); + profile_specifics->set_id(specifics_id); + return wallet_specifics; +} + } // namespace autofill \ No newline at end of file
diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h b/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h index 7eb8bf4..0780855 100644 --- a/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h +++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h
@@ -9,6 +9,7 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" +#include "components/sync/protocol/sync.pb.h" namespace autofill { @@ -16,6 +17,13 @@ CreditCard CreateServerCreditCard(const std::string& server_id); +sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForAddress( + const std::string& specifics_id); + +sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForCard( + const std::string& specifics_id, + const std::string& billing_address_id = ""); + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_SYNC_BRIDGE_TEST_UTIL_H_
diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc index fc0a4205..3bd0f3e 100644 --- a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc +++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
@@ -7,34 +7,39 @@ #include "base/base64.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/webdata/autofill_table.h" +#include "components/autofill/core/common/autofill_util.h" #include "components/sync/model/entity_data.h" +using autofill::data_util::TruncateUTF8; using sync_pb::AutofillWalletSpecifics; using syncer::EntityData; namespace autofill { namespace { -std::string TruncateUTF8(const std::string& data) { - std::string trimmed_value; - base::TruncateUTF8ToByteSize(data, AutofillTable::kMaxDataLength, - &trimmed_value); - return trimmed_value; -} - sync_pb::WalletMaskedCreditCard::WalletCardStatus LocalToServerStatus( const CreditCard& card) { switch (card.GetServerStatus()) { case CreditCard::OK: return sync_pb::WalletMaskedCreditCard::VALID; case CreditCard::EXPIRED: - default: return sync_pb::WalletMaskedCreditCard::EXPIRED; } } +CreditCard::ServerStatus ServerToLocalStatus( + sync_pb::WalletMaskedCreditCard::WalletCardStatus status) { + switch (status) { + case sync_pb::WalletMaskedCreditCard::VALID: + return CreditCard::OK; + case sync_pb::WalletMaskedCreditCard::EXPIRED: + return CreditCard::EXPIRED; + } +} + sync_pb::WalletMaskedCreditCard::WalletCardType WalletCardTypeFromCardNetwork( const std::string& network) { if (network == kAmericanExpressCard) @@ -54,6 +59,31 @@ return sync_pb::WalletMaskedCreditCard::UNKNOWN; } +const char* CardNetworkFromWalletCardType( + sync_pb::WalletMaskedCreditCard::WalletCardType type) { + switch (type) { + case sync_pb::WalletMaskedCreditCard::AMEX: + return kAmericanExpressCard; + case sync_pb::WalletMaskedCreditCard::DISCOVER: + return kDiscoverCard; + case sync_pb::WalletMaskedCreditCard::JCB: + return kJCBCard; + case sync_pb::WalletMaskedCreditCard::MASTER_CARD: + return kMasterCard; + case sync_pb::WalletMaskedCreditCard::UNIONPAY: + return kUnionPay; + case sync_pb::WalletMaskedCreditCard::VISA: + return kVisaCard; + + // These aren't supported by the client, so just declare a generic card. + case sync_pb::WalletMaskedCreditCard::MAESTRO: + case sync_pb::WalletMaskedCreditCard::SOLO: + case sync_pb::WalletMaskedCreditCard::SWITCH: + case sync_pb::WalletMaskedCreditCard::UNKNOWN: + return kGenericCard; + } +} + sync_pb::WalletMaskedCreditCard::WalletCardClass WalletCardClassFromCardType( CreditCard::CardType card_type) { switch (card_type) { @@ -63,11 +93,25 @@ return sync_pb::WalletMaskedCreditCard::DEBIT; case CreditCard::CARD_TYPE_PREPAID: return sync_pb::WalletMaskedCreditCard::PREPAID; - default: + case CreditCard::CARD_TYPE_UNKNOWN: return sync_pb::WalletMaskedCreditCard::UNKNOWN_CARD_CLASS; } } +CreditCard::CardType CardTypeFromWalletCardClass( + sync_pb::WalletMaskedCreditCard::WalletCardClass card_class) { + switch (card_class) { + case sync_pb::WalletMaskedCreditCard::CREDIT: + return CreditCard::CARD_TYPE_CREDIT; + case sync_pb::WalletMaskedCreditCard::DEBIT: + return CreditCard::CARD_TYPE_DEBIT; + case sync_pb::WalletMaskedCreditCard::PREPAID: + return CreditCard::CARD_TYPE_PREPAID; + case sync_pb::WalletMaskedCreditCard::UNKNOWN_CARD_CLASS: + return CreditCard::CARD_TYPE_UNKNOWN; + } +} + } // namespace std::string GetSpecificsIdForEntryServerId(const std::string& server_id) { @@ -172,6 +216,44 @@ return entity_data; } +AutofillProfile ProfileFromSpecifics( + const sync_pb::WalletPostalAddress& address) { + AutofillProfile profile(AutofillProfile::SERVER_PROFILE, std::string()); + + // AutofillProfile stores multi-line addresses with newline separators. + std::vector<base::StringPiece> street_address( + address.street_address().begin(), address.street_address().end()); + profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, + base::UTF8ToUTF16(base::JoinString(street_address, "\n"))); + + profile.SetRawInfo(COMPANY_NAME, base::UTF8ToUTF16(address.company_name())); + profile.SetRawInfo(ADDRESS_HOME_STATE, + base::UTF8ToUTF16(address.address_1())); + profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(address.address_2())); + profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + base::UTF8ToUTF16(address.address_3())); + // AutofillProfile doesn't support address_4 ("sub dependent locality"). + profile.SetRawInfo(ADDRESS_HOME_ZIP, + base::UTF8ToUTF16(address.postal_code())); + profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, + base::UTF8ToUTF16(address.sorting_code())); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, + base::UTF8ToUTF16(address.country_code())); + profile.set_language_code(address.language_code()); + + // SetInfo instead of SetRawInfo so the constituent pieces will be parsed + // for these data types. + profile.SetInfo(NAME_FULL, base::UTF8ToUTF16(address.recipient_name()), + profile.language_code()); + profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, + base::UTF8ToUTF16(address.phone_number()), + profile.language_code()); + + profile.GenerateServerProfileIdentifier(); + + return profile; +} + void SetAutofillWalletSpecificsFromServerCard( const CreditCard& card, AutofillWalletSpecifics* wallet_specifics) { @@ -209,4 +291,87 @@ return entity_data; } -} // namespace autofill \ No newline at end of file +CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) { + CreditCard result(CreditCard::MASKED_SERVER_CARD, card.id()); + result.SetNumber(base::UTF8ToUTF16(card.last_four())); + result.SetServerStatus(ServerToLocalStatus(card.status())); + result.SetNetworkForMaskedCard(CardNetworkFromWalletCardType(card.type())); + result.set_card_type(CardTypeFromWalletCardClass(card.card_class())); + result.SetRawInfo(CREDIT_CARD_NAME_FULL, + base::UTF8ToUTF16(card.name_on_card())); + result.SetExpirationMonth(card.exp_month()); + result.SetExpirationYear(card.exp_year()); + result.set_billing_address_id(card.billing_address_id()); + result.set_bank_name(card.bank_name()); + return result; +} + +void CopyRelevantWalletMetadataFromDisk( + const AutofillTable& table, + std::vector<CreditCard>* cards_from_server) { + std::vector<std::unique_ptr<CreditCard>> cards_on_disk; + table.GetServerCreditCards(&cards_on_disk); + + // Since the number of cards is fairly small, the brute-force search is good + // enough. + for (const auto& saved_card : cards_on_disk) { + for (CreditCard& server_card : *cards_from_server) { + if (saved_card->server_id() == server_card.server_id()) { + // The wallet data doesn't have the use stats. Use the ones present on + // disk to not overwrite them with bad data. + server_card.set_use_count(saved_card->use_count()); + server_card.set_use_date(saved_card->use_date()); + + // Keep the billing address id of the saved cards only if it points to + // a local address. + if (saved_card->billing_address_id().length() == kLocalGuidSize) { + server_card.set_billing_address_id(saved_card->billing_address_id()); + break; + } + } + } + } +} + +void PopulateWalletCardsAndAddresses( + const syncer::EntityChangeList& entity_data, + std::vector<CreditCard>* wallet_cards, + std::vector<AutofillProfile>* wallet_addresses) { + std::map<std::string, std::string> ids; + + for (const syncer::EntityChange& change : entity_data) { + DCHECK(change.data().specifics.has_autofill_wallet()); + + const sync_pb::AutofillWalletSpecifics& autofill_specifics = + change.data().specifics.autofill_wallet(); + + switch (autofill_specifics.type()) { + case sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD: + wallet_cards->push_back( + CardFromSpecifics(autofill_specifics.masked_card())); + break; + case sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS: + wallet_addresses->push_back( + ProfileFromSpecifics(autofill_specifics.address())); + + // Map the sync billing address id to the profile's id. + ids[autofill_specifics.address().id()] = + wallet_addresses->back().server_id(); + break; + case sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA: + case sync_pb::AutofillWalletSpecifics::UNKNOWN: + // Just ignore new entry types that the client doesn't know about. + break; + } + } + + // Set the billing address of the wallet cards to the id of the appropriate + // profile. + for (CreditCard& card : *wallet_cards) { + auto it = ids.find(card.billing_address_id()); + if (it != ids.end()) + card.set_billing_address_id(it->second); + } +} + +} // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h index bd5e40c..7207ea7 100644 --- a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h +++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h
@@ -8,11 +8,13 @@ #include <memory> #include <string> +#include "components/sync/model/entity_change.h" #include "components/sync/model/entity_data.h" namespace autofill { class AutofillProfile; +class AutofillTable; class CreditCard; // Returns the wallet specifics id for the specified |server_id|. @@ -40,6 +42,10 @@ std::unique_ptr<syncer::EntityData> CreateEntityDataFromAutofillServerProfile( const AutofillProfile& address); +// Creates an AutofillProfile from the specified |address| specifics. +AutofillProfile ProfileFromSpecifics( + const sync_pb::WalletPostalAddress& address); + // Sets the fields of the |wallet_specifics| based on the the specified |card|. void SetAutofillWalletSpecificsFromServerCard( const CreditCard& card, @@ -49,6 +55,26 @@ std::unique_ptr<syncer::EntityData> CreateEntityDataFromCard( const CreditCard& card); +// Creates an AutofillProfile from the specified |card| specifics. +CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card); + +// TODO(sebsg): This should probably copy the converted state for the address +// too. +// Copies the metadata from the local cards (if present) to the corresponding +// server cards so that they don't get overwritten. This is because the wallet +// data does not include those. They are handled by the +// AutofillWalletMetadataSyncBridge. +void CopyRelevantWalletMetadataFromDisk( + const AutofillTable& table, + std::vector<CreditCard>* cards_from_server); + +// Populates the wallet cards and addresses from the sync data and uses the +// sync data to link the card to its billing address. +void PopulateWalletCardsAndAddresses( + const ::syncer::EntityChangeList& entity_data, + std::vector<CreditCard>* wallet_cards, + std::vector<AutofillProfile>* wallet_addresses); + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_SYNC_BRIDGE_UTIL_H_
diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc b/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc new file mode 100644 index 0000000..b0aacc5 --- /dev/null +++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
@@ -0,0 +1,196 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/webdata/autofill_sync_bridge_util.h" + +#include <vector> + +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/test_autofill_clock.h" +#include "components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h" +#include "components/autofill/core/browser/webdata/autofill_table.h" +#include "components/autofill/core/common/autofill_constants.h" +#include "components/sync/base/hash_util.h" +#include "components/sync/model/entity_data.h" +#include "components/sync/protocol/sync.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { +namespace { + +using syncer::EntityChange; +using syncer::EntityData; + +class TestAutofillTable : public AutofillTable { + public: + explicit TestAutofillTable(std::vector<CreditCard> cards_on_disk) + : cards_on_disk_(cards_on_disk) {} + + ~TestAutofillTable() override {} + + bool GetServerCreditCards( + std::vector<std::unique_ptr<CreditCard>>* cards) const override { + for (const auto& card_on_disk : cards_on_disk_) + cards->push_back(std::make_unique<CreditCard>(card_on_disk)); + return true; + } + + private: + std::vector<CreditCard> cards_on_disk_; + + DISALLOW_COPY_AND_ASSIGN(TestAutofillTable); +}; + +EntityData SpecificsToEntity(const sync_pb::AutofillWalletSpecifics& specifics, + const std::string& client_tag) { + EntityData data; + *data.specifics.mutable_autofill_wallet() = specifics; + data.client_tag_hash = + syncer::GenerateSyncableHash(syncer::AUTOFILL_WALLET_DATA, client_tag); + return data; +} + +class AutofillSyncBridgeUtilTest : public testing::Test { + public: + AutofillSyncBridgeUtilTest() {} + ~AutofillSyncBridgeUtilTest() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillSyncBridgeUtilTest); +}; + +// Tests that the link between a card and its billing address from sync is +// present in the generated Autofill objects. +TEST_F(AutofillSyncBridgeUtilTest, + PopulateWalletCardsAndAddresses_BillingAddressIdTransfer) { + // Add an address and a card that has its billing address id set to the + // address' id. + syncer::EntityChangeList entity_data; + std::string address_id("address1"); + entity_data.push_back(EntityChange::CreateAdd( + address_id, + SpecificsToEntity(CreateAutofillWalletSpecificsForAddress(address_id), + /*client_tag=*/"address-address1") + .PassToPtr())); + entity_data.push_back(EntityChange::CreateAdd( + "card1", + SpecificsToEntity(CreateAutofillWalletSpecificsForCard( + /*id=*/"card1", /*billing_address_id=*/address_id), + /*client_tag=*/"card-card1") + .PassToPtr())); + + std::vector<CreditCard> wallet_cards; + std::vector<AutofillProfile> wallet_addresses; + PopulateWalletCardsAndAddresses(entity_data, &wallet_cards, + &wallet_addresses); + + ASSERT_EQ(1U, wallet_cards.size()); + ASSERT_EQ(1U, wallet_addresses.size()); + + // Make sure the card's billing address id is equal to the address' server id. + EXPECT_EQ(wallet_addresses.back().server_id(), + wallet_cards.back().billing_address_id()); +} + +// Verify that the billing address id from the card saved on disk is kept if it +// is a local profile guid. +TEST_F(AutofillSyncBridgeUtilTest, + CopyRelevantWalletMetadataFromDisk_KeepLocalAddresses) { + std::vector<CreditCard> cards_on_disk; + std::vector<CreditCard> wallet_cards; + + // Create a local profile to be used as a billing address. + AutofillProfile billing_address; + + // Create a card on disk that refers to that local profile as its billing + // address. + cards_on_disk.push_back(CreditCard()); + cards_on_disk.back().set_billing_address_id(billing_address.guid()); + + // Create a card pulled from wallet with the same id, but a different billing + // address id. + wallet_cards.push_back(CreditCard(cards_on_disk.back())); + wallet_cards.back().set_billing_address_id("1234"); + + // Setup the TestAutofillTable with the cards_on_disk. + TestAutofillTable table(cards_on_disk); + + CopyRelevantWalletMetadataFromDisk(table, &wallet_cards); + + ASSERT_EQ(1U, wallet_cards.size()); + + // Make sure the wallet card replace its billing address id for the one that + // was saved on disk. + EXPECT_EQ(cards_on_disk.back().billing_address_id(), + wallet_cards.back().billing_address_id()); +} + +// Verify that the billing address id from the card saved on disk is overwritten +// if it does not refer to a local profile. +TEST_F(AutofillSyncBridgeUtilTest, + CopyRelevantWalletMetadataFromDisk_OverwriteOtherAddresses) { + std::string old_billing_id = "1234"; + std::string new_billing_id = "9876"; + std::vector<CreditCard> cards_on_disk; + std::vector<CreditCard> wallet_cards; + + // Create a card on disk that does not refer to a local profile (which have 36 + // chars ids). + cards_on_disk.push_back(CreditCard()); + cards_on_disk.back().set_billing_address_id(old_billing_id); + + // Create a card pulled from wallet with the same id, but a different billing + // address id. + wallet_cards.push_back(CreditCard(cards_on_disk.back())); + wallet_cards.back().set_billing_address_id(new_billing_id); + + // Setup the TestAutofillTable with the cards_on_disk. + TestAutofillTable table(cards_on_disk); + + CopyRelevantWalletMetadataFromDisk(table, &wallet_cards); + + ASSERT_EQ(1U, wallet_cards.size()); + + // Make sure the local address billing id that was saved on disk did not + // replace the new one. + EXPECT_EQ(new_billing_id, wallet_cards.back().billing_address_id()); +} + +// Verify that the use stats on disk are kept when server cards are synced. +TEST_F(AutofillSyncBridgeUtilTest, + CopyRelevantWalletMetadataFromDisk_KeepUseStats) { + TestAutofillClock test_clock; + base::Time arbitrary_time = base::Time::FromDoubleT(25); + base::Time disk_time = base::Time::FromDoubleT(10); + test_clock.SetNow(arbitrary_time); + + std::vector<CreditCard> cards_on_disk; + std::vector<CreditCard> wallet_cards; + + // Create a card on disk with specific use stats. + cards_on_disk.push_back(CreditCard()); + cards_on_disk.back().set_use_count(3U); + cards_on_disk.back().set_use_date(disk_time); + + // Create a card pulled from wallet with the same id, but a different billing + // address id. + wallet_cards.push_back(CreditCard()); + wallet_cards.back().set_use_count(10U); + + // Setup the TestAutofillTable with the cards_on_disk. + TestAutofillTable table(cards_on_disk); + + CopyRelevantWalletMetadataFromDisk(table, &wallet_cards); + + ASSERT_EQ(1U, wallet_cards.size()); + + // Make sure the use stats from disk were kept + EXPECT_EQ(3U, wallet_cards.back().use_count()); + EXPECT_EQ(disk_time, wallet_cards.back().use_date()); +} + +} // namespace +} // namespace autofill \ No newline at end of file
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc index ce6c6172..ce6167f 100644 --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -2394,6 +2394,7 @@ syncer::ModelType model_type) const { return (model_type == syncer::AUTOFILL || model_type == syncer::AUTOFILL_PROFILE || + model_type == syncer::AUTOFILL_WALLET_DATA || model_type == syncer::AUTOFILL_WALLET_METADATA); }
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc index bed8074..3cc9fa48e 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -8,6 +8,7 @@ #include "base/base64.h" #include "base/logging.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_profile.h" @@ -17,8 +18,10 @@ #include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" +#include "components/autofill/core/common/autofill_util.h" #include "components/sync/model/entity_data.h" #include "components/sync/model/mutable_data_batch.h" +#include "components/sync/model/sync_merge_result.h" #include "components/sync/model_impl/client_tag_based_model_type_processor.h" #include "components/sync/model_impl/sync_metadata_store_change_list.h" @@ -75,7 +78,11 @@ std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, AutofillWebDataBackend* web_data_backend) : ModelTypeSyncBridge(std::move(change_processor)), - web_data_backend_(web_data_backend) {} + web_data_backend_(web_data_backend) { + DCHECK(web_data_backend_); + + LoadMetadata(); +} AutofillWalletSyncBridge::~AutofillWalletSyncBridge() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -91,14 +98,14 @@ base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { - return ApplySyncChanges(std::move(metadata_change_list), - std::move(entity_data)); + SetSyncData(entity_data, /*is_initial_data=*/true); + return base::nullopt; } base::Optional<syncer::ModelError> AutofillWalletSyncBridge::ApplySyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { - NOTIMPLEMENTED(); + SetSyncData(entity_data, /*is_initial_data=*/false); return base::nullopt; } @@ -149,8 +156,132 @@ entity_data.specifics.autofill_wallet()); } +void AutofillWalletSyncBridge::SetSyncData( + const syncer::EntityChangeList& entity_data, + bool is_initial_data) { + std::vector<CreditCard> wallet_cards; + std::vector<AutofillProfile> wallet_addresses; + PopulateWalletCardsAndAddresses(entity_data, &wallet_cards, + &wallet_addresses); + + // Users can set billing address of the server credit card locally, but that + // information does not propagate to either Chrome Sync or Google Payments + // server. To preserve user's preferred billing address and most recent use + // stats, copy them from disk into |wallet_cards|. + AutofillTable* table = GetAutofillTable(); + CopyRelevantWalletMetadataFromDisk(*table, &wallet_cards); + + // In the common case, the database won't have changed. Committing an update + // to the database will require at least one DB page write and will schedule + // a fsync. To avoid this I/O, it should be more efficient to do a read and + // only do the writes if something changed. + std::vector<std::unique_ptr<CreditCard>> existing_cards; + table->GetServerCreditCards(&existing_cards); + AutofillWalletDiff cards_diff = + ComputeAutofillWalletDiff(existing_cards, wallet_cards); + if (!cards_diff.IsEmpty()) + table->SetServerCreditCards(wallet_cards); + + std::vector<std::unique_ptr<AutofillProfile>> existing_addresses; + table->GetServerProfiles(&existing_addresses); + AutofillWalletDiff addresses_diff = + ComputeAutofillWalletDiff(existing_addresses, wallet_addresses); + if (!addresses_diff.IsEmpty()) + table->SetServerProfiles(wallet_addresses); + + if (!is_initial_data) { + UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsAdded", + cards_diff.items_added); + UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsRemoved", + cards_diff.items_removed); + UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsAddedOrRemoved", + cards_diff.items_added + cards_diff.items_removed); + + UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddressesAdded", + addresses_diff.items_added); + UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddressesRemoved", + addresses_diff.items_removed); + UMA_HISTOGRAM_COUNTS_100( + "Autofill.WalletAddressesAddedOrRemoved", + addresses_diff.items_added + addresses_diff.items_removed); + } + + if (web_data_backend_ && (!cards_diff.IsEmpty() || !addresses_diff.IsEmpty())) + web_data_backend_->NotifyOfMultipleAutofillChanges(); +} + +// static +template <class Item> +AutofillWalletSyncBridge::AutofillWalletDiff +AutofillWalletSyncBridge::ComputeAutofillWalletDiff( + const std::vector<std::unique_ptr<Item>>& old_data, + const std::vector<Item>& new_data) { + // Build vectors of pointers, so that we can mutate (sort) them. + std::vector<const Item*> old_ptrs; + old_ptrs.reserve(old_data.size()); + for (const std::unique_ptr<Item>& old_item : old_data) + old_ptrs.push_back(old_item.get()); + std::vector<const Item*> new_ptrs; + new_ptrs.reserve(new_data.size()); + for (const Item& new_item : new_data) + new_ptrs.push_back(&new_item); + + // Sort our vectors. + auto compare = [](const Item* lhs, const Item* rhs) { + return lhs->Compare(*rhs) < 0; + }; + std::sort(old_ptrs.begin(), old_ptrs.end(), compare); + std::sort(new_ptrs.begin(), new_ptrs.end(), compare); + + // Walk over both of them and count added/removed elements. + AutofillWalletDiff result; + auto old_it = old_ptrs.begin(); + auto new_it = new_ptrs.begin(); + while (old_it != old_ptrs.end()) { + if (new_it == new_ptrs.end()) { + result.items_removed += std::distance(old_it, old_ptrs.end()); + break; + } + int cmp = (*old_it)->Compare(**new_it); + if (cmp < 0) { + ++result.items_removed; + ++old_it; + } else if (cmp == 0) { + ++old_it; + ++new_it; + } else { + ++result.items_added; + ++new_it; + } + } + result.items_added += std::distance(new_it, new_ptrs.end()); + + DCHECK_EQ(old_data.size() + result.items_added - result.items_removed, + new_data.size()); + + return result; +} + AutofillTable* AutofillWalletSyncBridge::GetAutofillTable() { return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); } +void AutofillWalletSyncBridge::LoadMetadata() { + if (!web_data_backend_ || !web_data_backend_->GetDatabase() || + !GetAutofillTable()) { + change_processor()->ReportError( + {FROM_HERE, "Failed to load AutofillWebDatabase."}); + return; + } + + auto batch = std::make_unique<syncer::MetadataBatch>(); + if (!GetAutofillTable()->GetAllSyncMetadata(syncer::AUTOFILL_PROFILE, + batch.get())) { + change_processor()->ReportError( + {FROM_HERE, "Failed reading autofill metadata from WebDatabase."}); + return; + } + change_processor()->ModelReadyToSync(std::move(batch)); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h index 394de20..82d8f40 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -19,9 +19,11 @@ namespace autofill { +class AutofillProfile; class AutofillTable; class AutofillWebDataBackend; class AutofillWebDataService; +class CreditCard; // Sync bridge responsible for propagating local changes to the processor and // applying remote changes to the local database. @@ -59,6 +61,30 @@ std::string GetStorageKey(const syncer::EntityData& entity_data) override; private: + struct AutofillWalletDiff { + int items_added = 0; + int items_removed = 0; + + bool IsEmpty() const { return items_added == 0 && items_removed == 0; } + }; + + // Sets the wallet data from |entity_data| to this client. Records metrics + // about added/deleted data if not the |is_initial_data|. + void SetSyncData(const syncer::EntityChangeList& entity_data, + bool is_initial_data); + + // Computes a "diff" (items added, items removed) of two vectors of items, + // which should be either CreditCard or AutofillProfile. This is used for two + // purposes: + // 1) Detecting if anything has changed, so that we don't write to disk in the + // common case where nothing has changed. + // 2) Recording metrics on the number of added/removed items. + // This is exposed as a static method so that it can be tested. + template <class Item> + static AutofillWalletDiff ComputeAutofillWalletDiff( + const std::vector<std::unique_ptr<Item>>& old_data, + const std::vector<Item>& new_data); + // Returns the table associated with the |web_data_backend_|. AutofillTable* GetAutofillTable(); @@ -66,6 +92,10 @@ // SupportsUserData, so it's guaranteed to outlive |this|. AutofillWebDataBackend* const web_data_backend_; + // Synchronously load sync metadata from the autofill table and pass it to the + // processor so that it can start tracking changes. + void LoadMetadata(); + // The bridge should be used on the same sequence where it is constructed. SEQUENCE_CHECKER(sequence_checker_);
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc index d702c4f..7513678 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -16,7 +16,10 @@ #include "base/test/bind_test_util.h" #include "base/test/scoped_task_environment.h" #include "base/time/time.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/country_names.h" +#include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h" #include "components/autofill/core/browser/webdata/autofill_sync_bridge_util.h" @@ -39,6 +42,7 @@ using base::ScopedTempDir; using sync_pb::AutofillWalletSpecifics; using syncer::DataBatch; +using syncer::EntityChange; using syncer::EntityData; using syncer::EntityDataPtr; using syncer::KeyAndData; @@ -46,12 +50,6 @@ using syncer::ModelType; using testing::UnorderedElementsAre; -// Non-UTF8 server IDs. -const char kAddr1ServerId[] = "addr1\xEF\xBF\xBE"; -const char kAddr2ServerId[] = "addr2\xEF\xBF\xBE"; -const char kCard1ServerId[] = "card1\xEF\xBF\xBE"; -const char kCard2ServerId[] = "card2\xEF\xBF\xBE"; - // Base64 encodings of the server IDs, used as ids in WalletMetadataSpecifics // (these are suitable for syncing, because they are valid UTF-8). const char kAddr1SpecificsId[] = "YWRkcjHvv74="; @@ -86,32 +84,6 @@ WebDatabase* db_; }; -AutofillWalletSpecifics CreateAutofillWalletSpecificsForCard( - const std::string& specifics_id) { - sync_pb::AutofillWalletSpecifics wallet_specifics; - wallet_specifics.set_type( - sync_pb::AutofillWalletSpecifics_WalletInfoType:: - AutofillWalletSpecifics_WalletInfoType_MASKED_CREDIT_CARD); - - sync_pb::WalletMaskedCreditCard* card_specifics = - wallet_specifics.mutable_masked_card(); - card_specifics->set_id(specifics_id); - return wallet_specifics; -} - -AutofillWalletSpecifics CreateAutofillWalletSpecificsForAddress( - const std::string& specifics_id) { - sync_pb::AutofillWalletSpecifics wallet_specifics; - wallet_specifics.set_type( - sync_pb::AutofillWalletSpecifics_WalletInfoType:: - AutofillWalletSpecifics_WalletInfoType_POSTAL_ADDRESS); - - sync_pb::WalletPostalAddress* address_specifics = - wallet_specifics.mutable_address(); - address_specifics->set_id(specifics_id); - return wallet_specifics; -} - void ExtractAutofillWalletSpecificsFromDataBatch( std::unique_ptr<DataBatch> batch, std::vector<AutofillWalletSpecifics>* output) { @@ -220,6 +192,29 @@ mock_processor_.CreateForwardingProcessor(), &backend_)); } + void StartSyncing( + const std::vector<AutofillWalletSpecifics>& remote_data = {}) { + base::RunLoop loop; + syncer::DataTypeActivationRequest request; + request.error_handler = base::DoNothing(); + real_processor_->OnSyncStarting( + request, + base::BindLambdaForTesting( + [&loop](std::unique_ptr<syncer::DataTypeActivationResponse>) { + loop.Quit(); + })); + loop.Run(); + + // Initialize the processor with initial_sync_done. + sync_pb::ModelTypeState state; + state.set_initial_sync_done(true); + syncer::UpdateResponseDataList initial_updates; + for (const AutofillWalletSpecifics& specifics : remote_data) { + initial_updates.push_back(SpecificsToUpdateResponse(specifics)); + } + real_processor_->OnUpdateReceived(state, initial_updates); + } + EntityData SpecificsToEntity(const AutofillWalletSpecifics& specifics) { EntityData data; *data.specifics.mutable_autofill_wallet() = specifics; @@ -241,6 +236,13 @@ return data; } + syncer::UpdateResponseData SpecificsToUpdateResponse( + const AutofillWalletSpecifics& specifics) { + syncer::UpdateResponseData data; + data.entity = SpecificsToEntity(specifics).PassToPtr(); + return data; + } + AutofillWalletSyncBridge* bridge() { return bridge_.get(); } syncer::MockModelTypeChangeProcessor& mock_processor() { @@ -297,27 +299,208 @@ TEST_F(AutofillWalletSyncBridgeTest, GetAllDataForDebugging_ShouldReturnAllData) { - AutofillProfile address1 = CreateServerProfile(kAddr1ServerId); - AutofillProfile address2 = CreateServerProfile(kAddr2ServerId); + AutofillProfile address1 = test::GetServerProfile(); + AutofillProfile address2 = test::GetServerProfile2(); table()->SetServerProfiles({address1, address2}); - CreditCard card1 = CreateServerCreditCard(kCard1ServerId); - CreditCard card2 = CreateServerCreditCard(kCard2ServerId); + CreditCard card1 = test::GetMaskedServerCard(); + CreditCard card2 = test::GetMaskedServerCardAmex(); table()->SetServerCreditCards({card1, card2}); - AutofillWalletSpecifics address_specifics1; - SetAutofillWalletSpecificsFromServerProfile(address1, &address_specifics1); - AutofillWalletSpecifics address_specifics2; - SetAutofillWalletSpecificsFromServerProfile(address2, &address_specifics2); + AutofillWalletSpecifics profile_specifics1; + SetAutofillWalletSpecificsFromServerProfile(address1, &profile_specifics1); + AutofillWalletSpecifics profile_specifics2; + SetAutofillWalletSpecificsFromServerProfile(address2, &profile_specifics2); AutofillWalletSpecifics card_specifics1; SetAutofillWalletSpecificsFromServerCard(card1, &card_specifics1); AutofillWalletSpecifics card_specifics2; SetAutofillWalletSpecificsFromServerCard(card2, &card_specifics2); EXPECT_THAT(GetAllLocalData(), - UnorderedElementsAre(EqualsSpecifics(address_specifics1), - EqualsSpecifics(address_specifics2), + UnorderedElementsAre(EqualsSpecifics(profile_specifics1), + EqualsSpecifics(profile_specifics2), EqualsSpecifics(card_specifics1), EqualsSpecifics(card_specifics2))); } +// Tests that when a new wallet card and new wallet address are sent by the +// server, the client only keeps the new data. +TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) { + // Create one profile and one card on the client. + AutofillProfile address1 = test::GetServerProfile(); + table()->SetServerProfiles({address1}); + CreditCard card1 = test::GetMaskedServerCard(); + table()->SetServerCreditCards({card1}); + + // Create a different profile and a different card on the server. + AutofillProfile address2 = test::GetServerProfile2(); + AutofillWalletSpecifics profile_specifics2; + SetAutofillWalletSpecificsFromServerProfile(address2, &profile_specifics2); + CreditCard card2 = test::GetMaskedServerCardAmex(); + AutofillWalletSpecifics card_specifics2; + SetAutofillWalletSpecificsFromServerCard(card2, &card_specifics2); + + StartSyncing({profile_specifics2, card_specifics2}); + + // Only the server card should be present on the client. + EXPECT_THAT(GetAllLocalData(), + UnorderedElementsAre(EqualsSpecifics(profile_specifics2), + EqualsSpecifics(card_specifics2))); +} + +// Tests that when the server sends no cards or address, the client should +// delete all it's existing data. +TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) { + // Create one profile and one card on the client. + AutofillProfile local_profile = test::GetServerProfile(); + table()->SetServerProfiles({local_profile}); + CreditCard local_card = test::GetMaskedServerCard(); + table()->SetServerCreditCards({local_card}); + + StartSyncing({}); + + EXPECT_TRUE(GetAllLocalData().empty()); +} + +// Test that when the server sends the same address and card as the client has, +// nothing changes on the client. +TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SameWalletAddressAndCard) { + // Create one profile and one card on the client. + AutofillProfile profile = test::GetServerProfile(); + table()->SetServerProfiles({profile}); + CreditCard card = test::GetMaskedServerCard(); + table()->SetServerCreditCards({card}); + + // Create the same profile and card on the server. + AutofillWalletSpecifics profile_specifics; + SetAutofillWalletSpecificsFromServerProfile(profile, &profile_specifics); + AutofillWalletSpecifics card_specifics; + SetAutofillWalletSpecificsFromServerCard(card, &card_specifics); + + StartSyncing({profile_specifics, card_specifics}); + + EXPECT_THAT(GetAllLocalData(), + UnorderedElementsAre(EqualsSpecifics(profile_specifics), + EqualsSpecifics(card_specifics))); +} + +// Tests that when there are multiple changes happening at the same time, the +// data from the server is what the client ends up with, +TEST_F(AutofillWalletSyncBridgeTest, + MergeSyncData_AddRemoveAndPreserveWalletAddressAndCard) { + // Create two profile and one card on the client. + AutofillProfile profile = test::GetServerProfile(); + AutofillProfile profile2 = test::GetServerProfile2(); + table()->SetServerProfiles({profile, profile2}); + CreditCard card = test::GetMaskedServerCard(); + table()->SetServerCreditCards({card}); + + // Create one of the same profiles and a different card on the server. + AutofillWalletSpecifics profile_specifics; + SetAutofillWalletSpecificsFromServerProfile(profile, &profile_specifics); + // The Amex card has different values for the relevant fields. + CreditCard card2 = test::GetMaskedServerCardAmex(); + AutofillWalletSpecifics card_specifics; + SetAutofillWalletSpecificsFromServerCard(card, &card_specifics); + + StartSyncing({profile_specifics, card_specifics}); + + // Make sure that the client only has the data from the server. + EXPECT_THAT(GetAllLocalData(), + UnorderedElementsAre(EqualsSpecifics(profile_specifics), + EqualsSpecifics(card_specifics))); +} + +// Test that all field values for a address sent form the server are copied on +// the address on the client. +TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletAddressData) { + // Create a profile to be synced from the server. + AutofillProfile profile = test::GetServerProfile(); + AutofillWalletSpecifics profile_specifics; + SetAutofillWalletSpecificsFromServerProfile(profile, &profile_specifics); + + StartSyncing({profile_specifics}); + + EXPECT_THAT(GetAllLocalData(), + UnorderedElementsAre(EqualsSpecifics(profile_specifics))); + + std::vector<std::unique_ptr<AutofillProfile>> profiles; + table()->GetServerProfiles(&profiles); + ASSERT_EQ(1U, profiles.size()); + + // Make sure that all the data was set properly. + EXPECT_EQ(profile.GetRawInfo(NAME_FULL), profiles[0]->GetRawInfo(NAME_FULL)); + EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), + profiles[0]->GetRawInfo(COMPANY_NAME)); + EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), + profiles[0]->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_STATE), + profiles[0]->GetRawInfo(ADDRESS_HOME_STATE)); + EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_CITY), + profiles[0]->GetRawInfo(ADDRESS_HOME_CITY)); + EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY), + profiles[0]->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)); + EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_ZIP), + profiles[0]->GetRawInfo(ADDRESS_HOME_ZIP)); + EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_COUNTRY), + profiles[0]->GetRawInfo(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER), + profiles[0]->GetRawInfo(PHONE_HOME_WHOLE_NUMBER)); + EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE), + profiles[0]->GetRawInfo(ADDRESS_HOME_SORTING_CODE)); + EXPECT_EQ(profile.language_code(), profiles[0]->language_code()); + + // Also make sure that those types are not empty, to exercice all the code + // paths. + EXPECT_FALSE(profile.GetRawInfo(NAME_FULL).empty()); + EXPECT_FALSE(profile.GetRawInfo(COMPANY_NAME).empty()); + EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS).empty()); + EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_STATE).empty()); + EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_CITY).empty()); + EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY).empty()); + EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_ZIP).empty()); + EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_COUNTRY).empty()); + EXPECT_FALSE(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER).empty()); + EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE).empty()); + EXPECT_FALSE(profile.language_code().empty()); +} + +// Test that all field values for a card sent form the server are copied on the +// card on the client. +TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) { + // Create a card to be synced from the server. + CreditCard card = test::GetMaskedServerCard(); + // Add this value type as it is not added by default but should be synced. + card.set_bank_name("The Bank"); + AutofillWalletSpecifics card_specifics; + SetAutofillWalletSpecificsFromServerCard(card, &card_specifics); + + StartSyncing({card_specifics}); + + EXPECT_THAT(GetAllLocalData(), + UnorderedElementsAre(EqualsSpecifics(card_specifics))); + + std::vector<std::unique_ptr<CreditCard>> cards; + table()->GetServerCreditCards(&cards); + ASSERT_EQ(1U, cards.size()); + + // Make sure that all the data was set properly. + EXPECT_EQ(card.network(), cards[0]->network()); + EXPECT_EQ(card.LastFourDigits(), cards[0]->LastFourDigits()); + EXPECT_EQ(card.expiration_month(), cards[0]->expiration_month()); + EXPECT_EQ(card.expiration_year(), cards[0]->expiration_year()); + EXPECT_EQ(card.billing_address_id(), cards[0]->billing_address_id()); + EXPECT_EQ(card.card_type(), cards[0]->card_type()); + EXPECT_EQ(card.bank_name(), cards[0]->bank_name()); + + // Also make sure that those types are not empty, to exercice all the code + // paths. + EXPECT_FALSE(card.network().empty()); + EXPECT_FALSE(card.LastFourDigits().empty()); + EXPECT_NE(0, card.expiration_month()); + EXPECT_NE(0, card.expiration_year()); + EXPECT_FALSE(card.billing_address_id().empty()); + EXPECT_NE(CreditCard::CARD_TYPE_UNKNOWN, card.card_type()); + EXPECT_FALSE(card.bank_name().empty()); +} + } // namespace autofill \ No newline at end of file
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc index bd3f5e6..27a429b9 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -33,7 +33,7 @@ return reinterpret_cast<void*>(&user_data_key); } -const char* CardNetworkFromWalletCardType( +const char* CardNetworkFromAutofillWalletCardType( sync_pb::WalletMaskedCreditCard::WalletCardType type) { switch (type) { case sync_pb::WalletMaskedCreditCard::AMEX: @@ -58,7 +58,7 @@ } } -CreditCard::CardType CardTypeFromWalletCardClass( +CreditCard::CardType CardTypeFromAutofillWalletCardClass( sync_pb::WalletMaskedCreditCard::WalletCardClass card_class) { switch (card_class) { case sync_pb::WalletMaskedCreditCard::CREDIT: @@ -72,7 +72,7 @@ } } -CreditCard::ServerStatus ServerToLocalStatus( +CreditCard::ServerStatus ServerToLocalWalletCardStatus( sync_pb::WalletMaskedCreditCard::WalletCardStatus status) { switch (status) { case sync_pb::WalletMaskedCreditCard::VALID: @@ -84,12 +84,14 @@ } } -CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) { +CreditCard CardFromWalletCardSpecifics( + const sync_pb::WalletMaskedCreditCard& card) { CreditCard result(CreditCard::MASKED_SERVER_CARD, card.id()); result.SetNumber(base::UTF8ToUTF16(card.last_four())); - result.SetServerStatus(ServerToLocalStatus(card.status())); - result.SetNetworkForMaskedCard(CardNetworkFromWalletCardType(card.type())); - result.set_card_type(CardTypeFromWalletCardClass(card.card_class())); + result.SetServerStatus(ServerToLocalWalletCardStatus(card.status())); + result.SetNetworkForMaskedCard( + CardNetworkFromAutofillWalletCardType(card.type())); + result.set_card_type(CardTypeFromAutofillWalletCardClass(card.card_class())); result.SetRawInfo(CREDIT_CARD_NAME_FULL, base::UTF8ToUTF16(card.name_on_card())); result.SetExpirationMonth(card.exp_month()); @@ -99,7 +101,7 @@ return result; } -AutofillProfile ProfileFromSpecifics( +AutofillProfile ProfileFromWalletCardSpecifics( const sync_pb::WalletPostalAddress& address) { AutofillProfile profile(AutofillProfile::SERVER_PROFILE, std::string()); @@ -275,11 +277,11 @@ switch (autofill_specifics.type()) { case sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD: wallet_cards->push_back( - CardFromSpecifics(autofill_specifics.masked_card())); + CardFromWalletCardSpecifics(autofill_specifics.masked_card())); break; case sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS: wallet_addresses->push_back( - ProfileFromSpecifics(autofill_specifics.address())); + ProfileFromWalletCardSpecifics(autofill_specifics.address())); // Map the sync billing address id to the profile's id. ids[autofill_specifics.address().id()] =
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index 16b8176..c7a629f 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -26,6 +26,7 @@ #include "components/signin/core/browser/account_info.h" #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_metrics.h" +#include "components/sync/base/bind_to_task_runner.h" #include "components/sync/base/cryptographer.h" #include "components/sync/base/passphrase_type.h" #include "components/sync/base/report_unrecoverable_error.h" @@ -105,10 +106,9 @@ sync_state = NOT_ALLOWED_BY_POLICY; } else if (disable_reasons & ProfileSyncService::DISABLE_REASON_PLATFORM_OVERRIDE) { - // This case means either a command-line flag or Android's "MasterSync" - // toggle. However, the latter is not plumbed into ProfileSyncService until - // after this method, so currently we only get here for the command-line - // case. See http://crbug.com/568771. + // This case means Android's "MasterSync" toggle. However, that is not + // plumbed into ProfileSyncService until after this method, so we never get + // here. See http://crbug.com/568771. sync_state = NOT_ALLOWED_BY_PLATFORM; } else if (disable_reasons & ProfileSyncService::DISABLE_REASON_USER_CHOICE) { if (first_setup_complete) { @@ -1603,6 +1603,18 @@ syncer::ConfigureContext::STORAGE_IN_MEMORY; } data_type_manager_->Configure(types, configure_context); + + // Record in UMA whether we're configuring the full Sync feature or only the + // transport. + enum class ConfigureDataTypeManagerOption { + kFeature = 0, + kTransport = 1, + kMaxValue = kTransport + }; + UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureDataTypeManagerOption", + IsSyncFeatureEnabled() + ? ConfigureDataTypeManagerOption::kFeature + : ConfigureDataTypeManagerOption::kTransport); } syncer::UserShare* ProfileSyncService::GetUserShare() const { @@ -1703,9 +1715,13 @@ dtc_iter->second->state())); if (dtc_iter->second->state() != syncer::DataTypeController::NOT_RUNNING) { - dtc_iter->second->GetStatusCounters(base::BindRepeating( - &ProfileSyncService::OnDatatypeStatusCounterUpdated, - base::Unretained(this))); + // We use BindToCurrentSequence() to make sure observers (i.e. + // |type_debug_info_observers_|) are not notified synchronously, which + // the UI code (chrome://sync-internals) doesn't handle well. + dtc_iter->second->GetStatusCounters( + BindToCurrentSequence(base::BindRepeating( + &ProfileSyncService::OnDatatypeStatusCounterUpdated, + base::Unretained(this)))); } }
diff --git a/components/domain_reliability/service_unittest.cc b/components/domain_reliability/service_unittest.cc index a115f15..877fc046 100644 --- a/components/domain_reliability/service_unittest.cc +++ b/components/domain_reliability/service_unittest.cc
@@ -102,8 +102,8 @@ int SubscribePermissionStatusChange( content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override { NOTIMPLEMENTED();
diff --git a/components/drive/job_scheduler.cc b/components/drive/job_scheduler.cc index a88243e7..31523b7 100644 --- a/components/drive/job_scheduler.cc +++ b/components/drive/job_scheduler.cc
@@ -156,8 +156,8 @@ // Metadata jobs are cheap, so we run them concurrently. File jobs run serially. const int JobScheduler::kMaxJobCount[] = { - 5, // METADATA_QUEUE - 1, // FILE_QUEUE + 20, // METADATA_QUEUE + 1, // FILE_QUEUE }; JobScheduler::JobEntry::JobEntry(JobType type)
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 15b3a14..296d41e 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -206,6 +206,7 @@ "//components/encrypted_messages:encrypted_messages", "//components/variations", "//net", + "//services/network/public/cpp:cpp", "//third_party/metrics_proto", "//third_party/zlib/google:compression_utils", "//url", @@ -378,6 +379,8 @@ "//extensions/buildflags", "//mojo/public/cpp/bindings", "//net:test_support", + "//services/network:test_support", + "//services/network/public/cpp:cpp", "//services/service_manager/public/cpp", "//testing/gtest", "//third_party/zlib/google:compression_utils",
diff --git a/components/metrics/net/DEPS b/components/metrics/net/DEPS index fcbd832..633e4afc 100644 --- a/components/metrics/net/DEPS +++ b/components/metrics/net/DEPS
@@ -5,5 +5,7 @@ "+components/encrypted_messages", "+components/variations", "+net", + "+services/network/public/cpp", + "+services/network/test", "+third_party/cros_system_api", ]
diff --git a/components/metrics/net/net_metrics_log_uploader.cc b/components/metrics/net/net_metrics_log_uploader.cc index addad6b9..a213b92 100644 --- a/components/metrics/net/net_metrics_log_uploader.cc +++ b/components/metrics/net/net_metrics_log_uploader.cc
@@ -15,6 +15,8 @@ #include "net/base/url_util.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_fetcher.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" #include "third_party/metrics_proto/reporting_info.pb.h" #include "url/gurl.h" @@ -122,30 +124,43 @@ return result; } +void RecordUploadSizeForServiceTypeHistograms( + int64_t content_length, + metrics::MetricsLogUploader::MetricServiceType service_type) { + switch (service_type) { + case metrics::MetricsLogUploader::UMA: + UMA_HISTOGRAM_COUNTS_1M("UMA.LogUploader.UploadSize", content_length); + break; + case metrics::MetricsLogUploader::UKM: + UMA_HISTOGRAM_COUNTS_1M("UKM.LogUploader.UploadSize", content_length); + break; + } +} + } // namespace namespace metrics { NetMetricsLogUploader::NetMetricsLogUploader( - net::URLRequestContextGetter* request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, base::StringPiece server_url, base::StringPiece mime_type, MetricsLogUploader::MetricServiceType service_type, const MetricsLogUploader::UploadCallback& on_upload_complete) - : request_context_getter_(request_context_getter), + : url_loader_factory_(std::move(url_loader_factory)), server_url_(server_url), mime_type_(mime_type.data(), mime_type.size()), service_type_(service_type), on_upload_complete_(on_upload_complete) {} NetMetricsLogUploader::NetMetricsLogUploader( - net::URLRequestContextGetter* request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, base::StringPiece server_url, base::StringPiece insecure_server_url, base::StringPiece mime_type, MetricsLogUploader::MetricServiceType service_type, const MetricsLogUploader::UploadCallback& on_upload_complete) - : request_context_getter_(request_context_getter), + : url_loader_factory_(std::move(url_loader_factory)), server_url_(server_url), insecure_server_url_(insecure_server_url), mime_type_(mime_type.data(), mime_type.size()), @@ -179,88 +194,92 @@ const ReportingInfo& reporting_info, const GURL& url) { DCHECK(!log_hash.empty()); - current_fetch_ = - net::URLFetcher::Create(url, net::URLFetcher::POST, this, - GetNetworkTrafficAnnotation(service_type_)); - auto service = data_use_measurement::DataUseUserData::UMA; - switch (service_type_) { - case MetricsLogUploader::UMA: - service = data_use_measurement::DataUseUserData::UMA; - break; - case MetricsLogUploader::UKM: - service = data_use_measurement::DataUseUserData::UKM; - break; - } - data_use_measurement::DataUseUserData::AttachToFetcher(current_fetch_.get(), - service); - current_fetch_->SetRequestContext(request_context_getter_); + // TODO(crbug.com/808498): Restore the data use measurement when bug is fixed. + + auto resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->url = url; + // Drop cookies and auth data. + resource_request->load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA | + net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES; + resource_request->method = "POST"; + std::string reporting_info_string = SerializeReportingInfo(reporting_info); // If we are not using HTTPS for this upload, encrypt it. We do not encrypt // requests to localhost to allow testing with a local collector that doesn't // have decryption enabled. - if (!url.SchemeIs(url::kHttpsScheme) && !net::IsLocalhost(url)) { - std::string encrypted_message; - if (!EncryptString(compressed_log_data, &encrypted_message)) { - current_fetch_.reset(); - on_upload_complete_.Run(0, net::ERR_FAILED, false); - return; - } - current_fetch_->SetUploadData(mime_type_, encrypted_message); - + bool should_encrypt = + !url.SchemeIs(url::kHttpsScheme) && !net::IsLocalhost(url); + if (should_encrypt) { std::string encrypted_hash; std::string base64_encoded_hash; if (!EncryptString(log_hash, &encrypted_hash)) { - current_fetch_.reset(); on_upload_complete_.Run(0, net::ERR_FAILED, false); return; } base::Base64Encode(encrypted_hash, &base64_encoded_hash); - current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + - base64_encoded_hash); + resource_request->headers.SetHeader("X-Chrome-UMA-Log-SHA1", + base64_encoded_hash); std::string encrypted_reporting_info; std::string base64_reporting_info; if (!EncryptString(reporting_info_string, &encrypted_reporting_info)) { - current_fetch_.reset(); on_upload_complete_.Run(0, net::ERR_FAILED, false); return; } base::Base64Encode(encrypted_reporting_info, &base64_reporting_info); - current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-ReportingInfo: " + - base64_reporting_info); + resource_request->headers.SetHeader("X-Chrome-UMA-ReportingInfo", + base64_reporting_info); } else { - current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + log_hash); - current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-ReportingInfo:" + - reporting_info_string); - current_fetch_->SetUploadData(mime_type_, compressed_log_data); + resource_request->headers.SetHeader("X-Chrome-UMA-Log-SHA1", log_hash); + resource_request->headers.SetHeader("X-Chrome-UMA-ReportingInfo", + reporting_info_string); // Tell the server that we're uploading gzipped protobufs only if we are not // encrypting, since encrypted messages have to be decrypted server side // after decryption, not before. - current_fetch_->AddExtraRequestHeader("content-encoding: gzip"); + resource_request->headers.SetHeader("content-encoding", "gzip"); } - // Drop cookies and auth data. - current_fetch_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_DO_NOT_SEND_AUTH_DATA | - net::LOAD_DO_NOT_SEND_COOKIES); - current_fetch_->Start(); + + url_loader_ = network::SimpleURLLoader::Create( + std::move(resource_request), GetNetworkTrafficAnnotation(service_type_)); + + if (should_encrypt) { + std::string encrypted_message; + if (!EncryptString(compressed_log_data, &encrypted_message)) { + url_loader_.reset(); + on_upload_complete_.Run(0, net::ERR_FAILED, false); + return; + } + url_loader_->AttachStringForUpload(encrypted_message, mime_type_); + RecordUploadSizeForServiceTypeHistograms(encrypted_message.size(), + service_type_); + } else { + url_loader_->AttachStringForUpload(compressed_log_data, mime_type_); + RecordUploadSizeForServiceTypeHistograms(compressed_log_data.size(), + service_type_); + } + + // It's safe to use |base::Unretained(this)| here, because |this| owns + // the |url_loader_|, and the callback will be cancelled if the |url_loader_| + // is destroyed. + url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory_.get(), + base::BindOnce(&NetMetricsLogUploader::OnURLLoadComplete, + base::Unretained(this))); } -void NetMetricsLogUploader::OnURLFetchComplete(const net::URLFetcher* source) { - // We're not allowed to re-use the existing |URLFetcher|s, so free them here. - // Note however that |source| is aliased to the fetcher, so we should be - // careful not to delete it too early. - DCHECK_EQ(current_fetch_.get(), source); - int response_code = source->GetResponseCode(); - if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) - response_code = -1; - int error_code = 0; - const net::URLRequestStatus& request_status = source->GetStatus(); - if (request_status.status() != net::URLRequestStatus::SUCCESS) { - error_code = request_status.error(); - } - bool was_https = source->GetURL().SchemeIs(url::kHttpsScheme); - current_fetch_.reset(); +// The callback is only invoked if |url_loader_| it was bound against is alive. +void NetMetricsLogUploader::OnURLLoadComplete( + std::unique_ptr<std::string> response_body) { + int response_code = -1; + if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) + response_code = url_loader_->ResponseInfo()->headers->response_code(); + + int error_code = url_loader_->NetError(); + + bool was_https = url_loader_->GetFinalURL().SchemeIs(url::kHttpsScheme); + url_loader_.reset(); on_upload_complete_.Run(response_code, error_code, was_https); }
diff --git a/components/metrics/net/net_metrics_log_uploader.h b/components/metrics/net/net_metrics_log_uploader.h index 5c4045bd..99fce26 100644 --- a/components/metrics/net/net_metrics_log_uploader.h +++ b/components/metrics/net/net_metrics_log_uploader.h
@@ -11,29 +11,25 @@ #include "base/macros.h" #include "base/strings/string_piece.h" #include "components/metrics/metrics_log_uploader.h" -#include "net/url_request/url_fetcher_delegate.h" #include "third_party/metrics_proto/reporting_info.pb.h" #include "url/gurl.h" -namespace net { -class URLFetcher; -class URLRequestContextGetter; -} +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network namespace metrics { // Implementation of MetricsLogUploader using the Chrome network stack. -class NetMetricsLogUploader : public MetricsLogUploader, - public net::URLFetcherDelegate { +class NetMetricsLogUploader : public MetricsLogUploader { public: // Constructs a NetMetricsLogUploader which uploads data to |server_url| with // the specified |mime_type|. The |service_type| marks which service the // data usage should be attributed to. The |on_upload_complete| callback will // be called with the HTTP response code of the upload or with -1 on an error. - // The caller must ensure that |request_context_getter| remains valid for the - // lifetime of this class. NetMetricsLogUploader( - net::URLRequestContextGetter* request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, base::StringPiece server_url, base::StringPiece mime_type, MetricsLogUploader::MetricServiceType service_type, @@ -43,7 +39,7 @@ // |insecure_server_url|. That URL is used as a fallback if a connection // to |server_url| fails, requests are encrypted when sent to an HTTP URL. NetMetricsLogUploader( - net::URLRequestContextGetter* request_context_getter, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, base::StringPiece server_url, base::StringPiece insecure_server_url, base::StringPiece mime_type, @@ -65,15 +61,14 @@ const ReportingInfo& reporting_info, const GURL& url); - // net::URLFetcherDelegate: - void OnURLFetchComplete(const net::URLFetcher* source) override; + void OnURLLoadComplete(std::unique_ptr<std::string> response_body); // Encrypts a |plaintext| string, using the encrypted_messages component, // returns |encrypted| which is a serialized EncryptedMessage object. bool EncryptString(const std::string& plaintext, std::string* encrypted); - // The request context for fetches done using the network stack. - net::URLRequestContextGetter* const request_context_getter_; + // The URLLoader factory for loads done using the network stack. + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; const GURL server_url_; const GURL insecure_server_url_; @@ -81,7 +76,7 @@ const MetricsLogUploader ::MetricServiceType service_type_; const MetricsLogUploader::UploadCallback on_upload_complete_; // The outstanding transmission appears as a URL Fetch operation. - std::unique_ptr<net::URLFetcher> current_fetch_; + std::unique_ptr<network::SimpleURLLoader> url_loader_; DISALLOW_COPY_AND_ASSIGN(NetMetricsLogUploader); };
diff --git a/components/metrics/net/net_metrics_log_uploader_unittest.cc b/components/metrics/net/net_metrics_log_uploader_unittest.cc index 76652ec..f6aecdc9 100644 --- a/components/metrics/net/net_metrics_log_uploader_unittest.cc +++ b/components/metrics/net/net_metrics_log_uploader_unittest.cc
@@ -7,8 +7,14 @@ #include "base/base64.h" #include "base/bind.h" #include "base/macros.h" +#include "base/run_loop.h" +#include "base/test/bind_test_util.h" +#include "base/test/scoped_task_environment.h" #include "components/encrypted_messages/encrypted_message.pb.h" #include "net/url_request/test_url_fetcher_factory.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/metrics_proto/reporting_info.pb.h" #include "third_party/zlib/google/compression_utils.h" @@ -18,14 +24,25 @@ class NetMetricsLogUploaderTest : public testing::Test { public: - NetMetricsLogUploaderTest() : on_upload_complete_count_(0) { + NetMetricsLogUploaderTest() + : on_upload_complete_count_(0), + test_shared_url_loader_factory_( + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_)) { + test_url_loader_factory_.SetInterceptor(base::BindLambdaForTesting( + [&](const network::ResourceRequest& request) { + upload_data_ = network::GetUploadData(request); + headers_ = request.headers; + loop_.Quit(); + })); } void CreateAndOnUploadCompleteReuseUploader() { ReportingInfo reporting_info; reporting_info.set_attempt_count(10); uploader_.reset(new NetMetricsLogUploader( - nullptr, "https://dummy_server", "dummy_mime", MetricsLogUploader::UMA, + test_shared_url_loader_factory_, "https://dummy_server", "dummy_mime", + MetricsLogUploader::UMA, base::Bind(&NetMetricsLogUploaderTest::OnUploadCompleteReuseUploader, base::Unretained(this)))); uploader_->UploadLog("initial_dummy_data", "initial_dummy_hash", @@ -35,7 +52,8 @@ void CreateUploaderAndUploadToSecureURL(const std::string& url) { ReportingInfo dummy_reporting_info; uploader_.reset(new NetMetricsLogUploader( - nullptr, url, "dummy_mime", MetricsLogUploader::UMA, + test_shared_url_loader_factory_, url, "dummy_mime", + MetricsLogUploader::UMA, base::Bind(&NetMetricsLogUploaderTest::DummyOnUploadComplete, base::Unretained(this)))); uploader_->UploadLog("dummy_data", "dummy_hash", dummy_reporting_info); @@ -44,8 +62,8 @@ void CreateUploaderAndUploadToInsecureURL() { ReportingInfo dummy_reporting_info; uploader_.reset(new NetMetricsLogUploader( - nullptr, "http://dummy_insecure_server", "dummy_mime", - MetricsLogUploader::UMA, + test_shared_url_loader_factory_, "http://dummy_insecure_server", + "dummy_mime", MetricsLogUploader::UMA, base::Bind(&NetMetricsLogUploaderTest::DummyOnUploadComplete, base::Unretained(this)))); std::string compressed_message; @@ -71,20 +89,48 @@ } } + network::TestURLLoaderFactory::PendingRequest* GetPendingRequest( + size_t index) { + if (index >= test_url_loader_factory_.pending_requests()->size()) + return nullptr; + auto* request = &(*test_url_loader_factory_.pending_requests())[index]; + DCHECK(request); + return request; + } + int on_upload_complete_count() const { return on_upload_complete_count_; } + network::TestURLLoaderFactory* test_url_loader_factory() { + return &test_url_loader_factory_; + } + + const net::HttpRequestHeaders& last_request_headers() { return headers_; } + + const std::string& last_upload_data() { return upload_data_; } + + void WaitForRequest() { loop_.Run(); } + private: std::unique_ptr<NetMetricsLogUploader> uploader_; int on_upload_complete_count_; + + network::TestURLLoaderFactory test_url_loader_factory_; + scoped_refptr<network::SharedURLLoaderFactory> + test_shared_url_loader_factory_; + + base::test::ScopedTaskEnvironment scoped_task_environment_; + + base::RunLoop loop_; + std::string upload_data_; + net::HttpRequestHeaders headers_; + DISALLOW_COPY_AND_ASSIGN(NetMetricsLogUploaderTest); }; -void CheckReportingInfoHeader(net::TestURLFetcher* fetcher, +void CheckReportingInfoHeader(net::HttpRequestHeaders headers, int expected_attempt_count) { - net::HttpRequestHeaders headers; - fetcher->GetExtraRequestHeaders(&headers); std::string reporting_info_base64; EXPECT_TRUE( headers.GetHeader("X-Chrome-UMA-ReportingInfo", &reporting_info_base64)); @@ -97,18 +143,18 @@ } TEST_F(NetMetricsLogUploaderTest, OnUploadCompleteReuseUploader) { - net::TestURLFetcherFactory factory; CreateAndOnUploadCompleteReuseUploader(); + WaitForRequest(); // Mimic the initial fetcher callback. - net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); - CheckReportingInfoHeader(fetcher, 10); - fetcher->delegate()->OnURLFetchComplete(fetcher); + CheckReportingInfoHeader(last_request_headers(), 10); + test_url_loader_factory()->SimulateResponseWithoutRemovingFromPendingList( + GetPendingRequest(0), ""); // Mimic the second fetcher callback. - fetcher = factory.GetFetcherByID(0); - CheckReportingInfoHeader(fetcher, 20); - fetcher->delegate()->OnURLFetchComplete(fetcher); + CheckReportingInfoHeader(last_request_headers(), 20); + test_url_loader_factory()->SimulateResponseWithoutRemovingFromPendingList( + GetPendingRequest(1), ""); EXPECT_EQ(on_upload_complete_count(), 2); } @@ -116,29 +162,26 @@ // Test that attempting to upload to an HTTP URL results in an encrypted // message. TEST_F(NetMetricsLogUploaderTest, MessageOverHTTPIsEncrypted) { - net::TestURLFetcherFactory factory; CreateUploaderAndUploadToInsecureURL(); - net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); + WaitForRequest(); encrypted_messages::EncryptedMessage message; - EXPECT_TRUE(message.ParseFromString(fetcher->upload_data())); + EXPECT_TRUE(message.ParseFromString(last_upload_data())); } // Test that attempting to upload to an HTTPS URL results in an unencrypted // message. TEST_F(NetMetricsLogUploaderTest, MessageOverHTTPSIsNotEncrypted) { - net::TestURLFetcherFactory factory; CreateUploaderAndUploadToSecureURL("https://dummy_secure_server"); - net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); - EXPECT_EQ(fetcher->upload_data(), "dummy_data"); + WaitForRequest(); + EXPECT_EQ(last_upload_data(), "dummy_data"); } // Test that attempting to upload to localhost over http results in an // unencrypted message. TEST_F(NetMetricsLogUploaderTest, MessageOverHTTPLocalhostIsNotEncrypted) { - net::TestURLFetcherFactory factory; CreateUploaderAndUploadToSecureURL("http://localhost"); - net::TestURLFetcher* fetcher = factory.GetFetcherByID(0); - EXPECT_EQ(fetcher->upload_data(), "dummy_data"); + WaitForRequest(); + EXPECT_EQ(last_upload_data(), "dummy_data"); } } // namespace metrics
diff --git a/components/omnibox/browser/document_suggestions_service.cc b/components/omnibox/browser/document_suggestions_service.cc index 7906a090..4b74167fd 100644 --- a/components/omnibox/browser/document_suggestions_service.cc +++ b/components/omnibox/browser/document_suggestions_service.cc
@@ -74,8 +74,10 @@ const TemplateURLService* template_url_service, StartCallback start_callback, CompletionCallback completion_callback) { - std::string endpoint = variations::GetVariationParamValueByFeature( - omnibox::kDocumentProvider, "Endpoint"); + std::string endpoint = base::GetFieldTrialParamValueByFeature( + omnibox::kDocumentProvider, "DocumentProviderEndpoint"); + if (endpoint.empty()) + endpoint = "https://cloudsearch.googleapis.com/v1/query/search"; const GURL suggest_url = GURL(endpoint); DCHECK(suggest_url.is_valid()); @@ -111,16 +113,9 @@ // TODO(https://crbug.com/808498) re-add data use measurement once // SimpleURLLoader supports it. // We should attach data_use_measurement::DataUseUserData::OMNIBOX. - StartDownloadAndTransferLoader(std::move(request), std::string(), - traffic_annotation, std::move(start_callback), - std::move(completion_callback)); - - // TODO(skare): Include code to catch token fetch in-progress; otherwise - // we'll lose one set of results. // Create and fetch an OAuth2 token. - std::string scope = base::GetFieldTrialParamValueByFeature( - omnibox::kDocumentProvider, "OAuth2Scope"); + std::string scope = "https://www.googleapis.com/auth/cloud_search.query"; OAuth2TokenService::ScopeSet scopes; scopes.insert(scope); token_fetcher_ = std::make_unique<identity::PrimaryAccountAccessTokenFetcher>(
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index 081bedc..dbc6518 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -93,16 +93,8 @@ LOG(ERROR) << "SSL certificate is not valid"; if (!allowed_origin || invalid_ssl) { - // Don't show UI. Resolve .canMakepayment() with "false". Reject .show() - // with "NotSupportedError". - spec_ = std::make_unique<PaymentRequestSpec>( - mojom::PaymentOptions::New(), mojom::PaymentDetails::New(), - std::vector<mojom::PaymentMethodDataPtr>(), this, - delegate_->GetApplicationLocale()); - state_ = std::make_unique<PaymentRequestState>( - web_contents_, top_level_origin_, frame_origin_, spec_.get(), this, - delegate_->GetApplicationLocale(), delegate_->GetPersonalDataManager(), - delegate_.get(), &journey_logger_); + // Intentionally don't set |spec_| and |state_|. Don't show UI. Resolve + // .canMakepayment() with "false". Reject .show() with "NotSupportedError". return; } @@ -178,10 +170,16 @@ return; } + if (!state_) { + // SSL is not valid. + AreRequestedMethodsSupportedCallback(false); + return; + } + is_show_user_gesture_ = is_user_gesture; - // TODO(crbug.com/783811): Display a spinner when checking whether - // the methods are supported asynchronously for better user experience. + display_handle_->Show(this); + state_->AreRequestedMethodsSupported( base::BindOnce(&PaymentRequest::AreRequestedMethodsSupportedCallback, weak_ptr_factory_.GetWeakPtr())); @@ -205,10 +203,8 @@ void PaymentRequest::AreRequestedMethodsSupportedCallback( bool methods_supported) { if (methods_supported) { - journey_logger_.SetEventOccurred(JourneyLogger::EVENT_SHOWN); - - DCHECK(display_handle_); - display_handle_->Show(this); + if (SatisfiesSkipUIConstraints()) + Pay(); } else { journey_logger_.SetNotShown( JourneyLogger::NOT_SHOWN_REASON_NO_SUPPORTED_PAYMENT_METHOD); @@ -285,10 +281,11 @@ if (observer_for_testing_) observer_for_testing_->OnCanMakePaymentCalled(); - if (!delegate_->GetPrefService()->GetBoolean(kCanMakePaymentEnabled)) { + if (!delegate_->GetPrefService()->GetBoolean(kCanMakePaymentEnabled) || + !state_) { CanMakePaymentCallback(/*can_make_payment=*/false); } else { - state()->CanMakePayment( + state_->CanMakePayment( base::BindOnce(&PaymentRequest::CanMakePaymentCallback, weak_ptr_factory_.GetWeakPtr())); } @@ -389,6 +386,10 @@ display_handle_.reset(); } +void PaymentRequest::RecordDialogShownEventInJourneyLogger() { + journey_logger_.SetEventOccurred(JourneyLogger::EVENT_SHOWN); +} + bool PaymentRequest::IsIncognito() const { return delegate_->IsIncognito(); } @@ -415,10 +416,10 @@ } void PaymentRequest::CanMakePaymentCallback(bool can_make_payment) { - if (CanMakePaymentQueryFactory::GetInstance() - ->GetForContext(web_contents_->GetBrowserContext()) - ->CanQuery(top_level_origin_, frame_origin_, - spec()->stringified_method_data())) { + if (!spec_ || CanMakePaymentQueryFactory::GetInstance() + ->GetForContext(web_contents_->GetBrowserContext()) + ->CanQuery(top_level_origin_, frame_origin_, + spec_->stringified_method_data())) { RespondToCanMakePaymentQuery(can_make_payment, false); } else if (OriginSecurityChecker::IsOriginLocalhostOrFile(frame_origin_)) { RespondToCanMakePaymentQuery(can_make_payment, true);
diff --git a/components/payments/content/payment_request.h b/components/payments/content/payment_request.h index 42c6e25d..25b15e9a7 100644 --- a/components/payments/content/payment_request.h +++ b/components/payments/content/payment_request.h
@@ -102,6 +102,9 @@ // Hide this Payment Request if it's already showing. void HideIfNecessary(); + // Record the "dialog shown" event in the journey logger. + void RecordDialogShownEventInJourneyLogger(); + bool IsIncognito() const; // Returns true if this payment request supports skipping the Payment Sheet.
diff --git a/components/payments/content/payment_request_display_manager.h b/components/payments/content/payment_request_display_manager.h index 222556b..23e35d9 100644 --- a/components/payments/content/payment_request_display_manager.h +++ b/components/payments/content/payment_request_display_manager.h
@@ -31,8 +31,8 @@ public: class DisplayHandle { public: - explicit DisplayHandle(PaymentRequestDisplayManager* display_manager, - ContentPaymentRequestDelegate* delegate); + DisplayHandle(PaymentRequestDisplayManager* display_manager, + ContentPaymentRequestDelegate* delegate); ~DisplayHandle(); void Show(PaymentRequest* request); // Attempt to display |url| inside the Payment Request dialog and run
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc index 3cfe66c..766789d 100644 --- a/components/payments/content/payment_request_state.cc +++ b/components/payments/content/payment_request_state.cc
@@ -46,6 +46,8 @@ delegate_(delegate), personal_data_manager_(personal_data_manager), journey_logger_(journey_logger), + are_requested_methods_supported_( + !spec_->supported_card_networks().empty()), selected_shipping_profile_(nullptr), selected_shipping_option_error_profile_(nullptr), selected_contact_profile_(nullptr), @@ -140,6 +142,7 @@ SetDefaultProfileSelections(); get_all_instruments_finished_ = true; + are_requested_methods_supported_ |= !available_instruments_.empty(); NotifyOnGetAllPaymentInstrumentsFinished(); // Fullfill the pending CanMakePayment call. @@ -208,8 +211,7 @@ StatusCallback callback) { DCHECK(get_all_instruments_finished_); - std::move(callback).Run(!spec_->supported_card_networks().empty() || - !available_instruments_.empty()); + std::move(callback).Run(are_requested_methods_supported_); } std::string PaymentRequestState::GetAuthenticatedEmail() const {
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h index 47bab37..10f4d9b 100644 --- a/components/payments/content/payment_request_state.h +++ b/components/payments/content/payment_request_state.h
@@ -182,6 +182,13 @@ return get_all_instruments_finished_; } + // Returns true after is_get_all_instruments_finished() is true and supported + // payment method are found. Should not be called before + // is_get_all_instruments_finished() is true. + bool are_requested_methods_supported() const { + return are_requested_methods_supported_; + } + const std::string& GetApplicationLocale(); autofill::PersonalDataManager* GetPersonalDataManager(); autofill::RegionDataLoader* GetRegionDataLoader(); @@ -270,6 +277,7 @@ StatusCallback can_make_payment_callback_; StatusCallback are_requested_methods_supported_callback_; + bool are_requested_methods_supported_; autofill::AutofillProfile* selected_shipping_profile_; autofill::AutofillProfile* selected_shipping_option_error_profile_;
diff --git a/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc b/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc index cc68640..e9c32c42 100644 --- a/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc +++ b/components/services/pdf_compositor/pdf_compositor_impl_unittest.cc
@@ -52,12 +52,13 @@ return is_ready_; } - void OnCompositeToPdfCallback(mojom::PdfCompositor::Status status, - base::ReadOnlySharedMemoryRegion region) { + static void OnCompositeToPdfCallback( + mojom::PdfCompositor::Status status, + base::ReadOnlySharedMemoryRegion region) { // A stub for testing, no implementation. } - protected: + private: base::test::ScopedTaskEnvironment task_environment_; std::unique_ptr<base::RunLoop> run_loop_; bool is_ready_; @@ -89,44 +90,35 @@ // Frame 1 contains content 3 which corresponds to frame 2. // Frame 1 should be ready as frame 2 is ready. - ContentToFrameMap subframe_content_map; - subframe_content_map[3u] = 2u; + ContentToFrameMap subframe_content_map = {{3u, 2u}}; base::flat_set<uint64_t> pending_subframes; - bool is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map), - &pending_subframes); + bool is_ready = + impl.IsReadyToComposite(1u, subframe_content_map, &pending_subframes); EXPECT_TRUE(is_ready); EXPECT_TRUE(pending_subframes.empty()); // If another page of frame 1 needs content 2 which corresponds to frame 3. // This page is ready since frame 3 was painted also. - subframe_content_map.clear(); - subframe_content_map[2u] = 3u; - is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map), - &pending_subframes); + subframe_content_map = {{2u, 3u}}; + is_ready = + impl.IsReadyToComposite(1u, subframe_content_map, &pending_subframes); EXPECT_TRUE(is_ready); EXPECT_TRUE(pending_subframes.empty()); // Frame 1 with content 1, 2 and 3 should not be ready since content 1's // content in frame 4 is not painted yet. - subframe_content_map.clear(); - subframe_content_map[1u] = 4u; - subframe_content_map[2u] = 3u; - subframe_content_map[3u] = 2u; - is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map), - &pending_subframes); + subframe_content_map = {{1u, 4u}, {2u, 3u}, {3u, 2u}}; + is_ready = + impl.IsReadyToComposite(1u, subframe_content_map, &pending_subframes); EXPECT_FALSE(is_ready); ASSERT_EQ(pending_subframes.size(), 1u); EXPECT_EQ(*pending_subframes.begin(), 4u); // Add content of frame 4. Now it is ready for composition. - subframe_content_map.clear(); - subframe_content_map[1u] = 4u; - subframe_content_map[2u] = 3u; - subframe_content_map[3u] = 2u; impl.AddSubframeContent(4u, mojo::SharedBufferHandle::Create(10), ContentToFrameMap()); - is_ready = impl.IsReadyToComposite(1u, std::move(subframe_content_map), - &pending_subframes); + is_ready = + impl.IsReadyToComposite(1u, subframe_content_map, &pending_subframes); EXPECT_TRUE(is_ready); EXPECT_TRUE(pending_subframes.empty()); } @@ -134,28 +126,25 @@ TEST_F(PdfCompositorImplTest, MultiLayerDependency) { PdfCompositorImpl impl("unittest", nullptr); // Frame 3 has content 1 which refers to subframe 1. - ContentToFrameMap subframe_content_map; - subframe_content_map[1u] = 1u; + ContentToFrameMap subframe_content_map = {{1u, 1u}}; impl.AddSubframeContent(3u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + subframe_content_map); // Frame 5 has content 3 which refers to subframe 3. // Although frame 3's content is added, its subframe 1's content is not added. // So frame 5 is not ready. - subframe_content_map.clear(); - subframe_content_map[3u] = 3u; + subframe_content_map = {{3u, 3u}}; base::flat_set<uint64_t> pending_subframes; - bool is_ready = impl.IsReadyToComposite(5u, std::move(subframe_content_map), - &pending_subframes); + bool is_ready = + impl.IsReadyToComposite(5u, subframe_content_map, &pending_subframes); EXPECT_FALSE(is_ready); ASSERT_EQ(pending_subframes.size(), 1u); EXPECT_EQ(*pending_subframes.begin(), 1u); // Frame 6 is not ready either since it needs frame 5 to be ready. - subframe_content_map.clear(); - subframe_content_map[1u] = 5u; - is_ready = impl.IsReadyToComposite(6u, std::move(subframe_content_map), - &pending_subframes); + subframe_content_map = {{1u, 5u}}; + is_ready = + impl.IsReadyToComposite(6u, subframe_content_map, &pending_subframes); EXPECT_FALSE(is_ready); ASSERT_EQ(pending_subframes.size(), 1u); EXPECT_EQ(*pending_subframes.begin(), 5u); @@ -163,24 +152,20 @@ // When frame 1's content is added, frame 5 is ready. impl.AddSubframeContent(1u, mojo::SharedBufferHandle::Create(10), ContentToFrameMap()); - subframe_content_map.clear(); - subframe_content_map[3u] = 3u; - is_ready = impl.IsReadyToComposite(5u, std::move(subframe_content_map), - &pending_subframes); + subframe_content_map = {{3u, 3u}}; + is_ready = + impl.IsReadyToComposite(5u, subframe_content_map, &pending_subframes); EXPECT_TRUE(is_ready); EXPECT_TRUE(pending_subframes.empty()); // Add frame 5's content. - subframe_content_map.clear(); - subframe_content_map[3u] = 3u; impl.AddSubframeContent(5u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + subframe_content_map); // Frame 6 is ready too. - subframe_content_map.clear(); - subframe_content_map[1u] = 5u; - is_ready = impl.IsReadyToComposite(6u, std::move(subframe_content_map), - &pending_subframes); + subframe_content_map = {{1u, 5u}}; + is_ready = + impl.IsReadyToComposite(6u, subframe_content_map, &pending_subframes); EXPECT_TRUE(is_ready); EXPECT_TRUE(pending_subframes.empty()); } @@ -189,36 +174,31 @@ PdfCompositorImpl impl("unittest", nullptr); // Frame 3 has content 1, which refers to frame 1. // Frame 1 has content 3, which refers to frame 3. - ContentToFrameMap subframe_content_map; - subframe_content_map[3u] = 3u; + ContentToFrameMap subframe_content_map = {{3u, 3u}}; impl.AddSubframeContent(1u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + subframe_content_map); - subframe_content_map.clear(); - subframe_content_map[1u] = 1u; + subframe_content_map = {{1u, 1u}}; impl.AddSubframeContent(3u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + subframe_content_map); // Both frame 1 and 3 are painted, frame 5 should be ready. base::flat_set<uint64_t> pending_subframes; - subframe_content_map.clear(); - subframe_content_map[1u] = 3u; - bool is_ready = impl.IsReadyToComposite(5u, std::move(subframe_content_map), - &pending_subframes); + subframe_content_map = {{1u, 3u}}; + bool is_ready = + impl.IsReadyToComposite(5u, subframe_content_map, &pending_subframes); EXPECT_TRUE(is_ready); EXPECT_TRUE(pending_subframes.empty()); // Frame 6 has content 7, which refers to frame 7. - subframe_content_map.clear(); - subframe_content_map[7u] = 7u; + subframe_content_map = {{7u, 7u}}; impl.AddSubframeContent(6, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + subframe_content_map); // Frame 7 should be ready since frame 6's own content is added and it only // depends on frame 7. - subframe_content_map.clear(); - subframe_content_map[6u] = 6u; - is_ready = impl.IsReadyToComposite(7u, std::move(subframe_content_map), - &pending_subframes); + subframe_content_map = {{6u, 6u}}; + is_ready = + impl.IsReadyToComposite(7u, subframe_content_map, &pending_subframes); EXPECT_TRUE(is_ready); EXPECT_TRUE(pending_subframes.empty()); } @@ -227,71 +207,51 @@ MockPdfCompositorImpl impl; // Page 0 with frame 3 has content 1, which refers to frame 8. // When the content is not available, the request is not fulfilled. - ContentToFrameMap subframe_content_map; - subframe_content_map[1u] = 8u; + const ContentToFrameMap subframe_content_map = {{1u, 8u}}; EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0); impl.CompositePageToPdf( - 3u, 0, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 3u, 0, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); testing::Mock::VerifyAndClearExpectations(&impl); // When frame 8's content is ready, the previous request should be fulfilled. EXPECT_CALL(impl, OnFulfillRequest(3u, 0)).Times(1); impl.AddSubframeContent(8u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + ContentToFrameMap()); testing::Mock::VerifyAndClearExpectations(&impl); // The following requests which only depends on frame 8 should be // immediately fulfilled. EXPECT_CALL(impl, OnFulfillRequest(3u, 1)).Times(1); EXPECT_CALL(impl, OnFulfillRequest(3u, -1)).Times(1); - subframe_content_map.clear(); - subframe_content_map[1u] = 8u; impl.CompositePageToPdf( - 3u, 1, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 3u, 1, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); - subframe_content_map.clear(); - subframe_content_map[1u] = 8u; impl.CompositeDocumentToPdf( - 3u, mojo::SharedBufferHandle::Create(10), std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 3u, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); } TEST_F(PdfCompositorImplTest, MultiRequestsOrder) { MockPdfCompositorImpl impl; - // Page 0 with frame 3 has content 1, which refers to frame 8. + // Page 0 with frame 3 has content 1, which refers to frame 8. // When the content is not available, the request is not fulfilled. - ContentToFrameMap subframe_content_map; - subframe_content_map[1u] = 8u; + const ContentToFrameMap subframe_content_map = {{1u, 8u}}; EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0); impl.CompositePageToPdf( - 3u, 0, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 3u, 0, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); // The following requests which only depends on frame 8 should be // immediately fulfilled. - subframe_content_map.clear(); - subframe_content_map[1u] = 8u; impl.CompositePageToPdf( - 3u, 1, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 3u, 1, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); - subframe_content_map.clear(); - subframe_content_map[1u] = 8u; impl.CompositeDocumentToPdf( - 3u, mojo::SharedBufferHandle::Create(10), std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 3u, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); testing::Mock::VerifyAndClearExpectations(&impl); // When frame 8's content is ready, the previous request should be @@ -299,9 +259,8 @@ EXPECT_CALL(impl, OnFulfillRequest(3u, 0)).Times(1); EXPECT_CALL(impl, OnFulfillRequest(3u, 1)).Times(1); EXPECT_CALL(impl, OnFulfillRequest(3u, -1)).Times(1); - subframe_content_map.clear(); impl.AddSubframeContent(8u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + ContentToFrameMap()); } TEST_F(PdfCompositorImplTest, MultiRequestsDepOrder) { @@ -310,24 +269,18 @@ // 2. When the content is not available, the request is not // fulfilled. EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0); - ContentToFrameMap subframe_content_map; - subframe_content_map[1u] = 2u; + ContentToFrameMap subframe_content_map = {{1u, 2u}}; impl.CompositePageToPdf( - 1u, 0, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 1u, 0, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); // Page 1 with frame 1 has content 1, which refers to frame // 3. When the content is not available, the request is not // fulfilled either. - subframe_content_map.clear(); - subframe_content_map[1u] = 3u; + subframe_content_map = {{1u, 3u}}; impl.CompositePageToPdf( - 1u, 1, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 1u, 1, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); testing::Mock::VerifyAndClearExpectations(&impl); // When frame 3 and 2 become available, the pending requests should be @@ -335,25 +288,21 @@ testing::Sequence order; EXPECT_CALL(impl, OnFulfillRequest(1, 1)).Times(1).InSequence(order); EXPECT_CALL(impl, OnFulfillRequest(1, 0)).Times(1).InSequence(order); - subframe_content_map.clear(); impl.AddSubframeContent(3u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + ContentToFrameMap()); impl.AddSubframeContent(2u, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map)); + ContentToFrameMap()); } TEST_F(PdfCompositorImplTest, NotifyUnavailableSubframe) { MockPdfCompositorImpl impl; // Page 0 with frame 3 has content 1, which refers to frame 8. // When the content is not available, the request is not fulfilled. - ContentToFrameMap subframe_content_map; - subframe_content_map[1u] = 8u; + const ContentToFrameMap subframe_content_map = {{1u, 8u}}; EXPECT_CALL(impl, OnFulfillRequest(testing::_, testing::_)).Times(0); impl.CompositePageToPdf( - 3u, 0, mojo::SharedBufferHandle::Create(10), - std::move(subframe_content_map), - base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback, - base::Unretained(this))); + 3u, 0, mojo::SharedBufferHandle::Create(10), subframe_content_map, + base::BindOnce(&PdfCompositorImplTest::OnCompositeToPdfCallback)); testing::Mock::VerifyAndClearExpectations(&impl); // Notifies that frame 8's unavailable, the previous request should be
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index e3585ea..27934aaf 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -929,7 +929,7 @@ "//chrome/test/data/sync/", "//net/tools/testserver/", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", "$root_out_dir/pyproto/google/", ]
diff --git a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc index eb61e14..68358c25 100644 --- a/components/sync/engine_impl/non_blocking_type_commit_contribution.cc +++ b/components/sync/engine_impl/non_blocking_type_commit_contribution.cc
@@ -173,7 +173,10 @@ sync_pb::SyncEntity* commit_proto) { const EntityData& entity_data = commit_entity.entity.value(); commit_proto->set_id_string(entity_data.id); - commit_proto->set_client_defined_unique_tag(entity_data.client_tag_hash); + // Populate client_defined_unique_tag only for non-bookmark data types. + if (!entity_data.specifics.has_bookmark()) { + commit_proto->set_client_defined_unique_tag(entity_data.client_tag_hash); + } commit_proto->set_version(commit_entity.base_version); commit_proto->set_deleted(entity_data.is_deleted()); commit_proto->set_folder(entity_data.is_folder);
diff --git a/components/sync/protocol/BUILD.gn b/components/sync/protocol/BUILD.gn index 50c3e7f..9b967ac 100644 --- a/components/sync/protocol/BUILD.gn +++ b/components/sync/protocol/BUILD.gn
@@ -9,3 +9,8 @@ sources = sync_protocol_sources extra_configs = [ "//build/config/compiler:wexit_time_destructors" ] } + +group("chromiumsync_pyproto") { + # Python proto files used by components/sync/tools/testserver/chromiumsync.py + data = sync_protocol_pyprotos +}
diff --git a/components/sync/protocol/protocol_sources.gni b/components/sync/protocol/protocol_sources.gni index f5ab3954..2b1b740 100644 --- a/components/sync/protocol/protocol_sources.gni +++ b/components/sync/protocol/protocol_sources.gni
@@ -2,57 +2,66 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -sync_protocol_sources = [ - "//components/sync/protocol/app_notification_specifics.proto", - "//components/sync/protocol/app_setting_specifics.proto", - "//components/sync/protocol/app_specifics.proto", - "//components/sync/protocol/app_list_specifics.proto", - "//components/sync/protocol/arc_package_specifics.proto", - "//components/sync/protocol/article_specifics.proto", - "//components/sync/protocol/autofill_specifics.proto", - "//components/sync/protocol/bookmark_model_metadata.proto", - "//components/sync/protocol/bookmark_specifics.proto", - "//components/sync/protocol/client_commands.proto", - "//components/sync/protocol/client_debug_info.proto", - "//components/sync/protocol/device_info_specifics.proto", - "//components/sync/protocol/dictionary_specifics.proto", - "//components/sync/protocol/encryption.proto", - "//components/sync/protocol/entity_metadata.proto", - "//components/sync/protocol/experiment_status.proto", - "//components/sync/protocol/experiments_specifics.proto", - "//components/sync/protocol/extension_setting_specifics.proto", - "//components/sync/protocol/extension_specifics.proto", - "//components/sync/protocol/favicon_image_specifics.proto", - "//components/sync/protocol/favicon_tracking_specifics.proto", - "//components/sync/protocol/get_updates_caller_info.proto", - "//components/sync/protocol/history_delete_directive_specifics.proto", - "//components/sync/protocol/history_status.proto", - "//components/sync/protocol/loopback_server.proto", - "//components/sync/protocol/managed_user_setting_specifics.proto", - "//components/sync/protocol/managed_user_shared_setting_specifics.proto", - "//components/sync/protocol/managed_user_specifics.proto", - "//components/sync/protocol/managed_user_whitelist_specifics.proto", - "//components/sync/protocol/model_type_state.proto", - "//components/sync/protocol/model_type_store_schema_descriptor.proto", - "//components/sync/protocol/mountain_share_specifics.proto", - "//components/sync/protocol/nigori_specifics.proto", - "//components/sync/protocol/password_specifics.proto", - "//components/sync/protocol/preference_specifics.proto", - "//components/sync/protocol/printer_specifics.proto", - "//components/sync/protocol/priority_preference_specifics.proto", - "//components/sync/protocol/reading_list_specifics.proto", - "//components/sync/protocol/search_engine_specifics.proto", - "//components/sync/protocol/session_specifics.proto", - "//components/sync/protocol/sync.proto", - "//components/sync/protocol/sync_enums.proto", - "//components/sync/protocol/synced_notification_app_info_specifics.proto", - "//components/sync/protocol/synced_notification_specifics.proto", - "//components/sync/protocol/test.proto", - "//components/sync/protocol/theme_specifics.proto", - "//components/sync/protocol/typed_url_specifics.proto", - "//components/sync/protocol/unique_position.proto", - "//components/sync/protocol/user_consent_specifics.proto", - "//components/sync/protocol/user_consent_types.proto", - "//components/sync/protocol/user_event_specifics.proto", - "//components/sync/protocol/wifi_credential_specifics.proto", +sync_protocol_bases = [ + "app_notification_specifics", + "app_setting_specifics", + "app_specifics", + "app_list_specifics", + "arc_package_specifics", + "article_specifics", + "autofill_specifics", + "bookmark_model_metadata", + "bookmark_specifics", + "client_commands", + "client_debug_info", + "device_info_specifics", + "dictionary_specifics", + "encryption", + "entity_metadata", + "experiment_status", + "experiments_specifics", + "extension_setting_specifics", + "extension_specifics", + "favicon_image_specifics", + "favicon_tracking_specifics", + "get_updates_caller_info", + "history_delete_directive_specifics", + "history_status", + "loopback_server", + "managed_user_setting_specifics", + "managed_user_shared_setting_specifics", + "managed_user_specifics", + "managed_user_whitelist_specifics", + "model_type_state", + "model_type_store_schema_descriptor", + "mountain_share_specifics", + "nigori_specifics", + "password_specifics", + "preference_specifics", + "printer_specifics", + "priority_preference_specifics", + "reading_list_specifics", + "search_engine_specifics", + "session_specifics", + "sync", + "sync_enums", + "synced_notification_app_info_specifics", + "synced_notification_specifics", + "test", + "theme_specifics", + "typed_url_specifics", + "unique_position", + "user_consent_specifics", + "user_consent_types", + "user_event_specifics", + "wifi_credential_specifics", ] + +sync_protocol_sources = [] +sync_protocol_pyprotos = [] + +foreach(base, sync_protocol_bases) { + sync_protocol_sources += [ "//components/sync/protocol/${base}.proto" ] + sync_protocol_pyprotos += + [ "$root_out_dir/pyproto/components/sync/protocol/${base}_pb2.py" ] +}
diff --git a/components/ui_devtools/devtools_server.cc b/components/ui_devtools/devtools_server.cc index 294e430..6827164 100644 --- a/components/ui_devtools/devtools_server.cc +++ b/components/ui_devtools/devtools_server.cc
@@ -133,10 +133,11 @@ return; constexpr int kBacklog = 1; + auto request = mojo::MakeRequest(&server_socket); network_context->CreateTCPServerSocket( net::IPEndPoint(address, port_), kBacklog, net::MutableNetworkTrafficAnnotationTag(kUIDevtoolsServer), - mojo::MakeRequest(&server_socket), + std::move(request), base::BindOnce(&UiDevToolsServer::MakeServer, weak_ptr_factory_.GetWeakPtr(), std::move(server_socket))); }
diff --git a/components/variations/net/variations_http_headers.cc b/components/variations/net/variations_http_headers.cc index 790856b..c7fb6981 100644 --- a/components/variations/net/variations_http_headers.cc +++ b/components/variations/net/variations_http_headers.cc
@@ -45,8 +45,6 @@ "googleweblight.com", }; -const char kClientData[] = "X-Client-Data"; - // The result of checking if a URL should have variations headers appended. // This enum is used to record UMA histogram values, and should not be // reordered. @@ -101,12 +99,14 @@ void RemoveVariationsHeader(const net::RedirectInfo& redirect_info, const network::ResourceResponseHead& response_head, std::vector<std::string>* to_be_removed_headers) { - if (!internal::ShouldAppendVariationHeaders(redirect_info.new_url)) - to_be_removed_headers->push_back(kClientData); + if (!ShouldAppendVariationHeaders(redirect_info.new_url)) + to_be_removed_headers->push_back(kClientDataHeader); } } // namespace +const char kClientDataHeader[] = "X-Client-Data"; + bool AppendVariationHeaders(const GURL& url, InIncognito incognito, SignedIn signed_in, @@ -119,17 +119,15 @@ // international TLD domains *.google.<TLD> or *.youtube.<TLD>. // 2. Only transmit for non-Incognito profiles. // 3. For the X-Client-Data header, only include non-empty variation IDs. - if ((incognito == InIncognito::kYes) || - !internal::ShouldAppendVariationHeaders(url)) { + if ((incognito == InIncognito::kYes) || !ShouldAppendVariationHeaders(url)) return false; - } const std::string variation_ids_header = VariationsHttpHeaderProvider::GetInstance()->GetClientDataHeader( signed_in == SignedIn::kYes); if (!variation_ids_header.empty()) { // Note that prior to M33 this header was named X-Chrome-Variations. - headers->SetHeaderIfMissing(kClientData, variation_ids_header); + headers->SetHeaderIfMissing(kClientDataHeader, variation_ids_header); return true; } return false; @@ -145,13 +143,13 @@ std::set<std::string> GetVariationHeaderNames() { std::set<std::string> headers; - headers.insert(kClientData); + headers.insert(kClientDataHeader); return headers; } void StripVariationHeaderIfNeeded(const GURL& new_location, net::URLRequest* request) { - if (!internal::ShouldAppendVariationHeaders(new_location)) { + if (!ShouldAppendVariationHeaders(new_location)) { for (const std::string& header : GetVariationHeaderNames()) request->RemoveRequestHeaderByName(header); } @@ -183,9 +181,6 @@ std::move(request), incognito, SignedIn::kNo, annotation_tag); } -namespace internal { - -// static bool ShouldAppendVariationHeaders(const GURL& url) { if (!url.is_valid()) { LogUrlValidationHistogram(INVALID_URL); @@ -209,6 +204,4 @@ return true; } -} // namespace internal - } // namespace variations
diff --git a/components/variations/net/variations_http_headers.h b/components/variations/net/variations_http_headers.h index f7c783e..402afa3 100644 --- a/components/variations/net/variations_http_headers.h +++ b/components/variations/net/variations_http_headers.h
@@ -28,6 +28,9 @@ enum class SignedIn { kNo, kYes }; +// The name string for the header for variations information. +extern const char kClientDataHeader[]; + // Adds Chrome experiment and metrics state as custom headers to |headers|. // The content of the headers will depend on |incognito| and |signed_in| // parameters. It is fine to pass SignedIn::NO if the state is not known to the @@ -75,15 +78,11 @@ InIncognito incognito, const net::NetworkTrafficAnnotationTag& annotation_tag); -namespace internal { - // Checks whether variation headers should be appended to requests to the // specified |url|. Returns true for google.<TLD> and youtube.<TLD> URLs with // the https scheme. bool ShouldAppendVariationHeaders(const GURL& url); -} // namespace internal - } // namespace variations #endif // COMPONENTS_VARIATIONS_NET_VARIATIONS_HTTP_HEADERS_H_
diff --git a/components/variations/net/variations_http_headers_unittest.cc b/components/variations/net/variations_http_headers_unittest.cc index 1469550..3a94444 100644 --- a/components/variations/net/variations_http_headers_unittest.cc +++ b/components/variations/net/variations_http_headers_unittest.cc
@@ -148,8 +148,7 @@ for (size_t i = 0; i < arraysize(cases); ++i) { const GURL url(cases[i].url); - EXPECT_EQ(cases[i].should_append_headers, - internal::ShouldAppendVariationHeaders(url)) + EXPECT_EQ(cases[i].should_append_headers, ShouldAppendVariationHeaders(url)) << url; } }
diff --git a/components/variations/variations_http_header_provider.cc b/components/variations/variations_http_header_provider.cc index 5055b9e3..0b1e4c8 100644 --- a/components/variations/variations_http_header_provider.cc +++ b/components/variations/variations_http_header_provider.cc
@@ -101,6 +101,14 @@ return ForceIdsResult::SUCCESS; } +void VariationsHttpHeaderProvider::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void VariationsHttpHeaderProvider::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + void VariationsHttpHeaderProvider::ResetForTesting() { base::AutoLock scoped_lock(lock_); @@ -205,6 +213,11 @@ // with such discrepancies. cached_variation_ids_header_ = GenerateBase64EncodedProto(false); cached_variation_ids_header_signed_in_ = GenerateBase64EncodedProto(true); + + for (auto& observer : observer_list_) { + observer.VariationIdsHeaderUpdated(cached_variation_ids_header_, + cached_variation_ids_header_signed_in_); + } } std::string VariationsHttpHeaderProvider::GenerateBase64EncodedProto(
diff --git a/components/variations/variations_http_header_provider.h b/components/variations/variations_http_header_provider.h index 8bf60c2..9ee5aa6 100644 --- a/components/variations/variations_http_header_provider.h +++ b/components/variations/variations_http_header_provider.h
@@ -13,6 +13,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/metrics/field_trial.h" +#include "base/observer_list.h" #include "base/synchronization/lock.h" #include "components/variations/synthetic_trials.h" #include "components/variations/variations_associated_data.h" @@ -30,6 +31,17 @@ class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer, public SyntheticTrialObserver { public: + class Observer { + public: + // Called when variation ids headers are updated. + virtual void VariationIdsHeaderUpdated( + const std::string& variation_ids_header, + const std::string& variation_ids_header_signed_in) {} + + protected: + virtual ~Observer() {} + }; + static VariationsHttpHeaderProvider* GetInstance(); // Returns the value of the client data header, computing and caching it if @@ -61,6 +73,10 @@ const std::vector<std::string>& variation_ids, const std::string& command_line_variation_ids); + // Methods to register or remove observers of variation ids header update. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + // Resets any cached state for tests. void ResetForTesting(); @@ -140,6 +156,10 @@ std::string cached_variation_ids_header_; std::string cached_variation_ids_header_signed_in_; + // List of observers to notify on variation ids header update. + // Makes sure list is empty on destruction. + base::ObserverList<Observer, true> observer_list_; + DISALLOW_COPY_AND_ASSIGN(VariationsHttpHeaderProvider); };
diff --git a/components/viz/client/hit_test_data_provider_draw_quad.cc b/components/viz/client/hit_test_data_provider_draw_quad.cc index 5d9947b8..822e04d 100644 --- a/components/viz/client/hit_test_data_provider_draw_quad.cc +++ b/components/viz/client/hit_test_data_provider_draw_quad.cc
@@ -27,9 +27,11 @@ for (const auto& render_pass : compositor_frame.render_pass_list) { // Skip the render_pass if the transform is not invertible (i.e. it will not // be able to receive events). + gfx::Transform transform_to_root_target = + render_pass->transform_to_root_target; + transform_to_root_target.FlattenTo2d(); gfx::Transform transform_from_root_target; - if (!render_pass->transform_to_root_target.GetInverse( - &transform_from_root_target)) { + if (!transform_to_root_target.GetInverse(&transform_from_root_target)) { continue; } @@ -49,9 +51,11 @@ // Skip the quad if the transform is not invertible (i.e. it will not // be able to receive events). + gfx::Transform quad_to_target_transform = + quad->shared_quad_state->quad_to_target_transform; + quad_to_target_transform.FlattenTo2d(); gfx::Transform target_to_quad_transform; - if (!quad->shared_quad_state->quad_to_target_transform.GetInverse( - &target_to_quad_transform)) { + if (!quad_to_target_transform.GetInverse(&target_to_quad_transform)) { continue; }
diff --git a/components/viz/service/surfaces/surface_hittest.cc b/components/viz/service/surfaces/surface_hittest.cc index 83d97e9..83d6b0b 100644 --- a/components/viz/service/surfaces/surface_hittest.cc +++ b/components/viz/service/surfaces/surface_hittest.cc
@@ -70,8 +70,9 @@ // embedded in target_surface_id, or vice versa. if (GetTransformToTargetSurface(target_surface_id, original_surface_id, &transform)) { - if (transform.GetInverse(&transform)) - transform.TransformPoint(point); + gfx::Transform inverse_transform; + if (transform.GetInverse(&inverse_transform)) + inverse_transform.TransformPoint(point); else return false; } else if (GetTransformToTargetSurface(original_surface_id, target_surface_id, @@ -105,11 +106,13 @@ referenced_passes->insert(render_pass); - // The |transform_to_root_target| matrix cannot be inverted if it has a - // z-scale of 0 or due to floating point errors. + // The |transform_to_root_target| matrix may have no back-projection if the + // forward projection is degenerate. gfx::Transform transform_from_root_target; - if (!render_pass->transform_to_root_target.GetInverse( - &transform_from_root_target)) { + gfx::Transform transform_to_root_target = + render_pass->transform_to_root_target; + transform_to_root_target.FlattenTo2d(); + if (!transform_to_root_target.GetInverse(&transform_from_root_target)) { return false; } @@ -234,19 +237,23 @@ referenced_passes->insert(render_pass); - // The |transform_to_root_target| matrix cannot be inverted if it has a - // z-scale of 0 or due to floating point errors. + // The |transform_to_root_target| matrix may have no back-projection if the + // forward projection is degenerate. gfx::Transform transform_from_root_target; - if (!render_pass->transform_to_root_target.GetInverse( - &transform_from_root_target)) { + gfx::Transform transform_to_root_target = + render_pass->transform_to_root_target; + transform_to_root_target.FlattenTo2d(); + if (!transform_to_root_target.GetInverse(&transform_from_root_target)) { return false; } for (const DrawQuad* quad : render_pass->quad_list) { if (quad->material == DrawQuad::SURFACE_CONTENT) { gfx::Transform target_to_quad_transform; - if (!quad->shared_quad_state->quad_to_target_transform.GetInverse( - &target_to_quad_transform)) { + gfx::Transform quad_to_target_transform = + quad->shared_quad_state->quad_to_target_transform; + quad_to_target_transform.FlattenTo2d(); + if (!quad_to_target_transform.GetInverse(&target_to_quad_transform)) { return false; } @@ -326,8 +333,9 @@ // We now transform the point to content space and test if it hits the // rect. - if (!quad->shared_quad_state->quad_to_target_transform.GetInverse( - target_to_quad_transform)) { + gfx::Transform transform = quad->shared_quad_state->quad_to_target_transform; + transform.FlattenTo2d(); + if (!transform.GetInverse(target_to_quad_transform)) { return false; }
diff --git a/components/viz/service/surfaces/surface_hittest_unittest.cc b/components/viz/service/surfaces/surface_hittest_unittest.cc index f3ed3b67..00c930e 100644 --- a/components/viz/service/surfaces/surface_hittest_unittest.cc +++ b/components/viz/service/surfaces/surface_hittest_unittest.cc
@@ -561,4 +561,96 @@ EXPECT_EQ(2, accept_delegate.accept_target_overrides()); } +// Hit test against a child surface that has a non-flat transform. This +// verifies that the transform is flattened before hit testing. +TEST_F(SurfaceHittestTest, Hittest_ChildSurfaceWithNonFlatTransform) { + // Creates a root surface. + gfx::Rect root_rect(300, 300); + RenderPass* root_pass = nullptr; + CompositorFrame root_frame = CreateCompositorFrame(root_rect, &root_pass); + + // Add a reference to the child surface on the root surface. + ParentLocalSurfaceIdAllocator child_allocator; + SurfaceId child_surface_id(kChildFrameSink, + child_allocator.GetCurrentLocalSurfaceId()); + gfx::Rect child_rect(200, 200); + CreateSurfaceDrawQuad( + root_pass, + gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1.0f), + root_rect, child_rect, child_surface_id); + + // Submit the root frame. + ParentLocalSurfaceIdAllocator root_allocator; + SurfaceId root_surface_id(kRootFrameSink, + root_allocator.GetCurrentLocalSurfaceId()); + root_support().SubmitCompositorFrame( + root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame)); + + // Creates a child surface. + RenderPass* child_pass = nullptr; + CompositorFrame child_frame = CreateCompositorFrame(child_rect, &child_pass); + + // Add a solid quad in the child surface. + gfx::Rect child_solid_quad_rect(100, 100); + CreateSolidColorDrawQuad( + child_pass, + gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, 0.0f, 1.0f, 0.0f, 50.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f), + root_rect, child_solid_quad_rect); + + // Submit the frame. + child_support().SubmitCompositorFrame( + child_allocator.GetCurrentLocalSurfaceId(), std::move(child_frame)); + + TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id, + gfx::Point(10, 10), false}, + {root_surface_id, gfx::Point(99, 99), root_surface_id, + gfx::Point(99, 99), true}, + {root_surface_id, gfx::Point(100, 100), child_surface_id, + gfx::Point(50, 50), true}, + {root_surface_id, gfx::Point(199, 199), child_surface_id, + gfx::Point(149, 149), true}, + {root_surface_id, gfx::Point(200, 200), root_surface_id, + gfx::Point(200, 200), true}, + {root_surface_id, gfx::Point(290, 290), root_surface_id, + gfx::Point(290, 290), false}}; + + RunTests(nullptr, surface_manager(), tests, arraysize(tests)); + + // Submit another root frame, with a slightly perturbed child Surface. + root_frame = CreateCompositorFrame(root_rect, &root_pass); + CreateSurfaceDrawQuad( + root_pass, + gfx::Transform(1.0f, 0.0f, 0.0f, 75.0f, 0.0f, 1.0f, 0.0f, 75.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f), + root_rect, child_rect, child_surface_id); + root_support().SubmitCompositorFrame( + root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame)); + + // Verify that point (100, 100) no longer falls on the child surface. + // Verify that the transform to the child surface's space has also shifted. + { + SurfaceHittest hittest(nullptr, surface_manager()); + + gfx::Point point(100, 100); + gfx::Transform transform; + bool query_renderer; + EXPECT_EQ(root_surface_id, + hittest.GetTargetSurfaceAtPoint(root_surface_id, point, + &transform, &query_renderer)); + transform.TransformPoint(&point); + EXPECT_EQ(gfx::Point(100, 100), point); + EXPECT_EQ(query_renderer, true); + + gfx::Point point_in_target_space(100, 100); + gfx::Transform target_transform; + EXPECT_TRUE(hittest.GetTransformToTargetSurface( + root_surface_id, child_surface_id, &target_transform)); + target_transform.TransformPoint(&point_in_target_space); + EXPECT_NE(transform, target_transform); + EXPECT_EQ(gfx::Point(25, 25), point_in_target_space); + } +} + } // namespace viz
diff --git a/components/webcrypto/fuzzer_support.cc b/components/webcrypto/fuzzer_support.cc index 06d0acd..d4460ed0 100644 --- a/components/webcrypto/fuzzer_support.cc +++ b/components/webcrypto/fuzzer_support.cc
@@ -26,7 +26,7 @@ InitOnce() { base::CommandLine::Init(0, nullptr); mojo::core::Init(); - blink::Platform::Initialize(this, CurrentThread()); + blink::Platform::CreateMainThreadAndInitialize(this); } ~InitOnce() override {}
diff --git a/content/browser/android/content_feature_list.cc b/content/browser/android/content_feature_list.cc index 2cff631..a3b57a91 100644 --- a/content/browser/android/content_feature_list.cc +++ b/content/browser/android/content_feature_list.cc
@@ -22,6 +22,7 @@ // this array may either refer to features defined in the header of this file or // in other locations in the code base (e.g. content_features.h). const base::Feature* kFeaturesExposedToJava[] = { + &features::kBackgroundMediaRendererHasModerateBinding, &kEnhancedSelectionInsertionHandle, };
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc index 20e14a94..5f23089 100644 --- a/content/browser/child_process_launcher.cc +++ b/content/browser/child_process_launcher.cc
@@ -168,7 +168,9 @@ bool ChildProcessLauncherPriority::operator==( const ChildProcessLauncherPriority& other) const { - return background == other.background && frame_depth == other.frame_depth && + return foreground == other.foreground && + has_media_stream == other.has_media_stream && + frame_depth == other.frame_depth && intersects_viewport == other.intersects_viewport && boost_for_pending_views == other.boost_for_pending_views #if defined(OS_ANDROID)
diff --git a/content/browser/child_process_launcher.h b/content/browser/child_process_launcher.h index 3ccccf3..9fbdfe8 100644 --- a/content/browser/child_process_launcher.h +++ b/content/browser/child_process_launcher.h
@@ -56,7 +56,30 @@ #endif struct ChildProcessLauncherPriority { - bool background; + ChildProcessLauncherPriority(bool foreground, + bool has_media_stream, + unsigned int frame_depth, + bool intersects_viewport, + bool boost_for_pending_views +#if defined(OS_ANDROID) + , + ChildProcessImportance importance +#endif + ) + : foreground(foreground), + has_media_stream(has_media_stream), + frame_depth(frame_depth), + intersects_viewport(intersects_viewport), + boost_for_pending_views(boost_for_pending_views) +#if defined(OS_ANDROID) + , + importance(importance) +#endif + { + } + + bool foreground; + bool has_media_stream; unsigned int frame_depth; bool intersects_viewport; bool boost_for_pending_views; @@ -64,6 +87,9 @@ ChildProcessImportance importance; #endif + // Returns true if the child process is backgrounded. + bool is_background() const { return !foreground && !has_media_stream; } + bool operator==(const ChildProcessLauncherPriority& other) const; bool operator!=(const ChildProcessLauncherPriority& other) const { return !(*this == other);
diff --git a/content/browser/child_process_launcher_helper_android.cc b/content/browser/child_process_launcher_helper_android.cc index a368f8c..f1fa1ab 100644 --- a/content/browser/child_process_launcher_helper_android.cc +++ b/content/browser/child_process_launcher_helper_android.cc
@@ -221,9 +221,10 @@ JNIEnv* env = AttachCurrentThread(); DCHECK(env); return Java_ChildProcessLauncherHelperImpl_setPriority( - env, java_peer_, process.Handle(), !priority.background, - priority.frame_depth, priority.intersects_viewport, - priority.boost_for_pending_views, static_cast<jint>(priority.importance)); + env, java_peer_, process.Handle(), priority.foreground, + priority.has_media_stream, priority.frame_depth, + priority.intersects_viewport, priority.boost_for_pending_views, + static_cast<jint>(priority.importance)); } // static
diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc index 82a6e9f..c981f7f 100644 --- a/content/browser/child_process_launcher_helper_linux.cc +++ b/content/browser/child_process_launcher_helper_linux.cc
@@ -158,7 +158,7 @@ const ChildProcessLauncherPriority& priority) { DCHECK(CurrentlyOnProcessLauncherTaskRunner()); if (process.CanBackgroundProcesses()) - process.SetProcessBackgrounded(priority.background); + process.SetProcessBackgrounded(priority.is_background()); } // static
diff --git a/content/browser/child_process_launcher_helper_mac.cc b/content/browser/child_process_launcher_helper_mac.cc index bd13825..c1b02ef 100644 --- a/content/browser/child_process_launcher_helper_mac.cc +++ b/content/browser/child_process_launcher_helper_mac.cc
@@ -269,7 +269,7 @@ const ChildProcessLauncherPriority& priority) { if (process.CanBackgroundProcesses()) { process.SetProcessBackgrounded(MachBroker::GetInstance(), - priority.background); + priority.is_background()); } }
diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc index 5d81eb2..4deb943 100644 --- a/content/browser/child_process_launcher_helper_win.cc +++ b/content/browser/child_process_launcher_helper_win.cc
@@ -115,7 +115,7 @@ const ChildProcessLauncherPriority& priority) { DCHECK(CurrentlyOnProcessLauncherTaskRunner()); if (process.CanBackgroundProcesses()) - process.SetProcessBackgrounded(priority.background); + process.SetProcessBackgrounded(priority.is_background()); } // static
diff --git a/content/browser/fileapi/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc index 1e42768..11c3863f8 100644 --- a/content/browser/fileapi/fileapi_message_filter.cc +++ b/content/browser/fileapi/fileapi_message_filter.cc
@@ -29,8 +29,6 @@ #include "content/public/browser/browser_thread.h" #include "ipc/ipc_platform_file.h" #include "net/base/mime_util.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/shareable_file_reference.h" @@ -66,7 +64,6 @@ FileAPIMessageFilter::FileAPIMessageFilter( int process_id, - net::URLRequestContextGetter* request_context_getter, storage::FileSystemContext* file_system_context, ChromeBlobStorageContext* blob_storage_context) : BrowserMessageFilter(kFileApiFilteredMessageClasses, @@ -74,41 +71,14 @@ process_id_(process_id), context_(file_system_context), security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()), - request_context_getter_(request_context_getter), - request_context_(nullptr), blob_storage_context_(blob_storage_context) { DCHECK(context_); - DCHECK(request_context_getter_.get()); - DCHECK(blob_storage_context); -} - -FileAPIMessageFilter::FileAPIMessageFilter( - int process_id, - net::URLRequestContext* request_context, - storage::FileSystemContext* file_system_context, - ChromeBlobStorageContext* blob_storage_context) - : BrowserMessageFilter(kFileApiFilteredMessageClasses, - arraysize(kFileApiFilteredMessageClasses)), - process_id_(process_id), - context_(file_system_context), - security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()), - request_context_(request_context), - blob_storage_context_(blob_storage_context) { - DCHECK(context_); - DCHECK(request_context_); DCHECK(blob_storage_context); } void FileAPIMessageFilter::OnChannelConnected(int32_t peer_pid) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (request_context_getter_.get()) { - DCHECK(!request_context_); - request_context_ = request_context_getter_->GetURLRequestContext(); - request_context_getter_ = nullptr; - DCHECK(request_context_); - } - operation_runner_ = context_->CreateFileSystemOperationRunner(); } @@ -343,11 +313,6 @@ const std::string& blob_uuid, int64_t offset) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!request_context_) { - // We can't write w/o a request context, trying to do so will crash. - NOTREACHED(); - return; - } FileSystemURL url(context_->CrackURL(path)); if (!ValidateFileSystemURL(request_id, url)) @@ -362,7 +327,7 @@ blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid); operations_[request_id] = operation_runner()->Write( - request_context_, url, std::move(blob), offset, + url, std::move(blob), offset, base::Bind(&FileAPIMessageFilter::DidWrite, this, request_id)); }
diff --git a/content/browser/fileapi/fileapi_message_filter.h b/content/browser/fileapi/fileapi_message_filter.h index 7188c68..d6b37f6 100644 --- a/content/browser/fileapi/fileapi_message_filter.h +++ b/content/browser/fileapi/fileapi_message_filter.h
@@ -41,11 +41,6 @@ struct FileSystemInfo; } -namespace net { -class URLRequestContext; -class URLRequestContextGetter; -} // namespace net - namespace storage { class ShareableFileReference; } @@ -58,14 +53,7 @@ // FileAPIMessageFilter into separate classes. See crbug.com/263741. class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter { public: - // Used by the renderer process host on the UI thread. FileAPIMessageFilter(int process_id, - net::URLRequestContextGetter* request_context_getter, - storage::FileSystemContext* file_system_context, - ChromeBlobStorageContext* blob_storage_context); - // Used by the worker process host on the IO thread. - FileAPIMessageFilter(int process_id, - net::URLRequestContext* request_context, storage::FileSystemContext* file_system_context, ChromeBlobStorageContext* blob_storage_context); @@ -168,11 +156,6 @@ typedef std::map<int, OperationID> OperationsMap; OperationsMap operations_; - // The getter holds the context until OnChannelConnected() can be called from - // the IO thread, which will extract the net::URLRequestContext from it. - scoped_refptr<net::URLRequestContextGetter> request_context_getter_; - net::URLRequestContext* request_context_; - scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; std::unique_ptr<storage::FileSystemOperationRunner> operation_runner_;
diff --git a/content/browser/fileapi/fileapi_message_filter_unittest.cc b/content/browser/fileapi/fileapi_message_filter_unittest.cc index c996e7c..5302dee 100644 --- a/content/browser/fileapi/fileapi_message_filter_unittest.cc +++ b/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -55,8 +55,6 @@ filter_ = new FileAPIMessageFilter( 0 /* process_id */, - BrowserContext::GetDefaultStoragePartition(&browser_context_) - ->GetURLRequestContext(), file_system_context_.get(), blob_storage_context_); // Complete initialization. @@ -74,8 +72,6 @@ TEST_F(FileAPIMessageFilterTest, CloseChannelWithInflightRequest) { scoped_refptr<FileAPIMessageFilter> filter(new FileAPIMessageFilter( 0 /* process_id */, - BrowserContext::GetDefaultStoragePartition(&browser_context_) - ->GetURLRequestContext(), file_system_context_.get(), ChromeBlobStorageContext::GetFor(&browser_context_))); filter->OnChannelConnected(0); @@ -98,14 +94,10 @@ TEST_F(FileAPIMessageFilterTest, MultipleFilters) { scoped_refptr<FileAPIMessageFilter> filter1(new FileAPIMessageFilter( 0 /* process_id */, - BrowserContext::GetDefaultStoragePartition(&browser_context_) - ->GetURLRequestContext(), file_system_context_.get(), ChromeBlobStorageContext::GetFor(&browser_context_))); scoped_refptr<FileAPIMessageFilter> filter2(new FileAPIMessageFilter( 1 /* process_id */, - BrowserContext::GetDefaultStoragePartition(&browser_context_) - ->GetURLRequestContext(), file_system_context_.get(), ChromeBlobStorageContext::GetFor(&browser_context_))); filter1->OnChannelConnected(0);
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc index a64a441..0277986 100644 --- a/content/browser/gpu/gpu_internals_ui.cc +++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -226,6 +226,9 @@ NewDescriptionValuePair("Driver version", active_gpu.driver_version)); basic_info->Append( NewDescriptionValuePair("Driver date", active_gpu.driver_date)); + basic_info->Append(NewDescriptionValuePair( + "GPU CUDA compute capability major version", + std::make_unique<base::Value>(active_gpu.cuda_compute_capability_major))); basic_info->Append(NewDescriptionValuePair("Pixel shader version", gpu_info.pixel_shader_version)); basic_info->Append(NewDescriptionValuePair("Vertex shader version",
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc index 9c30505..d9c8efb 100644 --- a/content/browser/indexed_db/database_impl.cc +++ b/content/browser/indexed_db/database_impl.cc
@@ -78,7 +78,6 @@ void Put(int64_t transaction_id, int64_t object_store_id, ::indexed_db::mojom::ValuePtr value, - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles, std::vector<IndexedDBBlobInfo> blob_info, const IndexedDBKey& key, blink::WebIDBPutMode mode, @@ -281,8 +280,6 @@ new IndexedDBCallbacks(dispatcher_host_->AsWeakPtr(), origin_, std::move(callbacks_info), idb_runner_)); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles( - value->blob_or_file_info.size()); base::CheckedNumeric<uint64_t> total_blob_size = 0; std::vector<IndexedDBBlobInfo> blob_info(value->blob_or_file_info.size()); for (size_t i = 0; i < value->blob_or_file_info.size(); ++i) { @@ -309,7 +306,6 @@ uint64_t size = handle->size(); UMA_HISTOGRAM_MEMORY_KB("Storage.IndexedDB.PutBlobSizeKB", size / 1024ull); total_blob_size += size; - handles[i] = std::move(handle); if (info->file) { if (!info->file->path.empty() && @@ -318,14 +314,15 @@ mojo::ReportBadMessage(kInvalidBlobFilePath); return; } - blob_info[i] = IndexedDBBlobInfo(info->uuid, info->file->path, + blob_info[i] = IndexedDBBlobInfo(std::move(handle), info->file->path, info->file->name, info->mime_type); if (info->size != -1) { blob_info[i].set_last_modified(info->file->last_modified); blob_info[i].set_size(info->size); } } else { - blob_info[i] = IndexedDBBlobInfo(info->uuid, info->mime_type, info->size); + blob_info[i] = + IndexedDBBlobInfo(std::move(handle), info->mime_type, info->size); } } UMA_HISTOGRAM_COUNTS_1000("WebCore.IndexedDB.PutBlobsCount", @@ -340,8 +337,8 @@ FROM_HERE, base::BindOnce(&IDBSequenceHelper::Put, base::Unretained(helper_), transaction_id, object_store_id, std::move(value), - std::move(handles), std::move(blob_info), key, mode, - index_keys, std::move(callbacks))); + std::move(blob_info), key, mode, index_keys, + std::move(callbacks))); } void DatabaseImpl::SetIndexKeys( @@ -657,7 +654,6 @@ int64_t transaction_id, int64_t object_store_id, ::indexed_db::mojom::ValuePtr mojo_value, - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles, std::vector<IndexedDBBlobInfo> blob_info, const IndexedDBKey& key, blink::WebIDBPutMode mode, @@ -681,7 +677,7 @@ IndexedDBValue value; swap(value.bits, mojo_value->bits); swap(value.blob_info, blob_info); - connection_->database()->Put(transaction, object_store_id, &value, &handles, + connection_->database()->Put(transaction, object_store_id, &value, std::make_unique<IndexedDBKey>(key), mode, std::move(callbacks), index_keys);
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index 8fb6b84..ba773f3 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -366,10 +366,6 @@ return false; } -GURL GetURLFromUUID(const std::string& uuid) { - return GURL("blob:uuid/" + uuid); -} - Status DeleteBlobsInRange(IndexedDBBackingStore::Transaction* transaction, int64_t database_id, int64_t object_store_id, @@ -390,8 +386,7 @@ INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA); return InternalInconsistencyStatus(); } - transaction->PutBlobInfo(database_id, object_store_id, user_key, nullptr, - nullptr); + transaction->PutBlobInfo(database_id, object_store_id, user_key, nullptr); } return s; } @@ -1288,7 +1283,6 @@ int64_t object_store_id, const IndexedDBKey& key, IndexedDBValue* value, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles, RecordIdentifier* record_identifier) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); @@ -1312,14 +1306,10 @@ v.append(value->bits); leveldb_transaction->Put(object_store_data_key, &v); - s = transaction->PutBlobInfoIfNeeded(database_id, - object_store_id, - object_store_data_key, - &value->blob_info, - handles); + s = transaction->PutBlobInfoIfNeeded( + database_id, object_store_id, object_store_data_key, &value->blob_info); if (!s.ok()) return s; - DCHECK(handles->empty()); const std::string exists_entry_key = ExistsEntryKey::Encode(database_id, object_store_id, key); @@ -1369,8 +1359,8 @@ const std::string object_store_data_key = ObjectStoreDataKey::Encode( database_id, object_store_id, record_identifier.primary_key()); leveldb_transaction->Remove(object_store_data_key); - Status s = transaction->PutBlobInfoIfNeeded( - database_id, object_store_id, object_store_data_key, nullptr, nullptr); + Status s = transaction->PutBlobInfoIfNeeded(database_id, object_store_id, + object_store_data_key, nullptr); if (!s.ok()) return s; @@ -1710,11 +1700,9 @@ } } - void WriteBlobToFileOnIOThread( - const FilePath& file_path, - const GURL& blob_url, - const base::Time& last_modified, - scoped_refptr<net::URLRequestContextGetter> request_context_getter) { + void WriteBlobToFileOnIOThread(const FilePath& file_path, + std::unique_ptr<storage::BlobDataHandle> blob, + const base::Time& last_modified) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); std::unique_ptr<storage::FileStreamWriter> writer( storage::FileStreamWriter::CreateForLocalFile( @@ -1724,43 +1712,11 @@ std::make_unique<FileWriterDelegate>( std::move(writer), storage::FlushPolicy::FLUSH_ON_COMPLETION)); - DCHECK(blob_url.is_valid()); - net::URLRequestContext* request_context = - request_context_getter->GetURLRequestContext(); - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("persist_blob_to_indexed_db", R"( - semantics { - sender: "Indexed DB" - description: - "A web page's script has created a Blob (or File) object (either " - "directly via constructors, or by using file upload to a form, or " - "via a fetch()). The script has then made a request to store data " - "including the Blob via the Indexed DB API. As part of committing " - "the database transaction, the content of the Blob is being copied " - "into a file in the database's directory." - trigger: - "The script has made a request to store data including a Blob via " - "the Indexed DB API." - data: - "A Blob or File object referenced by script, either created " - "directly via constructors, or by using file upload to a form, or " - "drag/drop, or via a fetch() or other APIs that produce Blobs." - destination: LOCAL - } - policy { - cookies_allowed: NO - setting: "This feature cannot be disabled by settings." - policy_exception_justification: "Not implemented." - })"); - std::unique_ptr<net::URLRequest> blob_request( - request_context->CreateRequest(blob_url, net::DEFAULT_PRIORITY, - delegate.get(), traffic_annotation)); - blob_request->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | - net::LOAD_DO_NOT_SEND_COOKIES); + DCHECK(blob); this->file_path_ = file_path; this->last_modified_ = last_modified; - delegate->Start(std::move(blob_request), + delegate->Start(blob->CreateReader(), base::Bind(&LocalWriteClosure::Run, this)); chained_blob_writer_->set_delegate(std::move(delegate)); } @@ -1849,14 +1805,15 @@ base::BindOnce(&Transaction::ChainedBlobWriter::ReportWriteCompletion, chained_blob_writer, true, info.size)); } else { - DCHECK(descriptor.url().is_valid()); + DCHECK(descriptor.blob()); scoped_refptr<LocalWriteClosure> write_closure( new LocalWriteClosure(chained_blob_writer, task_runner_.get())); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&LocalWriteClosure::WriteBlobToFileOnIOThread, - write_closure, path, descriptor.url(), - descriptor.last_modified(), request_context_getter_)); + base::BindOnce( + &LocalWriteClosure::WriteBlobToFileOnIOThread, write_closure, path, + std::make_unique<storage::BlobDataHandle>(*descriptor.blob()), + descriptor.last_modified())); } return true; } @@ -3139,8 +3096,8 @@ entry.last_modified())); } else { new_files_to_write->push_back( - WriteDescriptor(GetURLFromUUID(entry.uuid()), next_blob_key, - entry.size(), entry.last_modified())); + WriteDescriptor(entry.blob_handle(), next_blob_key, entry.size(), + entry.last_modified())); } entry.set_key(next_blob_key); new_blob_keys.push_back(&entry); @@ -3454,23 +3411,12 @@ blob_info_.swap(*blob_info); } -void IndexedDBBackingStore::BlobChangeRecord::SetHandles( - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles) { - handles_.clear(); - if (handles) - handles_.swap(*handles); -} - std::unique_ptr<IndexedDBBackingStore::BlobChangeRecord> IndexedDBBackingStore::BlobChangeRecord::Clone() const { std::unique_ptr<IndexedDBBackingStore::BlobChangeRecord> record( new BlobChangeRecord(key_, object_store_id_)); record->blob_info_ = blob_info_; - for (const auto& handle : handles_) { - record->handles_.push_back( - std::make_unique<storage::BlobDataHandle>(*handle)); - } return record; } @@ -3478,8 +3424,7 @@ int64_t database_id, int64_t object_store_id, const std::string& object_store_data_key, - std::vector<IndexedDBBlobInfo>* blob_info, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles) { + std::vector<IndexedDBBlobInfo>* blob_info) { if (!blob_info || blob_info->empty()) { blob_change_map_.erase(object_store_data_key); incognito_blob_map_.erase(object_store_data_key); @@ -3499,8 +3444,7 @@ if (!found) return Status::OK(); } - PutBlobInfo( - database_id, object_store_id, object_store_data_key, blob_info, handles); + PutBlobInfo(database_id, object_store_id, object_store_data_key, blob_info); return Status::OK(); } @@ -3512,8 +3456,7 @@ int64_t database_id, int64_t object_store_id, const std::string& object_store_data_key, - std::vector<IndexedDBBlobInfo>* blob_info, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles) { + std::vector<IndexedDBBlobInfo>* blob_info) { DCHECK(!object_store_data_key.empty()); if (database_id_ < 0) database_id_ = database_id; @@ -3532,21 +3475,18 @@ } DCHECK_EQ(record->object_store_id(), object_store_id); record->SetBlobInfo(blob_info); - record->SetHandles(handles); - DCHECK(!handles || handles->empty()); } IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( - const GURL& url, + const storage::BlobDataHandle* blob, int64_t key, int64_t size, base::Time last_modified) : is_file_(false), - url_(url), + blob_(*blob), key_(key), size_(size), - last_modified_(last_modified) { -} + last_modified_(last_modified) {} IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( const FilePath& file_path, @@ -3565,7 +3505,7 @@ IndexedDBBackingStore::Transaction::WriteDescriptor::~WriteDescriptor() = default; IndexedDBBackingStore::Transaction::WriteDescriptor& - IndexedDBBackingStore::Transaction::WriteDescriptor:: - operator=(const WriteDescriptor& other) = default; +IndexedDBBackingStore::Transaction::WriteDescriptor::operator=( + const WriteDescriptor& other) = default; } // namespace content
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index 4ec5251..a473d7b 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -122,15 +122,12 @@ const std::vector<IndexedDBBlobInfo>& blob_info() const { return blob_info_; } - void SetHandles( - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles); std::unique_ptr<BlobChangeRecord> Clone() const; private: std::string key_; int64_t object_store_id_; std::vector<IndexedDBBlobInfo> blob_info_; - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles_; DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord); }; @@ -164,14 +161,11 @@ int64_t database_id, int64_t object_store_id, const std::string& object_store_data_key, - std::vector<IndexedDBBlobInfo>*, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles); - void PutBlobInfo( - int64_t database_id, - int64_t object_store_id, - const std::string& object_store_data_key, - std::vector<IndexedDBBlobInfo>*, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles); + std::vector<IndexedDBBlobInfo>*); + void PutBlobInfo(int64_t database_id, + int64_t object_store_id, + const std::string& object_store_data_key, + std::vector<IndexedDBBlobInfo>*); LevelDBTransaction* transaction() { return transaction_.get(); } @@ -189,7 +183,7 @@ class CONTENT_EXPORT WriteDescriptor { public: - WriteDescriptor(const GURL& url, + WriteDescriptor(const storage::BlobDataHandle* blob, int64_t key, int64_t size, base::Time last_modified); @@ -202,9 +196,9 @@ WriteDescriptor& operator=(const WriteDescriptor& other); bool is_file() const { return is_file_; } - const GURL& url() const { + const storage::BlobDataHandle* blob() const { DCHECK(!is_file_); - return url_; + return &blob_.value(); } const base::FilePath& file_path() const { DCHECK(is_file_); @@ -216,7 +210,7 @@ private: bool is_file_; - GURL url_; + base::Optional<storage::BlobDataHandle> blob_; base::FilePath file_path_; int64_t key_; int64_t size_; @@ -456,7 +450,6 @@ int64_t object_store_id, const IndexedDBKey& key, IndexedDBValue* value, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles, RecordIdentifier* record) WARN_UNUSED_RESULT; virtual leveldb::Status ClearObjectStore( IndexedDBBackingStore::Transaction* transaction,
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index eaa915e6..f65bd17 100644 --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/guid.h" #include "base/logging.h" #include "base/macros.h" #include "base/sequenced_task_runner.h" @@ -28,7 +29,9 @@ #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h" #include "net/url_request/url_request_test_util.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/quota/special_storage_policy.h" #include "storage/browser/test/mock_quota_manager_proxy.h" #include "storage/browser/test/mock_special_storage_policy.h" @@ -330,13 +333,15 @@ void SetUp() override { IndexedDBBackingStoreTest::SetUp(); + blob_context_ = std::make_unique<storage::BlobStorageContext>(); + // useful keys and values during tests blob_info_.push_back( - IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("blob type"), 1)); + IndexedDBBlobInfo(CreateBlob(), base::UTF8ToUTF16("blob type"), 1)); blob_info_.push_back(IndexedDBBlobInfo( - "uuid 4", base::FilePath(FILE_PATH_LITERAL("path/to/file")), + CreateBlob(), base::FilePath(FILE_PATH_LITERAL("path/to/file")), base::UTF8ToUTF16("file name"), base::UTF8ToUTF16("file type"))); - blob_info_.push_back(IndexedDBBlobInfo("uuid 5", base::FilePath(), + blob_info_.push_back(IndexedDBBlobInfo(CreateBlob(), base::FilePath(), base::UTF8ToUTF16("file name"), base::UTF8ToUTF16("file type"))); value3_ = IndexedDBValue("value3", blob_info_); @@ -344,6 +349,11 @@ key3_ = IndexedDBKey(ASCIIToUTF16("key3")); } + std::unique_ptr<storage::BlobDataHandle> CreateBlob() { + return blob_context_->AddFinishedBlob( + std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID())); + } + // This just checks the data that survive getting stored and recalled, e.g. // the file path and UUID will change and thus aren't verified. bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const { @@ -403,7 +413,7 @@ if (desc.file_path() != info.file_path()) return false; } else { - if (desc.url() != GURL("blob:uuid/" + info.uuid())) + if (desc.blob()->uuid() != info.blob_handle()->uuid()) return false; } } @@ -428,6 +438,8 @@ IndexedDBValue value3_; private: + std::unique_ptr<storage::BlobStorageContext> blob_context_; + // Blob details referenced by |value3_|. The various CheckBlob*() methods // can be used to verify the state as a test progresses. std::vector<IndexedDBBlobInfo> blob_info_; @@ -470,10 +482,9 @@ { IndexedDBBackingStore::Transaction transaction1(backing_store); transaction1.Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; leveldb::Status s = backing_store->PutRecord( - &transaction1, 1, 1, key, &value, &handles, &record); + &transaction1, 1, 1, key, &value, &record); EXPECT_TRUE(s.ok()); scoped_refptr<TestCallback> callback( base::MakeRefCounted<TestCallback>()); @@ -521,12 +532,10 @@ std::make_unique<IndexedDBBackingStore::Transaction>( test->backing_store()); state->transaction1->Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; EXPECT_TRUE(test->backing_store() ->PutRecord(state->transaction1.get(), 1, 1, - test->key3_, &test->value3_, &handles, - &record) + test->key3_, &test->value3_, &record) .ok()); state->callback1 = base::MakeRefCounted<TestCallback>(); EXPECT_TRUE( @@ -599,7 +608,7 @@ RunAllTasksUntilIdle(); } -TEST_F(IndexedDBBackingStoreTest, DeleteRange) { +TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRange) { const std::vector<IndexedDBKey> keys = { IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")), IndexedDBKey(ASCIIToUTF16("key2")), IndexedDBKey(ASCIIToUTF16("key3"))}; @@ -620,8 +629,12 @@ scoped_refptr<TestCallback> callback1; std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2; scoped_refptr<TestCallback> callback2; + std::vector<std::unique_ptr<storage::BlobDataHandle>> blobs; } state; + for (size_t j = 0; j < 4; ++j) + state.blobs.push_back(CreateBlob()); + idb_context_->TaskRunner()->PostTask( FROM_HERE, base::BindOnce( @@ -633,19 +646,26 @@ backing_store->ClearRemovals(); std::vector<IndexedDBValue> values = { - IndexedDBValue( - "value0", {IndexedDBBlobInfo( - "uuid 0", base::UTF8ToUTF16("type 0"), 1)}), - IndexedDBValue( - "value1", {IndexedDBBlobInfo( - "uuid 1", base::UTF8ToUTF16("type 1"), 1)}), - IndexedDBValue( - "value2", {IndexedDBBlobInfo( - "uuid 2", base::UTF8ToUTF16("type 2"), 1)}), - IndexedDBValue( - "value3", - {IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("type 3"), - 1)})}; + IndexedDBValue("value0", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[0]), + base::UTF8ToUTF16("type 0"), 1)}), + IndexedDBValue("value1", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[1]), + base::UTF8ToUTF16("type 1"), 1)}), + IndexedDBValue("value2", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[2]), + base::UTF8ToUTF16("type 2"), 1)}), + IndexedDBValue("value3", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[3]), + base::UTF8ToUTF16("type 3"), 1)})}; ASSERT_GE(keys.size(), values.size()); // Initiate transaction1 - write records. @@ -653,14 +673,12 @@ std::make_unique<IndexedDBBackingStore::Transaction>( backing_store); state->transaction1->Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; for (size_t i = 0; i < values.size(); ++i) { EXPECT_TRUE(backing_store ->PutRecord(state->transaction1.get(), database_id, object_store_id, - keys[i], &values[i], &handles, - &record) + keys[i], &values[i], &record) .ok()); } @@ -728,7 +746,7 @@ } } -TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) { +TEST_F(IndexedDBBackingStoreTestWithBlobs, DeleteRangeEmptyRange) { const std::vector<IndexedDBKey> keys = { IndexedDBKey(ASCIIToUTF16("key0")), IndexedDBKey(ASCIIToUTF16("key1")), IndexedDBKey(ASCIIToUTF16("key2")), IndexedDBKey(ASCIIToUTF16("key3")), @@ -748,8 +766,12 @@ scoped_refptr<TestCallback> callback1; std::unique_ptr<IndexedDBBackingStore::Transaction> transaction2; scoped_refptr<TestCallback> callback2; + std::vector<std::unique_ptr<storage::BlobDataHandle>> blobs; } state; + for (size_t j = 0; j < 4; ++j) + state.blobs.push_back(CreateBlob()); + idb_context_->TaskRunner()->PostTask( FROM_HERE, base::BindOnce( @@ -761,19 +783,26 @@ backing_store->ClearRemovals(); std::vector<IndexedDBValue> values = { - IndexedDBValue( - "value0", {IndexedDBBlobInfo( - "uuid 0", base::UTF8ToUTF16("type 0"), 1)}), - IndexedDBValue( - "value1", {IndexedDBBlobInfo( - "uuid 1", base::UTF8ToUTF16("type 1"), 1)}), - IndexedDBValue( - "value2", {IndexedDBBlobInfo( - "uuid 2", base::UTF8ToUTF16("type 2"), 1)}), - IndexedDBValue( - "value3", - {IndexedDBBlobInfo("uuid 3", base::UTF8ToUTF16("type 3"), - 1)})}; + IndexedDBValue("value0", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[0]), + base::UTF8ToUTF16("type 0"), 1)}), + IndexedDBValue("value1", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[1]), + base::UTF8ToUTF16("type 1"), 1)}), + IndexedDBValue("value2", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[2]), + base::UTF8ToUTF16("type 2"), 1)}), + IndexedDBValue("value3", + {IndexedDBBlobInfo( + std::make_unique<storage::BlobDataHandle>( + *state->blobs[3]), + base::UTF8ToUTF16("type 3"), 1)})}; ASSERT_GE(keys.size(), values.size()); // Initiate transaction1 - write records. @@ -782,14 +811,12 @@ backing_store); state->transaction1->Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; for (size_t i = 0; i < values.size(); ++i) { EXPECT_TRUE(backing_store ->PutRecord(state->transaction1.get(), database_id, object_store_id, - keys[i], &values[i], &handles, - &record) + keys[i], &values[i], &record) .ok()); } // Start committing transaction1. @@ -869,12 +896,10 @@ std::make_unique<IndexedDBBackingStore::Transaction>( test->backing_store()); state->transaction1->Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles1; IndexedDBBackingStore::RecordIdentifier record1; EXPECT_TRUE(test->backing_store() ->PutRecord(state->transaction1.get(), 1, 1, - test->key3_, &test->value3_, &handles1, - &record1) + test->key3_, &test->value3_, &record1) .ok()); state->callback1 = base::MakeRefCounted<TestCallback>(); EXPECT_TRUE( @@ -898,12 +923,10 @@ std::make_unique<IndexedDBBackingStore::Transaction>( test->backing_store()); state->transaction2->Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles2; IndexedDBBackingStore::RecordIdentifier record2; EXPECT_TRUE(test->backing_store() ->PutRecord(state->transaction2.get(), 1, 1, - test->key1_, &test->value1_, &handles2, - &record2) + test->key1_, &test->value1_, &record2) .ok()); state->callback2 = base::MakeRefCounted<TestCallback>(); EXPECT_TRUE( @@ -953,12 +976,10 @@ std::make_unique<IndexedDBBackingStore::Transaction>( test->backing_store()); state->transaction1->Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; EXPECT_TRUE(test->backing_store() ->PutRecord(state->transaction1.get(), 1, 1, - test->key3_, &test->value3_, &handles, - &record) + test->key3_, &test->value3_, &record) .ok()); state->callback1 = base::MakeRefCounted<TestCallback>(); EXPECT_TRUE( @@ -1081,11 +1102,10 @@ { IndexedDBBackingStore::Transaction transaction1(backing_store); transaction1.Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; leveldb::Status s = backing_store->PutRecord( &transaction1, high_database_id, high_object_store_id, key1, - &value1, &handles, &record); + &value1, &record); EXPECT_TRUE(s.ok()); s = backing_store->PutIndexDataForRecord( @@ -1158,21 +1178,19 @@ IndexedDBBackingStore::Transaction transaction1(backing_store); transaction1.Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; leveldb::Status s = backing_store->PutRecord( &transaction1, database_id, KeyPrefix::kInvalidId, key, &value, - &handles, &record); + &record); EXPECT_FALSE(s.ok()); s = backing_store->PutRecord(&transaction1, database_id, 0, key, - &value, &handles, &record); + &value, &record); EXPECT_FALSE(s.ok()); s = backing_store->PutRecord(&transaction1, KeyPrefix::kInvalidId, - object_store_id, key, &value, &handles, - &record); + object_store_id, key, &value, &record); EXPECT_FALSE(s.ok()); s = backing_store->PutRecord(&transaction1, 0, object_store_id, key, - &value, &handles, &record); + &value, &record); EXPECT_FALSE(s.ok()); s = backing_store->GetRecord(&transaction1, database_id, @@ -1503,11 +1521,10 @@ // Save a value. IndexedDBBackingStore::Transaction transaction1(backing_store); transaction1.Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; leveldb::Status s = backing_store->PutRecord( &transaction1, state->database_id, state->object_store_id, key, - &value, &handles, &record); + &value, &record); EXPECT_TRUE(s.ok()); scoped_refptr<TestCallback> callback( base::MakeRefCounted<TestCallback>()); @@ -1648,13 +1665,12 @@ std::make_unique<IndexedDBBackingStore::Transaction>( test->backing_store()); state->transaction1->Begin(); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; IndexedDBBackingStore::RecordIdentifier record; EXPECT_TRUE(test->backing_store() ->PutRecord(state->transaction1.get(), state->database_id, state->object_store_id, test->key3_, - &test->value3_, &handles, &record) + &test->value3_, &record) .ok()); state->callback1 = base::MakeRefCounted<TestCallback>(); EXPECT_TRUE(
diff --git a/content/browser/indexed_db/indexed_db_blob_info.cc b/content/browser/indexed_db/indexed_db_blob_info.cc index a2308c4..0e40f9c 100644 --- a/content/browser/indexed_db/indexed_db_blob_info.cc +++ b/content/browser/indexed_db/indexed_db_blob_info.cc
@@ -14,11 +14,12 @@ : is_file_(false), size_(-1), key_(DatabaseMetaDataKey::kInvalidBlobKey) { } -IndexedDBBlobInfo::IndexedDBBlobInfo(const std::string& uuid, - const base::string16& type, - int64_t size) +IndexedDBBlobInfo::IndexedDBBlobInfo( + std::unique_ptr<storage::BlobDataHandle> blob_handle, + const base::string16& type, + int64_t size) : is_file_(false), - uuid_(uuid), + blob_handle_(*blob_handle), type_(type), size_(size), key_(DatabaseMetaDataKey::kInvalidBlobKey) {} @@ -28,18 +29,18 @@ int64_t key) : is_file_(false), type_(type), size_(size), key_(key) {} -IndexedDBBlobInfo::IndexedDBBlobInfo(const std::string& uuid, - const base::FilePath& file_path, - const base::string16& file_name, - const base::string16& type) +IndexedDBBlobInfo::IndexedDBBlobInfo( + std::unique_ptr<storage::BlobDataHandle> blob_handle, + const base::FilePath& file_path, + const base::string16& file_name, + const base::string16& type) : is_file_(true), - uuid_(uuid), + blob_handle_(*blob_handle), type_(type), size_(-1), file_name_(file_name), file_path_(file_path), - key_(DatabaseMetaDataKey::kInvalidBlobKey) { -} + key_(DatabaseMetaDataKey::kInvalidBlobKey) {} IndexedDBBlobInfo::IndexedDBBlobInfo(int64_t key, const base::string16& type, @@ -62,12 +63,6 @@ size_ = size; } -void IndexedDBBlobInfo::set_uuid(const std::string& uuid) { - DCHECK(uuid_.empty()); - uuid_ = uuid; - DCHECK(!uuid_.empty()); -} - void IndexedDBBlobInfo::set_file_path(const base::FilePath& file_path) { DCHECK(file_path_.empty()); file_path_ = file_path;
diff --git a/content/browser/indexed_db/indexed_db_blob_info.h b/content/browser/indexed_db/indexed_db_blob_info.h index 8b111943..2e36c081 100644 --- a/content/browser/indexed_db/indexed_db_blob_info.h +++ b/content/browser/indexed_db/indexed_db_blob_info.h
@@ -11,8 +11,10 @@ #include "base/callback.h" #include "base/files/file_path.h" +#include "base/optional.h" #include "base/time/time.h" #include "content/common/content_export.h" +#include "storage/browser/blob/blob_data_handle.h" namespace content { @@ -22,12 +24,12 @@ typedef base::RepeatingCallback<void(const base::FilePath&)> ReleaseCallback; IndexedDBBlobInfo(); // These two are used for Blobs. - IndexedDBBlobInfo(const std::string& uuid, + IndexedDBBlobInfo(std::unique_ptr<storage::BlobDataHandle> blob_handle, const base::string16& type, int64_t size); IndexedDBBlobInfo(const base::string16& type, int64_t size, int64_t key); // These two are used for Files. - IndexedDBBlobInfo(const std::string& uuid, + IndexedDBBlobInfo(std::unique_ptr<storage::BlobDataHandle> blob_handle, const base::FilePath& file_path, const base::string16& file_name, const base::string16& type); @@ -40,7 +42,9 @@ IndexedDBBlobInfo& operator=(const IndexedDBBlobInfo& other); bool is_file() const { return is_file_; } - const std::string& uuid() const { return uuid_; } + const storage::BlobDataHandle* blob_handle() const { + return blob_handle_.has_value() ? &blob_handle_.value() : nullptr; + } const base::string16& type() const { return type_; } int64_t size() const { return size_; } const base::string16& file_name() const { return file_name_; } @@ -53,7 +57,6 @@ const ReleaseCallback& release_callback() const { return release_callback_; } void set_size(int64_t size); - void set_uuid(const std::string& uuid); void set_file_path(const base::FilePath& file_path); void set_last_modified(const base::Time& time); void set_key(int64_t key); @@ -62,7 +65,8 @@ private: bool is_file_; - std::string uuid_; // Always for Blob; sometimes for File. + base::Optional<storage::BlobDataHandle> + blob_handle_; // Always for Blob; sometimes for File. base::string16 type_; // Mime type. int64_t size_; // -1 if unknown for File. base::string16 file_name_; // Only for File.
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc index 8e16c5d..3038de8e 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.cc +++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -738,10 +738,9 @@ IndexedDBCallbacks::IOThreadHelper::CreateBlobData( const IndexedDBBlobInfo& blob_info) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!blob_info.uuid().empty()) { + if (blob_info.blob_handle()) { // We're sending back a live blob, not a reference into our backing store. - return dispatcher_host_->blob_storage_context()->GetBlobDataFromUUID( - blob_info.uuid()); + return std::make_unique<storage::BlobDataHandle>(*blob_info.blob_handle()); } scoped_refptr<ShareableFileReference> shareable_file = ShareableFileReference::Get(blob_info.file_path());
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 3baba4f2..7d16b23 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -1216,7 +1216,6 @@ PutOperationParams() {} int64_t object_store_id; IndexedDBValue value; - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; std::unique_ptr<IndexedDBKey> key; blink::WebIDBPutMode put_mode; scoped_refptr<IndexedDBCallbacks> callbacks; @@ -1230,7 +1229,6 @@ IndexedDBTransaction* transaction, int64_t object_store_id, IndexedDBValue* value, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles, std::unique_ptr<IndexedDBKey> key, blink::WebIDBPutMode put_mode, scoped_refptr<IndexedDBCallbacks> callbacks, @@ -1248,7 +1246,6 @@ std::make_unique<PutOperationParams>()); params->object_store_id = object_store_id; params->value.swap(*value); - params->handles.swap(*handles); params->key = std::move(key); params->put_mode = put_mode; params->callbacks = callbacks; @@ -1336,7 +1333,7 @@ // transaction in case of error. s = backing_store_->PutRecord(transaction->BackingStoreTransaction(), id(), params->object_store_id, *key, ¶ms->value, - ¶ms->handles, &record_identifier); + &record_identifier); if (!s.ok()) return s;
diff --git a/content/browser/indexed_db/indexed_db_database.h b/content/browser/indexed_db/indexed_db_database.h index 0fc4f636..a3c8f43 100644 --- a/content/browser/indexed_db/indexed_db_database.h +++ b/content/browser/indexed_db/indexed_db_database.h
@@ -167,7 +167,6 @@ void Put(IndexedDBTransaction* transaction, int64_t object_store_id, IndexedDBValue* value, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles, std::unique_ptr<IndexedDBKey> key, blink::WebIDBPutMode mode, scoped_refptr<IndexedDBCallbacks> callbacks,
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc index fd5e264..69ac503 100644 --- a/content/browser/indexed_db/indexed_db_database_unittest.cc +++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -451,12 +451,11 @@ // Put is asynchronous IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>()); - std::vector<std::unique_ptr<storage::BlobDataHandle>> handles; std::unique_ptr<IndexedDBKey> key(std::make_unique<IndexedDBKey>("key")); std::vector<IndexedDBIndexKeys> index_keys; scoped_refptr<MockIndexedDBCallbacks> request( new MockIndexedDBCallbacks(false)); - db_->Put(transaction_, store_id, &value, &handles, std::move(key), + db_->Put(transaction_, store_id, &value, std::move(key), blink::kWebIDBPutModeAddOnly, request, index_keys); // Deletion is asynchronous.
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/content/browser/indexed_db/indexed_db_fake_backing_store.cc index 46b713f..9890819 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -41,7 +41,6 @@ int64_t object_store_id, const IndexedDBKey& key, IndexedDBValue* value, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles, RecordIdentifier* record) { return leveldb::Status::OK(); }
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.h b/content/browser/indexed_db/indexed_db_fake_backing_store.h index 42ab318..091108d 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.h +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -34,7 +34,6 @@ int64_t object_store_id, const IndexedDBKey& key, IndexedDBValue* value, - std::vector<std::unique_ptr<storage::BlobDataHandle>>* handles, RecordIdentifier* record) override; leveldb::Status ClearObjectStore(Transaction*,
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc index 8f9321e..8c76962d 100644 --- a/content/browser/media/media_web_contents_observer.cc +++ b/content/browser/media/media_web_contents_observer.cc
@@ -210,6 +210,7 @@ UpdateVideoLock(); + // TODO(872066): check for |pip_player_| fully matching paused player. if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() && pip_player_->render_frame_host == render_frame_host) { PictureInPictureWindowControllerImpl* pip_controller = @@ -265,6 +266,7 @@ return; } + // TODO(872066): check for |pip_player_| fully matching paused player. if (!web_contents()->IsBeingDestroyed() && pip_player_.has_value() && pip_player_->render_frame_host == render_frame_host) { PictureInPictureWindowControllerImpl* pip_controller =
diff --git a/content/browser/network_service_instance.cc b/content/browser/network_service_instance.cc index 45ec9ffc..95c2be4 100644 --- a/content/browser/network_service_instance.cc +++ b/content/browser/network_service_instance.cc
@@ -13,6 +13,7 @@ #include "net/log/net_log_util.h" #include "services/network/network_service.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/network_switches.h" #include "services/service_manager/public/cpp/connector.h" @@ -21,6 +22,7 @@ namespace { network::mojom::NetworkServicePtr* g_network_service_ptr = nullptr; +network::NetworkConnectionTracker* g_network_connection_tracker; network::NetworkService* g_network_service; void CreateNetworkServiceOnIO(network::mojom::NetworkServiceRequest request) { @@ -104,4 +106,18 @@ g_network_service_ptr->FlushForTesting(); } +network::NetworkConnectionTracker* GetNetworkConnectionTracker() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!g_network_connection_tracker) { + g_network_connection_tracker = new network::NetworkConnectionTracker( + base::BindRepeating(&GetNetworkService)); + } + return g_network_connection_tracker; +} + +void SetNetworkConnectionTrackerForTesting( + network::NetworkConnectionTracker* network_connection_tracker) { + g_network_connection_tracker = network_connection_tracker; +} + } // namespace content
diff --git a/content/browser/permissions/permission_controller_impl.cc b/content/browser/permissions/permission_controller_impl.cc index 75ccdf0..965cfcb 100644 --- a/content/browser/permissions/permission_controller_impl.cc +++ b/content/browser/permissions/permission_controller_impl.cc
@@ -101,15 +101,15 @@ int PermissionControllerImpl::SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { PermissionControllerDelegate* delegate = browser_context_->GetPermissionControllerDelegate(); if (!delegate) return kNoPendingOperation; return delegate->SubscribePermissionStatusChange( - permission, requesting_origin, embedding_origin, callback); + permission, render_frame_host, requesting_origin, callback); } void PermissionControllerImpl::UnsubscribePermissionStatusChange(
diff --git a/content/browser/permissions/permission_controller_impl.h b/content/browser/permissions/permission_controller_impl.h index 460f0335..3b9de91 100644 --- a/content/browser/permissions/permission_controller_impl.h +++ b/content/browser/permissions/permission_controller_impl.h
@@ -55,8 +55,8 @@ int SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback); void UnsubscribePermissionStatusChange(int subscription_id);
diff --git a/content/browser/permissions/permission_service_context.cc b/content/browser/permissions/permission_service_context.cc index 05cd21b..e644dd0 100644 --- a/content/browser/permissions/permission_service_context.cc +++ b/content/browser/permissions/permission_service_context.cc
@@ -97,15 +97,10 @@ auto subscription = std::make_unique<PermissionSubscription>(this, std::move(observer)); GURL requesting_origin(origin.Serialize()); - GURL embedding_origin = GetEmbeddingOrigin(); int subscription_id = PermissionControllerImpl::FromBrowserContext(browser_context) ->SubscribePermissionStatusChange( - permission_type, requesting_origin, - // If the embedding_origin is empty, we'll use the |origin| - // instead. - embedding_origin.is_empty() ? requesting_origin - : embedding_origin, + permission_type, render_frame_host_, requesting_origin, base::Bind(&PermissionSubscription::OnPermissionStatusChanged, base::Unretained(subscription.get()))); subscription->set_id(subscription_id);
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc index b97d2ad..7f18562 100644 --- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc +++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
@@ -158,6 +158,8 @@ return; } + DCHECK(media_player_id_.has_value()); + window_->SetPlaybackState(is_playing ? OverlayWindow::PlaybackState::kPlaying : OverlayWindow::PlaybackState::kPaused); }
diff --git a/content/browser/renderer_host/input/fling_controller_unittest.cc b/content/browser/renderer_host/input/fling_controller_unittest.cc index 128a4703..7447a68 100644 --- a/content/browser/renderer_host/input/fling_controller_unittest.cc +++ b/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -195,7 +195,8 @@ EXPECT_EQ(0.f, last_sent_wheel_.delta_y); } -TEST_F(FlingControllerTest, ControllerHandlesTouchscreenGestureFling) { +// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms. +TEST_F(FlingControllerTest, DISABLED_ControllerHandlesTouchscreenGestureFling) { base::TimeTicks progress_time = base::TimeTicks::Now(); SimulateFlingStart(blink::kWebGestureDeviceTouchscreen, gfx::Vector2dF(1000, 0)); @@ -221,7 +222,9 @@ EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType()); } -TEST_F(FlingControllerTest, ControllerSendsWheelEndWhenTouchpadFlingIsOver) { +// TODO(https://crbug.com/836996): Timing-dependent flakes on some platforms. +TEST_F(FlingControllerTest, + DISABLED_ControllerSendsWheelEndWhenTouchpadFlingIsOver) { base::TimeTicks progress_time = base::TimeTicks::Now(); SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(100, 0)); EXPECT_TRUE(FlingInProgress());
diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc index 3a3ddba..658171df8 100644 --- a/content/browser/renderer_host/input/touch_action_filter.cc +++ b/content/browser/renderer_host/input/touch_action_filter.cc
@@ -6,6 +6,7 @@ #include <math.h> +#include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" @@ -42,7 +43,7 @@ force_enable_zoom_(false) {} TouchActionFilter::~TouchActionFilter() { - function_call_sequence_.clear(); + gesture_sequence_.clear(); } FilterGestureEventResult TouchActionFilter::FilterGestureEvent( @@ -56,6 +57,7 @@ case WebInputEvent::kGestureScrollBegin: { DCHECK(!suppress_manipulation_events_); DCHECK(!touchscreen_scroll_in_progress_); + gesture_sequence_.append("GSB "); touchscreen_scroll_in_progress_ = true; // TODO(https://crbug.com/851644): Make sure the value is properly set. if (!scrolling_touch_action_.has_value()) @@ -101,7 +103,7 @@ break; case WebInputEvent::kGestureScrollEnd: - function_call_sequence_.clear(); + gesture_sequence_.clear(); DCHECK(touchscreen_scroll_in_progress_); touchscreen_scroll_in_progress_ = false; ReportGestureEventFiltered(suppress_manipulation_events_); @@ -154,17 +156,10 @@ scrolling_touch_action_ = allowed_touch_action_; // TODO(https://crbug.com/851644): Make sure the value is properly set. if (!scrolling_touch_action_.has_value()) { - auto index_of_set = - std::find(std::begin(function_call_sequence_), - std::end(function_call_sequence_), kOnSetTouchActionCall); - auto index_of_reset = - std::find(std::begin(function_call_sequence_), - std::end(function_call_sequence_), kResetTouchActionCall); - if (index_of_set != std::end(function_call_sequence_) && - index_of_reset != std::end(function_call_sequence_) && - index_of_reset > index_of_set) { - base::debug::DumpWithoutCrashing(); - } + static auto* crash_key = base::debug::AllocateCrashKeyString( + "touchaction-gestures", base::debug::CrashKeySize::Size256); + base::debug::SetCrashKeyString(crash_key, gesture_sequence_); + base::debug::DumpWithoutCrashing(); SetTouchAction(cc::kTouchActionAuto); } DCHECK(!drop_current_tap_ending_event_); @@ -194,7 +189,7 @@ void TouchActionFilter::OnSetTouchAction(cc::TouchAction touch_action) { if (touch_action != cc::kTouchActionAuto) - function_call_sequence_.push_back(kOnSetTouchActionCall); + gesture_sequence_.append("Set "); // TODO(https://crbug.com/849819): add a DCHECK for // |has_touch_event_handler_|. // For multiple fingers, we take the intersection of the touch actions for @@ -253,7 +248,7 @@ // their begin event(s) suppressed will be suppressed until the next // sequenceo. if (has_touch_event_handler_) { - function_call_sequence_.push_back(kResetTouchActionCall); + gesture_sequence_.append("Reset "); allowed_touch_action_.reset(); white_listed_touch_action_.reset(); } else {
diff --git a/content/browser/renderer_host/input/touch_action_filter.h b/content/browser/renderer_host/input/touch_action_filter.h index fa07dbe3..5b8b0e5 100644 --- a/content/browser/renderer_host/input/touch_action_filter.h +++ b/content/browser/renderer_host/input/touch_action_filter.h
@@ -113,14 +113,7 @@ // Whitelisted touch action received from the compositor. base::Optional<cc::TouchAction> white_listed_touch_action_; - // DEBUG ONLY! Record the sequence of function calls, cleared at GSE. When it - // is GSB and |scrolling_touch_action_| has no value, check this sequence. - enum FunctionCalls { - kOnSetTouchActionCall, - kResetTouchActionCall, - }; - - std::vector<FunctionCalls> function_call_sequence_; + std::string gesture_sequence_; DISALLOW_COPY_AND_ASSIGN(TouchActionFilter); };
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 3eb5677..166816c 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1391,14 +1391,16 @@ is_keep_alive_ref_count_disabled_(false), route_provider_binding_(this), visible_clients_(0), - priority_({ - blink::kLaunchingProcessIsBackgrounded, frame_depth_, - false /* intersects_viewport */, - blink::kLaunchingProcessIsBoostedForPendingView, + priority_(!blink::kLaunchingProcessIsBackgrounded, + false /* has_media_stream */, + frame_depth_, + false /* intersects_viewport */, + blink::kLaunchingProcessIsBoostedForPendingView #if defined(OS_ANDROID) - ChildProcessImportance::NORMAL, + , + ChildProcessImportance::NORMAL #endif - }), + ), id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), browser_context_(browser_context), storage_partition_impl_(storage_partition_impl), @@ -1847,8 +1849,7 @@ AddFilter(new PepperRendererConnection(GetID())); #endif AddFilter(new FileAPIMessageFilter( - GetID(), storage_partition_impl_->GetURLRequestContext(), - storage_partition_impl_->GetFileSystemContext(), + GetID(), storage_partition_impl_->GetFileSystemContext(), blob_storage_context.get())); AddFilter(new BlobDispatcherHost(GetID(), blob_storage_context)); #if defined(OS_MACOSX) @@ -2198,7 +2199,7 @@ } bool RenderProcessHostImpl::IsProcessBackgrounded() const { - return priority_.background; + return priority_.is_background(); } void RenderProcessHostImpl::IncrementKeepAliveRefCount( @@ -4112,36 +4113,35 @@ void RenderProcessHostImpl::UpdateProcessPriority() { if (!run_renderer_in_process() && (!child_process_launcher_.get() || child_process_launcher_->IsStarting())) { - priority_.background = blink::kLaunchingProcessIsBackgrounded; + priority_.foreground = !blink::kLaunchingProcessIsBackgrounded; priority_.boost_for_pending_views = blink::kLaunchingProcessIsBoostedForPendingView; return; } - const ChildProcessLauncherPriority priority = { - // We background a process as soon as it hosts no active audio/video streams - // and no visible widgets -- the callers must call this function whenever we - // transition in/out of those states. - visible_clients_ == 0 && media_stream_count_ == 0 && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableRendererBackgrounding), - frame_depth_, - intersects_viewport_, - // boost_for_pending_views - !!pending_views_, + const ChildProcessLauncherPriority priority( + // We consider a process in foreground if it hosts no visible widgets -- + // the callers must call this function whenever we transition in/out of + // those states. + visible_clients_ > 0 || base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableRendererBackgrounding), + media_stream_count_ > 0, frame_depth_, intersects_viewport_, + // boost_for_pending_views + !!pending_views_ #if defined(OS_ANDROID) - GetEffectiveImportance(), + , + GetEffectiveImportance() #endif - }; + ); const bool should_background_changed = - priority_.background != priority.background; + priority_.is_background() != priority.is_background(); if (priority_ == priority) return; TRACE_EVENT2("renderer_host", "RenderProcessHostImpl::UpdateProcessPriority", - "should_background", priority.background, "has_pending_views", - priority.boost_for_pending_views); + "should_background", priority.is_background(), + "has_pending_views", priority.boost_for_pending_views); priority_ = priority; #if defined(OS_WIN) @@ -4170,7 +4170,7 @@ // |priority_.boost_for_pending_views| state is not sent to renderer simply // due to lack of need. if (should_background_changed) { - GetRendererInterface()->SetProcessBackgrounded(priority.background); + GetRendererInterface()->SetProcessBackgrounded(priority.is_background()); } } @@ -4184,7 +4184,8 @@ if (child_process_launcher_) { DCHECK(child_process_launcher_->GetProcess().IsValid()); - DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, priority_.background); + DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, + priority_.is_background()); // Unpause the channel now that the process is launched. We don't flush it // yet to ensure that any initialization messages sent here (e.g., things @@ -4197,20 +4198,21 @@ child_process_launcher_->GetProcess().Handle()); } - // Not all platforms launch processes in the same backgrounded state. Make - // sure |priority_.background| reflects this platform's initial process - // state. +// Not all platforms launch processes in the same backgrounded state. Make +// sure |priority_.foreground| reflects this platform's initial process +// state. #if defined(OS_MACOSX) - priority_.background = - child_process_launcher_->GetProcess().IsProcessBackgrounded( + priority_.foreground = + !child_process_launcher_->GetProcess().IsProcessBackgrounded( MachBroker::GetInstance()); #elif defined(OS_ANDROID) // Android child process priority works differently and cannot be queried // directly from base::Process. - DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, priority_.background); + DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, + priority_.is_background()); #else - priority_.background = - child_process_launcher_->GetProcess().IsProcessBackgrounded(); + priority_.foreground = + !child_process_launcher_->GetProcess().IsProcessBackgrounded(); #endif // defined(OS_MACOSX) // Disable updating process priority on startup on desktop platforms for now
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc index b0ab486..ab15474 100644 --- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc +++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -46,61 +46,6 @@ namespace { -// This class wraps a mojo::AssociatedInterfacePtr<URLLoader>. It also is a -// URLLoader implementation and delegates URLLoader calls to the wrapped loader. -class DelegatingURLLoader final : public network::mojom::URLLoader { - public: - explicit DelegatingURLLoader(network::mojom::URLLoaderPtr loader) - : binding_(this), loader_(std::move(loader)) {} - ~DelegatingURLLoader() override {} - - void FollowRedirect(const base::Optional<std::vector<std::string>>& - to_be_removed_request_headers, - const base::Optional<net::HttpRequestHeaders>& - modified_request_headers) override { - DCHECK(!modified_request_headers.has_value()) - << "Redirect with modified headers was not supported yet. " - "crbug.com/845683"; - loader_->FollowRedirect(base::nullopt, base::nullopt); - } - void ProceedWithResponse() override { NOTREACHED(); } - - void SetPriority(net::RequestPriority priority, - int intra_priority_value) override { - loader_->SetPriority(priority, intra_priority_value); - } - - void PauseReadingBodyFromNet() override { - loader_->PauseReadingBodyFromNet(); - } - void ResumeReadingBodyFromNet() override { - loader_->ResumeReadingBodyFromNet(); - } - - network::mojom::URLLoaderPtr CreateInterfacePtrAndBind() { - network::mojom::URLLoaderPtr loader; - binding_.Bind(mojo::MakeRequest(&loader)); - // This unretained pointer is safe, because |binding_| is owned by |this| - // and the callback will never be called after |this| is destroyed. - binding_.set_connection_error_handler( - base::BindOnce(&DelegatingURLLoader::Cancel, base::Unretained(this))); - return loader; - } - - private: - // Called when the network::mojom::URLLoaderPtr in the service worker is - // deleted. - void Cancel() { - // Cancel loading as stated in url_loader.mojom. - loader_ = nullptr; - } - - mojo::Binding<network::mojom::URLLoader> binding_; - network::mojom::URLLoaderPtr loader_; - - DISALLOW_COPY_AND_ASSIGN(DelegatingURLLoader); -}; - void NotifyNavigationPreloadRequestSentOnUI( const network::ResourceRequest& request, const std::pair<int, int>& worker_id, @@ -441,10 +386,8 @@ public: URLLoaderAssets( std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory, - std::unique_ptr<network::mojom::URLLoader> url_loader, std::unique_ptr<DelegatingURLLoaderClient> url_loader_client) : url_loader_factory_(std::move(url_loader_factory)), - url_loader_(std::move(url_loader)), url_loader_client_(std::move(url_loader_client)) {} void MaybeReportToDevTools(std::pair<int, int> worker_id, @@ -457,7 +400,6 @@ virtual ~URLLoaderAssets() {} std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory_; - std::unique_ptr<network::mojom::URLLoader> url_loader_; std::unique_ptr<DelegatingURLLoaderClient> url_loader_client_; DISALLOW_COPY_AND_ASSIGN(URLLoaderAssets); @@ -721,30 +663,26 @@ DCHECK_LT(request_id, -1); preload_handle_ = blink::mojom::FetchEventPreloadHandle::New(); - network::mojom::URLLoaderClientPtr url_loader_client_ptr; + network::mojom::URLLoaderClientPtr inner_url_loader_client; preload_handle_->url_loader_client_request = - mojo::MakeRequest(&url_loader_client_ptr); + mojo::MakeRequest(&inner_url_loader_client); auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>( - std::move(url_loader_client_ptr), std::move(on_response), request); - network::mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; - url_loader_client->Bind(&url_loader_client_ptr_to_pass); - network::mojom::URLLoaderPtr url_loader_associated_ptr; + std::move(inner_url_loader_client), std::move(on_response), request); + network::mojom::URLLoaderClientPtr url_loader_client_to_pass; + url_loader_client->Bind(&url_loader_client_to_pass); + network::mojom::URLLoaderPtr url_loader; url_loader_factory->CreateLoaderAndStart( - mojo::MakeRequest(&url_loader_associated_ptr), - original_info->GetRouteID(), request_id, + mojo::MakeRequest(&url_loader), original_info->GetRouteID(), request_id, network::mojom::kURLLoadOptionNone, request, - std::move(url_loader_client_ptr_to_pass), + std::move(url_loader_client_to_pass), net::MutableNetworkTrafficAnnotationTag( original_request->traffic_annotation())); - auto url_loader = std::make_unique<DelegatingURLLoader>( - std::move(url_loader_associated_ptr)); - preload_handle_->url_loader = - url_loader->CreateInterfacePtrAndBind().PassInterface(); + preload_handle_->url_loader = url_loader.PassInterface(); + url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>( - std::move(url_loader_factory), std::move(url_loader), - std::move(url_loader_client)); + std::move(url_loader_factory), std::move(url_loader_client)); return true; } @@ -784,40 +722,33 @@ // Create the DelegatingURLLoaderClient, which becomes the // URLLoaderClient for the navigation preload network request. - network::mojom::URLLoaderClientPtr url_loader_client_ptr; + network::mojom::URLLoaderClientPtr inner_url_loader_client; preload_handle_->url_loader_client_request = - mojo::MakeRequest(&url_loader_client_ptr); + mojo::MakeRequest(&inner_url_loader_client); auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>( - std::move(url_loader_client_ptr), std::move(on_response), + std::move(inner_url_loader_client), std::move(on_response), resource_request); // Start the network request for the URL using the network loader. // TODO(falken): What to do about routing_id, request_id? - network::mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; - url_loader_client->Bind(&url_loader_client_ptr_to_pass); - network::mojom::URLLoaderPtr url_loader_associated_ptr; + network::mojom::URLLoaderClientPtr url_loader_client_to_pass; + url_loader_client->Bind(&url_loader_client_to_pass); + network::mojom::URLLoaderPtr url_loader; url_loader_factory_getter->GetNetworkFactory()->CreateLoaderAndStart( - mojo::MakeRequest(&url_loader_associated_ptr), -1 /* routing_id? */, + mojo::MakeRequest(&url_loader), -1 /* routing_id? */, -1 /* request_id? */, network::mojom::kURLLoadOptionNone, - resource_request, std::move(url_loader_client_ptr_to_pass), + resource_request, std::move(url_loader_client_to_pass), net::MutableNetworkTrafficAnnotationTag( kNavigationPreloadTrafficAnnotation)); - // Hook the load up to DelegatingURLLoader, which will call our - // DelegatingURLLoaderClient. - auto url_loader = std::make_unique<DelegatingURLLoader>( - std::move(url_loader_associated_ptr)); - preload_handle_->url_loader = - url_loader->CreateInterfacePtrAndBind().PassInterface(); + preload_handle_->url_loader = url_loader.PassInterface(); DCHECK(!url_loader_assets_); // Unlike the non-S13N code path, we don't own the URLLoaderFactory being used // (it's the generic network factory), so we don't need to pass it to // URLLoaderAssets to keep it alive. - std::unique_ptr<network::mojom::URLLoaderFactory> null_factory; url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>( - std::move(null_factory), std::move(url_loader), - std::move(url_loader_client)); + nullptr /* url_loader_factory */, std::move(url_loader_client)); return true; }
diff --git a/content/browser/shared_worker/shared_worker_host.cc b/content/browser/shared_worker/shared_worker_host.cc index 3184042..192a0af 100644 --- a/content/browser/shared_worker/shared_worker_host.cc +++ b/content/browser/shared_worker/shared_worker_host.cc
@@ -164,20 +164,13 @@ // Add the network factory to the bundle to pass to the renderer. The bundle // is only provided (along with |script_loader_factory|) if - // NetworkService/S13nSW is enabled. + // NetworkService/S13nServiceWorker is enabled, and default factory isn't + // provided if NetworkService is on but S13nServiceWorker is off. DCHECK(!script_loader_factory || factory_bundle); - if (factory_bundle) { + if (factory_bundle && !factory_bundle->default_factory_info()) { + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); network::mojom::URLLoaderFactoryPtrInfo network_factory_info; - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - // NetworkService is on: Use the network service. - CreateNetworkFactory(mojo::MakeRequest(&network_factory_info)); - } else { - // NetworkService is off: RenderProcessHost gives us a non-NetworkService - // network factory. - RenderProcessHost::FromID(process_id_) - ->CreateURLLoaderFactory(mojo::MakeRequest(&network_factory_info)); - } - DCHECK(!factory_bundle->default_factory_info()); + CreateNetworkFactory(mojo::MakeRequest(&network_factory_info)); factory_bundle->default_factory_info() = std::move(network_factory_info); // TODO(falken): We might need to set the default factory to AppCache
diff --git a/content/browser/shared_worker/shared_worker_script_loader.cc b/content/browser/shared_worker/shared_worker_script_loader.cc index d363f74..2927380 100644 --- a/content/browser/shared_worker/shared_worker_script_loader.cc +++ b/content/browser/shared_worker/shared_worker_script_loader.cc
@@ -6,6 +6,7 @@ #include "content/browser/appcache/appcache_request_handler.h" #include "content/browser/loader/navigation_loader_interceptor.h" +#include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/service_worker/service_worker_provider_host.h" #include "content/public/browser/resource_context.h" #include "net/url_request/redirect_util.h" @@ -15,6 +16,7 @@ namespace content { SharedWorkerScriptLoader::SharedWorkerScriptLoader( + int process_id, int32_t routing_id, int32_t request_id, uint32_t options, @@ -25,7 +27,8 @@ ResourceContext* resource_context, scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) - : routing_id_(routing_id), + : process_id_(process_id), + routing_id_(routing_id), request_id_(request_id), options_(options), resource_request_(resource_request), @@ -143,6 +146,12 @@ interceptor_index_ = 0; url_loader_client_binding_.Unbind(); redirect_info_.reset(); + + // Cancel the request on ResourceDispatcherHost so that we can fall back + // to network again. + DCHECK(ResourceDispatcherHostImpl::Get()); + ResourceDispatcherHostImpl::Get()->CancelRequest(process_id_, request_id_); + Start(); }
diff --git a/content/browser/shared_worker/shared_worker_script_loader.h b/content/browser/shared_worker/shared_worker_script_loader.h index 4730433..cd3d6d5 100644 --- a/content/browser/shared_worker/shared_worker_script_loader.h +++ b/content/browser/shared_worker/shared_worker_script_loader.h
@@ -43,6 +43,7 @@ // non-NetworkService factories used for non-http(s) URLs, e.g., a // chrome-extension:// URL. SharedWorkerScriptLoader( + int process_id, int32_t routing_id, int32_t request_id, uint32_t options, @@ -93,6 +94,7 @@ std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_; size_t interceptor_index_ = 0; + const int process_id_; const int32_t routing_id_; const int32_t request_id_; const uint32_t options_;
diff --git a/content/browser/shared_worker/shared_worker_script_loader_factory.cc b/content/browser/shared_worker/shared_worker_script_loader_factory.cc index c4a876b..74eaef6 100644 --- a/content/browser/shared_worker/shared_worker_script_loader_factory.cc +++ b/content/browser/shared_worker/shared_worker_script_loader_factory.cc
@@ -20,12 +20,14 @@ namespace content { SharedWorkerScriptLoaderFactory::SharedWorkerScriptLoaderFactory( + int process_id, ServiceWorkerContextWrapper* context, base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host, base::WeakPtr<AppCacheHost> appcache_host, ResourceContext* resource_context, scoped_refptr<network::SharedURLLoaderFactory> loader_factory) - : service_worker_provider_host_(std::move(service_worker_provider_host)), + : process_id_(process_id), + service_worker_provider_host_(std::move(service_worker_provider_host)), appcache_host_(std::move(appcache_host)), resource_context_(resource_context), loader_factory_(std::move(loader_factory)) { @@ -61,9 +63,9 @@ // Create a SharedWorkerScriptLoader to load the script. mojo::MakeStrongBinding( std::make_unique<SharedWorkerScriptLoader>( - routing_id, request_id, options, resource_request, std::move(client), - service_worker_provider_host_, appcache_host_, resource_context_, - loader_factory_, traffic_annotation), + process_id_, routing_id, request_id, options, resource_request, + std::move(client), service_worker_provider_host_, appcache_host_, + resource_context_, loader_factory_, traffic_annotation), std::move(request)); }
diff --git a/content/browser/shared_worker/shared_worker_script_loader_factory.h b/content/browser/shared_worker/shared_worker_script_loader_factory.h index 356baea..f54949b 100644 --- a/content/browser/shared_worker/shared_worker_script_loader_factory.h +++ b/content/browser/shared_worker/shared_worker_script_loader_factory.h
@@ -37,6 +37,7 @@ // the NetworkService. However, it may internally contain non-NetworkService // factories used for non-http(s) URLs, e.g., a chrome-extension:// URL. SharedWorkerScriptLoaderFactory( + int process_id, ServiceWorkerContextWrapper* context, base::WeakPtr<ServiceWorkerProviderHost> provider_host, base::WeakPtr<AppCacheHost> appcache_host, @@ -56,6 +57,7 @@ void Clone(network::mojom::URLLoaderFactoryRequest request) override; private: + const int process_id_; base::WeakPtr<ServiceWorkerProviderHost> service_worker_provider_host_; base::WeakPtr<AppCacheHost> appcache_host_; ResourceContext* resource_context_ = nullptr;
diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc index 1defce7..9ed1be7 100644 --- a/content/browser/shared_worker/shared_worker_service_impl.cc +++ b/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -83,6 +83,17 @@ factory_bundle->factories_info().emplace(url::kFileScheme, file_factory_ptr.PassInterface()); } + + // Use RenderProcessHost's network factory as the default factory if + // NetworkService is off. If NetworkService is on the default factory is + // set in CreateScriptLoaderOnIO(). + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + network::mojom::URLLoaderFactoryPtr default_factory; + RenderProcessHost::FromID(process_id) + ->CreateURLLoaderFactory(mojo::MakeRequest(&default_factory)); + factory_bundle->default_factory_info() = default_factory.PassInterface(); + } + return factory_bundle; } @@ -116,20 +127,25 @@ url_loader_factory = network::SharedURLLoaderFactory::Create( std::move(blob_url_loader_factory_info)); } else { + // Add the network factory to the bundle. If NetworkService is off the + // default factory was already set in CreateFactoryBundle(). + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService) || + factory_bundle_for_browser_info->default_factory_info()); // Create a factory bundle to use. scoped_refptr<URLLoaderFactoryBundle> factory_bundle = base::MakeRefCounted<URLLoaderFactoryBundle>( std::move(factory_bundle_for_browser_info)); url_loader_factory = factory_bundle; - // Add the network factory to the bundle. The factory from - // CloneNetworkFactory() doesn't support reconnection to the network service - // after a crash, but it's OK since it's used for a single shared worker - // startup. - network::mojom::URLLoaderFactoryPtr network_factory_ptr; - loader_factory_getter->CloneNetworkFactory( - mojo::MakeRequest(&network_factory_ptr)); - factory_bundle->SetDefaultFactory(std::move(network_factory_ptr)); + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + // The factory from CloneNetworkFactory() doesn't support reconnection to + // the network service after a crash, but it's OK since it's used for a + // single shared worker startup. + network::mojom::URLLoaderFactoryPtr network_factory_ptr; + loader_factory_getter->CloneNetworkFactory( + mojo::MakeRequest(&network_factory_ptr)); + factory_bundle->SetDefaultFactory(std::move(network_factory_ptr)); + } } // It's safe for |appcache_handle_core| to be a raw pointer. The core is owned @@ -144,8 +160,9 @@ network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory; mojo::MakeStrongAssociatedBinding( std::make_unique<SharedWorkerScriptLoaderFactory>( - context.get(), host->AsWeakPtr(), std::move(appcache_host), - context->resource_context(), std::move(url_loader_factory)), + process_id, context.get(), host->AsWeakPtr(), + std::move(appcache_host), context->resource_context(), + std::move(url_loader_factory)), mojo::MakeRequest(&script_loader_factory)); // We continue in StartWorker.
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 4d758960..3d07ce8e0 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -291,6 +291,33 @@ gfx::PointF(95, 95)); } +void NonFlatTransformedSurfaceHitTestHelper( + Shell* shell, + net::test_server::EmbeddedTestServer* embedded_test_server) { + GURL main_url(embedded_test_server->GetURL( + "/frame_tree/page_with_non_flat_transformed_frame.html")); + EXPECT_TRUE(NavigateToURL(shell, main_url)); + auto* web_contents = static_cast<WebContentsImpl*>(shell->web_contents()); + + FrameTreeNode* root = web_contents->GetFrameTree()->root(); + ASSERT_EQ(1U, root->child_count()); + + FrameTreeNode* child_node = root->child_at(0); + GURL site_url(embedded_test_server->GetURL("baz.com", "/title1.html")); + EXPECT_EQ(site_url, child_node->current_url()); + EXPECT_NE(shell->web_contents()->GetSiteInstance(), + child_node->current_frame_host()->GetSiteInstance()); + + RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>( + child_node->current_frame_host()->GetRenderWidgetHost()->GetView()); + + WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host()); + + DispatchMouseEventAndWaitUntilDispatch(web_contents, rwhv_child, + gfx::PointF(5, 5), rwhv_child, + gfx::PointF(5, 5)); +} + // Helper function that performs a surface hittest in nested frame. void NestedSurfaceHitTestTestHelper( Shell* shell, @@ -1834,6 +1861,16 @@ NestedSurfaceHitTestTestHelper(shell(), embedded_test_server()); } +IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, + NonFlatTransformedSurfaceHitTestTest) { + NonFlatTransformedSurfaceHitTestHelper(shell(), embedded_test_server()); +} + +IN_PROC_BROWSER_TEST_P(SitePerProcessHighDPIHitTestBrowserTest, + NonFlatTransformedSurfaceHitTestTest) { + NonFlatTransformedSurfaceHitTestHelper(shell(), embedded_test_server()); +} + #if defined(OS_LINUX) // Flaky timeouts and failures: https://crbug.com/833380 #define MAYBE_OverlapSurfaceHitTestTest DISABLED_OverlapSurfaceHitTestTest
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java index 8b23dd6a..67d5588 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java
@@ -435,7 +435,7 @@ } @CalledByNative - private void setPriority(int pid, boolean foreground, long frameDepth, + private void setPriority(int pid, boolean foreground, boolean hasMediaStream, long frameDepth, boolean intersectsViewport, boolean boostForPendingViews, @ChildProcessImportance int importance) { assert LauncherThread.runningOnLauncherThread(); @@ -451,12 +451,17 @@ boostForPendingViews = false; } + boolean mediaRendererHasModerate = ContentFeatureList.isEnabled( + ContentFeatureList.BACKGROUND_MEDIA_RENDERER_HAS_MODERATE_BINDING); + @ChildProcessImportance int newEffectiveImportance; - if ((foreground && frameDepth == 0) || importance == ChildProcessImportance.IMPORTANT) { + if ((foreground && frameDepth == 0) || importance == ChildProcessImportance.IMPORTANT + || (hasMediaStream && !mediaRendererHasModerate)) { newEffectiveImportance = ChildProcessImportance.IMPORTANT; } else if ((foreground && frameDepth > 0 && intersectsViewport) || boostForPendingViews - || importance == ChildProcessImportance.MODERATE) { + || importance == ChildProcessImportance.MODERATE + || (hasMediaStream && mediaRendererHasModerate)) { newEffectiveImportance = ChildProcessImportance.MODERATE; } else { newEffectiveImportance = ChildProcessImportance.NORMAL;
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java b/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java index e59b7cc..2a0060a9 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentFeatureList.java
@@ -33,5 +33,8 @@ public static final String ENHANCED_SELECTION_INSERTION_HANDLE = "EnhancedSelectionInsertionHandle"; + public static final String BACKGROUND_MEDIA_RENDERER_HAS_MODERATE_BINDING = + "BackgroundMediaRendererHasModerateBinding"; + private static native boolean nativeIsEnabled(String featureName); }
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 7a0734e..62eafade 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -196,7 +196,6 @@ "device.mojom.VibrationManager", "device.mojom.UsbDeviceManager", "device.mojom.VRService", - "device.mojom.VRService", "device.mojom.WakeLock", "discardable_memory.mojom.DiscardableSharedMemoryManager", "media.mojom.ImageCapture",
diff --git a/content/public/browser/network_service_instance.h b/content/public/browser/network_service_instance.h index 47e20afb..5f57eaaa 100644 --- a/content/public/browser/network_service_instance.h +++ b/content/public/browser/network_service_instance.h
@@ -8,6 +8,7 @@ #include "content/common/content_export.h" namespace network { +class NetworkConnectionTracker; class NetworkService; namespace mojom { class NetworkService; @@ -34,6 +35,17 @@ // Must only be called on the UI thread. CONTENT_EXPORT void FlushNetworkServiceInstanceForTesting(); +// Returns a NetworkConnectionTracker that can be used to subscribe for +// network change events. +// Must only be called on the UI thread. +CONTENT_EXPORT network::NetworkConnectionTracker* GetNetworkConnectionTracker(); + +// Sets the NetworkConnectionTracker instance to use. For testing only. +// Must be called on the UI thread. Must be called before the first call to +// GetNetworkConnectionTracker. +CONTENT_EXPORT void SetNetworkConnectionTrackerForTesting( + network::NetworkConnectionTracker* network_connection_tracker); + } // namespace content #endif // CONTENT_PUBLIC_BROWSER_NETWORK_SERVICE_INSTANCE_H_
diff --git a/content/public/browser/permission_controller_delegate.h b/content/public/browser/permission_controller_delegate.h index 2a81ed3..98eb6518 100644 --- a/content/public/browser/permission_controller_delegate.h +++ b/content/public/browser/permission_controller_delegate.h
@@ -77,13 +77,13 @@ const GURL& embedding_origin) = 0; // Runs the given |callback| whenever the |permission| associated with the - // pair { requesting_origin, embedding_origin } changes. - // Returns the subscription_id to be used to unsubscribe. Can be - // kNoPendingOperation if the subscribe was not successful. + // given RenderFrameHost changes. A nullptr should be passed if the request + // is from a worker. Returns the subscription_id to be used to unsubscribe. + // Can be kNoPendingOperation if the subscribe was not successful. virtual int SubscribePermissionStatusChange( - PermissionType permission, + content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) = 0; // Unregisters from permission status change notifications.
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 6b43766d..79725fa 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -620,6 +620,12 @@ const base::Feature kHideIncorrectlySizedFullscreenFrames{ "HideIncorrectlySizedFullscreenFrames", base::FEATURE_ENABLED_BY_DEFAULT}; +// Sets moderate binding to background renderers playing media, when enabled. +// Else the renderer will have strong binding. +const base::Feature kBackgroundMediaRendererHasModerateBinding{ + "BackgroundMediaRendererHasModerateBinding", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls whether the WebNFC API is enabled: // https://w3c.github.io/web-nfc/ const base::Feature kWebNfc{"WebNFC", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 5cd76739..fbbdce2 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -140,6 +140,8 @@ #if defined(OS_ANDROID) CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility; +CONTENT_EXPORT extern const base::Feature + kBackgroundMediaRendererHasModerateBinding; CONTENT_EXPORT extern const base::Feature kDisplayCutoutAPI; CONTENT_EXPORT extern const base::Feature kHideIncorrectlySizedFullscreenFrames; CONTENT_EXPORT extern const base::Feature kWebNfc;
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index 7ea6490..3107fb5 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc
@@ -252,7 +252,8 @@ return true; } -bool ContentRendererClient::IsBackgroundMediaSuspendEnabled() { +bool ContentRendererClient::IsBackgroundMediaSuspendEnabled( + RenderFrame* render_frame) { #if defined(OS_ANDROID) return true; #else
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 0aca5928..e76cf174 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -390,8 +390,8 @@ virtual bool IsIdleMediaSuspendEnabled(); // Whether the renderer should automatically suspend media playback on - // background tabs. - virtual bool IsBackgroundMediaSuspendEnabled(); + // background tabs for given |render_frame|. + virtual bool IsBackgroundMediaSuspendEnabled(RenderFrame* render_frame); // Called when a resource at |url| is loaded using an otherwise-valid legacy // Symantec certificate that will be distrusted in future. Allows the embedder
diff --git a/content/public/test/OWNERS b/content/public/test/OWNERS index 9f53b453..7b359503 100644 --- a/content/public/test/OWNERS +++ b/content/public/test/OWNERS
@@ -6,6 +6,9 @@ # For download tests support review. per-file test_download_http_response.*=file://components/download/OWNERS +# For Android-specific changes. +per-file *android*=file://content/public/test/android/OWNERS + # For security presubmit checks, though test mojom really don't need review. per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/content/public/test/mock_permission_manager.cc b/content/public/test/mock_permission_manager.cc index 9157b1b..32f1ef91 100644 --- a/content/public/test/mock_permission_manager.cc +++ b/content/public/test/mock_permission_manager.cc
@@ -34,8 +34,8 @@ int MockPermissionManager::SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { // Return a fake subscription_id. return 0;
diff --git a/content/public/test/mock_permission_manager.h b/content/public/test/mock_permission_manager.h index b140a499..d7da1d8 100644 --- a/content/public/test/mock_permission_manager.h +++ b/content/public/test/mock_permission_manager.h
@@ -52,8 +52,8 @@ const GURL& embedding_origin) override {} int SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void UnsubscribePermissionStatusChange(int subscription_id) override {}
diff --git a/content/renderer/indexed_db/indexed_db_callbacks_impl.cc b/content/renderer/indexed_db/indexed_db_callbacks_impl.cc index 839f4b8..5f0e57a 100644 --- a/content/renderer/indexed_db/indexed_db_callbacks_impl.cc +++ b/content/renderer/indexed_db/indexed_db_callbacks_impl.cc
@@ -4,7 +4,6 @@ #include "content/renderer/indexed_db/indexed_db_callbacks_impl.h" -#include "base/threading/thread_task_runner_handle.h" #include "content/common/indexed_db/indexed_db_constants.h" #include "content/renderer/indexed_db/indexed_db_dispatcher.h" #include "content/renderer/indexed_db/indexed_db_key_builders.h" @@ -109,10 +108,8 @@ IndexedDBCallbacksImpl::IndexedDBCallbacksImpl( std::unique_ptr<WebIDBCallbacks> callbacks, int64_t transaction_id, - const base::WeakPtr<WebIDBCursorImpl>& cursor, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner) - : callback_runner_(std::move(callback_runner)), - callbacks_(std::move(callbacks)), + const base::WeakPtr<WebIDBCursorImpl>& cursor) + : callbacks_(std::move(callbacks)), cursor_(cursor), transaction_id_(transaction_id) {} @@ -146,8 +143,7 @@ blink::WebIDBDataLoss data_loss, const std::string& data_loss_message, const content::IndexedDBDatabaseMetadata& metadata) { - WebIDBDatabase* database = - new WebIDBDatabaseImpl(std::move(database_info), callback_runner_); + WebIDBDatabase* database = new WebIDBDatabaseImpl(std::move(database_info)); WebIDBMetadata web_metadata; ConvertDatabaseMetadata(metadata, &web_metadata); callbacks_->OnUpgradeNeeded(old_version, database, web_metadata, data_loss, @@ -160,8 +156,7 @@ const content::IndexedDBDatabaseMetadata& metadata) { WebIDBDatabase* database = nullptr; if (database_info.is_valid()) { - database = - new WebIDBDatabaseImpl(std::move(database_info), callback_runner_); + database = new WebIDBDatabaseImpl(std::move(database_info)); } WebIDBMetadata web_metadata; @@ -175,8 +170,8 @@ const IndexedDBKey& key, const IndexedDBKey& primary_key, indexed_db::mojom::ValuePtr value) { - WebIDBCursorImpl* cursor = new WebIDBCursorImpl( - std::move(cursor_info), transaction_id_, callback_runner_); + WebIDBCursorImpl* cursor = + new WebIDBCursorImpl(std::move(cursor_info), transaction_id_); callbacks_->OnSuccess(cursor, WebIDBKeyBuilder::Build(key), WebIDBKeyBuilder::Build(primary_key), ConvertValue(value));
diff --git a/content/renderer/indexed_db/indexed_db_callbacks_impl.h b/content/renderer/indexed_db/indexed_db_callbacks_impl.h index 5cdcbbb..6024a4a8 100644 --- a/content/renderer/indexed_db/indexed_db_callbacks_impl.h +++ b/content/renderer/indexed_db/indexed_db_callbacks_impl.h
@@ -5,7 +5,6 @@ #ifndef CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_CALLBACKS_IMPL_H_ #define CONTENT_RENDERER_INDEXED_DB_INDEXED_DB_CALLBACKS_IMPL_H_ -#include "base/single_thread_task_runner.h" #include "content/common/indexed_db/indexed_db.mojom.h" #include "mojo/public/cpp/bindings/associated_binding.h" @@ -28,11 +27,9 @@ static blink::WebIDBValue ConvertValue( const indexed_db::mojom::ValuePtr& value); - IndexedDBCallbacksImpl( - std::unique_ptr<blink::WebIDBCallbacks> callbacks, - int64_t transaction_id, - const base::WeakPtr<WebIDBCursorImpl>& cursor, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner); + IndexedDBCallbacksImpl(std::unique_ptr<blink::WebIDBCallbacks> callbacks, + int64_t transaction_id, + const base::WeakPtr<WebIDBCursorImpl>& cursor); ~IndexedDBCallbacksImpl() override; // indexed_db::mojom::Callbacks implementation:
diff --git a/content/renderer/indexed_db/webidbcursor_impl.cc b/content/renderer/indexed_db/webidbcursor_impl.cc index 0ee145e..9c31bf08 100644 --- a/content/renderer/indexed_db/webidbcursor_impl.cc +++ b/content/renderer/indexed_db/webidbcursor_impl.cc
@@ -28,10 +28,8 @@ WebIDBCursorImpl::WebIDBCursorImpl( indexed_db::mojom::CursorAssociatedPtrInfo cursor_info, - int64_t transaction_id, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner) + int64_t transaction_id) : transaction_id_(transaction_id), - callback_runner_(std::move(callback_runner)), cursor_(std::move(cursor_info)), continue_count_(0), used_prefetches_(0), @@ -63,8 +61,7 @@ transaction_id_, this); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(), - callback_runner_); + std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr()); cursor_->Advance(count, GetCallbacksProxy(std::move(callbacks_impl))); } @@ -89,8 +86,7 @@ ++pending_onsuccess_callbacks_; auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(), - callback_runner_); + std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr()); cursor_->Prefetch(prefetch_amount_, GetCallbacksProxy(std::move(callbacks_impl))); @@ -111,8 +107,7 @@ transaction_id_, this); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr(), - callback_runner_); + std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr()); cursor_->Continue(IndexedDBKeyBuilder::Build(key), IndexedDBKeyBuilder::Build(primary_key), GetCallbacksProxy(std::move(callbacks_impl)));
diff --git a/content/renderer/indexed_db/webidbcursor_impl.h b/content/renderer/indexed_db/webidbcursor_impl.h index ff277dc5..f363d5dc 100644 --- a/content/renderer/indexed_db/webidbcursor_impl.h +++ b/content/renderer/indexed_db/webidbcursor_impl.h
@@ -21,10 +21,6 @@ #include "third_party/blink/public/platform/modules/indexeddb/web_idb_key.h" #include "third_party/blink/public/platform/modules/indexeddb/web_idb_value.h" -namespace base { -class SingleThreadTaskRunner; -} - namespace content { class IndexedDBCallbacksImpl; @@ -32,8 +28,7 @@ class CONTENT_EXPORT WebIDBCursorImpl : public blink::WebIDBCursor { public: WebIDBCursorImpl(indexed_db::mojom::CursorAssociatedPtrInfo cursor, - int64_t transaction_id, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner); + int64_t transaction_id); ~WebIDBCursorImpl() override; void Advance(unsigned long count, blink::WebIDBCallbacks* callback) override; @@ -71,7 +66,6 @@ int64_t transaction_id_; - scoped_refptr<base::SingleThreadTaskRunner> callback_runner_; indexed_db::mojom::CursorAssociatedPtr cursor_; // Prefetch cache.
diff --git a/content/renderer/indexed_db/webidbcursor_impl_unittest.cc b/content/renderer/indexed_db/webidbcursor_impl_unittest.cc index 071d1300..18495907 100644 --- a/content/renderer/indexed_db/webidbcursor_impl_unittest.cc +++ b/content/renderer/indexed_db/webidbcursor_impl_unittest.cc
@@ -123,9 +123,7 @@ indexed_db::mojom::CursorAssociatedPtr ptr; mock_cursor_ = std::make_unique<MockCursorImpl>( mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr)); - cursor_ = std::make_unique<WebIDBCursorImpl>( - ptr.PassInterface(), 1, - blink::scheduler::GetSingleThreadTaskRunnerForTesting()); + cursor_ = std::make_unique<WebIDBCursorImpl>(ptr.PassInterface(), 1); } protected:
diff --git a/content/renderer/indexed_db/webidbdatabase_impl.cc b/content/renderer/indexed_db/webidbdatabase_impl.cc index e0e036e..366aa15 100644 --- a/content/renderer/indexed_db/webidbdatabase_impl.cc +++ b/content/renderer/indexed_db/webidbdatabase_impl.cc
@@ -62,11 +62,8 @@ } // namespace -WebIDBDatabaseImpl::WebIDBDatabaseImpl( - DatabaseAssociatedPtrInfo database_info, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner) - : callback_runner_(std::move(callback_runner)), - database_(std::move(database_info)) {} +WebIDBDatabaseImpl::WebIDBDatabaseImpl(DatabaseAssociatedPtrInfo database_info) + : database_(std::move(database_info)) {} WebIDBDatabaseImpl::~WebIDBDatabaseImpl() = default; @@ -141,7 +138,7 @@ transaction_id, nullptr); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->Get(transaction_id, object_store_id, index_id, IndexedDBKeyRangeBuilder::Build(key_range), key_only, GetCallbacksProxy(std::move(callbacks_impl))); @@ -158,7 +155,7 @@ transaction_id, nullptr); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->GetAll(transaction_id, object_store_id, index_id, IndexedDBKeyRangeBuilder::Build(key_range), key_only, max_count, GetCallbacksProxy(std::move(callbacks_impl))); @@ -216,7 +213,7 @@ } auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->Put(transaction_id, object_store_id, std::move(mojo_value), key, put_mode, ConvertWebIndexKeys(index_ids, index_keys), GetCallbacksProxy(std::move(callbacks_impl))); @@ -255,7 +252,7 @@ transaction_id, nullptr); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->OpenCursor(transaction_id, object_store_id, index_id, IndexedDBKeyRangeBuilder::Build(key_range), direction, key_only, task_type, @@ -271,7 +268,7 @@ transaction_id, nullptr); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->Count(transaction_id, object_store_id, index_id, IndexedDBKeyRangeBuilder::Build(key_range), GetCallbacksProxy(std::move(callbacks_impl))); @@ -285,7 +282,7 @@ transaction_id, nullptr); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->DeleteRange(transaction_id, object_store_id, IndexedDBKeyRangeBuilder::Build(primary_key), GetCallbacksProxy(std::move(callbacks_impl))); @@ -299,7 +296,7 @@ transaction_id, nullptr); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->DeleteRange(transaction_id, object_store_id, IndexedDBKeyRangeBuilder::Build(key_range), GetCallbacksProxy(std::move(callbacks_impl))); @@ -312,7 +309,7 @@ transaction_id, nullptr); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, callback_runner_); + base::WrapUnique(callbacks), transaction_id, nullptr); database_->Clear(transaction_id, object_store_id, GetCallbacksProxy(std::move(callbacks_impl))); }
diff --git a/content/renderer/indexed_db/webidbdatabase_impl.h b/content/renderer/indexed_db/webidbdatabase_impl.h index d208d00e..b6e235c 100644 --- a/content/renderer/indexed_db/webidbdatabase_impl.h +++ b/content/renderer/indexed_db/webidbdatabase_impl.h
@@ -30,9 +30,7 @@ class CONTENT_EXPORT WebIDBDatabaseImpl : public blink::WebIDBDatabase { public: - WebIDBDatabaseImpl( - indexed_db::mojom::DatabaseAssociatedPtrInfo database, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner); + WebIDBDatabaseImpl(indexed_db::mojom::DatabaseAssociatedPtrInfo database); ~WebIDBDatabaseImpl() override; // blink::WebIDBDatabase @@ -148,7 +146,6 @@ size_t max_put_value_size_ = kMaxIDBMessageSizeInBytes; std::set<int32_t> observer_ids_; - scoped_refptr<base::SingleThreadTaskRunner> callback_runner_; indexed_db::mojom::DatabaseAssociatedPtr database_; };
diff --git a/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc b/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc index 491da74..879fd50 100644 --- a/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc +++ b/content/renderer/indexed_db/webidbdatabase_impl_unittest.cc
@@ -59,8 +59,7 @@ StrictMock<MockWebIDBCallbacks> callbacks; EXPECT_CALL(callbacks, OnError(_)).Times(1); - WebIDBDatabaseImpl database_impl( - nullptr, blink::scheduler::GetSingleThreadTaskRunnerForTesting()); + WebIDBDatabaseImpl database_impl(nullptr); database_impl.max_put_value_size_ = kMaxValueSizeForTesting; const WebIDBKey idb_key = WebIDBKey::CreateNumber(0); database_impl.Put(transaction_id, object_store_id, value, web_blob_info, @@ -87,8 +86,7 @@ StrictMock<MockWebIDBCallbacks> callbacks; EXPECT_CALL(callbacks, OnError(_)).Times(1); - WebIDBDatabaseImpl database_impl( - nullptr, blink::scheduler::GetSingleThreadTaskRunnerForTesting()); + WebIDBDatabaseImpl database_impl(nullptr); database_impl.max_put_value_size_ = kMaxValueSizeForTesting; database_impl.Put(transaction_id, object_store_id, value, web_blob_info, key.View(), blink::kWebIDBPutModeAddOrUpdate, &callbacks,
diff --git a/content/renderer/indexed_db/webidbfactory_impl.cc b/content/renderer/indexed_db/webidbfactory_impl.cc index 403596c..c262250 100644 --- a/content/renderer/indexed_db/webidbfactory_impl.cc +++ b/content/renderer/indexed_db/webidbfactory_impl.cc
@@ -36,7 +36,7 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner) { auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction, - nullptr, std::move(task_runner)); + nullptr); factory_->GetDatabaseNames(GetCallbacksProxy(std::move(callbacks_impl)), url::Origin(origin)); } @@ -50,7 +50,7 @@ const WebSecurityOrigin& origin, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( - base::WrapUnique(callbacks), transaction_id, nullptr, task_runner); + base::WrapUnique(callbacks), transaction_id, nullptr); auto database_callbacks_impl = std::make_unique<IndexedDBDatabaseCallbacksImpl>( base::WrapUnique(database_callbacks)); @@ -67,7 +67,7 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner) { auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), IndexedDBCallbacksImpl::kNoTransaction, - nullptr, std::move(task_runner)); + nullptr); factory_->DeleteDatabase(GetCallbacksProxy(std::move(callbacks_impl)), url::Origin(origin), name.Utf16(), force_close); }
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc index 79b906c..37b5473 100644 --- a/content/renderer/loader/resource_dispatcher.cc +++ b/content/renderer/loader/resource_dispatcher.cc
@@ -722,8 +722,7 @@ uint32_t options = network::mojom::kURLLoadOptionNone; // TODO(jam): use this flag for ResourceDispatcherHost code path once // MojoLoading is the only IPC code path. - if ((blink::ServiceWorkerUtils::IsServicificationEnabled() || - base::FeatureList::IsEnabled(network::features::kNetworkService)) && + if (blink::ServiceWorkerUtils::IsServicificationEnabled() && request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) { // MIME sniffing should be disabled for a request initiated by fetch(). options |= network::mojom::kURLLoadOptionSniffMimeType;
diff --git a/content/renderer/loader/url_loader_client_impl_unittest.cc b/content/renderer/loader/url_loader_client_impl_unittest.cc index 71bdf23..2fc2884 100644 --- a/content/renderer/loader/url_loader_client_impl_unittest.cc +++ b/content/renderer/loader/url_loader_client_impl_unittest.cc
@@ -7,6 +7,7 @@ #include <vector> #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "content/public/common/request_context_type.h" #include "content/renderer/loader/navigation_response_override_parameters.h" #include "content/renderer/loader/resource_dispatcher.h" #include "content/renderer/loader/test_request_peer.h" @@ -25,8 +26,13 @@ public network::mojom::URLLoaderFactory { protected: URLLoaderClientImplTest() : dispatcher_(new ResourceDispatcher()) { + auto request = std::make_unique<network::ResourceRequest>(); + // Set request context type to fetch so that ResourceDispatcher doesn't + // install MimeSniffingThrottle, which makes URLLoaderThrottleLoader + // defer the request. + request->fetch_request_context_type = REQUEST_CONTEXT_TYPE_FETCH; request_id_ = dispatcher_->StartAsync( - std::make_unique<network::ResourceRequest>(), 0, + std::move(request), 0, blink::scheduler::GetSingleThreadTaskRunnerForTesting(), TRAFFIC_ANNOTATION_FOR_TESTS, false, false, std::make_unique<TestRequestPeer>(dispatcher_.get(),
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.cc b/content/renderer/media/renderer_webmediaplayer_delegate.cc index 9b70963..41936bf 100644 --- a/content/renderer/media/renderer_webmediaplayer_delegate.cc +++ b/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -39,9 +39,10 @@ : RenderFrameObserver(render_frame), allow_idle_cleanup_( content::GetContentClient()->renderer()->IsIdleMediaSuspendEnabled()), - background_suspend_enabled_(content::GetContentClient() - ->renderer() - ->IsBackgroundMediaSuspendEnabled()), + background_suspend_enabled_( + content::GetContentClient() + ->renderer() + ->IsBackgroundMediaSuspendEnabled(render_frame)), tick_clock_(base::DefaultTickClock::GetInstance()) { idle_cleanup_interval_ = base::TimeDelta::FromSeconds(5); idle_timeout_ = base::TimeDelta::FromSeconds(15);
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc index 6e95055e..4588dbd 100644 --- a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc +++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -161,15 +161,19 @@ event->Signal(); } -void GetSdpAndTypeFromSessionDescription( +// Initializes |web_description| if |description_callback| returns non-null, +// otherwise does nothing. +void GetWebRTCSessionDescriptionFromSessionDescriptionCallback( const base::Callback<const webrtc::SessionDescriptionInterface*()>& description_callback, - std::string* sdp, std::string* type) { + blink::WebRTCSessionDescription* web_description) { const webrtc::SessionDescriptionInterface* description = description_callback.Run(); if (description) { - description->ToString(sdp); - *type = description->type(); + std::string sdp; + description->ToString(&sdp); + web_description->Initialize(blink::WebString::FromUTF8(description->type()), + blink::WebString::FromUTF8(sdp)); } } @@ -1355,41 +1359,45 @@ DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription"); - // Since local_description returns a pointer to a non-reference-counted object - // that lives on the signaling thread, we cannot fetch a pointer to it and use - // it directly here. Instead, we access the object completely on the signaling - // thread. - std::string sdp, type; + // Since webrtc::PeerConnectionInterface::local_description() returns a + // pointer to a non-reference-counted object that lives on the signaling + // thread, we cannot fetch a pointer to it and use it directly here. Instead, + // we access the object completely on the signaling thread. Initializing + // |local_description| on the signaling thread is safe because we own it and + // wait for it to be initialized here. + blink::WebRTCSessionDescription local_description; // IsNull() by default. base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb = base::Bind(&webrtc::PeerConnectionInterface::local_description, native_peer_connection_); RunSynchronousClosureOnSignalingThread( - base::Bind(&GetSdpAndTypeFromSessionDescription, - std::move(description_cb), base::Unretained(&sdp), - base::Unretained(&type)), + base::Bind(&GetWebRTCSessionDescriptionFromSessionDescriptionCallback, + std::move(description_cb), + base::Unretained(&local_description)), "localDescription"); - return CreateWebKitSessionDescription(sdp, type); + return local_description; } blink::WebRTCSessionDescription RTCPeerConnectionHandler::RemoteDescription() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription"); - // Since local_description returns a pointer to a non-reference-counted object - // that lives on the signaling thread, we cannot fetch a pointer to it and use - // it directly here. Instead, we access the object completely on the signaling - // thread. - std::string sdp, type; + // Since webrtc::PeerConnectionInterface::remote_description() returns a + // pointer to a non-reference-counted object that lives on the signaling + // thread, we cannot fetch a pointer to it and use it directly here. Instead, + // we access the object completely on the signaling thread. Initializing + // |remote_description| on the signaling thread is safe because we own it and + // wait for it to be initialized here. + blink::WebRTCSessionDescription remote_description; // IsNull() by default. base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb = base::Bind(&webrtc::PeerConnectionInterface::remote_description, native_peer_connection_); RunSynchronousClosureOnSignalingThread( - base::Bind(&GetSdpAndTypeFromSessionDescription, - std::move(description_cb), base::Unretained(&sdp), - base::Unretained(&type)), + base::Bind(&GetWebRTCSessionDescriptionFromSessionDescriptionCallback, + std::move(description_cb), + base::Unretained(&remote_description)), "remoteDescription"); - return CreateWebKitSessionDescription(sdp, type); + return remote_description; } webrtc::RTCErrorType RTCPeerConnectionHandler::SetConfiguration(
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc index 51a6af4..06c3314 100644 --- a/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc +++ b/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
@@ -704,7 +704,7 @@ pc_handler_->SetLocalDescription(request, description); RunMessageLoopsUntilIdle(); // A description that failed to be applied shouldn't be stored. - EXPECT_TRUE(pc_handler_->LocalDescription().Sdp().IsEmpty()); + EXPECT_TRUE(pc_handler_->LocalDescription().IsNull()); } TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) { @@ -760,7 +760,7 @@ pc_handler_->SetRemoteDescription(request, description); RunMessageLoopsUntilIdle(); // A description that failed to be applied shouldn't be stored. - EXPECT_TRUE(pc_handler_->RemoteDescription().Sdp().IsEmpty()); + EXPECT_TRUE(pc_handler_->RemoteDescription().IsNull()); } TEST_F(RTCPeerConnectionHandlerTest, setConfiguration) {
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index d078133..edc6d8e 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1717,12 +1717,6 @@ } void RenderThreadImpl::SetProcessBackgrounded(bool backgrounded) { - // Set timer slack to maximum on main thread when in background. - base::TimerSlack timer_slack = base::TIMER_SLACK_NONE; - if (backgrounded) - timer_slack = base::TIMER_SLACK_MAXIMUM; - main_message_loop_->SetTimerSlack(timer_slack); - main_thread_scheduler_->SetRendererBackgrounded(backgrounded); if (backgrounded) { needs_to_record_first_active_paint_ = false;
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc index c3695033..36901d77 100644 --- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc +++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -639,6 +639,13 @@ // Subresource loader factory must not be available. EXPECT_EQ(nullptr, provider_context->GetSubresourceLoaderFactory()); + // The SetController() call results in another Mojo call to + // ControllerServiceWorkerConnector.UpdateController(). Flush that interface + // pointer to ensure the message was received. + LOG(ERROR) << "3 FlushControllerConnector()"; + FlushControllerConnector(provider_context.get()); + LOG(ERROR) << "3 FlushControllerConnector() finished"; + // Performing a request using the subresource factory obtained before // falls back to the network. const GURL kURL3("https://www.example.com/foo3.png");
diff --git a/content/shell/browser/layout_test/layout_test_permission_manager.cc b/content/shell/browser/layout_test/layout_test_permission_manager.cc index 7cccc6f..a6ad4ea9 100644 --- a/content/shell/browser/layout_test/layout_test_permission_manager.cc +++ b/content/shell/browser/layout_test/layout_test_permission_manager.cc
@@ -156,11 +156,19 @@ int LayoutTestPermissionManager::SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + // If the request is from a worker, it won't have a RFH. + GURL embedding_origin = requesting_origin; + if (render_frame_host) { + WebContents* web_contents = + WebContents::FromRenderFrameHost(render_frame_host); + embedding_origin = web_contents->GetLastCommittedURL().GetOrigin(); + } + auto subscription = std::make_unique<Subscription>(); subscription->permission = PermissionDescription(permission, requesting_origin, embedding_origin);
diff --git a/content/shell/browser/layout_test/layout_test_permission_manager.h b/content/shell/browser/layout_test/layout_test_permission_manager.h index a54e80f..e182e35e 100644 --- a/content/shell/browser/layout_test/layout_test_permission_manager.h +++ b/content/shell/browser/layout_test/layout_test_permission_manager.h
@@ -51,8 +51,8 @@ const GURL& requesting_origin) override; int SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void UnsubscribePermissionStatusChange(int subscription_id) override;
diff --git a/content/shell/browser/shell_permission_manager.cc b/content/shell/browser/shell_permission_manager.cc index 25d33b9..3cfcbaa 100644 --- a/content/shell/browser/shell_permission_manager.cc +++ b/content/shell/browser/shell_permission_manager.cc
@@ -103,8 +103,8 @@ int ShellPermissionManager::SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { return PermissionController::kNoPendingOperation; }
diff --git a/content/shell/browser/shell_permission_manager.h b/content/shell/browser/shell_permission_manager.h index b054b925..844939e 100644 --- a/content/shell/browser/shell_permission_manager.h +++ b/content/shell/browser/shell_permission_manager.h
@@ -45,8 +45,8 @@ const GURL& requesting_origin) override; int SubscribePermissionStatusChange( PermissionType permission, + RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void UnsubscribePermissionStatusChange(int subscription_id) override;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 70f3441..1e9ee94 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1051,7 +1051,7 @@ "//ppapi/tests/test_page.css", "//ppapi/tests/test_url_loader_data/", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", ] }
diff --git a/content/test/data/frame_tree/page_with_non_flat_transformed_frame.html b/content/test/data/frame_tree/page_with_non_flat_transformed_frame.html new file mode 100644 index 0000000..817cada6 --- /dev/null +++ b/content/test/data/frame_tree/page_with_non_flat_transformed_frame.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<style> +iframe { + position:absolute; + top: 50px; + left: 50px; + width: 100px; + height: 100px; + transform-style: preserve-3d; + transform: matrix3d(1, 0, 0, 0, + 0, 1, 0, 0, + 1, 0, 1, 0, + 0, 0, -1000, 1); +} + +</style> +<html> +<body> +<iframe src="/cross-site/baz.com/title1.html"></iframe> +This page contains a positioned cross-origin iframe with a non-flat transform applied to it. +</body> +</html>
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 1beb27a..25ee41f3 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -43,10 +43,6 @@ # Conformance expectations # ======================== - # Failing new test added in https://github.com/KhronosGroup/WebGL/pull/2654 - self.Fail('conformance2/context/incorrect-context-object-behaviour.html', - bug=857303) - # Failing new test added in https://github.com/KhronosGroup/WebGL/pull/2665 self.Fail('conformance2/textures/misc/tex-subimage3d-canvas-bug.html', ['linux'], bug=859400)
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index edd9a3a..1fee10f 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -245,6 +245,9 @@ deps = [ ":fido", "//base", + "//device/bluetooth:mocks", + "//testing/gmock", + "//testing/gtest", ] libfuzzer_options = [ "max_len=2048" ] }
diff --git a/device/fido/ble/fido_ble_connection.cc b/device/fido/ble/fido_ble_connection.cc index 094f443..c57301e0 100644 --- a/device/fido/ble/fido_ble_connection.cc +++ b/device/fido/ble/fido_ble_connection.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/logging.h" -#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_gatt_connection.h" #include "device/bluetooth/bluetooth_gatt_notify_session.h" #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" @@ -72,32 +71,50 @@ } // namespace -FidoBleConnection::FidoBleConnection(std::string device_address) - : address_(std::move(device_address)), weak_factory_(this) {} - FidoBleConnection::FidoBleConnection( + BluetoothAdapter* adapter, std::string device_address, ConnectionStatusCallback connection_status_callback, ReadCallback read_callback) - : address_(std::move(device_address)), + : adapter_(adapter), + address_(std::move(device_address)), connection_status_callback_(std::move(connection_status_callback)), read_callback_(std::move(read_callback)), weak_factory_(this) { + DCHECK(adapter_); + adapter_->AddObserver(this); DCHECK(!address_.empty()); } FidoBleConnection::~FidoBleConnection() { - if (adapter_) - adapter_->RemoveObserver(this); + adapter_->RemoveObserver(this); } const BluetoothDevice* FidoBleConnection::GetBleDevice() const { - return adapter_ ? adapter_->GetDevice(address()) : nullptr; + return adapter_->GetDevice(address()); +} + +FidoBleConnection::FidoBleConnection(BluetoothAdapter* adapter, + std::string device_address) + : adapter_(adapter), + address_(std::move(device_address)), + weak_factory_(this) { + adapter_->AddObserver(this); } void FidoBleConnection::Connect() { - BluetoothAdapterFactory::GetAdapter( - base::Bind(&FidoBleConnection::OnGetAdapter, weak_factory_.GetWeakPtr())); + BluetoothDevice* device = adapter_->GetDevice(address_); + if (!device) { + DLOG(ERROR) << "Failed to get Device."; + OnConnectionError(); + return; + } + + device->CreateGattConnection( + base::Bind(&FidoBleConnection::OnCreateGattConnection, + weak_factory_.GetWeakPtr()), + base::Bind(&FidoBleConnection::OnCreateGattConnectionError, + weak_factory_.GetWeakPtr())); } void FidoBleConnection::ReadControlPointLength( @@ -269,34 +286,6 @@ base::Bind(OnWriteError, copyable_callback)); } -void FidoBleConnection::OnGetAdapter(scoped_refptr<BluetoothAdapter> adapter) { - if (!adapter) { - DLOG(ERROR) << "Failed to get Adapter."; - OnConnectionError(); - return; - } - - DVLOG(2) << "Got Adapter: " << adapter->GetAddress(); - adapter_ = std::move(adapter); - adapter_->AddObserver(this); - CreateGattConnection(); -} - -void FidoBleConnection::CreateGattConnection() { - BluetoothDevice* device = adapter_->GetDevice(address_); - if (!device) { - DLOG(ERROR) << "Failed to get Device."; - OnConnectionError(); - return; - } - - device->CreateGattConnection( - base::Bind(&FidoBleConnection::OnCreateGattConnection, - weak_factory_.GetWeakPtr()), - base::Bind(&FidoBleConnection::OnCreateGattConnectionError, - weak_factory_.GetWeakPtr())); -} - void FidoBleConnection::OnCreateGattConnection( std::unique_ptr<BluetoothGattConnection> connection) { connection_ = std::move(connection); @@ -410,11 +399,6 @@ } const BluetoothRemoteGattService* FidoBleConnection::GetFidoService() const { - if (!adapter_) { - DLOG(ERROR) << "No adapter present."; - return nullptr; - } - const BluetoothDevice* device = adapter_->GetDevice(address_); if (!device) { DLOG(ERROR) << "No device present."; @@ -440,7 +424,7 @@ BluetoothDevice* device) { if (adapter != adapter_ || device->GetAddress() != address_) return; - CreateGattConnection(); + Connect(); } void FidoBleConnection::DeviceAddressChanged(BluetoothAdapter* adapter,
diff --git a/device/fido/ble/fido_ble_connection.h b/device/fido/ble/fido_ble_connection.h index 29366b6..24f8298 100644 --- a/device/fido/ble/fido_ble_connection.h +++ b/device/fido/ble/fido_ble_connection.h
@@ -62,7 +62,8 @@ using ServiceRevisionsCallback = base::OnceCallback<void(std::set<ServiceRevision>)>; - FidoBleConnection(std::string device_address, + FidoBleConnection(BluetoothAdapter* adapter, + std::string device_address, ConnectionStatusCallback connection_status_callback, ReadCallback read_callback); ~FidoBleConnection() override; @@ -79,8 +80,10 @@ WriteCallback callback); protected: - explicit FidoBleConnection(std::string device_address); + // Used for testing. + FidoBleConnection(BluetoothAdapter* adapter, std::string device_address); + scoped_refptr<BluetoothAdapter> adapter_; std::string address_; ConnectionStatusCallback connection_status_callback_; ReadCallback read_callback_; @@ -100,9 +103,6 @@ void GattServicesDiscovered(BluetoothAdapter* adapter, BluetoothDevice* device) override; - void OnGetAdapter(scoped_refptr<BluetoothAdapter> adapter); - - void CreateGattConnection(); void OnCreateGattConnection( std::unique_ptr<BluetoothGattConnection> connection); void OnCreateGattConnectionError( @@ -142,7 +142,6 @@ static void OnWriteError(WriteCallback callback, BluetoothGattService::GattErrorCode error_code); - scoped_refptr<BluetoothAdapter> adapter_; std::unique_ptr<BluetoothGattConnection> connection_; std::unique_ptr<BluetoothGattNotifySession> notify_session_;
diff --git a/device/fido/ble/fido_ble_connection_unittest.cc b/device/fido/ble/fido_ble_connection_unittest.cc index c214c81..6f81ba39 100644 --- a/device/fido/ble/fido_ble_connection_unittest.cc +++ b/device/fido/ble/fido_ble_connection_unittest.cc
@@ -135,6 +135,8 @@ BluetoothAdapterFactory::SetAdapterForTesting(adapter_); } + BluetoothAdapter* adapter() { return adapter_.get(); } + void AddU2Device(const std::string& device_address) { auto u2f_device = std::make_unique<NiceMockBluetoothDevice>( adapter_.get(), /* bluetooth_class */ 0u, @@ -359,7 +361,7 @@ auto connect_do_nothing = [](bool) {}; auto read_do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, base::BindRepeating(connect_do_nothing), base::BindRepeating(read_do_nothing)); connection.Connect(); @@ -375,7 +377,7 @@ TestConnectionStatusCallback connection_status_callback; auto do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(do_nothing)); connection.Connect(); @@ -390,7 +392,7 @@ SetupConnectingU2fDevice(device_address); auto do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(do_nothing)); connection.Connect(); @@ -401,7 +403,7 @@ const std::string device_address = BluetoothTest::kTestDeviceAddress1; TestConnectionStatusCallback connection_status_callback; auto do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(do_nothing)); connection.Connect(); @@ -421,7 +423,7 @@ AddU2Device(device_address); SetupConnectingU2fDevice(device_address); auto do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(do_nothing)); connection.Connect(); @@ -440,7 +442,7 @@ AddU2Device(device_address); SetupConnectingU2fDevice(device_address); - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), read_callback.GetCallback()); connection.Connect(); @@ -462,7 +464,7 @@ SetupConnectingU2fDevice(device_address); auto read_do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(read_do_nothing)); connection.Connect(); @@ -499,7 +501,7 @@ SetupConnectingU2fDevice(device_address); auto read_do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(read_do_nothing)); connection.Connect(); @@ -599,7 +601,7 @@ SetupConnectingU2fDevice(device_address); auto read_do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(read_do_nothing)); connection.Connect(); @@ -625,7 +627,7 @@ SetupConnectingU2fDevice(device_address); auto read_do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(read_do_nothing)); connection.Connect(); @@ -672,7 +674,7 @@ AddU2Device(device_address); SetupConnectingU2fDevice(device_address); auto do_nothing = [](std::vector<uint8_t>) {}; - FidoBleConnection connection(device_address, + FidoBleConnection connection(adapter(), device_address, connection_status_callback.GetCallback(), base::BindRepeating(do_nothing)); connection.Connect();
diff --git a/device/fido/ble/fido_ble_device.cc b/device/fido/ble/fido_ble_device.cc index 1d47ab0..b45c554 100644 --- a/device/fido/ble/fido_ble_device.cc +++ b/device/fido/ble/fido_ble_device.cc
@@ -16,9 +16,10 @@ namespace device { -FidoBleDevice::FidoBleDevice(std::string address) : weak_factory_(this) { +FidoBleDevice::FidoBleDevice(BluetoothAdapter* adapter, std::string address) + : weak_factory_(this) { connection_ = std::make_unique<FidoBleConnection>( - std::move(address), + adapter, std::move(address), base::BindRepeating(&FidoBleDevice::OnConnectionStatus, base::Unretained(this)), base::BindRepeating(&FidoBleDevice::OnStatusMessage,
diff --git a/device/fido/ble/fido_ble_device.h b/device/fido/ble/fido_ble_device.h index 34e7b55..54e340c4 100644 --- a/device/fido/ble/fido_ble_device.h +++ b/device/fido/ble/fido_ble_device.h
@@ -24,12 +24,13 @@ namespace device { +class BluetoothAdapter; class FidoBleFrame; class COMPONENT_EXPORT(DEVICE_FIDO) FidoBleDevice : public FidoDevice { public: using FrameCallback = FidoBleTransaction::FrameCallback; - explicit FidoBleDevice(std::string address); + FidoBleDevice(BluetoothAdapter* adapter, std::string address); explicit FidoBleDevice(std::unique_ptr<FidoBleConnection> connection); ~FidoBleDevice() override;
diff --git a/device/fido/ble/fido_ble_device_unittest.cc b/device/fido/ble/fido_ble_device_unittest.cc index b40cba2..16eba7fd 100644 --- a/device/fido/ble/fido_ble_device_unittest.cc +++ b/device/fido/ble/fido_ble_device_unittest.cc
@@ -75,7 +75,7 @@ public: FidoBleDeviceTest() { auto connection = std::make_unique<MockFidoBleConnection>( - BluetoothTestBase::kTestDeviceAddress1); + adapter_.get(), BluetoothTestBase::kTestDeviceAddress1); connection_ = connection.get(); device_ = std::make_unique<FidoBleDevice>(std::move(connection)); connection_->connection_status_callback() = @@ -83,6 +83,7 @@ connection_->read_callback() = device_->GetReadCallbackForTesting(); } + MockBluetoothAdapter* adapter() { return adapter_.get(); } FidoBleDevice* device() { return device_.get(); } MockFidoBleConnection* connection() { return connection_; } @@ -102,6 +103,8 @@ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME}; private: + scoped_refptr<MockBluetoothAdapter> adapter_ = + base::MakeRefCounted<NiceMockBluetoothAdapter>(); MockFidoBleConnection* connection_; std::unique_ptr<FidoBleDevice> device_; }; @@ -223,10 +226,7 @@ // By default, a device is not in pairing mode. EXPECT_FALSE(device()->IsInPairingMode()); - // Initiate default connection behavior, which will attempt to obtain an - // adapter. - auto mock_adapter = base::MakeRefCounted<NiceMockBluetoothAdapter>(); - BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter); + // Initiate default connection behavior. EXPECT_CALL(*connection(), Connect()).WillOnce(Invoke([this] { connection()->FidoBleConnection::Connect(); })); @@ -235,11 +235,11 @@ // Add a mock fido device. This should also not be considered to be in pairing // mode. auto mock_bluetooth_device = std::make_unique<NiceMockBluetoothDevice>( - mock_adapter.get(), /* bluetooth_class */ 0u, + adapter(), /* bluetooth_class */ 0u, BluetoothTestBase::kTestDeviceNameU2f, BluetoothTestBase::kTestDeviceAddress1, /* paired */ true, /* connected */ false); - EXPECT_CALL(*mock_adapter, GetDevice(BluetoothTestBase::kTestDeviceAddress1)) + EXPECT_CALL(*adapter(), GetDevice(BluetoothTestBase::kTestDeviceAddress1)) .WillRepeatedly(Return(mock_bluetooth_device.get())); EXPECT_FALSE(device()->IsInPairingMode());
diff --git a/device/fido/ble/fido_ble_discovery.cc b/device/fido/ble/fido_ble_discovery.cc index 41b4c542..9b309c5 100644 --- a/device/fido/ble/fido_ble_discovery.cc +++ b/device/fido/ble/fido_ble_discovery.cc
@@ -34,7 +34,8 @@ for (BluetoothDevice* device : adapter()->GetDevices()) { if (base::ContainsKey(device->GetUUIDs(), FidoServiceUUID())) { VLOG(2) << "U2F BLE device: " << device->GetAddress(); - AddDevice(std::make_unique<FidoBleDevice>(device->GetAddress())); + AddDevice( + std::make_unique<FidoBleDevice>(adapter(), device->GetAddress())); } } @@ -56,7 +57,7 @@ BluetoothDevice* device) { if (base::ContainsKey(device->GetUUIDs(), FidoServiceUUID())) { VLOG(2) << "Discovered U2F BLE device: " << device->GetAddress(); - AddDevice(std::make_unique<FidoBleDevice>(device->GetAddress())); + AddDevice(std::make_unique<FidoBleDevice>(adapter, device->GetAddress())); } } @@ -66,7 +67,7 @@ !GetDevice(FidoBleDevice::GetId(device->GetAddress()))) { VLOG(2) << "Discovered U2F service on existing BLE device: " << device->GetAddress(); - AddDevice(std::make_unique<FidoBleDevice>(device->GetAddress())); + AddDevice(std::make_unique<FidoBleDevice>(adapter, device->GetAddress())); } }
diff --git a/device/fido/ble/mock_fido_ble_connection.cc b/device/fido/ble/mock_fido_ble_connection.cc index bb42a169..c2d7fe5 100644 --- a/device/fido/ble/mock_fido_ble_connection.cc +++ b/device/fido/ble/mock_fido_ble_connection.cc
@@ -8,8 +8,9 @@ namespace device { -MockFidoBleConnection::MockFidoBleConnection(std::string device_address) - : FidoBleConnection(std::move(device_address)) {} +MockFidoBleConnection::MockFidoBleConnection(BluetoothAdapter* adapter, + std::string device_address) + : FidoBleConnection(adapter, std::move(device_address)) {} MockFidoBleConnection::~MockFidoBleConnection() = default;
diff --git a/device/fido/ble/mock_fido_ble_connection.h b/device/fido/ble/mock_fido_ble_connection.h index 6fa4ea8d..7753ae90 100644 --- a/device/fido/ble/mock_fido_ble_connection.h +++ b/device/fido/ble/mock_fido_ble_connection.h
@@ -15,9 +15,11 @@ namespace device { +class BluetoothAdapter; + class MockFidoBleConnection : public FidoBleConnection { public: - explicit MockFidoBleConnection(std::string device_address); + MockFidoBleConnection(BluetoothAdapter* adapter, std::string device_address); ~MockFidoBleConnection() override; MOCK_METHOD0(Connect, void()); @@ -50,4 +52,4 @@ } // namespace device -#endif // DEVICE_FIDO_MOCK_FIDO_BLE_CONNECTION_H_ +#endif // DEVICE_FIDO_BLE_MOCK_FIDO_BLE_CONNECTION_H_
diff --git a/device/fido/cable/fido_cable_device.cc b/device/fido/cable/fido_cable_device.cc index 52082ee..1c5dd60 100644 --- a/device/fido/cable/fido_cable_device.cc +++ b/device/fido/cable/fido_cable_device.cc
@@ -113,8 +113,8 @@ // FidoCableDevice::EncryptionData ---------------------------------------- -FidoCableDevice::FidoCableDevice(std::string address) - : FidoBleDevice(std::move(address)), weak_factory_(this) {} +FidoCableDevice::FidoCableDevice(BluetoothAdapter* adapter, std::string address) + : FidoBleDevice(adapter, std::move(address)), weak_factory_(this) {} FidoCableDevice::FidoCableDevice(std::unique_ptr<FidoBleConnection> connection) : FidoBleDevice(std::move(connection)), weak_factory_(this) {}
diff --git a/device/fido/cable/fido_cable_device.h b/device/fido/cable/fido_cable_device.h index c2e8966..29e3907f 100644 --- a/device/fido/cable/fido_cable_device.h +++ b/device/fido/cable/fido_cable_device.h
@@ -20,8 +20,9 @@ namespace device { -class FidoBleFrame; +class BluetoothAdapter; class FidoBleConnection; +class FidoBleFrame; class COMPONENT_EXPORT(DEVICE_FIDO) FidoCableDevice : public FidoBleDevice { public: @@ -44,7 +45,7 @@ using FrameCallback = FidoBleTransaction::FrameCallback; - FidoCableDevice(std::string address); + FidoCableDevice(BluetoothAdapter* adapter, std::string address); // Constructor used for testing purposes. FidoCableDevice(std::unique_ptr<FidoBleConnection> connection); ~FidoCableDevice() override;
diff --git a/device/fido/cable/fido_cable_device_unittest.cc b/device/fido/cable/fido_cable_device_unittest.cc index 8cd0f968..29cb49abf 100644 --- a/device/fido/cable/fido_cable_device_unittest.cc +++ b/device/fido/cable/fido_cable_device_unittest.cc
@@ -16,6 +16,7 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "crypto/aead.h" #include "device/bluetooth/test/bluetooth_test.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/fido/ble/mock_fido_ble_connection.h" #include "device/fido/fido_parsing_utils.h" #include "device/fido/test_callback_receiver.h" @@ -31,6 +32,7 @@ using ::testing::Test; using TestDeviceCallbackReceiver = test::ValueCallbackReceiver<base::Optional<std::vector<uint8_t>>>; +using NiceMockBluetoothAdapter = ::testing::NiceMock<MockBluetoothAdapter>; // Sufficiently large test control point length as we are not interested // in testing fragmentations of BLE messages. All Cable messages are encrypted @@ -128,7 +130,7 @@ public: FidoCableDeviceTest() { auto connection = std::make_unique<MockFidoBleConnection>( - BluetoothTestBase::kTestDeviceAddress1); + adapter_.get(), BluetoothTestBase::kTestDeviceAddress1); connection_ = connection.get(); device_ = std::make_unique<FidoCableDevice>(std::move(connection)); device_->SetEncryptionData(kTestSessionKey, kTestEncryptionNonce); @@ -157,6 +159,8 @@ base::test::ScopedTaskEnvironment scoped_task_environment_; private: + scoped_refptr<MockBluetoothAdapter> adapter_ = + base::MakeRefCounted<NiceMockBluetoothAdapter>(); FakeCableAuthenticator authenticator_; MockFidoBleConnection* connection_; std::unique_ptr<FidoCableDevice> device_;
diff --git a/device/fido/cable/fido_cable_discovery.cc b/device/fido/cable/fido_cable_discovery.cc index 158cd92..0294fad8 100644 --- a/device/fido/cable/fido_cable_discovery.cc +++ b/device/fido/cable/fido_cable_discovery.cc
@@ -265,7 +265,8 @@ if (!extract_success) return; - auto cable_device = std::make_unique<FidoCableDevice>(device->GetAddress()); + auto cable_device = + std::make_unique<FidoCableDevice>(adapter, device->GetAddress()); // At most one handshake messages should be exchanged for each Cable device. if (!base::ContainsKey(cable_handshake_handlers_, cable_device->GetId())) { ConductEncryptionHandshake(std::move(cable_device),
diff --git a/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc b/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc index 35a4351..5b0432e0 100644 --- a/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc +++ b/device/fido/cable/fido_cable_handshake_handler_fuzzer.cc
@@ -8,9 +8,13 @@ #include <array> #include "base/containers/span.h" +#include "base/memory/ref_counted.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/fido/cable/fido_cable_device.h" #include "device/fido/cable/fido_cable_handshake_handler.h" #include "device/fido/fido_constants.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" namespace { @@ -30,7 +34,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* raw_data, size_t size) { auto data_span = base::make_span(raw_data, size); - device::FidoCableDevice test_cable_device(kTestDeviceAddress); + auto adapter = + base::MakeRefCounted<::testing::NiceMock<device::MockBluetoothAdapter>>(); + device::FidoCableDevice test_cable_device(adapter.get(), kTestDeviceAddress); device::FidoCableHandshakeHandler handshake_handler( &test_cable_device, kTestNonce, kTestSessionPreKey); handshake_handler.ValidateAuthenticatorHandshakeMessage(data_span);
diff --git a/device/fido/cable/fido_cable_handshake_handler_unittest.cc b/device/fido/cable/fido_cable_handshake_handler_unittest.cc index b2e2c08b..4fea793 100644 --- a/device/fido/cable/fido_cable_handshake_handler_unittest.cc +++ b/device/fido/cable/fido_cable_handshake_handler_unittest.cc
@@ -19,6 +19,7 @@ #include "crypto/hkdf.h" #include "crypto/hmac.h" #include "device/bluetooth/test/bluetooth_test.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/fido/ble/fido_ble_frames.h" #include "device/fido/ble/mock_fido_ble_connection.h" #include "device/fido/cable/fido_cable_device.h" @@ -37,6 +38,7 @@ using ::testing::Test; using TestDeviceCallbackReceiver = test::ValueCallbackReceiver<base::Optional<std::vector<uint8_t>>>; +using NiceMockBluetoothAdapter = ::testing::NiceMock<MockBluetoothAdapter>; // Sufficiently large test control point length as we are not interested // in testing fragmentations of BLE messages. All Cable messages are encrypted @@ -254,7 +256,7 @@ public: FidoCableHandshakeHandlerTest() { auto connection = std::make_unique<MockFidoBleConnection>( - BluetoothTestBase::kTestDeviceAddress1); + adapter_.get(), BluetoothTestBase::kTestDeviceAddress1); connection_ = connection.get(); device_ = std::make_unique<FidoCableDevice>(std::move(connection)); @@ -290,6 +292,8 @@ base::test::ScopedTaskEnvironment scoped_task_environment_; private: + scoped_refptr<MockBluetoothAdapter> adapter_ = + base::MakeRefCounted<NiceMockBluetoothAdapter>(); FakeCableAuthenticator authenticator_; MockFidoBleConnection* connection_; std::unique_ptr<FidoCableDevice> device_;
diff --git a/device/serial/BUILD.gn b/device/serial/BUILD.gn index 77132bf..0ab6e1a 100644 --- a/device/serial/BUILD.gn +++ b/device/serial/BUILD.gn
@@ -20,7 +20,6 @@ ":test_support", "//device:device_unittests", "//services/device/serial", - "//tools/battor_agent:battor_agent_lib", ] output_name = "device_serial" @@ -78,19 +77,4 @@ ] } } - - static_library("test_support") { - # TODO(leonhsl): Merge necessary parts of TestSerialIoHandler into - # battor_connection_impl_unittest.cc to hide serial impl completely. - visibility = [ "//tools/battor_agent:battor_agent_unittests" ] - - sources = [ - "test_serial_io_handler.cc", - "test_serial_io_handler.h", - ] - - public_deps = [ - ":serial", - ] - } }
diff --git a/device/serial/test_serial_io_handler.cc b/device/serial/test_serial_io_handler.cc deleted file mode 100644 index c04c2a9..0000000 --- a/device/serial/test_serial_io_handler.cc +++ /dev/null
@@ -1,126 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "device/serial/test_serial_io_handler.h" - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> - -#include "base/bind.h" -#include "services/device/public/mojom/serial.mojom.h" - -namespace device { - -TestSerialIoHandler::TestSerialIoHandler() - : SerialIoHandler(NULL), - opened_(false), - dtr_(false), - rts_(false), - flushes_(0) {} - -scoped_refptr<SerialIoHandler> TestSerialIoHandler::Create() { - return scoped_refptr<SerialIoHandler>(new TestSerialIoHandler); -} - -void TestSerialIoHandler::Open(const std::string& port, - const mojom::SerialConnectionOptions& options, - OpenCompleteCallback callback) { - DCHECK(!opened_); - opened_ = true; - ConfigurePort(options); - std::move(callback).Run(true); -} - -void TestSerialIoHandler::ReadImpl() { - if (!pending_read_buffer()) - return; - if (buffer_.empty()) - return; - - size_t num_bytes = - std::min(buffer_.size(), static_cast<size_t>(pending_read_buffer_len())); - memcpy(pending_read_buffer(), buffer_.data(), num_bytes); - buffer_.erase(buffer_.begin(), buffer_.begin() + num_bytes); - ReadCompleted(static_cast<uint32_t>(num_bytes), - mojom::SerialReceiveError::NONE); -} - -void TestSerialIoHandler::CancelReadImpl() { - ReadCompleted(0, read_cancel_reason()); -} - -void TestSerialIoHandler::WriteImpl() { - if (send_callback_) { - std::move(send_callback_).Run(); - return; - } - buffer_.insert(buffer_.end(), pending_write_buffer(), - pending_write_buffer() + pending_write_buffer_len()); - WriteCompleted(pending_write_buffer_len(), mojom::SerialSendError::NONE); - if (pending_read_buffer()) - ReadImpl(); -} - -void TestSerialIoHandler::CancelWriteImpl() { - WriteCompleted(0, write_cancel_reason()); -} - -bool TestSerialIoHandler::ConfigurePortImpl() { - info_.bitrate = options().bitrate; - info_.data_bits = options().data_bits; - info_.parity_bit = options().parity_bit; - info_.stop_bits = options().stop_bits; - info_.cts_flow_control = options().cts_flow_control; - return true; -} - -mojom::SerialDeviceControlSignalsPtr TestSerialIoHandler::GetControlSignals() - const { - auto signals = mojom::SerialDeviceControlSignals::New(); - *signals = device_control_signals_; - return signals; -} - -mojom::SerialConnectionInfoPtr TestSerialIoHandler::GetPortInfo() const { - auto info = mojom::SerialConnectionInfo::New(); - *info = info_; - return info; -} - -bool TestSerialIoHandler::Flush() const { - flushes_++; - return true; -} - -bool TestSerialIoHandler::SetControlSignals( - const mojom::SerialHostControlSignals& signals) { - if (signals.has_dtr) - dtr_ = signals.dtr; - if (signals.has_rts) - rts_ = signals.rts; - return true; -} - -bool TestSerialIoHandler::SetBreak() { - return true; -} - -bool TestSerialIoHandler::ClearBreak() { - return true; -} - -void TestSerialIoHandler::ForceReceiveError( - device::mojom::SerialReceiveError error) { - ReadCompleted(0, error); -} - -void TestSerialIoHandler::ForceSendError(device::mojom::SerialSendError error) { - WriteCompleted(0, error); -} - -TestSerialIoHandler::~TestSerialIoHandler() = default; - -} // namespace device
diff --git a/device/serial/test_serial_io_handler.h b/device/serial/test_serial_io_handler.h deleted file mode 100644 index d60be3a..0000000 --- a/device/serial/test_serial_io_handler.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef DEVICE_SERIAL_TEST_SERIAL_IO_HANDLER_H_ -#define DEVICE_SERIAL_TEST_SERIAL_IO_HANDLER_H_ - -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "device/serial/serial_io_handler.h" -#include "services/device/public/mojom/serial.mojom.h" - -namespace device { - -class TestSerialIoHandler : public SerialIoHandler { - public: - TestSerialIoHandler(); - - static scoped_refptr<SerialIoHandler> Create(); - - // SerialIoHandler overrides. - void Open(const std::string& port, - const mojom::SerialConnectionOptions& options, - OpenCompleteCallback callback) override; - void ReadImpl() override; - void CancelReadImpl() override; - void WriteImpl() override; - void CancelWriteImpl() override; - bool ConfigurePortImpl() override; - mojom::SerialDeviceControlSignalsPtr GetControlSignals() const override; - mojom::SerialConnectionInfoPtr GetPortInfo() const override; - bool Flush() const override; - bool SetControlSignals( - const mojom::SerialHostControlSignals& signals) override; - bool SetBreak() override; - bool ClearBreak() override; - void ForceReceiveError(device::mojom::SerialReceiveError error); - void ForceSendError(device::mojom::SerialSendError error); - - mojom::SerialConnectionInfo* connection_info() { return &info_; } - mojom::SerialDeviceControlSignals* device_control_signals() { - return &device_control_signals_; - } - bool dtr() { return dtr_; } - bool rts() { return rts_; } - int flushes() { return flushes_; } - // This callback will be called when this IoHandler processes its next write, - // instead of the normal behavior of echoing the data to reads. - void set_send_callback(base::OnceClosure callback) { - send_callback_ = std::move(callback); - } - - protected: - ~TestSerialIoHandler() override; - - private: - bool opened_; - mojom::SerialConnectionInfo info_; - mojom::SerialDeviceControlSignals device_control_signals_; - bool dtr_; - bool rts_; - mutable int flushes_; - std::vector<uint8_t> buffer_; - base::OnceClosure send_callback_; - - DISALLOW_COPY_AND_ASSIGN(TestSerialIoHandler); -}; - -} // namespace device - -#endif // DEVICE_SERIAL_TEST_SERIAL_IO_HANDLER_H_
diff --git a/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc b/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc index 03e7d72..b151a27 100644 --- a/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc +++ b/device/vr/android/gvr/cardboard_gamepad_data_fetcher.cc
@@ -26,7 +26,7 @@ CardboardGamepadDataFetcher::Factory::Factory( CardboardGamepadDataProvider* data_provider, - unsigned int display_id) + device::mojom::XRDeviceId display_id) : data_provider_(data_provider), display_id_(display_id) { DVLOG(1) << __FUNCTION__ << "=" << this; } @@ -47,7 +47,7 @@ CardboardGamepadDataFetcher::CardboardGamepadDataFetcher( CardboardGamepadDataProvider* data_provider, - unsigned int display_id) + device::mojom::XRDeviceId display_id) : display_id_(display_id) { // Called on UI thread. DVLOG(1) << __FUNCTION__ << "=" << this; @@ -93,7 +93,7 @@ pad.buttons_length = 1; pad.axes_length = 0; - pad.display_id = display_id_; + pad.display_id = static_cast<unsigned int>(display_id_); pad.hand = GamepadHand::kNone; }
diff --git a/device/vr/android/gvr/cardboard_gamepad_data_fetcher.h b/device/vr/android/gvr/cardboard_gamepad_data_fetcher.h index 0b6193f..0fe4651 100644 --- a/device/vr/android/gvr/cardboard_gamepad_data_fetcher.h +++ b/device/vr/android/gvr/cardboard_gamepad_data_fetcher.h
@@ -9,6 +9,7 @@ #include "device/gamepad/gamepad_data_fetcher.h" #include "device/vr/android/gvr/cardboard_gamepad_data_provider.h" +#include "device/vr/public/mojom/vr_service.mojom.h" #include "device/vr/vr_export.h" namespace device { @@ -17,18 +18,19 @@ public: class Factory : public GamepadDataFetcherFactory { public: - Factory(CardboardGamepadDataProvider*, unsigned int display_id); + Factory(CardboardGamepadDataProvider*, + device::mojom::XRDeviceId display_id); ~Factory() override; std::unique_ptr<GamepadDataFetcher> CreateDataFetcher() override; GamepadSource source() override; private: CardboardGamepadDataProvider* data_provider_; - unsigned int display_id_; + device::mojom::XRDeviceId display_id_; }; CardboardGamepadDataFetcher(CardboardGamepadDataProvider*, - unsigned int display_id); + device::mojom::XRDeviceId display_id); ~CardboardGamepadDataFetcher() override; GamepadSource source() override; @@ -41,7 +43,7 @@ void SetGamepadData(CardboardGamepadData); private: - unsigned int display_id_; + device::mojom::XRDeviceId display_id_; CardboardGamepadData gamepad_data_; DISALLOW_COPY_AND_ASSIGN(CardboardGamepadDataFetcher);
diff --git a/device/vr/android/gvr/gvr_delegate_provider.h b/device/vr/android/gvr/gvr_delegate_provider.h index f45939ae..60c3419 100644 --- a/device/vr/android/gvr/gvr_delegate_provider.h +++ b/device/vr/android/gvr/gvr_delegate_provider.h
@@ -19,7 +19,7 @@ public: GvrDelegateProvider() = default; virtual bool ShouldDisableGvrDevice() = 0; - virtual void SetDeviceId(unsigned int device_id) = 0; + virtual void SetDeviceId(mojom::XRDeviceId device_id) = 0; virtual void StartWebXRPresentation( mojom::VRDisplayInfoPtr display_info, mojom::XRRuntimeSessionOptionsPtr options,
diff --git a/device/vr/android/gvr/gvr_device.cc b/device/vr/android/gvr/gvr_device.cc index 73913dd..c47946f2 100644 --- a/device/vr/android/gvr/gvr_device.cc +++ b/device/vr/android/gvr/gvr_device.cc
@@ -93,12 +93,12 @@ } mojom::VRDisplayInfoPtr CreateVRDisplayInfo(gvr::GvrApi* gvr_api, - uint32_t device_id) { + mojom::XRDeviceId device_id) { TRACE_EVENT0("input", "GvrDelegate::CreateVRDisplayInfo"); mojom::VRDisplayInfoPtr device = mojom::VRDisplayInfo::New(); - device->index = device_id; + device->id = device_id; device->capabilities = mojom::VRDisplayCapabilities::New(); device->capabilities->hasPosition = false; @@ -143,7 +143,7 @@ } GvrDevice::GvrDevice() - : VRDeviceBase(VRDeviceId::GVR_DEVICE_ID), + : VRDeviceBase(mojom::XRDeviceId::GVR_DEVICE_ID), exclusive_controller_binding_(this), weak_ptr_factory_(this) { GvrDelegateProvider* delegate_provider = GetGvrDelegateProvider();
diff --git a/device/vr/android/gvr/gvr_device_provider.cc b/device/vr/android/gvr/gvr_device_provider.cc index ea77025b..56f8e79 100644 --- a/device/vr/android/gvr/gvr_device_provider.cc +++ b/device/vr/android/gvr/gvr_device_provider.cc
@@ -12,10 +12,10 @@ GvrDeviceProvider::~GvrDeviceProvider() = default; void GvrDeviceProvider::Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) { vr_device_ = GvrDevice::Create(); if (vr_device_)
diff --git a/device/vr/android/gvr/gvr_device_provider.h b/device/vr/android/gvr/gvr_device_provider.h index c833e473..527b8471 100644 --- a/device/vr/android/gvr/gvr_device_provider.h +++ b/device/vr/android/gvr/gvr_device_provider.h
@@ -21,10 +21,10 @@ ~GvrDeviceProvider() override; void Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) override; bool Initialized() override;
diff --git a/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc b/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc index f48fcd3..0d50dd8c 100644 --- a/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc +++ b/device/vr/android/gvr/gvr_gamepad_data_fetcher.cc
@@ -26,7 +26,7 @@ } // namespace GvrGamepadDataFetcher::Factory::Factory(GvrGamepadDataProvider* data_provider, - unsigned int display_id) + mojom::XRDeviceId display_id) : data_provider_(data_provider), display_id_(display_id) { DVLOG(1) << __FUNCTION__ << "=" << this; } @@ -46,7 +46,7 @@ GvrGamepadDataFetcher::GvrGamepadDataFetcher( GvrGamepadDataProvider* data_provider, - unsigned int display_id) + mojom::XRDeviceId display_id) : display_id_(display_id) { // Called on UI thread. DVLOG(1) << __FUNCTION__ << "=" << this; @@ -93,7 +93,7 @@ pad.buttons_length = 1; pad.axes_length = 2; - pad.display_id = display_id_; + pad.display_id = static_cast<unsigned int>(display_id_); pad.is_xr = true;
diff --git a/device/vr/android/gvr/gvr_gamepad_data_fetcher.h b/device/vr/android/gvr/gvr_gamepad_data_fetcher.h index 816046e5..e4a0da5 100644 --- a/device/vr/android/gvr/gvr_gamepad_data_fetcher.h +++ b/device/vr/android/gvr/gvr_gamepad_data_fetcher.h
@@ -9,6 +9,7 @@ #include "device/gamepad/gamepad_data_fetcher.h" #include "device/vr/android/gvr/gvr_gamepad_data_provider.h" +#include "device/vr/public/mojom/vr_service.mojom.h" #include "device/vr/vr_export.h" namespace device { @@ -17,17 +18,17 @@ public: class Factory : public GamepadDataFetcherFactory { public: - Factory(GvrGamepadDataProvider*, unsigned int display_id); + Factory(GvrGamepadDataProvider*, mojom::XRDeviceId display_id); ~Factory() override; std::unique_ptr<GamepadDataFetcher> CreateDataFetcher() override; GamepadSource source() override; private: GvrGamepadDataProvider* data_provider_; - unsigned int display_id_; + mojom::XRDeviceId display_id_; }; - GvrGamepadDataFetcher(GvrGamepadDataProvider*, unsigned int display_id); + GvrGamepadDataFetcher(GvrGamepadDataProvider*, mojom::XRDeviceId display_id); ~GvrGamepadDataFetcher() override; GamepadSource source() override; @@ -40,7 +41,7 @@ void SetGamepadData(GvrGamepadData); private: - unsigned int display_id_; + mojom::XRDeviceId display_id_; GvrGamepadData gamepad_data_; DISALLOW_COPY_AND_ASSIGN(GvrGamepadDataFetcher);
diff --git a/device/vr/buildflags/BUILD.gn b/device/vr/buildflags/BUILD.gn index fa4c3d9..2bbefac 100644 --- a/device/vr/buildflags/BUILD.gn +++ b/device/vr/buildflags/BUILD.gn
@@ -10,8 +10,9 @@ header = "buildflags.h" flags = [ "ENABLE_ARCORE=$enable_arcore", - "ENABLE_VR=$enable_vr", - "ENABLE_OPENVR=$enable_openvr", + "ENABLE_ISOLATED_XR_SERVICE=$enable_isolated_xr_service", "ENABLE_OCULUS_VR=$enable_oculus_vr", + "ENABLE_OPENVR=$enable_openvr", + "ENABLE_VR=$enable_vr", ] }
diff --git a/device/vr/buildflags/buildflags.gni b/device/vr/buildflags/buildflags.gni index eb1a3885..13f05de 100644 --- a/device/vr/buildflags/buildflags.gni +++ b/device/vr/buildflags/buildflags.gni
@@ -50,4 +50,11 @@ # directories, we can stop requiring |enable_vr| here. enable_arcore = enable_vr && is_android && !is_chromecast && (current_cpu == "arm" || current_cpu == "arm64") + + # When enabled, host Desktop VR devices (OpenVR and Oculus) in a separate + # process. When disabled, and Oculus/OpenVR are enabled, they are hosted + # in the browser process. + # TODO(billorr): Enable by default when OpenVR or Oculus are enabled after + # tests and controllers are working with the isolated process. + enable_isolated_xr_service = false }
diff --git a/device/vr/isolated_gamepad_data_fetcher.cc b/device/vr/isolated_gamepad_data_fetcher.cc index 22d15dd..b78f5d5a 100644 --- a/device/vr/isolated_gamepad_data_fetcher.cc +++ b/device/vr/isolated_gamepad_data_fetcher.cc
@@ -8,7 +8,7 @@ namespace device { IsolatedGamepadDataFetcher::Factory::Factory( - VRDeviceId display_id, + device::mojom::XRDeviceId display_id, device::mojom::IsolatedXRGamepadProviderFactoryPtr factory) : display_id_(display_id), factory_(std::move(factory)) {} @@ -23,12 +23,13 @@ } GamepadSource IsolatedGamepadDataFetcher::Factory::source() { - return (display_id_ == VRDeviceId::OPENVR_DEVICE_ID) ? GAMEPAD_SOURCE_OPENVR - : GAMEPAD_SOURCE_OCULUS; + return (display_id_ == device::mojom::XRDeviceId::OPENVR_DEVICE_ID) + ? GAMEPAD_SOURCE_OPENVR + : GAMEPAD_SOURCE_OCULUS; } IsolatedGamepadDataFetcher::IsolatedGamepadDataFetcher( - VRDeviceId display_id, + device::mojom::XRDeviceId display_id, device::mojom::IsolatedXRGamepadProviderPtr provider) : display_id_(display_id) { // We bind provider_ on the poling thread, but we're created on the main UI @@ -39,8 +40,9 @@ IsolatedGamepadDataFetcher::~IsolatedGamepadDataFetcher() = default; GamepadSource IsolatedGamepadDataFetcher::source() { - return (display_id_ == VRDeviceId::OPENVR_DEVICE_ID) ? GAMEPAD_SOURCE_OPENVR - : GAMEPAD_SOURCE_OCULUS; + return (display_id_ == device::mojom::XRDeviceId::OPENVR_DEVICE_ID) + ? GAMEPAD_SOURCE_OPENVR + : GAMEPAD_SOURCE_OCULUS; } void IsolatedGamepadDataFetcher::OnDataUpdated( @@ -164,10 +166,10 @@ // Gamepad extensions refer to display_id, corresponding to the WebVR // VRDisplay's dipslayId property. // As WebVR is deprecated, and we only hand out a maximum of one "display" - // per runtime, we use the VRDeviceId now to associate the controller with + // per runtime, we use the XRDeviceId now to associate the controller with // a headset. This doesn't change behavior, but the device/display naming // could be confusing here. - if (display_id_ == VRDeviceId::OPENVR_DEVICE_ID) { + if (display_id_ == device::mojom::XRDeviceId::OPENVR_DEVICE_ID) { swprintf(dest.id, Gamepad::kIdLengthCap, L"OpenVR Gamepad"); } else { if (dest.hand == GamepadHand::kLeft) { @@ -198,4 +200,26 @@ void IsolatedGamepadDataFetcher::OnAddedToProvider() {} +void IsolatedGamepadDataFetcher::Factory::RemoveGamepad( + device::mojom::XRDeviceId id) { + using namespace device; + // TODO(crbug.com/868101) - Remove this. + std::map<device::mojom::XRDeviceId, GamepadSource> + device_id_to_gamepad_source = { + {device::mojom::XRDeviceId::OCULUS_DEVICE_ID, GAMEPAD_SOURCE_OCULUS}, + {device::mojom::XRDeviceId::OPENVR_DEVICE_ID, GAMEPAD_SOURCE_OPENVR}, + }; + + GamepadDataFetcherManager::GetInstance()->RemoveSourceFactory( + device_id_to_gamepad_source[id]); +} + +void IsolatedGamepadDataFetcher::Factory::AddGamepad( + device::mojom::XRDeviceId device_id, + device::mojom::IsolatedXRGamepadProviderFactoryPtr gamepad_factory) { + device::GamepadDataFetcherManager::GetInstance()->AddFactory( + new device::IsolatedGamepadDataFetcher::Factory( + device_id, std::move(gamepad_factory))); +} + } // namespace device
diff --git a/device/vr/isolated_gamepad_data_fetcher.h b/device/vr/isolated_gamepad_data_fetcher.h index 8958b383..3951140 100644 --- a/device/vr/isolated_gamepad_data_fetcher.h +++ b/device/vr/isolated_gamepad_data_fetcher.h
@@ -13,21 +13,26 @@ class IsolatedGamepadDataFetcher : public GamepadDataFetcher { public: - class Factory : public GamepadDataFetcherFactory { + class DEVICE_VR_EXPORT Factory : public GamepadDataFetcherFactory { public: - Factory(VRDeviceId display_id, + Factory(device::mojom::XRDeviceId display_id, device::mojom::IsolatedXRGamepadProviderFactoryPtr factory); ~Factory() override; std::unique_ptr<GamepadDataFetcher> CreateDataFetcher() override; GamepadSource source() override; + static void AddGamepad( + device::mojom::XRDeviceId device_id, + device::mojom::IsolatedXRGamepadProviderFactoryPtr gamepad_factory); + static void RemoveGamepad(device::mojom::XRDeviceId device_id); + private: - VRDeviceId display_id_; + device::mojom::XRDeviceId display_id_; device::mojom::IsolatedXRGamepadProviderFactoryPtr factory_; }; IsolatedGamepadDataFetcher( - VRDeviceId display_id, + device::mojom::XRDeviceId display_id, device::mojom::IsolatedXRGamepadProviderPtr provider); ~IsolatedGamepadDataFetcher() override; @@ -40,7 +45,7 @@ void OnDataUpdated(device::mojom::XRGamepadDataPtr data); private: - VRDeviceId display_id_; + device::mojom::XRDeviceId display_id_; bool have_outstanding_request_ = false; std::set<unsigned int> active_gamepads_; device::mojom::XRGamepadDataPtr data_;
diff --git a/device/vr/oculus/oculus_device.cc b/device/vr/oculus/oculus_device.cc index da6a168..25cea45 100644 --- a/device/vr/oculus/oculus_device.cc +++ b/device/vr/oculus/oculus_device.cc
@@ -48,10 +48,10 @@ return eye_parameters; } -mojom::VRDisplayInfoPtr CreateVRDisplayInfo(unsigned int id, +mojom::VRDisplayInfoPtr CreateVRDisplayInfo(mojom::XRDeviceId id, ovrSession session) { mojom::VRDisplayInfoPtr display_info = mojom::VRDisplayInfo::New(); - display_info->index = id; + display_info->id = id; display_info->displayName = std::string("Oculus"); display_info->capabilities = mojom::VRDisplayCapabilities::New(); display_info->capabilities->hasPosition = true; @@ -84,7 +84,7 @@ } // namespace OculusDevice::OculusDevice() - : VRDeviceBase(VRDeviceId::OCULUS_DEVICE_ID), + : VRDeviceBase(mojom::XRDeviceId::OCULUS_DEVICE_ID), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), exclusive_controller_binding_(this), gamepad_provider_factory_binding_(this),
diff --git a/device/vr/oculus/oculus_device.h b/device/vr/oculus/oculus_device.h index cefc6076..d60ae9c 100644 --- a/device/vr/oculus/oculus_device.h +++ b/device/vr/oculus/oculus_device.h
@@ -18,9 +18,10 @@ class OculusRenderLoop; -class OculusDevice : public VRDeviceBase, - public mojom::XRSessionController, - public mojom::IsolatedXRGamepadProviderFactory { +class DEVICE_VR_EXPORT OculusDevice + : public VRDeviceBase, + public mojom::XRSessionController, + public mojom::IsolatedXRGamepadProviderFactory { public: explicit OculusDevice(); ~OculusDevice() override;
diff --git a/device/vr/oculus/oculus_device_provider.cc b/device/vr/oculus/oculus_device_provider.cc index 0b8fa24f..b91253c 100644 --- a/device/vr/oculus/oculus_device_provider.cc +++ b/device/vr/oculus/oculus_device_provider.cc
@@ -21,22 +21,24 @@ } void OculusVRDeviceProvider::Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(device::mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + remove_device_callback, base::OnceClosure initialization_complete) { CreateDevice(); if (device_) { - add_device_callback.Run( - static_cast<unsigned int>(VRDeviceId::OCULUS_DEVICE_ID), - device_->GetVRDisplayInfo(), device_->BindXRRuntimePtr()); + add_device_callback.Run(device::mojom::XRDeviceId::OCULUS_DEVICE_ID, + device_->GetVRDisplayInfo(), + device_->BindXRRuntimePtr()); // Removed in our destructor, as VRDeviceId::OCULUS_DEVICE_ID corresponds to // device::GAMEPAD_SOURCE_OCULUS. GamepadDataFetcherManager::GetInstance()->AddFactory( - new IsolatedGamepadDataFetcher::Factory(VRDeviceId::OCULUS_DEVICE_ID, - device_->BindGamepadFactory())); + new IsolatedGamepadDataFetcher::Factory( + device::mojom::XRDeviceId::OCULUS_DEVICE_ID, + device_->BindGamepadFactory())); } initialized_ = true; std::move(initialization_complete).Run();
diff --git a/device/vr/oculus/oculus_device_provider.h b/device/vr/oculus/oculus_device_provider.h index 24791e1..6451c09e 100644 --- a/device/vr/oculus/oculus_device_provider.h +++ b/device/vr/oculus/oculus_device_provider.h
@@ -12,8 +12,6 @@ #include "device/vr/vr_device_provider.h" #include "device/vr/vr_export.h" -typedef struct ovrHmdStruct* ovrSession; - namespace device { class OculusDevice; @@ -24,10 +22,11 @@ ~OculusVRDeviceProvider() override; void Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(device::mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + remove_device_callback, base::OnceClosure initialization_complete) override; bool Initialized() override;
diff --git a/device/vr/openvr/openvr_device.cc b/device/vr/openvr/openvr_device.cc index efd90999..28b5a88 100644 --- a/device/vr/openvr/openvr_device.cc +++ b/device/vr/openvr/openvr_device.cc
@@ -62,9 +62,9 @@ } mojom::VRDisplayInfoPtr CreateVRDisplayInfo(vr::IVRSystem* vr_system, - unsigned int id) { + device::mojom::XRDeviceId id) { mojom::VRDisplayInfoPtr display_info = mojom::VRDisplayInfo::New(); - display_info->index = id; + display_info->id = id; display_info->displayName = GetOpenVRString(vr_system, vr::Prop_ManufacturerName_String) + " " + GetOpenVRString(vr_system, vr::Prop_ModelNumber_String); @@ -128,7 +128,7 @@ } // namespace OpenVRDevice::OpenVRDevice() - : VRDeviceBase(VRDeviceId::OPENVR_DEVICE_ID), + : VRDeviceBase(device::mojom::XRDeviceId::OPENVR_DEVICE_ID), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), exclusive_controller_binding_(this), gamepad_provider_factory_binding_(this),
diff --git a/device/vr/openvr/openvr_device.h b/device/vr/openvr/openvr_device.h index fea6cfb..61a7e618 100644 --- a/device/vr/openvr/openvr_device.h +++ b/device/vr/openvr/openvr_device.h
@@ -18,9 +18,10 @@ class OpenVRRenderLoop; -class OpenVRDevice : public VRDeviceBase, - public mojom::XRSessionController, - public mojom::IsolatedXRGamepadProviderFactory { +class DEVICE_VR_EXPORT OpenVRDevice + : public VRDeviceBase, + public mojom::XRSessionController, + public mojom::IsolatedXRGamepadProviderFactory { public: OpenVRDevice(); ~OpenVRDevice() override;
diff --git a/device/vr/openvr/openvr_device_provider.cc b/device/vr/openvr/openvr_device_provider.cc index bcb9cb8f..377eca334 100644 --- a/device/vr/openvr/openvr_device_provider.cc +++ b/device/vr/openvr/openvr_device_provider.cc
@@ -37,10 +37,11 @@ } void OpenVRDeviceProvider::Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(device::mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + remove_device_callback, base::OnceClosure initialization_complete) { CreateDevice(); if (device_) { @@ -62,8 +63,9 @@ device_ = std::make_unique<OpenVRDevice>(); if (device_->IsInitialized()) { GamepadDataFetcherManager::GetInstance()->AddFactory( - new IsolatedGamepadDataFetcher::Factory(VRDeviceId::OPENVR_DEVICE_ID, - device_->BindGamepadFactory())); + new IsolatedGamepadDataFetcher::Factory( + device::mojom::XRDeviceId::OPENVR_DEVICE_ID, + device_->BindGamepadFactory())); } else { device_ = nullptr; }
diff --git a/device/vr/openvr/openvr_device_provider.h b/device/vr/openvr/openvr_device_provider.h index 7dc8229..ed9f4285 100644 --- a/device/vr/openvr/openvr_device_provider.h +++ b/device/vr/openvr/openvr_device_provider.h
@@ -23,10 +23,11 @@ ~OpenVRDeviceProvider() override; void Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(device::mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + remove_device_callback, base::OnceClosure initialization_complete) override; bool Initialized() override;
diff --git a/device/vr/orientation/orientation_device.cc b/device/vr/orientation/orientation_device.cc index d32cd63..e8b2067 100644 --- a/device/vr/orientation/orientation_device.cc +++ b/device/vr/orientation/orientation_device.cc
@@ -23,11 +23,11 @@ namespace { static constexpr int kDefaultPumpFrequencyHz = 60; -mojom::VRDisplayInfoPtr CreateVRDisplayInfo(unsigned int id) { +mojom::VRDisplayInfoPtr CreateVRDisplayInfo(mojom::XRDeviceId id) { static const char DEVICE_NAME[] = "VR Orientation Device"; mojom::VRDisplayInfoPtr display_info = mojom::VRDisplayInfo::New(); - display_info->index = id; + display_info->id = id; display_info->displayName = DEVICE_NAME; display_info->capabilities = mojom::VRDisplayCapabilities::New(); display_info->capabilities->hasPosition = false; @@ -52,7 +52,7 @@ VROrientationDevice::VROrientationDevice( mojom::SensorProviderPtr* sensor_provider, base::OnceClosure ready_callback) - : VRDeviceBase(VRDeviceId::ORIENTATION_DEVICE_ID), + : VRDeviceBase(mojom::XRDeviceId::ORIENTATION_DEVICE_ID), ready_callback_(std::move(ready_callback)), binding_(this) { (*sensor_provider)
diff --git a/device/vr/orientation/orientation_device_provider.cc b/device/vr/orientation/orientation_device_provider.cc index 7f327156..5cdf236 100644 --- a/device/vr/orientation/orientation_device_provider.cc +++ b/device/vr/orientation/orientation_device_provider.cc
@@ -21,10 +21,10 @@ VROrientationDeviceProvider::~VROrientationDeviceProvider() = default; void VROrientationDeviceProvider::Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) { if (device_ && device_->IsAvailable()) { add_device_callback.Run(device_->GetId(), device_->GetVRDisplayInfo(),
diff --git a/device/vr/orientation/orientation_device_provider.h b/device/vr/orientation/orientation_device_provider.h index d7772325..a260c5b 100644 --- a/device/vr/orientation/orientation_device_provider.h +++ b/device/vr/orientation/orientation_device_provider.h
@@ -24,10 +24,10 @@ ~VROrientationDeviceProvider() override; void Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) override; bool Initialized() override; @@ -42,7 +42,7 @@ std::unique_ptr<VROrientationDevice> device_; base::RepeatingCallback< - void(unsigned int, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> + void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback_; base::OnceClosure initialized_callback_;
diff --git a/device/vr/orientation/orientation_device_provider_unittest.cc b/device/vr/orientation/orientation_device_provider_unittest.cc index bccfdc3..2909230 100644 --- a/device/vr/orientation/orientation_device_provider_unittest.cc +++ b/device/vr/orientation/orientation_device_provider_unittest.cc
@@ -83,22 +83,26 @@ return init_params; } - base::RepeatingCallback< - void(unsigned int, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr device)> + base::RepeatingCallback<void(device::mojom::XRDeviceId, + mojom::VRDisplayInfoPtr, + mojom::XRRuntimePtr device)> DeviceAndIdCallbackFailIfCalled() { - return base::BindRepeating([](unsigned int id, mojom::VRDisplayInfoPtr, + return base::BindRepeating([](device::mojom::XRDeviceId id, + mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr device) { FAIL(); }); }; - base::RepeatingCallback<void(unsigned int)> DeviceIdCallbackFailIfCalled() { - return base::BindRepeating([](unsigned int id) { FAIL(); }); + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + DeviceIdCallbackFailIfCalled() { + return base::BindRepeating([](device::mojom::XRDeviceId id) { FAIL(); }); }; - base::RepeatingCallback< - void(unsigned int, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr device)> + base::RepeatingCallback<void(device::mojom::XRDeviceId, + mojom::VRDisplayInfoPtr, + mojom::XRRuntimePtr device)> DeviceAndIdCallbackMustBeCalled(base::RunLoop* loop) { return base::BindRepeating( - [](base::OnceClosure quit_closure, unsigned int id, + [](base::OnceClosure quit_closure, device::mojom::XRDeviceId id, mojom::VRDisplayInfoPtr info, mojom::XRRuntimePtr device) { ASSERT_TRUE(device); ASSERT_TRUE(info); @@ -107,10 +111,10 @@ loop->QuitClosure()); }; - base::RepeatingCallback<void(unsigned int)> DeviceIdCallbackMustBeCalled( - base::RunLoop* loop) { + base::RepeatingCallback<void(device::mojom::XRDeviceId)> + DeviceIdCallbackMustBeCalled(base::RunLoop* loop) { return base::BindRepeating( - [](base::OnceClosure quit_closure, unsigned int id) { + [](base::OnceClosure quit_closure, device::mojom::XRDeviceId id) { std::move(quit_closure).Run(); }, loop->QuitClosure());
diff --git a/device/vr/public/mojom/isolated_xr_service.mojom b/device/vr/public/mojom/isolated_xr_service.mojom index 9366552..9666ddcd 100644 --- a/device/vr/public/mojom/isolated_xr_service.mojom +++ b/device/vr/public/mojom/isolated_xr_service.mojom
@@ -6,6 +6,8 @@ import "device/vr/public/mojom/vr_service.mojom"; +const string kVrIsolatedServiceName = "xr_device_service"; + // The XRSessionController lives in the vr device service, and corresponds to // a set of the XRSession bindings. The client is the browser process, which // will pause or stop sessions depending events/state such as focus or other @@ -132,3 +134,34 @@ // browser process). GetIsolatedXRGamepadProvider(IsolatedXRGamepadProvider& provider); }; + +// Notify the browser process about a set of runtimes. The browser process +// implements this interface to be notified about runtime changes from the XR +// device service. +interface IsolatedXRRuntimeProviderClient { + // Called when runtimes are initially enumerated, or when devices are later + // attached and become available. + OnDeviceAdded(XRRuntime runtime, + IsolatedXRGamepadProviderFactory gamepad_factory, + device.mojom.VRDisplayInfo display_info); + + // Called when runtimes become unavailable - for example if the hardware is + // disconnected or the APIs notify us that they are shutting down. + // device_index corresponds to display_info->index for a previously added + // device. + OnDeviceRemoved(device.mojom.XRDeviceId device_index); + + // Called once after all the initial OnDeviceAdded calls are completed. + // This is a signal to the browser that it knows what hardware is available, + // and can unblock any callbacks/promises that WebXR APIs are blocked. + OnDevicesEnumerated(); +}; + +// Provides access to XRRuntimes. This is implemented in the XR device service, +// and consumed by the browser. +interface IsolatedXRRuntimeProvider { + // Register a client, and triggers OnDeviceAdded for all available runtimes, + // followed by OnDevicesEnumerated. + // Should only be called once. + RequestDevices(IsolatedXRRuntimeProviderClient client); +};
diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom index eb75e876..f0faf52 100644 --- a/device/vr/public/mojom/vr_service.mojom +++ b/device/vr/public/mojom/vr_service.mojom
@@ -16,6 +16,19 @@ // WebXR interfaces // +// TODO: Use EnableIf to only define values on platforms that have +// implementations. +enum XRDeviceId { + LAYOUT_TEST_DEVICE_ID = 0, // Fake device used by layout tests. + GVR_DEVICE_ID = 1, + OPENVR_DEVICE_ID = 2, + OCULUS_DEVICE_ID = 3, + ARCORE_DEVICE_ID = 4, + ORIENTATION_DEVICE_ID = 5, + FAKE_DEVICE_ID = 6, // Fake device used by unit tests. +}; + + enum XRHandedness { NONE = 0, LEFT = 1, @@ -166,7 +179,7 @@ }; struct VRDisplayInfo { - uint32 index; + XRDeviceId id; string displayName; VRDisplayCapabilities capabilities; VRStageParameters? stageParameters;
diff --git a/device/vr/test/fake_vr_device.cc b/device/vr/test/fake_vr_device.cc index ba0baf3a..eeaafc65 100644 --- a/device/vr/test/fake_vr_device.cc +++ b/device/vr/test/fake_vr_device.cc
@@ -6,8 +6,8 @@ namespace device { -FakeVRDevice::FakeVRDevice(unsigned int id) - : VRDeviceBase(static_cast<VRDeviceId>(id)), controller_binding_(this) { +FakeVRDevice::FakeVRDevice(mojom::XRDeviceId id) + : VRDeviceBase(id), controller_binding_(this) { SetVRDisplayInfo(InitBasicDevice()); } @@ -15,7 +15,7 @@ mojom::VRDisplayInfoPtr FakeVRDevice::InitBasicDevice() { mojom::VRDisplayInfoPtr display_info = mojom::VRDisplayInfo::New(); - display_info->index = GetId(); + display_info->id = GetId(); display_info->displayName = "FakeVRDevice"; display_info->capabilities = mojom::VRDisplayCapabilities::New();
diff --git a/device/vr/test/fake_vr_device.h b/device/vr/test/fake_vr_device.h index fc1aa6f..a1ed5d6 100644 --- a/device/vr/test/fake_vr_device.h +++ b/device/vr/test/fake_vr_device.h
@@ -17,7 +17,7 @@ class DEVICE_VR_EXPORT FakeVRDevice : public VRDeviceBase, public mojom::XRSessionController { public: - FakeVRDevice(unsigned int id); + explicit FakeVRDevice(mojom::XRDeviceId id); ~FakeVRDevice() override; void RequestSession(
diff --git a/device/vr/test/fake_vr_device_provider.cc b/device/vr/test/fake_vr_device_provider.cc index dc4d097..567775b 100644 --- a/device/vr/test/fake_vr_device_provider.cc +++ b/device/vr/test/fake_vr_device_provider.cc
@@ -22,7 +22,7 @@ device_base->BindXRRuntimePtr()); } -void FakeVRDeviceProvider::RemoveDevice(unsigned int device_id) { +void FakeVRDeviceProvider::RemoveDevice(mojom::XRDeviceId device_id) { auto it = std::find_if( devices_.begin(), devices_.end(), [device_id](const std::unique_ptr<VRDeviceBase>& device) { @@ -34,10 +34,10 @@ } void FakeVRDeviceProvider::Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) { add_device_callback_ = std::move(add_device_callback); remove_device_callback_ = std::move(remove_device_callback);
diff --git a/device/vr/test/fake_vr_device_provider.h b/device/vr/test/fake_vr_device_provider.h index 81924fa..a5e5602 100644 --- a/device/vr/test/fake_vr_device_provider.h +++ b/device/vr/test/fake_vr_device_provider.h
@@ -22,13 +22,13 @@ // Adds devices to the provider with the given device, which will be // returned when GetDevices is queried. void AddDevice(std::unique_ptr<VRDeviceBase> device); - void RemoveDevice(unsigned int device_id); + void RemoveDevice(mojom::XRDeviceId device_id); void Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, base::OnceClosure initialization_complete) override; bool Initialized() override; @@ -36,9 +36,9 @@ std::vector<std::unique_ptr<VRDeviceBase>> devices_; bool initialized_; base::RepeatingCallback< - void(unsigned int, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> + void(mojom::XRDeviceId, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback_; - base::RepeatingCallback<void(unsigned int)> remove_device_callback_; + base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback_; DISALLOW_COPY_AND_ASSIGN(FakeVRDeviceProvider); };
diff --git a/device/vr/test/fake_vr_display_impl_client.cc b/device/vr/test/fake_vr_display_impl_client.cc index c263a433..94f13e2e 100644 --- a/device/vr/test/fake_vr_display_impl_client.cc +++ b/device/vr/test/fake_vr_display_impl_client.cc
@@ -19,7 +19,7 @@ } void FakeVRDisplayImplClient::OnChanged(mojom::VRDisplayInfoPtr display) { - service_client_->SetLastDeviceId(display->index); + service_client_->SetLastDeviceId(display->id); } } // namespace device
diff --git a/device/vr/test/fake_vr_service_client.cc b/device/vr/test/fake_vr_service_client.cc index 7cb9183..0fcb1dd 100644 --- a/device/vr/test/fake_vr_service_client.cc +++ b/device/vr/test/fake_vr_service_client.cc
@@ -24,11 +24,11 @@ display_clients_.push_back(std::move(display_client)); } -void FakeVRServiceClient::SetLastDeviceId(unsigned int id) { +void FakeVRServiceClient::SetLastDeviceId(mojom::XRDeviceId id) { last_device_id_ = id; } -bool FakeVRServiceClient::CheckDeviceId(unsigned int id) { +bool FakeVRServiceClient::CheckDeviceId(mojom::XRDeviceId id) { return id == last_device_id_; }
diff --git a/device/vr/test/fake_vr_service_client.h b/device/vr/test/fake_vr_service_client.h index 62d5d70..c0905ee 100644 --- a/device/vr/test/fake_vr_service_client.h +++ b/device/vr/test/fake_vr_service_client.h
@@ -22,13 +22,13 @@ void OnDisplayConnected(mojom::XRDevicePtr device, mojom::VRDisplayClientRequest request, mojom::VRDisplayInfoPtr displayInfo) override; - void SetLastDeviceId(unsigned int id); - bool CheckDeviceId(unsigned int id); + void SetLastDeviceId(mojom::XRDeviceId id); + bool CheckDeviceId(mojom::XRDeviceId id); private: std::vector<mojom::VRDisplayInfoPtr> displays_; std::vector<std::unique_ptr<FakeVRDisplayImplClient>> display_clients_; - unsigned int last_device_id_ = 0; + mojom::XRDeviceId last_device_id_ = static_cast<mojom::XRDeviceId>(0); mojo::Binding<mojom::VRServiceClient> m_binding_; DISALLOW_COPY_AND_ASSIGN(FakeVRServiceClient);
diff --git a/device/vr/vr_device.h b/device/vr/vr_device.h index aaa2294f..abc3dff 100644 --- a/device/vr/vr_device.h +++ b/device/vr/vr_device.h
@@ -27,16 +27,6 @@ VIEWER_TYPE_COUNT, }; -// Hardcoded list of ids for each device type. -enum class VRDeviceId : unsigned int { - GVR_DEVICE_ID = 1, - OPENVR_DEVICE_ID = 2, - OCULUS_DEVICE_ID = 3, - ARCORE_DEVICE_ID = 4, - ORIENTATION_DEVICE_ID = 5, - FAKE_DEVICE_ID = 6, -}; - // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class XrRuntimeAvailable {
diff --git a/device/vr/vr_device_base.cc b/device/vr/vr_device_base.cc index d5f3e5f..87e4b8e 100644 --- a/device/vr/vr_device_base.cc +++ b/device/vr/vr_device_base.cc
@@ -9,12 +9,12 @@ namespace device { -VRDeviceBase::VRDeviceBase(VRDeviceId id) - : id_(static_cast<unsigned int>(id)), runtime_binding_(this) {} +VRDeviceBase::VRDeviceBase(mojom::XRDeviceId id) + : id_(id), runtime_binding_(this) {} VRDeviceBase::~VRDeviceBase() = default; -unsigned int VRDeviceBase::GetId() const { +mojom::XRDeviceId VRDeviceBase::GetId() const { return id_; } @@ -64,7 +64,7 @@ void VRDeviceBase::SetVRDisplayInfo(mojom::VRDisplayInfoPtr display_info) { DCHECK(display_info); - DCHECK(display_info->index == id_); + DCHECK(display_info->id == id_); bool initialized = !!display_info_; display_info_ = std::move(display_info);
diff --git a/device/vr/vr_device_base.h b/device/vr/vr_device_base.h index 230a0acf..93ec057 100644 --- a/device/vr/vr_device_base.h +++ b/device/vr/vr_device_base.h
@@ -22,7 +22,7 @@ // TODO(mthiesse, crbug.com/769373): Remove DEVICE_VR_EXPORT. class DEVICE_VR_EXPORT VRDeviceBase : public mojom::XRRuntime { public: - explicit VRDeviceBase(VRDeviceId id); + explicit VRDeviceBase(mojom::XRDeviceId id); ~VRDeviceBase() override; // VRDevice Implementation @@ -36,7 +36,7 @@ virtual void RequestHitTest( mojom::XRRayPtr ray, mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback); - unsigned int GetId() const; + device::mojom::XRDeviceId GetId() const; bool HasExclusiveSession(); void EndMagicWindowSession(VRDisplayImpl* session); @@ -91,7 +91,7 @@ bool presenting_ = false; - unsigned int id_; + device::mojom::XRDeviceId id_; bool magic_window_enabled_ = true; mojo::Binding<mojom::XRRuntime> runtime_binding_;
diff --git a/device/vr/vr_device_base_unittest.cc b/device/vr/vr_device_base_unittest.cc index 6eb9f45..318b292 100644 --- a/device/vr/vr_device_base_unittest.cc +++ b/device/vr/vr_device_base_unittest.cc
@@ -21,7 +21,7 @@ class VRDeviceBaseForTesting : public VRDeviceBase { public: - VRDeviceBaseForTesting() : VRDeviceBase(VRDeviceId::FAKE_DEVICE_ID) {} + VRDeviceBaseForTesting() : VRDeviceBase(mojom::XRDeviceId::FAKE_DEVICE_ID) {} ~VRDeviceBaseForTesting() override = default; void SetVRDisplayInfoForTest(mojom::VRDisplayInfoPtr display_info) { @@ -102,9 +102,9 @@ return device; } - mojom::VRDisplayInfoPtr MakeVRDisplayInfo(unsigned int device_id) { + mojom::VRDisplayInfoPtr MakeVRDisplayInfo(mojom::XRDeviceId device_id) { mojom::VRDisplayInfoPtr display_info = mojom::VRDisplayInfo::New(); - display_info->index = device_id; + display_info->id = device_id; display_info->capabilities = mojom::VRDisplayCapabilities::New(); return display_info; } @@ -150,7 +150,8 @@ } TEST_F(VRDeviceTest, NoMagicWindowPosesWhileBrowsing) { - auto device = std::make_unique<FakeVRDevice>(1); + auto device = + std::make_unique<FakeVRDevice>(static_cast<device::mojom::XRDeviceId>(1)); device->SetPose(mojom::VRPose::New()); device->GetFrameData(base::BindOnce(
diff --git a/device/vr/vr_device_provider.h b/device/vr/vr_device_provider.h index 26732491..27616ca 100644 --- a/device/vr/vr_device_provider.h +++ b/device/vr/vr_device_provider.h
@@ -19,10 +19,11 @@ // If the VR API requires initialization that should happen here. virtual void Initialize( - base::RepeatingCallback<void(unsigned int, + base::RepeatingCallback<void(mojom::XRDeviceId id, mojom::VRDisplayInfoPtr, mojom::XRRuntimePtr)> add_device_callback, - base::RepeatingCallback<void(unsigned int)> remove_device_callback, + base::RepeatingCallback<void(mojom::XRDeviceId id)> + remove_device_callback, base::OnceClosure initialization_complete) = 0; // Returns true if initialization is complete.
diff --git a/device/vr/vr_display_impl_unittest.cc b/device/vr/vr_display_impl_unittest.cc index f6d4b1a..c568c97 100644 --- a/device/vr/vr_display_impl_unittest.cc +++ b/device/vr/vr_display_impl_unittest.cc
@@ -24,7 +24,7 @@ protected: void SetUp() override { - device_ = std::make_unique<FakeVRDevice>(1); + device_ = std::make_unique<FakeVRDevice>(static_cast<mojom::XRDeviceId>(1)); device_->SetPose(mojom::VRPose::New()); mojom::VRServiceClientPtr proxy; client_ = std::make_unique<FakeVRServiceClient>(mojo::MakeRequest(&proxy));
diff --git a/docs/updating_clang.md b/docs/updating_clang.md index b0e3041..594fb39 100644 --- a/docs/updating_clang.md +++ b/docs/updating_clang.md
@@ -18,6 +18,8 @@ gs://chromium-browser-clang/$x/llvmobjdump-$rev.tgz ; \ gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/llvmcfiverify-$rev.tgz \ gs://chromium-browser-clang/$x/llvmcfiverify-$rev.tgz ; \ + gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/safestack-$rev.tgz \ + gs://chromium-browser-clang/$x/safestack-$rev.tgz ; \ gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/translation_unit-$rev.tgz \ gs://chromium-browser-clang/$x/translation_unit-$rev.tgz ; \ gsutil.py cp -n -a public-read gs://chromium-browser-clang-staging/$x/llvm-code-coverage-$rev.tgz \
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index 15011a3..ba2df9d 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn
@@ -238,7 +238,7 @@ "//extensions/test/data/", "//net/tools/testserver/", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", "$root_out_dir/extensions_shell_and_test.pak", ]
diff --git a/extensions/browser/updater/update_service.cc b/extensions/browser/updater/update_service.cc index 93dda0f4..df22e6a 100644 --- a/extensions/browser/updater/update_service.cc +++ b/extensions/browser/updater/update_service.cc
@@ -136,11 +136,18 @@ complete_event = true; finish_delayed_installation = true; { + update_client::ErrorCategory error_category = + update_client::ErrorCategory::kNone; update_client::CrxUpdateItem update_item; - if (!update_client_->GetCrxUpdateState(extension_id, &update_item)) { - NOTREACHED(); + if (update_client_->GetCrxUpdateState(extension_id, &update_item)) { + // When update_client_->GetCrxUpdateState(...) returns false, it means + // that |update_client_| can't find any information about this + // |extension_id|. It could be possible that |extension_id| was + // uninstalled when |update_client_| was checking for updates. + // (see bug http://crbug.com/869663). + error_category = update_item.error_category; } - switch (update_item.error_category) { + switch (error_category) { case update_client::ErrorCategory::kUpdateCheck: ReportUpdateCheckResult( ExtensionUpdaterUpdateResult::UPDATE_CHECK_ERROR,
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json index fbdd8920..fe678ee3 100644 --- a/extensions/common/api/_permission_features.json +++ b/extensions/common/api/_permission_features.json
@@ -432,7 +432,9 @@ "96FF2FFA5C9173C76D47184B3E86D267B37781DE", // http://crbug.com/642141 "0136FCB13DB29FD5CD442F56E59E53B61F1DF96F", // http://crbug.com/642141 "CBCC42ABED43A4B58FE3810E62AFFA010EB0349F", // PDF Viewer - "75C7F4B720314B6CB1B5817CD86089DB95CD2461" // Chromevox on chromecast + "75C7F4B720314B6CB1B5817CD86089DB95CD2461", // Chromevox on chromecast + "46578A13607D38F1DC8E280C4F499FB0A2F9565C", // http://crbug.com/819404 + "898FB5A39687D210766B8998BA4530B99C9E6586" // http://crbug.com/819404 ] }, "nativeMessaging": { @@ -611,7 +613,7 @@ } ], "system.powerSource": { - "channel": "dev", + "channel": "stable", "extension_types": ["platform_app"], "platforms": ["chromeos"], "session_types": ["kiosk"]
diff --git a/extensions/test/data/web_view/apitest/main.js b/extensions/test/data/web_view/apitest/main.js index 56174c5..cb90671 100644 --- a/extensions/test/data/web_view/apitest/main.js +++ b/extensions/test/data/web_view/apitest/main.js
@@ -1673,25 +1673,35 @@ }, requestFilter, extraInfoSpec); var loadstartCalled = false; - webview.addEventListener('loadstart', function(e) { - embedder.test.assertTrue(e.isTopLevel); - embedder.test.assertEq(embedder.detectUserAgentURL, e.url); - loadstartCalled = true; - }); - webview.addEventListener('loadredirect', function(e) { - embedder.test.assertTrue(e.isTopLevel); - embedder.test.assertEq(embedder.detectUserAgentURL, - e.oldUrl.replace('127.0.0.1', 'localhost')); - embedder.test.assertEq(embedder.redirectGuestURLDest, - e.newUrl.replace('127.0.0.1', 'localhost')); - if (loadstartCalled) { - embedder.test.succeed(); - } else { - embedder.test.fail(); - } - }); - webview.src = embedder.detectUserAgentURL; + var listener = function() { + webview.removeEventListener('loadstop', listener); + // Now load the real URL for the test. + webview.src = embedder.detectUserAgentURL; + + webview.addEventListener('loadstart', function(e) { + embedder.test.assertTrue(e.isTopLevel); + embedder.test.assertEq(embedder.detectUserAgentURL, e.url); + loadstartCalled = true; + }); + + webview.addEventListener('loadredirect', function(e) { + embedder.test.assertTrue(e.isTopLevel); + embedder.test.assertEq(embedder.detectUserAgentURL, + e.oldUrl.replace('127.0.0.1', 'localhost')); + embedder.test.assertEq(embedder.redirectGuestURLDest, + e.newUrl.replace('127.0.0.1', 'localhost')); + if (loadstartCalled) { + embedder.test.succeed(); + } else { + embedder.test.fail(); + } + }); + }; + webview.addEventListener('loadstop', listener); + + // Load an empty URL to wait for the webRequest listener to be set up. + webview.src = embedder.emptyGuestURL; document.body.appendChild(webview); }
diff --git a/gpu/DEPS b/gpu/DEPS index 0273fe3..020fd3a 100644 --- a/gpu/DEPS +++ b/gpu/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+third_party/angle", "+third_party/amd", + "+third_party/nvml", "+third_party/re2", "+third_party/smhasher", "+third_party/swiftshader",
diff --git a/gpu/config/BUILD.gn b/gpu/config/BUILD.gn index a595002..47f44e86 100644 --- a/gpu/config/BUILD.gn +++ b/gpu/config/BUILD.gn
@@ -168,6 +168,12 @@ "setupapi.lib", ] + sources += [ + "//third_party/nvml/nvml.h", + "nvml_info.cc", + "nvml_info.h", + ] + if (is_chrome_branded && is_official_build) { sources += [ "//third_party/amd/AmdCfxPxExt.h",
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index d08fb7e..d52450d 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -489,7 +489,7 @@ "vendor_id": "0x10de", "driver_version": { "op": "<=", - "value": "8.17.12.6973" + "value": "269.73" }, "features": [ "disable_d3d11" @@ -1850,7 +1850,7 @@ }, "driver_version": { "op": "<", - "value": "21.21.13.7576" + "value": "375.76" }, "vendor_id": "0x10de", "features": [
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc index ca66ab08..1de8bed3 100644 --- a/gpu/config/gpu_info.cc +++ b/gpu/config/gpu_info.cc
@@ -19,6 +19,8 @@ enumerator->AddString("driverVendor", device.driver_vendor); enumerator->AddString("driverVersion", device.driver_version); enumerator->AddString("driverDate", device.driver_date); + enumerator->AddInt("cudaComputeCapabilityMajor", + device.cuda_compute_capability_major); enumerator->EndGPUDevice(); } @@ -94,8 +96,8 @@ GPUInfo::GPUDevice::GPUDevice() : vendor_id(0), device_id(0), - active(false) { -} + active(false), + cuda_compute_capability_major(0) {} GPUInfo::GPUDevice::GPUDevice(const GPUInfo::GPUDevice& other) = default;
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h index e367ee0..21c70eb 100644 --- a/gpu/config/gpu_info.h +++ b/gpu/config/gpu_info.h
@@ -137,6 +137,10 @@ std::string driver_vendor; std::string driver_version; std::string driver_date; + + // NVIDIA CUDA compute capability, major version. 0 if undetermined. Can be + // used to determine the hardware generation that the GPU belongs to. + int cuda_compute_capability_major; }; GPUInfo();
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc index 0bfcff229..41a2834 100644 --- a/gpu/config/gpu_info_collector_win.cc +++ b/gpu/config/gpu_info_collector_win.cc
@@ -36,6 +36,7 @@ #include "base/threading/thread.h" #include "base/trace_event/trace_event.h" #include "base/win/scoped_com_initializer.h" +#include "gpu/config/nvml_info.h" #include "third_party/vulkan/include/vulkan/vulkan.h" namespace gpu { @@ -124,6 +125,28 @@ } #endif +std::string ParseNVIDIARegistryDriverVersion(std::string registry_version) { + // The NVIDIA driver version in the registry is most commonly in the format: + // XX.XX.XD.DDDD + // Where "X" corresponds to an OS-specific digit and "D" corresponds to a + // digit of the actual driver version. We convert it to the following format: + // DDD.DD + // This matches with the actual driver version that NVML also returns. + std::string second_to_last_digits; + std::string last_digits; + if (!RE2::FullMatch(registry_version, "\\d+\\.\\d+\\.(\\d+)\\.(\\d+)", + &second_to_last_digits, &last_digits)) { + return registry_version; + } + std::string digits = second_to_last_digits + last_digits; + if (digits.length() < 5u) { + return registry_version; + } + digits.erase(0, digits.length() - 5u); + DCHECK(digits.length() == 5u); + return digits.substr(0u, 3u) + "." + digits.substr(3u); +} + bool CollectDriverInfoD3D(const std::wstring& device_id, GPUInfo* gpu_info) { TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); @@ -199,6 +222,28 @@ found_intel = true; if (device.vendor_id == 0x1002) found_amd = true; + if (device.vendor_id == 0x10de) { + std::string nvml_driver_version; + int major_cuda_compute_capability = 0; + int minor_cuda_compute_capability = 0; + bool nvml_success = GetNvmlDeviceInfo( + device.device_id, &nvml_driver_version, + &major_cuda_compute_capability, &minor_cuda_compute_capability); + if (nvml_success) { + // We use the NVML driver version instead of the registry version, + // since the registry version includes OS-specific digits that are + // not part of the actual driver version. + device.driver_version = nvml_driver_version; + device.cuda_compute_capability_major = + major_cuda_compute_capability; + } else { + // If we can't get the actual driver version from NVML, do + // best-effort parsing of the actual driver version from the + // registry driver version. + device.driver_version = + ParseNVIDIARegistryDriverVersion(device.driver_version); + } + } devices.push_back(device); }
diff --git a/gpu/config/nvml_info.cc b/gpu/config/nvml_info.cc new file mode 100644 index 0000000..521aa5b --- /dev/null +++ b/gpu/config/nvml_info.cc
@@ -0,0 +1,126 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/config/nvml_info.h" + +#include <windows.h> + +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "third_party/nvml/nvml.h" + +namespace { + +const unsigned int kDriverVersionCapacity = 80u; + +} // anonymous namespace + +typedef decltype(&nvmlInit) INITPROC; +typedef decltype(&nvmlShutdown) SHUTDOWNPROC; +typedef decltype(&nvmlSystemGetDriverVersion) GETDRIVERVERSIONPROC; +typedef decltype(&nvmlDeviceGetCount) DEVICEGETCOUNTPROC; +typedef decltype(&nvmlDeviceGetHandleByIndex) DEVICEGETHANDLEBYINDEXPROC; +typedef decltype(&nvmlDeviceGetPciInfo) DEVICEGETPCIINFOPROC; +typedef decltype( + &nvmlDeviceGetCudaComputeCapability) DEVICEGETCUDACOMPUTECAPABILITYPROC; + +bool GetNvmlDeviceInfo(uint32_t pci_device_id, + std::string* driver_version, + int* major_cuda_compute_capability, + int* minor_cuda_compute_capability) { + DCHECK(major_cuda_compute_capability); + DCHECK(minor_cuda_compute_capability); + *major_cuda_compute_capability = 0; + *minor_cuda_compute_capability = 0; + + base::FilePath dll_path; + if (!base::PathService::Get(base::DIR_PROGRAM_FILES6432, &dll_path)) { + return false; + } + dll_path = dll_path.Append(L"NVIDIA Corporation\\NVSMI\\nvml.dll"); + HINSTANCE hinstNVML = LoadLibrary(dll_path.value().data()); + + if (!hinstNVML) { + return false; + } + + INITPROC fnNvmlInit = (INITPROC)GetProcAddress(hinstNVML, "nvmlInit"); + SHUTDOWNPROC fnNvmlShutdown = + (SHUTDOWNPROC)GetProcAddress(hinstNVML, "nvmlShutdown"); + GETDRIVERVERSIONPROC fnNvmlSystemGetDriverVersion = + (GETDRIVERVERSIONPROC)GetProcAddress(hinstNVML, + "nvmlSystemGetDriverVersion"); + DEVICEGETCOUNTPROC fnNvmlDeviceGetCount = + (DEVICEGETCOUNTPROC)GetProcAddress(hinstNVML, "nvmlDeviceGetCount"); + DEVICEGETHANDLEBYINDEXPROC fnNvmlDeviceGetHandleByIndex = + (DEVICEGETHANDLEBYINDEXPROC)GetProcAddress(hinstNVML, + "nvmlDeviceGetHandleByIndex"); + DEVICEGETPCIINFOPROC fnNvmlDeviceGetPciInfo = + (DEVICEGETPCIINFOPROC)GetProcAddress(hinstNVML, "nvmlDeviceGetPciInfo"); + DEVICEGETCUDACOMPUTECAPABILITYPROC fnNvmlDeviceGetCudaComputeCapability = + (DEVICEGETCUDACOMPUTECAPABILITYPROC)GetProcAddress( + hinstNVML, "nvmlDeviceGetCudaComputeCapability"); + + if (!fnNvmlInit || !fnNvmlShutdown || !fnNvmlSystemGetDriverVersion) { + return false; + } + + nvmlReturn_t result = fnNvmlInit(); + if (NVML_SUCCESS != result) { + return false; + } + + char driver_version_temp[kDriverVersionCapacity]; + + result = + fnNvmlSystemGetDriverVersion(driver_version_temp, kDriverVersionCapacity); + if (NVML_SUCCESS != result) { + fnNvmlShutdown(); + return false; + } + + *driver_version = driver_version_temp; + + if (fnNvmlDeviceGetCount && fnNvmlDeviceGetHandleByIndex && + fnNvmlDeviceGetPciInfo && fnNvmlDeviceGetCudaComputeCapability) { + unsigned int device_count; + result = fnNvmlDeviceGetCount(&device_count); + if (NVML_SUCCESS == result) { + for (unsigned int i = 0; i < device_count; i++) { + nvmlDevice_t device; + nvmlPciInfo_t pci; + + result = fnNvmlDeviceGetHandleByIndex(i, &device); + if (NVML_SUCCESS != result) { + continue; + } + + result = fnNvmlDeviceGetPciInfo(device, &pci); + if (NVML_SUCCESS != result) { + continue; + } + + // We're looking for a particular PCI device. + if (pci.pciDeviceId != ((pci_device_id << 16) | 0x10deu)) { + continue; + } + + result = fnNvmlDeviceGetCudaComputeCapability( + device, major_cuda_compute_capability, + minor_cuda_compute_capability); + if (NVML_SUCCESS != result) { + *major_cuda_compute_capability = 0; + *minor_cuda_compute_capability = 0; + } + } + } + } + + result = fnNvmlShutdown(); + if (NVML_SUCCESS != result) { + return false; + } + return true; +}
diff --git a/gpu/config/nvml_info.h b/gpu/config/nvml_info.h new file mode 100644 index 0000000..e1f0f51 --- /dev/null +++ b/gpu/config/nvml_info.h
@@ -0,0 +1,22 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_CONFIG_NVML_INFO_H_ +#define GPU_CONFIG_NVML_INFO_H_ + +#include "build/build_config.h" + +#include <stdint.h> +#include <string> + +// Queries driver version and places it into driver_version. Writes +// major_cuda_compute_capability and minor_cuda_compute_capability of the GPU +// matching pci_device_id if one is found, or writes 0 into these outputs +// otherwise. Returns true on success. +bool GetNvmlDeviceInfo(uint32_t pci_device_id, + std::string* driver_version, + int* major_cuda_compute_capability, + int* minor_cuda_compute_capability); + +#endif // GPU_CONFIG_NVML_INFO_H_ \ No newline at end of file
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json index 2f689306..d472340a 100644 --- a/gpu/config/software_rendering_list.json +++ b/gpu/config/software_rendering_list.json
@@ -448,7 +448,7 @@ }, { "id": 59, - "description": "NVidia driver 8.15.11.8593 is crashy on Windows", + "description": "NVidia driver 185.93 is crashy on Windows", "cr_bugs": [155749], "os": { "type": "win" @@ -456,7 +456,7 @@ "vendor_id": "0x10de", "driver_version": { "op": "=", - "value": "8.15.11.8593" + "value": "185.93" }, "features": [ "accelerated_video_decode" @@ -499,7 +499,7 @@ }, { "id": 69, - "description": "NVIDIA driver 8.17.11.9621 is buggy with Stage3D baseline mode", + "description": "NVIDIA driver 196.21 is buggy with Stage3D baseline mode", "cr_bugs": [172771], "os": { "type": "win" @@ -507,7 +507,7 @@ "vendor_id": "0x10de", "driver_version": { "op": "=", - "value": "8.17.11.9621" + "value": "196.21" }, "features": [ "flash_stage3d_baseline" @@ -515,7 +515,7 @@ }, { "id": 70, - "description": "NVIDIA driver 8.17.11.8267 is buggy with Stage3D baseline mode", + "description": "NVIDIA driver 182.67 is buggy with Stage3D baseline mode", "cr_bugs": [172771], "os": { "type": "win" @@ -523,7 +523,7 @@ "vendor_id": "0x10de", "driver_version": { "op": "=", - "value": "8.17.11.8267" + "value": "182.67" }, "features": [ "flash_stage3d_baseline" @@ -699,8 +699,8 @@ "vendor_id": "0x10de", "driver_version": { "op": "between", - "value": "8.17.12.5729", - "value2": "8.17.12.8026" + "value": "257.29", + "value2": "280.26" }, "features": [ "accelerated_video_decode" @@ -716,8 +716,8 @@ "vendor_id": "0x10de", "driver_version": { "op": "between", - "value": "9.18.13.783", - "value2": "9.18.13.1090" + "value": "307.83", + "value2": "310.90" }, "features": [ "accelerated_video_decode" @@ -1429,7 +1429,7 @@ "vendor_id": "0x10de", "driver_version": { "op": "<=", - "value": "8.17.12.6973" + "value": "269.73" }, "features": [ "accelerated_webgl2"
diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom index 8d24a36..bf56d85 100644 --- a/gpu/ipc/common/gpu_info.mojom +++ b/gpu/ipc/common/gpu_info.mojom
@@ -19,6 +19,7 @@ string driver_vendor; string driver_version; string driver_date; + int32 cuda_compute_capability_major; }; // gpu::VideoCodecProfile
diff --git a/gpu/ipc/common/gpu_info_struct_traits.cc b/gpu/ipc/common/gpu_info_struct_traits.cc index 0696d192..cd6a8fe 100644 --- a/gpu/ipc/common/gpu_info_struct_traits.cc +++ b/gpu/ipc/common/gpu_info_struct_traits.cc
@@ -16,6 +16,7 @@ out->vendor_id = data.vendor_id(); out->device_id = data.device_id(); out->active = data.active(); + out->cuda_compute_capability_major = data.cuda_compute_capability_major(); return data.ReadVendorString(&out->vendor_string) && data.ReadDeviceString(&out->device_string) && data.ReadDriverVendor(&out->driver_vendor) &&
diff --git a/gpu/ipc/common/gpu_info_struct_traits.h b/gpu/ipc/common/gpu_info_struct_traits.h index b5b9d6f3..2af4721 100644 --- a/gpu/ipc/common/gpu_info_struct_traits.h +++ b/gpu/ipc/common/gpu_info_struct_traits.h
@@ -54,6 +54,11 @@ static const std::string& driver_date(const gpu::GPUInfo::GPUDevice& input) { return input.driver_date; } + + static int cuda_compute_capability_major( + const gpu::GPUInfo::GPUDevice& input) { + return input.cuda_compute_capability_major; + } }; template <>
diff --git a/headless/lib/browser/headless_permission_manager.cc b/headless/lib/browser/headless_permission_manager.cc index ce2b687..46fa0038 100644 --- a/headless/lib/browser/headless_permission_manager.cc +++ b/headless/lib/browser/headless_permission_manager.cc
@@ -73,8 +73,8 @@ int HeadlessPermissionManager::SubscribePermissionStatusChange( content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) { return content::PermissionController::kNoPendingOperation; }
diff --git a/headless/lib/browser/headless_permission_manager.h b/headless/lib/browser/headless_permission_manager.h index 86488a0a..95cadf7 100644 --- a/headless/lib/browser/headless_permission_manager.h +++ b/headless/lib/browser/headless_permission_manager.h
@@ -49,8 +49,8 @@ const GURL& requesting_origin) override; int SubscribePermissionStatusChange( content::PermissionType permission, + content::RenderFrameHost* render_frame_host, const GURL& requesting_origin, - const GURL& embedding_origin, const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override; void UnsubscribePermissionStatusChange(int subscription_id) override;
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index ff04033..1aa05022 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -1398,6 +1398,7 @@ #pragma mark - Promo support - (void)scheduleShowPromo { + [self.mainBVC.dispatcher showConsentBumpIfNeeded]; // Don't show promos if first run is shown. (Note: This flag is only YES // while the first run UI is visible. However, as this function is called // immediately after the UI is shown, it's a safe check.)
diff --git a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.h b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.h index ee2f3e15..5feda6d2 100644 --- a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.h +++ b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.h
@@ -64,6 +64,7 @@ base::Time delete_end; BrowsingDataRemoveMask mask; base::OnceClosure callback; + base::Time task_started; }; // Setter for |is_removing_|; DCHECKs that we can only start removing if we're
diff --git a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm index 59b439f..6df5a4b 100644 --- a/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm +++ b/ios/chrome/browser/browsing_data/browsing_data_remover_impl.mm
@@ -276,7 +276,8 @@ void BrowsingDataRemoverImpl::RunNextTask() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!removal_queue_.empty()); - const RemovalTask& removal_task = removal_queue_.front(); + RemovalTask& removal_task = removal_queue_.front(); + removal_task.task_started = base::Time::Now(); RemoveImpl(removal_task.delete_begin, removal_task.delete_end, removal_task.mask); } @@ -674,6 +675,22 @@ { RemovalTask task = std::move(removal_queue_.front()); + // Only log clear browsing data on regular browsing mode. In OTR mode, only + // few types of data are cleared and the rest is handled by deleting the + // browser state, so logging in these cases will render the histogram not + // useful. + if (!browser_state_->IsOffTheRecord()) { + base::TimeDelta delta = base::Time::Now() - task.task_started; + bool is_deletion_start_earliest = task.delete_begin.is_null(); + bool is_deletion_end_now = task.delete_end.is_max(); + if (is_deletion_start_earliest && is_deletion_end_now) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "History.ClearBrowsingData.Duration.FullDeletion", delta); + } else { + UMA_HISTOGRAM_MEDIUM_TIMES( + "History.ClearBrowsingData.Duration.PartialDeletion", delta); + } + } removal_queue_.pop(); // Schedule the task to be executed soon. This ensure that the IsRemoving()
diff --git a/ios/chrome/browser/browsing_data/browsing_data_remover_impl_unittest.mm b/ios/chrome/browser/browsing_data/browsing_data_remover_impl_unittest.mm index 54e1eb99..577acd18 100644 --- a/ios/chrome/browser/browsing_data/browsing_data_remover_impl_unittest.mm +++ b/ios/chrome/browser/browsing_data/browsing_data_remover_impl_unittest.mm
@@ -13,6 +13,7 @@ #include "base/run_loop.h" #include "base/scoped_observer.h" #import "base/test/ios/wait_util.h" +#include "base/test/metrics/histogram_tester.h" #include "components/open_from_clipboard/clipboard_recent_content.h" #include "components/open_from_clipboard/fake_clipboard_recent_content.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" @@ -26,6 +27,9 @@ #error "This file requires ARC support." #endif +using base::test::ios::WaitUntilConditionOrTimeout; +using base::test::ios::kWaitForActionTimeout; + namespace { // Flags passed when calling Remove(). Clear as much data as possible, avoiding @@ -45,6 +49,11 @@ BrowsingDataRemoveMask::REMOVE_VISITED_LINKS | BrowsingDataRemoveMask::REMOVE_LAST_USER_ACCOUNT; +const char kFullDeletionHistogram[] = + "History.ClearBrowsingData.Duration.FullDeletion"; +const char kPartialDeletionHistogram[] = + "History.ClearBrowsingData.Duration.PartialDeletion"; + // Observer used to validate that BrowsingDataRemoverImpl notifies its // observers. class TestBrowsingDataRemoverObserver : public BrowsingDataRemoverObserver { @@ -114,12 +123,11 @@ kRemoveMask, base::DoNothing()); TestBrowsingDataRemoverObserver* observer_ptr = &observer; - EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForActionTimeout, ^{ - // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. - base::RunLoop().RunUntilIdle(); - return observer_ptr->last_remove_mask() == kRemoveMask; - })); + EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ + // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. + base::RunLoop().RunUntilIdle(); + return observer_ptr->last_remove_mask() == kRemoveMask; + })); } // Tests that BrowsingDataRemoverImpl::Remove() can be called multiple times. @@ -134,12 +142,55 @@ --remaining_calls; })); - EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForActionTimeout, ^{ - // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. - base::RunLoop().RunUntilIdle(); - return remaining_calls == 0; - })); + EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ + // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. + base::RunLoop().RunUntilIdle(); + return remaining_calls == 0; + })); +} + +// Tests that BrowsingDataRemoverImpl::Remove() Logs the duration to the correct +// histogram for full deletion. +TEST_F(BrowsingDataRemoverImplTest, LogDurationForFullDeletion) { + base::HistogramTester histogram_tester; + __block int remaining_calls = 1; + histogram_tester.ExpectTotalCount(kFullDeletionHistogram, 0); + histogram_tester.ExpectTotalCount(kPartialDeletionHistogram, 0); + + browsing_data_remover_.Remove(browsing_data::TimePeriod::ALL_TIME, + kRemoveMask, base::BindOnce(^{ + --remaining_calls; + })); + EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ + // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. + base::RunLoop().RunUntilIdle(); + return remaining_calls == 0; + })); + + histogram_tester.ExpectTotalCount(kFullDeletionHistogram, 1); + histogram_tester.ExpectTotalCount(kPartialDeletionHistogram, 0); +} + +// Tests that BrowsingDataRemoverImpl::Remove() Logs the duration to the correct +// histogram for partial deletion. +TEST_F(BrowsingDataRemoverImplTest, LogDurationForPartialDeletion) { + base::HistogramTester histogram_tester; + __block int remaining_calls = 1; + histogram_tester.ExpectTotalCount(kFullDeletionHistogram, 0); + histogram_tester.ExpectTotalCount(kPartialDeletionHistogram, 0); + + browsing_data_remover_.Remove(browsing_data::TimePeriod::LAST_HOUR, + kRemoveMask, base::BindOnce(^{ + --remaining_calls; + })); + EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ + // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. + base::RunLoop().RunUntilIdle(); + return remaining_calls == 0; + })); + + histogram_tester.ExpectTotalCount(kFullDeletionHistogram, 0); + histogram_tester.ExpectTotalCount(kPartialDeletionHistogram, 1); } // Tests that BrowsingDataRemoverImpl::Remove() can finish performing its @@ -154,10 +205,9 @@ // Simulate destruction of BrowserState. browsing_data_remover_.Shutdown(); - EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForActionTimeout, ^{ - // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. - base::RunLoop().RunUntilIdle(); - return remaining_calls == 0; - })); + EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ + // Spin the RunLoop as WaitUntilConditionOrTimeout doesn't. + base::RunLoop().RunUntilIdle(); + return remaining_calls == 0; + })); }
diff --git a/ios/chrome/browser/infobars/infobar.mm b/ios/chrome/browser/infobars/infobar.mm index f68bbe1..b363de4 100644 --- a/ios/chrome/browser/infobars/infobar.mm +++ b/ios/chrome/browser/infobars/infobar.mm
@@ -31,6 +31,7 @@ InfoBarIOS::~InfoBarIOS() { DCHECK(controller_); [controller_ detachView]; + [controller_ setDelegate:nullptr]; controller_ = nil; }
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm index 0c6556985..f3da9ae8 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_client.mm
@@ -62,6 +62,7 @@ #include "ios/chrome/browser/unified_consent/feature.h" #include "ios/chrome/common/channel_info.h" #include "ios/web/public/web_thread.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -158,7 +159,7 @@ metrics::MetricsLogUploader::MetricServiceType service_type, const metrics::MetricsLogUploader::UploadCallback& on_upload_complete) { return std::make_unique<metrics::NetMetricsLogUploader>( - GetApplicationContext()->GetSystemURLRequestContext(), server_url, + GetApplicationContext()->GetSharedURLLoaderFactory(), server_url, insecure_server_url, mime_type, service_type, on_upload_complete); }
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn index b14479bc1..e24dab4 100644 --- a/ios/chrome/browser/ui/BUILD.gn +++ b/ios/chrome/browser/ui/BUILD.gn
@@ -345,6 +345,7 @@ "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/app_launcher", "//ios/chrome/browser/ui/authentication", + "//ios/chrome/browser/ui/authentication/consent_bump", "//ios/chrome/browser/ui/autofill:autofill", "//ios/chrome/browser/ui/bookmarks", "//ios/chrome/browser/ui/browser_container",
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index b188d4b6..c5afa910 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -42,6 +42,7 @@ "//components/signin/core/browser", "//components/signin/ios/browser", "//components/strings", + "//components/unified_consent", "//google_apis", "//ios/chrome/app/strings", "//ios/chrome/browser",
diff --git a/ios/chrome/browser/ui/authentication/authentication_constants.h b/ios/chrome/browser/ui/authentication/authentication_constants.h index 11e2ce8..7b67c717 100644 --- a/ios/chrome/browser/ui/authentication/authentication_constants.h +++ b/ios/chrome/browser/ui/authentication/authentication_constants.h
@@ -12,8 +12,8 @@ extern const CGFloat kAuthenticationHeaderImageWidth; // Font sizes -extern const CGFloat kAuthenticationTitleFontSize; -extern const CGFloat kAuthenticationTextFontSize; +extern const UIFontTextStyle kAuthenticationTitleFontStyle; +extern const UIFontTextStyle kAuthenticationTextFontStyle; // Color displayed in the non-safe area. extern const int kAuthenticationHeaderBackgroundColor;
diff --git a/ios/chrome/browser/ui/authentication/authentication_constants.mm b/ios/chrome/browser/ui/authentication/authentication_constants.mm index 3d7cace..8257d4c 100644 --- a/ios/chrome/browser/ui/authentication/authentication_constants.mm +++ b/ios/chrome/browser/ui/authentication/authentication_constants.mm
@@ -11,8 +11,8 @@ const CGFloat kAuthenticationHeaderImageHeight = 88.; const CGFloat kAuthenticationHeaderImageWidth = 360.; -const CGFloat kAuthenticationTitleFontSize = 23.; -const CGFloat kAuthenticationTextFontSize = 12.; +const UIFontTextStyle kAuthenticationTitleFontStyle = UIFontTextStyleTitle2; +const UIFontTextStyle kAuthenticationTextFontStyle = UIFontTextStyleCaption1; const int kAuthenticationHeaderBackgroundColor = 0xf8f9fa; const CGFloat kAuthenticationHorizontalMargin = 16.;
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm index 3ac9fad..ab76c9a 100644 --- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
@@ -22,6 +22,7 @@ #include "components/signin/core/browser/profile_management_switches.h" #include "components/signin/core/browser/signin_metrics.h" #include "components/strings/grit/components_strings.h" +#include "components/unified_consent/unified_consent_service.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/signin/account_tracker_service_factory.h" @@ -45,6 +46,7 @@ #import "ios/chrome/browser/ui/uikit_ui_util.h" #import "ios/chrome/browser/ui/util/label_link_controller.h" #include "ios/chrome/browser/unified_consent/feature.h" +#include "ios/chrome/browser/unified_consent/unified_consent_service_factory.h" #include "ios/chrome/common/string_util.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" @@ -296,6 +298,14 @@ - (void)acceptSignInAndCommitSyncChanges { DCHECK(_didSignIn); + if (_unifiedConsentEnabled) { + // The consent has to be given as soon as the user is signed in. Even when + // they open the settings through the link. + unified_consent::UnifiedConsentService* unifiedConsentService = + UnifiedConsentServiceFactory::GetForBrowserState(_browserState); + DCHECK(unifiedConsentService); + unifiedConsentService->SetUnifiedConsentGiven(true); + } SyncSetupServiceFactory::GetForBrowserState(_browserState)->CommitChanges(); [self acceptSignInAndShowAccountsSettings:_unifiedConsentCoordinator .settingsLinkWasTapped];
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/BUILD.gn b/ios/chrome/browser/ui/authentication/consent_bump/BUILD.gn index ffa5eed..4d5a260 100644 --- a/ios/chrome/browser/ui/authentication/consent_bump/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/consent_bump/BUILD.gn
@@ -19,9 +19,11 @@ ":consent_bump_ui", "//base", "//components/strings", + "//components/unified_consent", "//ios/chrome/app/strings", "//ios/chrome/browser/ui/authentication/unified_consent", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + "//ios/chrome/browser/unified_consent", "//ui/base", ] }
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h index 29d1aa2..9b7a49e 100644 --- a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h +++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h
@@ -7,6 +7,9 @@ #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" +namespace ios { +class ChromeBrowserState; +} // namespace ios @protocol ConsentBumpCoordinatorDelegate; // Coordinator handling the consent bump. @@ -18,6 +21,10 @@ // Delegate for this coordinator. @property(nonatomic, weak) id<ConsentBumpCoordinatorDelegate> delegate; +// Returns YES if the consent bump should be presented to the user. ++ (BOOL)shouldShowConsentBumpWithBrowserState: + (ios::ChromeBrowserState*)browserState; + @end #endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.mm index 775a726..c34573a 100644 --- a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.mm +++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.mm
@@ -5,12 +5,14 @@ #import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h" #include "base/logging.h" +#include "components/unified_consent/unified_consent_service.h" #import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator_delegate.h" #import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_mediator.h" #import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.h" #import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.h" #import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller_delegate.h" #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_coordinator.h" +#include "ios/chrome/browser/unified_consent/unified_consent_service_factory.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -46,6 +48,13 @@ @synthesize personalizationCoordinator = _personalizationCoordinator; @synthesize mediator = _mediator; ++ (BOOL)shouldShowConsentBumpWithBrowserState: + (ios::ChromeBrowserState*)browserState { + unified_consent::UnifiedConsentService* consent_service = + UnifiedConsentServiceFactory::GetForBrowserState(browserState); + return consent_service && consent_service->ShouldShowConsentBump(); +} + #pragma mark - Properties - (UIViewController*)viewController {
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm index 3a41b4a..1a33e27 100644 --- a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm
@@ -86,7 +86,7 @@ l10n_util::GetNSString(IDS_IOS_CONSENT_BUMP_PERSONALIZATION_TITLE); title.textColor = [UIColor colorWithWhite:0 alpha:kAuthenticationTitleColorAlpha]; - title.font = [UIFont systemFontOfSize:kAuthenticationTitleFontSize]; + title.font = [UIFont preferredFontForTextStyle:kAuthenticationTitleFontStyle]; title.numberOfLines = 0; [container addSubview:title]; @@ -97,7 +97,7 @@ l10n_util::GetNSString(IDS_IOS_CONSENT_BUMP_PERSONALIZATION_MESSAGE); text.textColor = [UIColor colorWithWhite:0 alpha:kAuthenticationTextColorAlpha]; - text.font = [UIFont systemFontOfSize:kAuthenticationTextFontSize]; + text.font = [UIFont preferredFontForTextStyle:kAuthenticationTextFontStyle]; text.numberOfLines = 0; [container addSubview:text];
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_header_item.mm b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_header_item.mm index 9ef77112..a41ae4c 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_header_item.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_header_item.mm
@@ -31,7 +31,6 @@ - (instancetype)initWithReuseIdentifier:(NSString*)reuseIdentifier { self = [super initWithReuseIdentifier:reuseIdentifier]; if (self) { - self.contentView.backgroundColor = UIColor.whiteColor; UILabel* label = [[UILabel alloc] init]; label.translatesAutoresizingMaskIntoConstraints = NO; label.text = @@ -53,6 +52,10 @@ @"V:|-(TopMargin)-[label]", ]; ApplyVisualConstraintsWithMetrics(constraints, views, metrics); + + self.isAccessibilityElement = YES; + self.accessibilityLabel = + l10n_util::GetNSString(IDS_IOS_ACCOUNT_IDENTITY_CHOOSER_CHOOSE_ACCOUNT); } return self; }
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm b/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm index f13ed8b..75ca9b0 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.mm
@@ -116,6 +116,10 @@ AddSameCenterYConstraint(self, _arrowDownImageView); AddSameCenterConstraints(_checkmarkImageView, _arrowDownImageView); ApplyVisualConstraintsWithMetrics(constraints, views, metrics); + + // Accessibility. + self.isAccessibilityElement = YES; + self.accessibilityTraits = UIAccessibilityTraitButton; } return self; } @@ -127,6 +131,8 @@ self.enabled = canChangeIdentity; self.arrowDownImageView.hidden = !canChangeIdentity; self.checkmarkImageView.hidden = canChangeIdentity; + self.accessibilityTraits = canChangeIdentity ? UIAccessibilityTraitButton + : UIAccessibilityTraitStaticText; } - (void)setIdentityAvatar:(UIImage*)identityAvatar { @@ -137,8 +143,11 @@ DCHECK(email); if (!name.length) { [self.identityView setTitle:email subtitle:nil]; + self.accessibilityLabel = email; } else { [self.identityView setTitle:name subtitle:email]; + self.accessibilityLabel = + [NSString stringWithFormat:@"%@, %@", name, email]; } }
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm index c80fa97..4954719 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
@@ -193,7 +193,7 @@ _consentStringIds.push_back(IDS_IOS_ACCOUNT_UNIFIED_CONSENT_TITLE); title.textColor = [UIColor colorWithWhite:0 alpha:kAuthenticationTitleColorAlpha]; - title.font = [UIFont systemFontOfSize:kAuthenticationTitleFontSize]; + title.font = [UIFont preferredFontForTextStyle:kAuthenticationTitleFontStyle]; title.numberOfLines = 0; [container addSubview:title]; @@ -374,7 +374,7 @@ DCHECK(parentView); UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; label.translatesAutoresizingMaskIntoConstraints = NO; - label.font = [UIFont systemFontOfSize:kAuthenticationTextFontSize]; + label.font = [UIFont preferredFontForTextStyle:kAuthenticationTextFontStyle]; label.text = l10n_util::GetNSString(stringId); _consentStringIds.push_back(stringId); label.textColor =
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index b5a3927..efa5474 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -117,6 +117,8 @@ #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/alert_coordinator/repost_form_coordinator.h" #import "ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h" +#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h" +#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator_delegate.h" #import "ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.h" #import "ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.h" #import "ios/chrome/browser/ui/background_generator.h" @@ -424,6 +426,7 @@ AppRatingPromptDelegate, BubblePresenterDelegate, CaptivePortalDetectorTabHelperDelegate, + ConsentBumpCoordinatorDelegate, CRWNativeContentProvider, CRWWebStateDelegate, DialogPresenterDelegate, @@ -737,6 +740,9 @@ // Whether the safe area insets should be used to adjust the viewport. @property(nonatomic, readonly) BOOL usesSafeInsetsForViewportAdjustments; +// Coordinator to ask the user for the new consent. +@property(nonatomic, strong) ConsentBumpCoordinator* consentBumpCoordinator; + // BVC initialization // ------------------ // If the BVC is initialized with a valid browser state & tab model immediately, @@ -944,6 +950,7 @@ // DialogPresenterDelegate property @synthesize dialogPresenterDelegateIsPresenting = _dialogPresenterDelegateIsPresenting; +@synthesize consentBumpCoordinator = _consentBumpCoordinator; #pragma mark - Object lifecycle @@ -5046,6 +5053,21 @@ } } +- (void)showConsentBumpIfNeeded { + DCHECK(!self.consentBumpCoordinator); + if (![ConsentBumpCoordinator + shouldShowConsentBumpWithBrowserState:_browserState]) { + return; + } + self.consentBumpCoordinator = + [[ConsentBumpCoordinator alloc] initWithBaseViewController:self]; + self.consentBumpCoordinator.delegate = self; + [self.consentBumpCoordinator start]; + [self presentViewController:self.consentBumpCoordinator.viewController + animated:YES + completion:nil]; +} + #pragma mark - ToolbarOwner (Public) - (CGRect)toolbarFrame { @@ -5972,4 +5994,20 @@ [self.dispatcher showSignin:command baseViewController:self]; } +#pragma mark - ConsentBumpCoordinatorDelegate + +- (void)consentBumpCoordinator:(ConsentBumpCoordinator*)coordinator + didFinishNeedingToShowSettings:(BOOL)shouldShowSettings { + DCHECK(self.consentBumpCoordinator); + DCHECK(self.consentBumpCoordinator.viewController); + [self.consentBumpCoordinator.viewController + dismissViewControllerAnimated:YES + completion:nil]; + self.consentBumpCoordinator = nil; + if (shouldShowSettings) { + // TODO(crbug.com/827072): Needs to open the sync and Google services + // panel from the settings. + } +} + @end
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index 944ec99..8deedff2 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -119,6 +119,9 @@ // Prepares the browser to display a popup menu. - (void)prepareForPopupMenuPresentation:(PopupMenuCommandType)type; +// Shows the consent bump if it is required. +- (void)showConsentBumpIfNeeded; + @end #endif // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h index 61f0ff4..f445df7 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h
@@ -8,6 +8,7 @@ #include <memory> #include "ios/web/public/web_state/web_state_observer.h" +#include "url/gurl.h" class FullscreenController; class FullscreenMediator; @@ -52,6 +53,8 @@ std::unique_ptr<ScopedFullscreenDisabler> ssl_disabler_; // The disabler for loading. std::unique_ptr<ScopedFullscreenDisabler> loading_disabler_; + // The URL received in the NavigationContext of the last finished navigation. + GURL last_navigation_url_; }; #endif // IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_WEB_STATE_OBSERVER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm index 1ce7a5d..a67c76f 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm
@@ -13,6 +13,7 @@ #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/ssl_status.h" +#include "ios/web/public/url_util.h" #import "ios/web/public/web_state/navigation_context.h" #import "ios/web/public/web_state/ui/crw_web_view_proxy.h" #import "ios/web/public/web_state/web_state.h" @@ -81,6 +82,10 @@ void FullscreenWebStateObserver::DidFinishNavigation( web::WebState* web_state, web::NavigationContext* navigation_context) { + const GURL& navigation_url = navigation_context->GetUrl(); + bool url_changed = web::GURLByRemovingRefFromGURL(navigation_url) != + web::GURLByRemovingRefFromGURL(last_navigation_url_); + last_navigation_url_ = navigation_url; // Due to limitations in WKWebView's rendering, different MIME types must be // inset using different techniques: // - PDFs need to be inset using the scroll view's |contentInset| property or @@ -94,9 +99,9 @@ web_state->GetWebViewProxy().shouldUseViewContentInset = force_content_inset || web_state->GetContentsMimeType() == "application/pdf"; - // Reset the model so that the toolbar is visible when navigating to a new - // document. - if (!navigation_context->IsSameDocument()) + // Only reset the model for document-changing navigations or same-document + // navigations that update the visible URL. + if (!navigation_context->IsSameDocument() || url_changed) model_->ResetForNavigation(); // Disable fullscreen if there is a problem with the SSL status. SetDisableFullscreenForSSL(ShouldDisableFullscreenForWebStateSSL(web_state));
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm index 062211df..35a21caf 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm
@@ -71,19 +71,60 @@ EXPECT_EQ(model().progress(), 1.0); } -// Tests that the FullscreenModel is not reset for a same-document navigation. -TEST_F(FullscreenWebStateObserverTest, NoResetForSameDocument) { +// Tests that the FullscreenModel is not reset for same-document navigations +// with the same URL. +TEST_F(FullscreenWebStateObserverTest, NoResetForSameDocumentSameURL) { + // Navigate to a URL. + web::FakeNavigationContext context; + context.SetUrl(GURL("https://www.test.com")); + web_state().OnNavigationFinished(&context); + model().SetYContentOffset(0.0); // Simulate a scroll to 0.5 progress. SimulateFullscreenUserScrollForProgress(&model(), 0.5); EXPECT_EQ(model().progress(), 0.5); - // Simulate a same-document navigation and verify that the 0.5 progress hasn't - // been reset to 1.0. - web::FakeNavigationContext context; + // Simulate a same-document navigation to the same URL and verify that the 0.5 + // progress hasn't been reset to 1.0. context.SetIsSameDocument(true); web_state().OnNavigationFinished(&context); EXPECT_EQ(model().progress(), 0.5); } +// Tests that the FullscreenModel is not reset for a same-document navigation. +TEST_F(FullscreenWebStateObserverTest, NoResetForSameDocumentFragmentChange) { + // Navigate to a URL. + web::FakeNavigationContext context; + context.SetUrl(GURL("https://www.test.com")); + web_state().OnNavigationFinished(&context); + model().SetYContentOffset(0.0); + // Simulate a scroll to 0.5 progress. + SimulateFullscreenUserScrollForProgress(&model(), 0.5); + EXPECT_EQ(model().progress(), 0.5); + // Simulate a same-document navigation to a URL with a different fragment and + // verify that the 0.5 progress hasn't been reset to 1.0. + context.SetUrl(GURL("https://www.test.com#fragment")); + context.SetIsSameDocument(true); + web_state().OnNavigationFinished(&context); + EXPECT_EQ(model().progress(), 0.5); +} + +// Tests that the FullscreenModel is not reset for a same-document navigation. +TEST_F(FullscreenWebStateObserverTest, ResetForSameDocumentURLChange) { + // Navigate to a URL. + web::FakeNavigationContext context; + context.SetUrl(GURL("https://www.test.com")); + web_state().OnNavigationFinished(&context); + model().SetYContentOffset(0.0); + // Simulate a scroll to 0.5 progress. + SimulateFullscreenUserScrollForProgress(&model(), 0.5); + EXPECT_EQ(model().progress(), 0.5); + // Simulate a same-document navigation to a new URL and verify that the 0.5 + // progress is reset to 1.0. + context.SetUrl(GURL("https://www.test2.com")); + context.SetIsSameDocument(true); + web_state().OnNavigationFinished(&context); + EXPECT_EQ(model().progress(), 1.0); +} + // Tests that the model is disabled when a load is occurring. TEST_F(FullscreenWebStateObserverTest, DisableDuringLoadWithUIRefreshDisabled) { base::test::ScopedFeatureList scoped_feature_list;
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 377e54e..3939e7b8 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -42,13 +42,13 @@ "dataplan_usage_collection_view_controller.mm", "do_not_track_collection_view_controller.h", "do_not_track_collection_view_controller.mm", - "google_services_settings_command_handler.h", "google_services_settings_consumer.h", "google_services_settings_coordinator.h", "google_services_settings_coordinator.mm", "google_services_settings_local_commands.h", "google_services_settings_mediator.h", "google_services_settings_mediator.mm", + "google_services_settings_service_delegate.h", "google_services_settings_view_controller.h", "google_services_settings_view_controller.mm", "google_services_settings_view_controller_model_delegate.h",
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm index d3f107c..287a2b5 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm +++ b/ios/chrome/browser/ui/settings/google_services_settings_coordinator.mm
@@ -16,6 +16,7 @@ #import "ios/chrome/browser/ui/settings/google_services_settings_local_commands.h" #import "ios/chrome/browser/ui/settings/google_services_settings_mediator.h" #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller.h" +#include "ios/chrome/browser/unified_consent/unified_consent_service_factory.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -39,26 +40,29 @@ - (void)start { UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; - GoogleServicesSettingsViewController* controller = + GoogleServicesSettingsViewController* viewController = [[GoogleServicesSettingsViewController alloc] initWithLayout:layout style:CollectionViewControllerStyleAppBar]; - controller.presentationDelegate = self; - controller.localDispatcher = self; - self.viewController = controller; + viewController.presentationDelegate = self; + viewController.localDispatcher = self; + self.viewController = viewController; SyncSetupService* syncSetupService = SyncSetupServiceFactory::GetForBrowserState(self.browserState); browser_sync::ProfileSyncService* syncService = ProfileSyncServiceFactory::GetForBrowserState(self.browserState); + unified_consent::UnifiedConsentService* unifiedConsentService = + UnifiedConsentServiceFactory::GetForBrowserState(self.browserState); self.mediator = [[GoogleServicesSettingsMediator alloc] - initWithPrefService:self.browserState->GetPrefs() - syncService:syncService - syncSetupService:syncSetupService]; - self.mediator.consumer = controller; + initWithPrefService:self.browserState->GetPrefs() + syncService:syncService + syncSetupService:syncSetupService + unifiedConsentService:unifiedConsentService]; + self.mediator.consumer = viewController; self.mediator.authService = AuthenticationServiceFactory::GetForBrowserState(self.browserState); - controller.modelDelegate = self.mediator; - controller.commandHandler = self.mediator; + viewController.modelDelegate = self.mediator; + viewController.serviceDelegate = self.mediator; DCHECK(self.navigationController); [self.navigationController pushViewController:self.viewController animated:YES];
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm index cfd671dd..b043652 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/google_services_settings_egtest.mm
@@ -98,7 +98,8 @@ EARL_GREY_TEST_SKIPPED(@"This test is UIRefresh only."); [SigninEarlGreyUI signinWithIdentity:[SigninEarlGreyUtils fakeIdentity1]]; PrefService* prefService = GetOriginalBrowserState()->GetPrefs(); - prefService->SetBoolean(kUnifiedConsentGiven, true); + GREYAssert(prefService->GetBoolean(kUnifiedConsentGiven), + @"Unified consent should be given"); [self openGoogleServicesSettings]; [self assertSyncEverythingSection]; [self assertPersonalizedServicesCollapsed:YES]; @@ -205,13 +206,18 @@ [NSString stringWithFormat:@"%@, %@", accessibilityLabel, GetNSString(detailTextID)]; } - return [[EarlGrey - selectElementWithMatcher:grey_allOf( - grey_accessibilityLabel(accessibilityLabel), - grey_kindOfClass( - [UICollectionViewCell class]), - grey_sufficientlyVisible(), nil)] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 150) + id<GREYMatcher> cellMatcher = + grey_allOf(grey_accessibilityLabel(accessibilityLabel), + grey_kindOfClass([UICollectionViewCell class]), + grey_sufficientlyVisible(), nil); + // Needs to scroll slowly to make sure to not miss a cell if it is not + // currently on the screen. It should not be bigger than the visible part + // of the collection view. + const CGFloat kPixelsToScroll = 300; + id<GREYAction> searchAction = + grey_scrollInDirection(kGREYDirectionDown, kPixelsToScroll); + return [[EarlGrey selectElementWithMatcher:cellMatcher] + usingSearchAction:searchAction onElementWithMatcher:self.scrollViewMatcher]; }
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_mediator.h b/ios/chrome/browser/ui/settings/google_services_settings_mediator.h index 1703b34..7f0955b 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_mediator.h +++ b/ios/chrome/browser/ui/settings/google_services_settings_mediator.h
@@ -7,8 +7,8 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/settings/google_services_settings_command_handler.h" #import "ios/chrome/browser/ui/settings/google_services_settings_consumer.h" +#import "ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h" #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller.h" #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller_model_delegate.h" @@ -20,10 +20,13 @@ namespace browser_sync { class ProfileSyncService; }; +namespace unified_consent { +class UnifiedConsentService; +} // namespace unified_consent // Mediator for the Google services settings. @interface GoogleServicesSettingsMediator - : NSObject<GoogleServicesSettingsCommandHandler, + : NSObject<GoogleServicesSettingsServiceDelegate, GoogleServicesSettingsViewControllerModelDelegate> // View controller. @@ -37,6 +40,8 @@ syncService: (browser_sync::ProfileSyncService*)syncService syncSetupService:(SyncSetupService*)syncSetupService + unifiedConsentService: + (unified_consent::UnifiedConsentService*)unifiedConsentService NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm index 8c876f6..af64b70 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm +++ b/ios/chrome/browser/ui/settings/google_services_settings_mediator.mm
@@ -11,6 +11,7 @@ #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" #include "components/unified_consent/pref_names.h" +#include "components/unified_consent/unified_consent_service.h" #import "ios/chrome/browser/signin/authentication_service.h" #import "ios/chrome/browser/signin/authentication_service_factory.h" #include "ios/chrome/browser/sync/sync_observer_bridge.h" @@ -84,6 +85,9 @@ std::unique_ptr<SyncObserverBridge> _syncObserver; } +// Unified consent service. +@property(nonatomic, assign) + unified_consent::UnifiedConsentService* unifiedConsentService; // Returns YES if the user is authenticated. @property(nonatomic, assign, readonly) BOOL isAuthenticated; // Returns YES if the user has given his consent to use Google services. @@ -116,6 +120,7 @@ @implementation GoogleServicesSettingsMediator +@synthesize unifiedConsentService = _unifiedConsentService; @synthesize consumer = _consumer; @synthesize authService = _authService; @synthesize prefService = _prefService; @@ -132,17 +137,21 @@ #pragma mark - Load model -- (instancetype)initWithPrefService:(PrefService*)prefService - syncService: - (browser_sync::ProfileSyncService*)syncService - syncSetupService:(SyncSetupService*)syncSetupService { +- (instancetype) + initWithPrefService:(PrefService*)prefService + syncService:(browser_sync::ProfileSyncService*)syncService + syncSetupService:(SyncSetupService*)syncSetupService +unifiedConsentService: + (unified_consent::UnifiedConsentService*)unifiedConsentService { self = [super init]; if (self) { DCHECK(prefService); DCHECK(syncService); DCHECK(syncSetupService); + DCHECK(unifiedConsentService); _prefService = prefService; _syncSetupService = syncSetupService; + _unifiedConsentService = unifiedConsentService; _syncObserver.reset(new SyncObserverBridge(self, syncService)); prefObserverBridge_ = std::make_unique<PrefObserverBridge>(self); prefChangeRegistrar_.Init(prefService); @@ -207,7 +216,7 @@ } - (BOOL)isConsentGiven { - return self.prefService->GetBoolean(kUnifiedConsentGiven); + return self.unifiedConsentService->IsUnifiedConsentGiven(); } - (CollectionViewItem*)syncEverythingItem { @@ -496,14 +505,14 @@ [self loadNonPersonalizedSection]; } -#pragma mark - GoogleServicesSettingsCommandHandler +#pragma mark - GoogleServicesSettingsServiceDelegate - (void)toggleSyncEverythingWithValue:(BOOL)value { if (value == self.isConsentGiven) return; // Mark the switch has being animated to avoid being reloaded. base::AutoReset<BOOL> autoReset(&_syncEverythingSwitchBeingAnimated, YES); - self.prefService->SetBoolean(kUnifiedConsentGiven, value); + self.unifiedConsentService->SetUnifiedConsentGiven(value); } - (void)toggleSyncDataSync:(NSInteger)dataTypeInt withValue:(BOOL)value {
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_command_handler.h b/ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h similarity index 95% rename from ios/chrome/browser/ui/settings/google_services_settings_command_handler.h rename to ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h index f3a0032f..fb7bcd16 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_command_handler.h +++ b/ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SETTINGS_COMMAND_HANDLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SETTINGS_COMMAND_HANDLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SETTINGS_SERVICE_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SETTINGS_SERVICE_DELEGATE_H_ // List of Google Services Settings commands. typedef NS_ENUM(NSInteger, GoogleServicesSettingsCommandID) { @@ -34,7 +34,7 @@ }; // Protocol to handle Google services settings commands. -@protocol GoogleServicesSettingsCommandHandler<NSObject> +@protocol GoogleServicesSettingsServiceDelegate<NSObject> // Called when GoogleServicesSettingsCommandIDToggleSyncEverything is triggered. - (void)toggleSyncEverythingWithValue:(BOOL)value; @@ -60,4 +60,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SETTINGS_COMMAND_HANDLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_SETTINGS_SERVICE_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_view_controller.h b/ios/chrome/browser/ui/settings/google_services_settings_view_controller.h index 22b1f69..27b0026 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_view_controller.h +++ b/ios/chrome/browser/ui/settings/google_services_settings_view_controller.h
@@ -10,7 +10,7 @@ #import "ios/chrome/browser/ui/settings/google_services_settings_consumer.h" @class GoogleServicesSettingsViewController; -@protocol GoogleServicesSettingsCommandHandler; +@protocol GoogleServicesSettingsServiceDelegate; @protocol GoogleServicesSettingsLocalCommands; @protocol GoogleServicesSettingsViewControllerModelDelegate; @@ -36,8 +36,8 @@ @property(nonatomic, weak) id<GoogleServicesSettingsViewControllerModelDelegate> modelDelegate; // Handler for GoogleServicesSettingsCommand. -@property(nonatomic, weak) id<GoogleServicesSettingsCommandHandler> - commandHandler; +@property(nonatomic, weak) id<GoogleServicesSettingsServiceDelegate> + serviceDelegate; // Local command dispatcher. @property(nonatomic, weak) id<GoogleServicesSettingsLocalCommands> localDispatcher;
diff --git a/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm b/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm index b386b175..cef94c6 100644 --- a/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm +++ b/ios/chrome/browser/ui/settings/google_services_settings_view_controller.mm
@@ -10,8 +10,8 @@ #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_collapsible_item.h" #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h" -#import "ios/chrome/browser/ui/settings/google_services_settings_command_handler.h" #import "ios/chrome/browser/ui/settings/google_services_settings_local_commands.h" +#import "ios/chrome/browser/ui/settings/google_services_settings_service_delegate.h" #import "ios/chrome/browser/ui/settings/google_services_settings_view_controller_model_delegate.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -32,7 +32,7 @@ @synthesize presentationDelegate = _presentationDelegate; @synthesize modelDelegate = _modelDelegate; -@synthesize commandHandler = _commandHandler; +@synthesize serviceDelegate = _serviceDelegate; @synthesize localDispatcher = _localDispatcher; - (instancetype)initWithLayout:(UICollectionViewLayout*)layout @@ -104,23 +104,23 @@ static_cast<GoogleServicesSettingsCommandID>(syncSwitchItem.commandID); switch (commandID) { case GoogleServicesSettingsCommandIDToggleSyncEverything: - [self.commandHandler toggleSyncEverythingWithValue:isOn]; + [self.serviceDelegate toggleSyncEverythingWithValue:isOn]; break; case GoogleServicesSettingsCommandIDToggleDataTypeSync: - [self.commandHandler toggleSyncDataSync:syncSwitchItem.dataType - withValue:isOn]; + [self.serviceDelegate toggleSyncDataSync:syncSwitchItem.dataType + withValue:isOn]; break; case GoogleServicesSettingsCommandIDToggleAutocompleteSearchesService: - [self.commandHandler toggleAutocompleteSearchesServiceWithValue:isOn]; + [self.serviceDelegate toggleAutocompleteSearchesServiceWithValue:isOn]; break; case GoogleServicesSettingsCommandIDTogglePreloadPagesService: - [self.commandHandler togglePreloadPagesServiceWithValue:isOn]; + [self.serviceDelegate togglePreloadPagesServiceWithValue:isOn]; break; case GoogleServicesSettingsCommandIDToggleImproveChromeService: - [self.commandHandler toggleImproveChromeServiceWithValue:isOn]; + [self.serviceDelegate toggleImproveChromeServiceWithValue:isOn]; break; case GoogleServicesSettingsCommandIDToggleBetterSearchAndBrowsingService: - [self.commandHandler toggleBetterSearchAndBrowsingServiceWithValue:isOn]; + [self.serviceDelegate toggleBetterSearchAndBrowsingServiceWithValue:isOn]; break; case GoogleServicesSettingsCommandIDNoOp: case GoogleServicesSettingsCommandIDOpenGoogleActivityControlsDialog:
diff --git a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm index 50820db..36ca586 100644 --- a/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password_details_collection_view_controller.mm
@@ -634,6 +634,7 @@ CollectionViewItem* item = [self.collectionViewModel itemAtIndexPath:indexPath]; switch (item.type) { + case ItemTypeSite: case ItemTypeUsername: case ItemTypePassword: return [MDCCollectionViewCell
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 583fe530..4222789 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -1652,6 +1652,19 @@ BindToCurrentLoop(base::BindRepeating( &WebMediaPlayerImpl::OnFrameSinkDestroyed, AsWeakPtr())))); bridge_->SetContentsOpaque(opaque_); + + // If the element is already in Picture-in-Picture mode, it means that it + // was set in this mode prior to this load, with a different + // WebMediaPlayerImpl. The new player needs to send its id, size and + // surface id to the browser process to make sure the states are properly + // updated. + // TODO(872056): the surface should be activated but for some reasons, it + // does not. It is possible that this will no longer be neded after 872056 + // is fixed. + if (client_->DisplayType() == + WebMediaPlayer::DisplayType::kPictureInPicture) { + OnSurfaceIdUpdated(bridge_->GetSurfaceId()); + } } }
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc index ace97d8..74e74d8a 100644 --- a/media/gpu/android/media_codec_video_decoder.cc +++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -755,6 +755,16 @@ // the codec isn't already draining. drain_type_ = drain_type; + // We can safely invalidate outstanding buffers for both types of drain, and + // doing so can only make the drain complete quicker. Note that we do this + // even if we're eliding the drain, since we're either going to flush the + // codec or destroy it. While we're not required to do this, it might affect + // stability if we don't (https://crbug.com/869365). AVDA, in particular, + // dropped all pending codec output buffers when starting a reset (seek) or + // a destroy. + if (codec_) + codec_->DiscardOutputBuffers(); + // Skip the drain if possible. Only VP8 codecs need draining because // they can hang in release() or flush() otherwise // (http://crbug.com/598963). @@ -770,9 +780,6 @@ if (!codec_->IsDraining()) pending_decodes_.push_back(PendingDecode::CreateEos()); - // We can safely invalidate outstanding buffers for both types of drain, and - // doing so can only make the drain complete quicker. - codec_->DiscardOutputBuffers(); PumpCodec(true); }
diff --git a/mojo/public/cpp/bindings/lib/control_message_proxy.cc b/mojo/public/cpp/bindings/lib/control_message_proxy.cc index 5e6c3808..aeb5026 100644 --- a/mojo/public/cpp/bindings/lib/control_message_proxy.cc +++ b/mojo/public/cpp/bindings/lib/control_message_proxy.cc
@@ -127,7 +127,12 @@ : receiver_(receiver) { } -ControlMessageProxy::~ControlMessageProxy() = default; +ControlMessageProxy::~ControlMessageProxy() { + // If this is destroyed in the middle of a flush, make sure the callback is + // still run. + if (!pending_flush_callback_.is_null()) + RunFlushForTestingClosure(); +} void ControlMessageProxy::QueryVersion( const base::Callback<void(uint32_t)>& callback) {
diff --git a/net/BUILD.gn b/net/BUILD.gn index 52af8ae..be36d39 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -5259,7 +5259,7 @@ data += [ "tools/testserver/", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", "$root_out_dir/pyproto/google/", ]
diff --git a/net/base/network_change_notifier_fuchsia_unittest.cc b/net/base/network_change_notifier_fuchsia_unittest.cc index 6a4ce587..67bd849 100644 --- a/net/base/network_change_notifier_fuchsia_unittest.cc +++ b/net/base/network_change_notifier_fuchsia_unittest.cc
@@ -152,6 +152,11 @@ fuchsia::netstack::NetAddress addr, uint8_t prefixLen, SetInterfaceAddressCallback callback) override {} + void RemoveInterfaceAddress( + uint32_t nicid, + fuchsia::netstack::NetAddress addr, + uint8_t prefixLen, + RemoveInterfaceAddressCallback callback) override {} void SetDhcpClientStatus(uint32_t nicid, bool enabled, SetDhcpClientStatusCallback callback) override {}
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 9bcf4c3..afd1792 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -65,7 +65,8 @@ "static_spki_hashes": [ "GoogleBackup2048", "GoogleG2", - "GeoTrustGlobal", + "GoogleG3", + "GTSCA1O1", "GlobalSignRootCA_R2" ], "report_uri": "http://clients3.google.com/cert_upload_json"
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index 23216f0..8415ee28 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -109,6 +109,61 @@ wSHGFg== -----END CERTIFICATE----- +GoogleG3 +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgINAeOpMBz8cgY4P5pTHTANBgkqhkiG9w0BAQsFADBMMSAw +HgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFs +U2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAwNDJaFw0yMTEy +MTUwMDAwNDJaMFQxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVHb29nbGUgVHJ1c3Qg +U2VydmljZXMxJTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzMw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKUkvqHv/OJGuo2nIYaNVW +XQ5IWi01CXZaz6TIHLGp/lOJ+600/4hbn7vn6AAB3DVzdQOts7G5pH0rJnnOFUAK +71G4nzKMfHCGUksW/mona+Y2emJQ2N+aicwJKetPKRSIgAuPOB6Aahh8Hb2XO3h9 +RUk2T0HNouB2VzxoMXlkyW7XUR5mw6JkLHnA52XDVoRTWkNty5oCINLvGmnRsJ1z +ouAqYGVQMc/7sy+/EYhALrVJEA8KbtyX+r8snwU5C1hUrwaW6MWOARa8qBpNQcWT +kaIeoYvy/sGIJEmjR0vFEwHdp1cSaWIr6/4g72n7OqXwfinu7ZYW97EfoOSQJeAz +AgMBAAGjggEzMIIBLzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUH +AwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFHfCuFCa +Z3Z2sS3ChtCDoH6mfrpLMB8GA1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd/cGYYu +MDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdv +b2cvZ3NyMjAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29nL2dz +cjIvZ3NyMi5jcmwwPwYDVR0gBDgwNjA0BgZngQwBAgIwKjAoBggrBgEFBQcCARYc +aHR0cHM6Ly9wa2kuZ29vZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEA +HLeJluRT7bvs26gyAZ8so81trUISd7O45skDUmAge1cnxhG1P2cNmSxbWsoiCt2e +ux9LSD+PAj2LIYRFHW31/6xoic1k4tbWXkDCjir37xTTNqRAMPUyFRWSdvt+nlPq +wnb8Oa2I/maSJukcxDjNSfpDh/Bd1lZNgdd/8cLdsE3+wypufJ9uXO1iQpnh9zbu +FIwsIONGl1p3A8CgxkqI/UAih3JaGOqcpcdaCIzkBaR9uYQ1X4k2Vg5APRLouzVy +7a8IVk6wuy6pm+T7HT4LY8ibS5FEZlfAFLSW8NwsVz9SBK2Vqn1N0PIMn5xA6NZV +c7o835DLAFshEWfC7TIe3g== +-----END CERTIFICATE----- + +GTSCA1O1 +-----BEGIN CERTIFICATE----- +MIIESjCCAzKgAwIBAgINAeO0mqGNiqmBJWlQuDANBgkqhkiG9w0BAQsFADBMMSAw +HgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFs +U2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAwNDJaFw0yMTEy +MTUwMDAwNDJaMEIxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVHb29nbGUgVHJ1c3Qg +U2VydmljZXMxEzARBgNVBAMTCkdUUyBDQSAxTzEwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDQGM9F1IvN05zkQO9+tN1pIRvJzzyOTHW5DzEZhD2ePCnv +UA0Qk28FgICfKqC9EksC4T2fWBYk/jCfC3R3VZMdS/dN4ZKCEPZRrAzDsiKUDzRr +mBBJ5wudgzndIMYcLe/RGGFl5yODIKgjEv/SJH/UL+dEaltN11BmsK+eQmMF++Ac +xGNhr59qM/9il71I2dN8FGfcddwuaej4bXhp0LcQBbjxMcI7JP0aM3T4I+DsaxmK +FsbjzaTNC9uzpFlgOIg7rR25xoynUxv8vNmkq7zdPGHXkxWY7oG9j+JkRyBABk7X +rJfoucBZEqFJJSPk7XA0LKW0Y3z5oz2D0c1tJKwHAgMBAAGjggEzMIIBLzAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFJjR+G4Q68+b7GCfGJAboOt9Cf0rMB8G +A1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd/cGYYuMDUGCCsGAQUFBwEBBCkwJzAl +BggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdvb2cvZ3NyMjAyBgNVHR8EKzAp +MCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29nL2dzcjIvZ3NyMi5jcmwwPwYDVR0g +BDgwNjA0BgZngQwBAgIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly9wa2kuZ29vZy9y +ZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAGoA+Nnn78y6pRjd9XlQWNa7H +TgiZ/r3RNGkmUmYHPQq6Scti9PEajvwRT2iWTHQr02fesqOqBY2ETUwgZQ+lltoN +FvhsO9tvBCOIazpswWC9aJ9xju4tWDQH8NVU6YZZ/XteDSGU9YzJqPjY8q3MDxrz +mqepBCf5o8mw/wJ4a2G6xzUr6Fb6T8McDO22PLRL6u3M4Tzs3A2M1j6bykJYi8wW +IRdAvKLWZu/axBVbzYmqmwkm5zLSDW5nIAJbELCQCZwMH56t2Dvqofxs6BBcCFIZ +USpxu6x6td0V7SvJCCosirSmIatj/9dSSVDQibet8q/7UK4v4ZUN80atnZz1yg== +-----END CERTIFICATE----- + GeoTrustGlobal -----BEGIN CERTIFICATE----- MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
diff --git a/net/proxy_resolution/proxy_config_service_android.cc b/net/proxy_resolution/proxy_config_service_android.cc index cbc0a904..8c5ee731 100644 --- a/net/proxy_resolution/proxy_config_service_android.cc +++ b/net/proxy_resolution/proxy_config_service_android.cc
@@ -211,7 +211,8 @@ network_task_runner_(network_task_runner), jni_task_runner_(jni_task_runner), get_property_callback_(get_property_callback), - exclude_pac_url_(false) { + exclude_pac_url_(false), + has_proxy_override_(false) { } void SetupJNI() { @@ -265,6 +266,9 @@ // Called in the JNI sequence. void ProxySettingsChanged() { DCHECK(InJNISequence()); + if (has_proxy_override_) + return; + ProxyConfigWithAnnotation proxy_config; GetLatestProxyConfigInternal(get_property_callback_, &proxy_config); network_task_runner_->PostTask( @@ -278,6 +282,9 @@ const std::string& pac_url, const std::vector<std::string>& exclusion_list) { DCHECK(InJNISequence()); + if (has_proxy_override_) + return; + ProxyConfigWithAnnotation proxy_config; if (exclude_pac_url_) { CreateStaticProxyConfig(host, port, "", exclusion_list, &proxy_config); @@ -294,6 +301,33 @@ exclude_pac_url_ = enabled; } + // Called in the JNI sequence. + void SetProxyOverride(const std::string& host, + int port, + const std::vector<std::string>& exclusion_list) { + DCHECK(InJNISequence()); + has_proxy_override_ = true; + ProxyConfigWithAnnotation proxy_config; + CreateStaticProxyConfig(host, port, "", exclusion_list, &proxy_config); + network_task_runner_->PostTask( + FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this, + proxy_config)); + } + + // Called in the JNI sequence. + void ClearProxyOverride() { + DCHECK(InJNISequence()); + if (!has_proxy_override_) + return; + + ProxyConfigWithAnnotation proxy_config; + GetLatestProxyConfigInternal(get_property_callback_, &proxy_config); + network_task_runner_->PostTask( + FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this, + proxy_config)); + has_proxy_override_ = false; + } + private: friend class base::RefCountedThreadSafe<Delegate>; @@ -365,6 +399,8 @@ GetPropertyCallback get_property_callback_; ProxyConfigWithAnnotation proxy_config_; bool exclude_pac_url_; + // This may only be accessed or modified on the JNI thread + bool has_proxy_override_; DISALLOW_COPY_AND_ASSIGN(Delegate); }; @@ -414,4 +450,15 @@ delegate_->ProxySettingsChanged(); } +void ProxyConfigServiceAndroid::SetProxyOverride( + const std::string& host, + int port, + const std::vector<std::string>& exclusion_list) { + delegate_->SetProxyOverride(host, port, exclusion_list); +} + +void ProxyConfigServiceAndroid::ClearProxyOverride() { + delegate_->ClearProxyOverride(); +} + } // namespace net
diff --git a/net/proxy_resolution/proxy_config_service_android.h b/net/proxy_resolution/proxy_config_service_android.h index fd2729d..ed70a5df 100644 --- a/net/proxy_resolution/proxy_config_service_android.h +++ b/net/proxy_resolution/proxy_config_service_android.h
@@ -76,6 +76,11 @@ ConfigAvailability GetLatestProxyConfig( ProxyConfigWithAnnotation* config) override; + void SetProxyOverride(const std::string& host, + int port, + const std::vector<std::string>& exclusion_list); + void ClearProxyOverride(); + private: friend class ProxyConfigServiceAndroidTestBase; class Delegate;
diff --git a/net/proxy_resolution/proxy_config_service_android_unittest.cc b/net/proxy_resolution/proxy_config_service_android_unittest.cc index 859019a..8c89180 100644 --- a/net/proxy_resolution/proxy_config_service_android_unittest.cc +++ b/net/proxy_resolution/proxy_config_service_android_unittest.cc
@@ -110,6 +110,18 @@ EXPECT_EQ(expected, proxy_info.ToPacString()); } + void SetProxyOverride(const std::string& host, + int port, + const std::vector<std::string>& exclusion_list) { + service_.SetProxyOverride(host, port, exclusion_list); + base::RunLoop().RunUntilIdle(); + } + + void ClearProxyOverride() { + service_.ClearProxyOverride(); + base::RunLoop().RunUntilIdle(); + } + StringMap configuration_; TestObserver observer_; // |java_looper_preparer_| appears before |service_| so that Java's Looper is @@ -166,6 +178,124 @@ TestMapping("http://example.com/", "PROXY httpproxy.com:80"); } +TEST_F(ProxyConfigServiceAndroidTest, TestOverrideNoProxy) { + std::vector<std::string> exclusion_list; + + // Check that webview uses the default proxy + TestMapping("http://example.com/", "DIRECT"); + + // Check that webview uses the custom proxy + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); + + // Check that webview uses the default proxy + ClearProxyOverride(); + TestMapping("http://example.com/", "DIRECT"); +} + +TEST_F(ProxyConfigServiceAndroidTest, TestOverrideAndProxy) { + std::vector<std::string> exclusion_list; + + // Check that webview uses the default proxy + TestMapping("http://example.com/", "DIRECT"); + + // Check that webview uses the custom proxy + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); + + // Check that webview continues to use the custom proxy + AddProperty("http.proxyHost", "httpsomeproxy.com"); + ProxySettingsChanged(); + TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); + + // Check that webview uses the non default proxy + ClearProxyOverride(); + TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); +} + +TEST_F(ProxyConfigServiceAndroidTest, TestProxyAndOverride) { + std::vector<std::string> exclusion_list; + + // Check that webview uses the default proxy + TestMapping("http://example.com/", "DIRECT"); + + // Check that webview uses the non default proxy + AddProperty("http.proxyHost", "httpsomeproxy.com"); + ProxySettingsChanged(); + TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); + + // Check that webview uses the custom proxy + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); + + // Check that webview uses the non default proxy + ClearProxyOverride(); + TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); +} + +TEST_F(ProxyConfigServiceAndroidTest, TestOverrideThenProxy) { + std::vector<std::string> exclusion_list; + + // Check that webview uses the default proxy + TestMapping("http://example.com/", "DIRECT"); + + // Check that webview uses the custom proxy + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); + + // Check that webview uses the default proxy + ClearProxyOverride(); + TestMapping("http://example.com/", "DIRECT"); + + // Check that webview uses the non default proxy + AddProperty("http.proxyHost", "httpsomeproxy.com"); + ProxySettingsChanged(); + TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); +} + +TEST_F(ProxyConfigServiceAndroidTest, TestClearOverride) { + std::vector<std::string> exclusion_list; + + // Check that webview uses the default proxy + TestMapping("http://example.com/", "DIRECT"); + + // Check that webview uses the default proxy + ClearProxyOverride(); + TestMapping("http://example.com/", "DIRECT"); +} + +TEST_F(ProxyConfigServiceAndroidTest, TestProxyAndClearOverride) { + std::vector<std::string> exclusion_list; + + // Check that webview uses the non default proxy + AddProperty("http.proxyHost", "httpsomeproxy.com"); + ProxySettingsChanged(); + TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); + + // Check that webview uses the non default proxy + ClearProxyOverride(); + TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80"); +} + +TEST_F(ProxyConfigServiceAndroidTest, TestOverrideExclusionList) { + std::vector<std::string> exclusion_list; + exclusion_list.push_back("excluded.com"); + + // Check that webview uses the default proxy + TestMapping("http://excluded.com/", "DIRECT"); + TestMapping("http://example.com/", "DIRECT"); + + // Check that webview handles the exclusion list correctly + SetProxyOverride("httpoverrideproxy.com", 200, exclusion_list); + TestMapping("http://excluded.com/", "DIRECT"); + TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200"); + + // Check that webview uses the default proxy + ClearProxyOverride(); + TestMapping("http://excluded.com/", "DIRECT"); + TestMapping("http://example.com/", "DIRECT"); +} + // !! The following test cases are automatically generated from // !! net/android/tools/proxy_test_cases.py. // !! Please edit that file instead of editing the test cases below and
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index cdaae400..d0740c6 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1743,6 +1743,7 @@ } void QuicChromiumClientSession::OnNoNewNetwork() { + DCHECK(IsCryptoHandshakeConfirmed()); wait_for_new_network_ = true; DVLOG(1) << "Force blocking the packet writer"; @@ -2090,6 +2091,13 @@ LogHandshakeStatusOnConnectionMigrationSignal(); + if (!IsCryptoHandshakeConfirmed()) { + HistogramAndLogMigrationFailure( + net_log_, MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED, + connection_id(), "Path degrading before handshake confirmed"); + return; + } + const NetLogWithSource migration_net_log = NetLogWithSource::Make( net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION); migration_net_log.BeginEvent(
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index da6418f..6068944 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -109,6 +109,7 @@ MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED, MIGRATION_STATUS_TIMEOUT, MIGRATION_STATUS_ON_WRITE_ERROR_DISABLED, + MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED, MIGRATION_STATUS_MAX };
diff --git a/net/quic/quic_stream_factory_peer.cc b/net/quic/quic_stream_factory_peer.cc index b7dca56d..efbb473 100644 --- a/net/quic/quic_stream_factory_peer.cc +++ b/net/quic/quic_stream_factory_peer.cc
@@ -49,6 +49,19 @@ return factory->HasActiveCertVerifierJob(server_id); } +// static +QuicChromiumClientSession* QuicStreamFactoryPeer::GetPendingSession( + QuicStreamFactory* factory, + const quic::QuicServerId& server_id, + const HostPortPair& destination) { + QuicSessionKey session_key(server_id, SocketTag()); + QuicStreamFactory::QuicSessionAliasKey key(destination, session_key); + DCHECK(factory->HasActiveJob(session_key)); + DCHECK_EQ(factory->all_sessions_.size(), 1u); + DCHECK(key == factory->all_sessions_.begin()->second); + return factory->all_sessions_.begin()->first; +} + QuicChromiumClientSession* QuicStreamFactoryPeer::GetActiveSession( QuicStreamFactory* factory, const quic::QuicServerId& server_id) {
diff --git a/net/quic/quic_stream_factory_peer.h b/net/quic/quic_stream_factory_peer.h index 008a298..cebf703 100644 --- a/net/quic/quic_stream_factory_peer.h +++ b/net/quic/quic_stream_factory_peer.h
@@ -47,6 +47,11 @@ static bool HasActiveCertVerifierJob(QuicStreamFactory* factory, const quic::QuicServerId& server_id); + static QuicChromiumClientSession* GetPendingSession( + QuicStreamFactory* factory, + const quic::QuicServerId& server_id, + const HostPortPair& destination); + static QuicChromiumClientSession* GetActiveSession( QuicStreamFactory* factory, const quic::QuicServerId& server_id);
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 33fc61e..218afb4d 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -333,6 +333,15 @@ server_id); } + // Get the pending, not activated session, if there is only one session alive. + QuicChromiumClientSession* GetPendingSession( + const HostPortPair& host_port_pair) { + quic::QuicServerId server_id(host_port_pair.host(), host_port_pair.port(), + false); + return QuicStreamFactoryPeer::GetPendingSession(factory_.get(), server_id, + host_port_pair); + } + QuicChromiumClientSession* GetActiveSession( const HostPortPair& host_port_pair) { quic::QuicServerId server_id(host_port_pair.host(), host_port_pair.port(), @@ -4382,6 +4391,54 @@ EXPECT_TRUE(quic_data3.AllWriteDataConsumed()); } +// This test verifies that the connection will not attempt connection migration +// (send connectivity probes on alternate path) when path degrading is detected +// and handshake is not confirmed. +TEST_P(QuicStreamFactoryTest, + NoMigrationOnPathDegradingBeforeHandshakeConfirmed) { + InitializeConnectionMigrationV2Test( + {kDefaultNetworkForTests, kNewNetworkForTests}); + + // Using a testing task runner. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + + // Use cold start mode to send crypto message for handshake. + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::COLD_START_WITH_CHLO_SENT); + + MockQuicData socket_data; + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(ASYNC, client_maker_.MakeDummyCHLOPacket(1)); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request(host_port_pair_, version_, privacy_mode_, + DEFAULT_PRIORITY, SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, + &net_error_details_, callback_.callback())); + + base::RunLoop().RunUntilIdle(); + + // Ensure that session is alive but not active. + EXPECT_FALSE(HasActiveSession(host_port_pair_)); + EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_)); + QuicChromiumClientSession* session = GetPendingSession(host_port_pair_); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); + + // Cause the connection to report path degrading to the session. + // Session will ignore the signal as handshake is not completed. + session->connection()->OnPathDegradingTimeout(); + EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); + + EXPECT_FALSE(HasActiveSession(host_port_pair_)); + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); +} + // Test that connection will be closed with PACKET_WRITE_ERROR if a write error // is triggered before handshake is confirmed and connection migration is turned // on.
diff --git a/printing/pdf_metafile_skia.cc b/printing/pdf_metafile_skia.cc index 3ae8f73..4daaf91 100644 --- a/printing/pdf_metafile_skia.cc +++ b/printing/pdf_metafile_skia.cc
@@ -218,10 +218,14 @@ DCHECK_EQ(data_->type_, SkiaDocumentType::MSKP); DCHECK(!data_->pdf_data_); - SkDynamicMemoryWStream stream; + cc::PlaybackParams::CustomDataRasterCallback custom_callback = + base::BindRepeating(&PdfMetafileSkia::CustomDataToSkPictureCallback, + base::Unretained(this)); sk_sp<SkPicture> pic = ToSkPicture(data_->pages_[0].content_, - SkRect::MakeSize(data_->pages_[0].size_)); + SkRect::MakeSize(data_->pages_[0].size_), + nullptr, custom_callback); SkSerialProcs procs = SerializationProcs(&data_->subframe_content_info_); + SkDynamicMemoryWStream stream; pic->serialize(&stream, &procs); data_->pdf_data_ = stream.detachAsStream(); }
diff --git a/remoting/client/audio/BUILD.gn b/remoting/client/audio/BUILD.gn index 63571057..dda19b5 100644 --- a/remoting/client/audio/BUILD.gn +++ b/remoting/client/audio/BUILD.gn
@@ -10,6 +10,7 @@ "audio_frame_supplier.h", "audio_jitter_buffer.cc", "audio_jitter_buffer.h", + "audio_playback_sink.h", "audio_player.cc", "audio_player.h", "audio_player_android.cc", @@ -18,6 +19,8 @@ "audio_player_buffer.h", "audio_stream_consumer.cc", "audio_stream_consumer.h", + "audio_stream_format.cc", + "audio_stream_format.h", ] configs += [ "//remoting/build/config:version" ] @@ -37,6 +40,14 @@ } } +source_set("test_support") { + testonly = true + sources = [ + "fake_async_audio_data_supplier.cc", + "fake_async_audio_data_supplier.h", + ] +} + source_set("unit_tests") { testonly = true
diff --git a/remoting/client/audio/async_audio_data_supplier.h b/remoting/client/audio/async_audio_data_supplier.h index eed0b7d..c3c91a2 100644 --- a/remoting/client/audio/async_audio_data_supplier.h +++ b/remoting/client/audio/async_audio_data_supplier.h
@@ -12,7 +12,8 @@ // This interface allows caller to asynchronously request for audio data. class AsyncAudioDataSupplier { public: - struct GetDataRequest { + class GetDataRequest { + public: // |data| must outlive |this|. GetDataRequest(void* data, size_t bytes_needed); virtual ~GetDataRequest();
diff --git a/remoting/client/audio/audio_jitter_buffer.cc b/remoting/client/audio/audio_jitter_buffer.cc index c7fe0cd..80c074b 100644 --- a/remoting/client/audio/audio_jitter_buffer.cc +++ b/remoting/client/audio/audio_jitter_buffer.cc
@@ -36,17 +36,6 @@ namespace remoting { -bool AudioJitterBuffer::StreamFormat::operator==( - const StreamFormat& other) const { - return bytes_per_sample == other.bytes_per_sample && - channels == other.channels && sample_rate == other.sample_rate; -} - -bool AudioJitterBuffer::StreamFormat::operator!=( - const StreamFormat& other) const { - return !(*this == other); -} - AudioJitterBuffer::AudioJitterBuffer( OnFormatChangedCallback on_format_changed) { DETACH_FROM_THREAD(thread_checker_); @@ -61,7 +50,7 @@ DCHECK_EQ(AudioPacket::ENCODING_RAW, packet->encoding()); DCHECK_NE(AudioPacket::SAMPLING_RATE_INVALID, packet->sampling_rate()); - StreamFormat stream_format; + AudioStreamFormat stream_format; stream_format.bytes_per_sample = packet->bytes_per_sample(); stream_format.channels = packet->channels(); stream_format.sample_rate = packet->sampling_rate(); @@ -103,13 +92,13 @@ queued_requests_.clear(); } -void AudioJitterBuffer::ResetBuffer(const StreamFormat& new_format) { +void AudioJitterBuffer::ResetBuffer(const AudioStreamFormat& new_format) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); queued_packets_.clear(); queued_bytes_ = 0; first_packet_offset_ = 0; ClearGetDataRequests(); - stream_format_ = std::make_unique<StreamFormat>(new_format); + stream_format_ = std::make_unique<AudioStreamFormat>(new_format); underrun_protection_mode_ = true; if (on_format_changed_) { on_format_changed_.Run(*stream_format_);
diff --git a/remoting/client/audio/audio_jitter_buffer.h b/remoting/client/audio/audio_jitter_buffer.h index 2fbf0966..5f744f5b 100644 --- a/remoting/client/audio/audio_jitter_buffer.h +++ b/remoting/client/audio/audio_jitter_buffer.h
@@ -14,6 +14,7 @@ #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "remoting/client/audio/async_audio_data_supplier.h" +#include "remoting/client/audio/audio_stream_format.h" #include "remoting/proto/audio.pb.h" namespace remoting { @@ -22,17 +23,8 @@ // and feeds the requests with the data when the buffer has enough data. class AudioJitterBuffer : public AsyncAudioDataSupplier { public: - struct StreamFormat { - bool operator==(const StreamFormat& other) const; - bool operator!=(const StreamFormat& other) const; - - int bytes_per_sample = 0; - int channels = 0; - int sample_rate = 0; - }; - using OnFormatChangedCallback = - base::RepeatingCallback<void(const StreamFormat& format)>; + base::RepeatingCallback<void(const AudioStreamFormat& format)>; // |callback| is called once the jitter buffer gets the first packet or the // stream format has been changed. @@ -52,7 +44,7 @@ // Clears the jitter buffer, drops all pending requests, and notify // |on_format_changed_| that the format has been changed. - void ResetBuffer(const StreamFormat& new_format); + void ResetBuffer(const AudioStreamFormat& new_format); // Feeds data from the jitter buffer into the pending requests. OnDataFilled() // will be called and request will be removed from the queue when a request @@ -69,7 +61,7 @@ // The stream format of the last audio packet. This is nullptr if the buffer // has never received any packet. - std::unique_ptr<StreamFormat> stream_format_; + std::unique_ptr<AudioStreamFormat> stream_format_; // AudioPackets queued up by the jitter buffer before they are consumed by // GetDataRequests.
diff --git a/remoting/client/audio/audio_jitter_buffer_unittest.cc b/remoting/client/audio/audio_jitter_buffer_unittest.cc index 25a9ed46..d5d3e63 100644 --- a/remoting/client/audio/audio_jitter_buffer_unittest.cc +++ b/remoting/client/audio/audio_jitter_buffer_unittest.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/callback.h" #include "remoting/client/audio/audio_jitter_buffer.h" +#include "remoting/client/audio/audio_stream_format.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting { @@ -77,15 +78,15 @@ std::list<std::unique_ptr<uint8_t[]>> consumer_buffers_; private: - struct SimpleGetDataRequest; + class SimpleGetDataRequest; - void OnFormatChanged(const AudioJitterBuffer::StreamFormat& format); + void OnFormatChanged(const AudioStreamFormat& format); AudioPacket::SamplingRate sample_rate_; - std::unique_ptr<AudioJitterBuffer::StreamFormat> stream_format_; + std::unique_ptr<AudioStreamFormat> stream_format_; }; -struct AudioJitterBufferTest::SimpleGetDataRequest +class AudioJitterBufferTest::SimpleGetDataRequest : public AsyncAudioDataSupplier::GetDataRequest { public: SimpleGetDataRequest(AudioJitterBufferTest* test, size_t bytes_to_write); @@ -164,9 +165,8 @@ size_t AudioJitterBufferTest::GetNumQueuedRequests() const { return audio_->queued_requests_.size(); } -void AudioJitterBufferTest::OnFormatChanged( - const AudioJitterBuffer::StreamFormat& format) { - stream_format_ = std::make_unique<AudioJitterBuffer::StreamFormat>(format); +void AudioJitterBufferTest::OnFormatChanged(const AudioStreamFormat& format) { + stream_format_ = std::make_unique<AudioStreamFormat>(format); } // SimpleGetDataRequest definitions
diff --git a/remoting/client/audio/audio_playback_sink.h b/remoting/client/audio/audio_playback_sink.h new file mode 100644 index 0000000..a02615f --- /dev/null +++ b/remoting/client/audio/audio_playback_sink.h
@@ -0,0 +1,35 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_CLIENT_AUDIO_AUDIO_PLAYBACK_SINK_H_ +#define REMOTING_CLIENT_AUDIO_AUDIO_PLAYBACK_SINK_H_ + +#include "base/macros.h" + +namespace remoting { + +class AsyncAudioDataSupplier; +struct AudioStreamFormat; + +// This is an interface acting as the downstream of AsyncAudioDataSupplier. +class AudioPlaybackSink { + public: + AudioPlaybackSink() = default; + virtual ~AudioPlaybackSink() = default; + + // Sets the data supplier to be used by the sink to request for more audio + // data. + // |supplier| must outlive |this|. + virtual void SetDataSupplier(AsyncAudioDataSupplier* supplier) = 0; + + // Called whenever the stream format is first received or has been changed. + virtual void ResetStreamFormat(const AudioStreamFormat& format) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(AudioPlaybackSink); +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_AUDIO_AUDIO_PLAYBACK_SINK_H_
diff --git a/remoting/client/audio/audio_stream_format.cc b/remoting/client/audio/audio_stream_format.cc new file mode 100644 index 0000000..3618615 --- /dev/null +++ b/remoting/client/audio/audio_stream_format.cc
@@ -0,0 +1,18 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/client/audio/audio_stream_format.h" + +namespace remoting { + +bool AudioStreamFormat::operator==(const AudioStreamFormat& other) const { + return bytes_per_sample == other.bytes_per_sample && + channels == other.channels && sample_rate == other.sample_rate; +} + +bool AudioStreamFormat::operator!=(const AudioStreamFormat& other) const { + return !(*this == other); +} + +} // namespace remoting
diff --git a/remoting/client/audio/audio_stream_format.h b/remoting/client/audio/audio_stream_format.h new file mode 100644 index 0000000..5e23978 --- /dev/null +++ b/remoting/client/audio/audio_stream_format.h
@@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_CLIENT_AUDIO_AUDIO_STREAM_FORMAT_H_ +#define REMOTING_CLIENT_AUDIO_AUDIO_STREAM_FORMAT_H_ + +namespace remoting { + +struct AudioStreamFormat { + bool operator==(const AudioStreamFormat& other) const; + bool operator!=(const AudioStreamFormat& other) const; + + int bytes_per_sample = 0; + int channels = 0; + int sample_rate = 0; +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_AUDIO_AUDIO_STREAM_FORMAT_H_
diff --git a/remoting/client/audio/fake_async_audio_data_supplier.cc b/remoting/client/audio/fake_async_audio_data_supplier.cc new file mode 100644 index 0000000..072873f --- /dev/null +++ b/remoting/client/audio/fake_async_audio_data_supplier.cc
@@ -0,0 +1,49 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/client/audio/fake_async_audio_data_supplier.h" + +#include <utility> + +#include "base/logging.h" + +namespace remoting { + +FakeAsyncAudioDataSupplier::FakeAsyncAudioDataSupplier() = default; + +FakeAsyncAudioDataSupplier::~FakeAsyncAudioDataSupplier() = default; + +void FakeAsyncAudioDataSupplier::AsyncGetData( + std::unique_ptr<GetDataRequest> request) { + pending_requests_.push_back(std::move(request)); + + if (fulfill_requests_immediately_) { + FulfillAllRequests(); + } +} + +void FakeAsyncAudioDataSupplier::ClearGetDataRequests() { + pending_requests_.clear(); +} + +void FakeAsyncAudioDataSupplier::FulfillNextRequest() { + DCHECK_GT(pending_requests_count(), 0u); + auto& request = pending_requests_.front(); + memset(request->data, kDummyAudioData, request->bytes_needed); + request->OnDataFilled(); + pending_requests_.pop_front(); + fulfilled_requests_count_++; +} + +void FakeAsyncAudioDataSupplier::FulfillAllRequests() { + while (pending_requests_count() > 0) { + FulfillNextRequest(); + } +} + +void FakeAsyncAudioDataSupplier::ResetFulfilledRequestsCounter() { + fulfilled_requests_count_ = 0u; +} + +} // namespace remoting
diff --git a/remoting/client/audio/fake_async_audio_data_supplier.h b/remoting/client/audio/fake_async_audio_data_supplier.h new file mode 100644 index 0000000..223b41bb --- /dev/null +++ b/remoting/client/audio/fake_async_audio_data_supplier.h
@@ -0,0 +1,64 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_CLIENT_AUDIO_FAKE_ASYNC_AUDIO_DATA_SUPPLIER_H_ +#define REMOTING_CLIENT_AUDIO_FAKE_ASYNC_AUDIO_DATA_SUPPLIER_H_ + +#include <cstdint> +#include <list> +#include <memory> + +#include "base/macros.h" +#include "remoting/client/audio/async_audio_data_supplier.h" + +namespace remoting { + +// A fake AsyncAudioDataSupplier implementation for testing. +class FakeAsyncAudioDataSupplier : public AsyncAudioDataSupplier { + public: + // Dummy audio data that will be filled into pending requests. + const uint8_t kDummyAudioData = 0x8b; + + FakeAsyncAudioDataSupplier(); + ~FakeAsyncAudioDataSupplier() override; + + // AsyncAudioDataSupplier implementations. + void AsyncGetData(std::unique_ptr<GetDataRequest> request) override; + void ClearGetDataRequests() override; + + // Fulfills the next pending request by filling it with |kDummyAudioData|. + void FulfillNextRequest(); + + // Fulfills all pending requests. + void FulfillAllRequests(); + + // Resets fulfilled_requests_count() to 0. + void ResetFulfilledRequestsCounter(); + + // Returns number of requests that are not fulfilled. + size_t pending_requests_count() const { return pending_requests_.size(); } + + // Returns number of requests that have been fulfilled. Can be reset to 0 by + // calling ResetFulfilledRequestsCounter(). + size_t fulfilled_requests_count() const { return fulfilled_requests_count_; } + + // If this is true, the instance will immediately fulfill get-data requests + // when AsyncGetData is called, otherwise the caller needs to call + // FulfillNextRequest() or FulfillAllRequests() to fulfill the requests. + // The default value is false. + void set_fulfill_requests_immediately(bool fulfill_requests_immediately) { + fulfill_requests_immediately_ = fulfill_requests_immediately; + } + + private: + bool fulfill_requests_immediately_ = false; + std::list<std::unique_ptr<GetDataRequest>> pending_requests_; + size_t fulfilled_requests_count_ = 0u; + + DISALLOW_COPY_AND_ASSIGN(FakeAsyncAudioDataSupplier); +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_AUDIO_FAKE_ASYNC_AUDIO_DATA_SUPPLIER_H_
diff --git a/remoting/ios/BUILD.gn b/remoting/ios/BUILD.gn index d99e335e..0d8fc28 100644 --- a/remoting/ios/BUILD.gn +++ b/remoting/ios/BUILD.gn
@@ -78,7 +78,8 @@ deps = [ "//base/test:run_all_unittests", "//base/test:test_support", - "//remoting//ios/facade:unit_tests", + "//remoting/ios/audio:unit_tests", + "//remoting/ios/facade:unit_tests", "//remoting/ios/persistence:unit_tests", ]
diff --git a/remoting/ios/audio/BUILD.gn b/remoting/ios/audio/BUILD.gn index 8132362..4bd0dd9 100644 --- a/remoting/ios/audio/BUILD.gn +++ b/remoting/ios/audio/BUILD.gn
@@ -8,6 +8,8 @@ source_set("audio") { sources = [ + "audio_playback_sink_ios.cc", + "audio_playback_sink_ios.h", "audio_player_ios.h", "audio_player_ios.mm", "audio_player_ios_wrapper.h", @@ -21,5 +23,26 @@ "//remoting/client/audio", ] + public_deps = [ + "//remoting/proto", + ] + + libs = [ "AudioToolbox.framework" ] + + configs += [ "//build/config/compiler:enable_arc" ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "audio_playback_sink_ios_unittest.cc", + ] + deps = [ + ":audio", + "//remoting/client/audio:test_support", + "//testing/gmock", + "//testing/gtest", + ] + configs += [ "//build/config/compiler:enable_arc" ] }
diff --git a/remoting/ios/audio/audio_playback_sink_ios.cc b/remoting/ios/audio/audio_playback_sink_ios.cc new file mode 100644 index 0000000..3f0a908 --- /dev/null +++ b/remoting/ios/audio/audio_playback_sink_ios.cc
@@ -0,0 +1,229 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/ios/audio/audio_playback_sink_ios.h" + +#include "base/logging.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" +#include "remoting/client/audio/async_audio_data_supplier.h" +#include "remoting/client/audio/audio_stream_format.h" + +namespace remoting { + +namespace { + +// Once we receive the stream format, we create +// |kRequiredBufferCountForPlayback| buffers from the audio queue, each with a +// duration of |kBufferLength|. The buffers will then be transferred to the +// supplier for priming. Once a buffer is filled up, we put it back to the audio +// queue and start running the queue. Buffer that has been consumed by the audio +// queue will be transferred back to the supplier for priming new audio data. We +// stop running the audio queue once all buffers have been transferred to the +// supplier. + +constexpr base::TimeDelta kBufferLength = base::TimeDelta::FromMilliseconds(10); +constexpr int kRequiredBufferCountForPlayback = 5; + +class AudioQueueGetDataRequest : public AsyncAudioDataSupplier::GetDataRequest { + public: + AudioQueueGetDataRequest( + AudioQueueBufferRef buffer, + base::OnceCallback<void(AudioQueueBufferRef)> on_data_received); + ~AudioQueueGetDataRequest() override; + + void OnDataFilled() override; + + private: + AudioQueueBufferRef buffer_; + base::OnceCallback<void(AudioQueueBufferRef)> on_data_received_; +}; + +AudioQueueGetDataRequest::AudioQueueGetDataRequest( + AudioQueueBufferRef buffer, + base::OnceCallback<void(AudioQueueBufferRef)> on_data_received) + : GetDataRequest(buffer->mAudioData, buffer->mAudioDataBytesCapacity), + buffer_(buffer), + on_data_received_(std::move(on_data_received)) { + buffer_->mAudioDataByteSize = buffer_->mAudioDataBytesCapacity; +} + +// Note that disposing of the output queue also disposes all of its buffers, +// so no cleanup is needed here. +AudioQueueGetDataRequest::~AudioQueueGetDataRequest() = default; + +void AudioQueueGetDataRequest::OnDataFilled() { + std::move(on_data_received_).Run(buffer_); +} + +} // namespace + +AudioPlaybackSinkIos::AudioPlaybackSinkIos() : weak_factory_(this) { + DETACH_FROM_THREAD(thread_checker_); +} + +AudioPlaybackSinkIos::~AudioPlaybackSinkIos() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DisposeOutputQueue(); +} + +void AudioPlaybackSinkIos::SetDataSupplier(AsyncAudioDataSupplier* supplier) { + DCHECK(supplier); + supplier_ = supplier; +} + +void AudioPlaybackSinkIos::ResetStreamFormat(const AudioStreamFormat& format) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + stream_format_.mSampleRate = format.sample_rate; + stream_format_.mFormatID = kAudioFormatLinearPCM; + stream_format_.mFormatFlags = + kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; + stream_format_.mBitsPerChannel = 8 * format.bytes_per_sample; + stream_format_.mChannelsPerFrame = format.channels; + stream_format_.mBytesPerPacket = format.bytes_per_sample * format.channels; + stream_format_.mBytesPerFrame = stream_format_.mBytesPerPacket; + stream_format_.mFramesPerPacket = 1; + stream_format_.mReserved = 0; + + ResetOutputQueue(); +} + +void AudioPlaybackSinkIos::AsyncGetAudioData(AudioQueueBufferRef buffer) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(supplier_); + + priming_buffers_count_++; + + supplier_->AsyncGetData(std::make_unique<AudioQueueGetDataRequest>( + buffer, base::BindOnce(&AudioPlaybackSinkIos::OnAudioDataReceived, + weak_factory_.GetWeakPtr()))); + + if (state_ == State::RUNNING && + priming_buffers_count_ == kRequiredBufferCountForPlayback) { + // Buffer underrun. Stop playback immediately. + StopPlayback(); + return; + } +} + +void AudioPlaybackSinkIos::OnAudioDataReceived(AudioQueueBufferRef buffer) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + AudioQueueEnqueueBuffer(output_queue_, buffer, 0, nullptr); + priming_buffers_count_--; + + if (state_ == State::STOPPED) { + StartPlayback(); + } +} + +// static +void AudioPlaybackSinkIos::OnBufferDequeued(void* context, + AudioQueueRef outAQ, + AudioQueueBufferRef buffer) { + AudioPlaybackSinkIos* instance = + reinterpret_cast<AudioPlaybackSinkIos*>(context); + DCHECK(instance); + instance->AsyncGetAudioData(buffer); +} + +void AudioPlaybackSinkIos::StartPlayback() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (state_ != State::STOPPED) { + return; + } + DCHECK(output_queue_); + OSStatus err = AudioQueueStart(output_queue_, nullptr); + + if (err) { + // This could be a transient failure when we try to start playback while the + // app is resuming from the background. We can reset the queue for now and + // wait for new audio data to trigger StartPlayback() again. + LOG(ERROR) << "AudioQueueStart failed: " << err; + + // StartPlayback() may be called from inside GetDataRequest::OnDataFilled(). + // In this case ResetOutputQueue() must be called in a separate task because + // it alters the pending requests in |supplier_|. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&AudioPlaybackSinkIos::ResetOutputQueue, + weak_factory_.GetWeakPtr())); + state_ = State::SCHEDULED_TO_RESET; + } else { + state_ = State::RUNNING; + } +} + +void AudioPlaybackSinkIos::StopPlayback() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(output_queue_); + + if (state_ != State::RUNNING) { + return; + } + + // Note that AudioQueueStop() will immediately return all enqueued buffers to + // us, which calls AsyncGetAudioData(). We change the state to STOPPED before + // AudioQueueStop() so that the buffers are immediately transferred to the + // supplier. + state_ = State::STOPPED; + + OSStatus err = AudioQueueStop(output_queue_, /* Immediate */ true); + HandleError(err, "AudioQueueStop"); +} + +void AudioPlaybackSinkIos::ResetOutputQueue() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DisposeOutputQueue(); + + OSStatus err = AudioQueueNewOutput(&stream_format_, OnBufferDequeued, this, + CFRunLoopGetCurrent(), + kCFRunLoopCommonModes, 0, &output_queue_); + if (HandleError(err, "AudioQueueNewOutput")) { + return; + } + + // Create buffers. + size_t buffer_byte_size = stream_format_.mSampleRate * + stream_format_.mBytesPerPacket * + kBufferLength.InSecondsF(); + for (int i = 0; i < kRequiredBufferCountForPlayback; i++) { + AudioQueueBufferRef buffer; + OSStatus err = + AudioQueueAllocateBuffer(output_queue_, buffer_byte_size, &buffer); + if (HandleError(err, "AudioQueueAllocateBuffer")) { + return; + } + + // Immediately request for audio data. + AsyncGetAudioData(buffer); + } +} + +void AudioPlaybackSinkIos::DisposeOutputQueue() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(supplier_); + if (!output_queue_) { + return; + } + + AudioQueueDispose(output_queue_, /* Immediate */ true); + supplier_->ClearGetDataRequests(); + priming_buffers_count_ = 0; + output_queue_ = nullptr; + + state_ = State::STOPPED; +} + +bool AudioPlaybackSinkIos::HandleError(OSStatus err, + const char* function_name) { + if (err) { + LOG(DFATAL) << "Failed to call " << function_name + << ", error code: " << err; + DisposeOutputQueue(); + return true; + } + return false; +} + +} // namespace remoting
diff --git a/remoting/ios/audio/audio_playback_sink_ios.h b/remoting/ios/audio/audio_playback_sink_ios.h new file mode 100644 index 0000000..c125461 --- /dev/null +++ b/remoting/ios/audio/audio_playback_sink_ios.h
@@ -0,0 +1,103 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_IOS_AUDIO_AUDIO_PLAYBACK_SINK_IOS_H_ +#define REMOTING_IOS_AUDIO_AUDIO_PLAYBACK_SINK_IOS_H_ + +#include <AudioToolbox/AudioToolbox.h> + +#include <list> +#include <memory> +#include <string> + +#include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" +#include "remoting/client/audio/audio_playback_sink.h" + +namespace remoting { + +// This is the iOS AudioPlaybackSink implementation that uses AudioQueue for +// playback. +class AudioPlaybackSinkIos : public AudioPlaybackSink { + public: + AudioPlaybackSinkIos(); + ~AudioPlaybackSinkIos() override; + + // AudioPlaybackSink implementations. + void SetDataSupplier(AsyncAudioDataSupplier* supplier) override; + void ResetStreamFormat(const AudioStreamFormat& format) override; + + private: + // STOPPED <-----------------------------+------------+ + // | Received packet | | + // (Start playback)--------+ | | + // | Failed | Succeeded | Buffer | + // v v | Underrun | + // SCHEDULED_TO_RESET RUNNING---------+ | + // | | | + // | | Sink destructing or | Audio queue + // | | format resetting | destroyed + // +--------------------+--------------------------+ + enum class State { + STOPPED, + SCHEDULED_TO_RESET, + RUNNING, + }; + + // Asks |supplier_| to fill audio data into the given buffer. + void AsyncGetAudioData(AudioQueueBufferRef buffer); + + // Callback called when |supplier_| has finished filling data for |buffer|. + void OnAudioDataReceived(AudioQueueBufferRef buffer); + + // Callback called when the AudioQueue API finished consuming the audio data. + static void OnBufferDequeued(void* context, + AudioQueueRef outAQ, + AudioQueueBufferRef buffer); + + // Starts playback immediately. Posts task to reset the output queue if it + // fails to start. + void StartPlayback(); + + // Stops playback immediately. + void StopPlayback(); + + // Disposes the current output queue and its buffers, creates a new queue + // and buffers, and immediately request for audio data from |supplier_|. + void ResetOutputQueue(); + + // Disposes the current output queue and its buffers. + void DisposeOutputQueue(); + + // If |err| is not no-error, prints an error log at DFATAL level and disposes + // the current output queue. The sink will then not be running until + // ResetStreamFormat() is called again. + // Returns true if error occurs and the output queue has been disposed. + bool HandleError(OSStatus err, const char* function_name); + + THREAD_CHECKER(thread_checker_); + + AsyncAudioDataSupplier* supplier_ = nullptr; + + // Number of buffers that are currently transferred to |supplier_| for + // priming. + size_t priming_buffers_count_ = 0; + + // The current stream format. + AudioStreamBasicDescription stream_format_; + + // The output queue. nullptr if ResetStreamFormat() has not been called. + AudioQueueRef output_queue_ = nullptr; + + // The current state. + State state_ = State::STOPPED; + + base::WeakPtrFactory<AudioPlaybackSinkIos> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(AudioPlaybackSinkIos); +}; + +} // namespace remoting + +#endif // REMOTING_IOS_AUDIO_AUDIO_PLAYBACK_SINK_IOS_H_
diff --git a/remoting/ios/audio/audio_playback_sink_ios_unittest.cc b/remoting/ios/audio/audio_playback_sink_ios_unittest.cc new file mode 100644 index 0000000..268d7f6 --- /dev/null +++ b/remoting/ios/audio/audio_playback_sink_ios_unittest.cc
@@ -0,0 +1,218 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/ios/audio/audio_playback_sink_ios.h" + +#include "base/bind.h" +#include "base/test/bind_test_util.h" +#include "base/threading/platform_thread.h" +#include "base/threading/thread.h" +#include "remoting/client/audio/audio_stream_format.h" +#include "remoting/client/audio/fake_async_audio_data_supplier.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace remoting { + +namespace { + +constexpr AudioStreamFormat kStreamFormat = {2, 2, 44100}; +constexpr base::TimeDelta kBufferPlaybackTimeout = + base::TimeDelta::FromMilliseconds(500); + +} // namespace + +class AudioPlaybackSinkIosTest : public ::testing::Test { + protected: + void SetUp() override; + void TearDown() override; + + void FeedStreamFormat(); + void BlockAndRunOnAudioThread(base::OnceClosure closure); + void Sleep(); + + base::Thread audio_thread_{"Chromoting Audio"}; + std::unique_ptr<FakeAsyncAudioDataSupplier> supplier_; + std::unique_ptr<AudioPlaybackSinkIos> sink_; +}; + +// Test fixture definitions + +void AudioPlaybackSinkIosTest::SetUp() { + audio_thread_.StartAndWaitForTesting(); + supplier_ = std::make_unique<FakeAsyncAudioDataSupplier>(); + sink_ = std::make_unique<AudioPlaybackSinkIos>(); + sink_->SetDataSupplier(supplier_.get()); +} + +void AudioPlaybackSinkIosTest::TearDown() { + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + sink_.reset(); + supplier_.reset(); + })); + audio_thread_.Stop(); +} + +void AudioPlaybackSinkIosTest::FeedStreamFormat() { + sink_->ResetStreamFormat(kStreamFormat); +} + +void AudioPlaybackSinkIosTest::BlockAndRunOnAudioThread( + base::OnceClosure closure) { + audio_thread_.task_runner()->PostTask(FROM_HERE, std::move(closure)); + audio_thread_.FlushForTesting(); +} + +void AudioPlaybackSinkIosTest::Sleep() { + base::PlatformThread::Sleep(kBufferPlaybackTimeout); +} + +// Test cases + +TEST_F(AudioPlaybackSinkIosTest, Init) { + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + ASSERT_EQ(0u, supplier_->pending_requests_count()); + FeedStreamFormat(); + + // New requests have been enqueued immediately. + ASSERT_GT(supplier_->pending_requests_count(), 0u); + })); +} + +TEST_F(AudioPlaybackSinkIosTest, NoLingeringRequestsAfterDestruction) { + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + FeedStreamFormat(); + ASSERT_GT(supplier_->pending_requests_count(), 0u); + + // Delete the audio sink. + sink_.reset(); + + // No lingering pending requests. + ASSERT_EQ(0u, supplier_->pending_requests_count()); + })); +} + +TEST_F(AudioPlaybackSinkIosTest, DestroyWhenPlaying) { + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + FeedStreamFormat(); + ASSERT_GT(supplier_->pending_requests_count(), 0u); + supplier_->FulfillAllRequests(); + + // Delete the audio sink. + sink_.reset(); + + // No lingering pending requests. + ASSERT_EQ(0u, supplier_->pending_requests_count()); + })); +} + +TEST_F(AudioPlaybackSinkIosTest, BufferUnderrunScenario) { + size_t max_number_of_requests; + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + ASSERT_EQ(0u, supplier_->pending_requests_count()); + FeedStreamFormat(); + max_number_of_requests = supplier_->pending_requests_count(); + ASSERT_GT(max_number_of_requests, 0u); + supplier_->FulfillAllRequests(); + // Old buffers are returned. New request has not come yet. + ASSERT_EQ(0u, supplier_->pending_requests_count()); + })); + + // Wait for the sink to consume all buffers and return them to the supplier. + Sleep(); + + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + // Audio buffers should now be returned to the supplier. The AudioQueue + // should be stopped because of buffer underrun. + ASSERT_EQ(max_number_of_requests, supplier_->pending_requests_count()); + + supplier_->FulfillAllRequests(); + + ASSERT_EQ(0u, supplier_->pending_requests_count()); + })); + + // Wait for the sink to consume all buffers. + Sleep(); + + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + // Audio buffers should now be returned to the supplier. Buffer underrun + // again. + ASSERT_EQ(max_number_of_requests, supplier_->pending_requests_count()); + })); +} + +TEST_F(AudioPlaybackSinkIosTest, KeepFulfillingRequestsOneByOne) { + size_t max_number_of_requests; + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + supplier_->set_fulfill_requests_immediately(true); + FeedStreamFormat(); + max_number_of_requests = supplier_->pending_requests_count(); + })); + + size_t number_of_fulfilled_requests = 0; + + // Keep the queue running and verify that the number of fulfilled requests + // keeps increasing. + for (int i = 0; i < 5; i++) { + Sleep(); + + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + // Make sure the number of pending requests does not exceed + // |max_number_of_requests|. + ASSERT_LE(supplier_->pending_requests_count(), max_number_of_requests); + + size_t new_number_of_fulfilled_requests = + supplier_->fulfilled_requests_count(); + ASSERT_GT(new_number_of_fulfilled_requests, number_of_fulfilled_requests); + number_of_fulfilled_requests = new_number_of_fulfilled_requests; + })); + } +} + +TEST_F(AudioPlaybackSinkIosTest, ChangeStreamFormat_NoPendingRequests) { + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + ASSERT_EQ(0u, supplier_->pending_requests_count()); + FeedStreamFormat(); + size_t max_number_of_requests = supplier_->pending_requests_count(); + ASSERT_GT(max_number_of_requests, 0u); + supplier_->FulfillAllRequests(); + // Old buffers are returned. New request has not come yet. + ASSERT_EQ(0u, supplier_->pending_requests_count()); + // Change the sample rate to 48000 now. + AudioStreamFormat new_stream_format = {2, 2, 48000}; + sink_->ResetStreamFormat(new_stream_format); + + // New pending requests are enqueued. + ASSERT_EQ(max_number_of_requests, supplier_->pending_requests_count()); + })); +} + +TEST_F(AudioPlaybackSinkIosTest, ChangeStreamFormat_WithPendingRequests) { + size_t max_number_of_requests; + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + ASSERT_EQ(0u, supplier_->pending_requests_count()); + FeedStreamFormat(); + max_number_of_requests = supplier_->pending_requests_count(); + ASSERT_GT(max_number_of_requests, 0u); + supplier_->FulfillAllRequests(); + // Old buffers are returned. New request has not come yet. + ASSERT_EQ(0u, supplier_->pending_requests_count()); + })); + + // Sleep until new requests are enqueued. + Sleep(); + + BlockAndRunOnAudioThread(base::BindLambdaForTesting([&]() { + // Verify that new requests are enqueued. + ASSERT_EQ(max_number_of_requests, supplier_->pending_requests_count()); + + // Change the sample rate to 48000 now. + AudioStreamFormat new_stream_format = {2, 2, 48000}; + sink_->ResetStreamFormat(new_stream_format); + + // Same number of enqueued requests. + ASSERT_EQ(max_number_of_requests, supplier_->pending_requests_count()); + })); +} + +} // namespace remoting
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index 8852fd1..a7f4e76ed 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -274,7 +274,7 @@ "//net/tools/testserver/", "//services/test/data", "//third_party/pyftpdlib/", - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", "//third_party/tlslite/", ] }
diff --git a/services/tracing/public/cpp/trace_event_agent.cc b/services/tracing/public/cpp/trace_event_agent.cc index 2623a650..d3427fc 100644 --- a/services/tracing/public/cpp/trace_event_agent.cc +++ b/services/tracing/public/cpp/trace_event_agent.cc
@@ -90,18 +90,26 @@ std::unique_ptr<TraceEventAgent> TraceEventAgent::Create( service_manager::Connector* connector, bool request_clock_sync_marker_on_android) { + std::unique_ptr<TraceEventAgent> new_agent; + if (TracingUsesPerfettoBackend()) { #if defined(PERFETTO_AVAILABLE) - return std::make_unique<PerfettoTraceEventAgent>( + new_agent = std::make_unique<PerfettoTraceEventAgent>( connector, request_clock_sync_marker_on_android); #else - LOG(FATAL) << "Perfetto is not yet available for this platform."; - return nullptr; + LOG(ERROR) << "Perfetto is not yet available for this platform; falling " + "back to using legacy TraceLog"; #endif - } else { - return std::make_unique<LegacyTraceEventAgent>( + } + + // Use legacy tracing if we're on an unsupported platform or the feature flag + // is disabled. + if (!new_agent) { + new_agent = std::make_unique<LegacyTraceEventAgent>( connector, request_clock_sync_marker_on_android); } + + return new_agent; } TraceEventAgent::TraceEventAgent(service_manager::Connector* connector,
diff --git a/services/tracing/tracing_service.cc b/services/tracing/tracing_service.cc index 726fc274..22c812e 100644 --- a/services/tracing/tracing_service.cc +++ b/services/tracing/tracing_service.cc
@@ -45,6 +45,8 @@ void TracingService::OnStart() { tracing_agent_registry_ = std::make_unique<AgentRegistry>(); + bool enable_legacy_tracing = true; + if (TracingUsesPerfettoBackend()) { #if defined(PERFETTO_SERVICE_AVAILABLE) perfetto_service_ = std::make_unique<tracing::PerfettoService>(); @@ -59,10 +61,13 @@ base::BindRepeating(&PerfettoTracingCoordinator::BindCoordinatorRequest, base::Unretained(perfetto_coordinator.get()))); perfetto_tracing_coordinator_ = std::move(perfetto_coordinator); -#else - LOG(FATAL) << "Perfetto is not yet available for this platform."; + enable_legacy_tracing = false; #endif - } else { + } + + // Use legacy tracing if we're on an unsupported platform or the feature flag + // is disabled. + if (enable_legacy_tracing) { auto tracing_coordinator = std::make_unique<Coordinator>(tracing_agent_registry_.get()); registry_.AddInterface(
diff --git a/services/ui/ws2/BUILD.gn b/services/ui/ws2/BUILD.gn index b171a50e..e85af2f0 100644 --- a/services/ui/ws2/BUILD.gn +++ b/services/ui/ws2/BUILD.gn
@@ -204,6 +204,7 @@ "//ui/aura:test_support", "//ui/events:test_support", "//ui/platform_window", + "//ui/wm", ] data_deps = [
diff --git a/services/ui/ws2/client_root.cc b/services/ui/ws2/client_root.cc index 5834462..3d5b6d0d 100644 --- a/services/ui/ws2/client_root.cc +++ b/services/ui/ws2/client_root.cc
@@ -46,9 +46,7 @@ window_->GetHost()->RemoveObserver(this); viz::HostFrameSinkManager* host_frame_sink_manager = - aura::Env::GetInstance() - ->context_factory_private() - ->GetHostFrameSinkManager(); + window_->env()->context_factory_private()->GetHostFrameSinkManager(); host_frame_sink_manager->InvalidateFrameSinkId( server_window->frame_sink_id()); } @@ -56,9 +54,7 @@ void ClientRoot::RegisterVizEmbeddingSupport() { // This function should only be called once. viz::HostFrameSinkManager* host_frame_sink_manager = - aura::Env::GetInstance() - ->context_factory_private() - ->GetHostFrameSinkManager(); + window_->env()->context_factory_private()->GetHostFrameSinkManager(); viz::FrameSinkId frame_sink_id = ServerWindow::GetMayBeNull(window_)->frame_sink_id(); host_frame_sink_manager->RegisterFrameSinkId(frame_sink_id, this); @@ -115,7 +111,8 @@ return; } - HandleBoundsOrScaleFactorChange(window_->bounds()); + HandleBoundsOrScaleFactorChange(is_top_level_ ? window_->GetBoundsInScreen() + : window_->bounds()); } void ClientRoot::HandleBoundsOrScaleFactorChange(const gfx::Rect& old_bounds) { @@ -125,7 +122,7 @@ // why this always notifies the client. window_tree_->window_tree_client_->OnWindowBoundsChanged( window_tree_->TransportIdForWindow(window_), old_bounds, - window_->bounds(), + is_top_level_ ? window_->GetBoundsInScreen() : window_->bounds(), ServerWindow::GetMayBeNull(window_)->local_surface_id()); }
diff --git a/services/ui/ws2/injected_event_handler.cc b/services/ui/ws2/injected_event_handler.cc index 66c99e5..56f9d1b9 100644 --- a/services/ui/ws2/injected_event_handler.cc +++ b/services/ui/ws2/injected_event_handler.cc
@@ -20,7 +20,7 @@ : window_service_(window_service), window_tree_host_(window_tree_host) { window_service_->AddObserver(this); window_tree_host_->window()->AddObserver(this); - aura::Env::GetInstance()->AddWindowEventDispatcherObserver(this); + window_tree_host_->window()->env()->AddWindowEventDispatcherObserver(this); } InjectedEventHandler::~InjectedEventHandler() { @@ -56,7 +56,7 @@ if (!window_service_) return; - aura::Env::GetInstance()->RemoveWindowEventDispatcherObserver(this); + window_tree_host_->window()->env()->RemoveWindowEventDispatcherObserver(this); window_tree_host_->window()->RemoveObserver(this); window_service_->RemoveObserver(this); window_service_ = nullptr;
diff --git a/services/ui/ws2/pointer_watcher.cc b/services/ui/ws2/pointer_watcher.cc index 326f301f..9536094 100644 --- a/services/ui/ws2/pointer_watcher.cc +++ b/services/ui/ws2/pointer_watcher.cc
@@ -4,6 +4,7 @@ #include "services/ui/ws2/pointer_watcher.h" +#include "services/ui/ws2/window_service.h" #include "services/ui/ws2/window_tree.h" #include "ui/aura/env.h" #include "ui/aura/window_event_dispatcher.h" @@ -26,11 +27,11 @@ } PointerWatcher::PointerWatcher(WindowTree* tree) : tree_(tree) { - aura::Env::GetInstance()->AddWindowEventDispatcherObserver(this); + tree->window_service()->env()->AddWindowEventDispatcherObserver(this); } PointerWatcher::~PointerWatcher() { - aura::Env::GetInstance()->RemoveWindowEventDispatcherObserver(this); + tree_->window_service()->env()->RemoveWindowEventDispatcherObserver(this); } bool PointerWatcher::DoesEventMatch(const ui::Event& event) const {
diff --git a/services/ui/ws2/server_window.cc b/services/ui/ws2/server_window.cc index 73d22ac..b7534af 100644 --- a/services/ui/ws2/server_window.cc +++ b/services/ui/ws2/server_window.cc
@@ -494,9 +494,7 @@ viz::mojom::CompositorFrameSinkClientPtr client) { attached_compositor_frame_sink_ = true; viz::HostFrameSinkManager* host_frame_sink_manager = - aura::Env::GetInstance() - ->context_factory_private() - ->GetHostFrameSinkManager(); + window_->env()->context_factory_private()->GetHostFrameSinkManager(); host_frame_sink_manager->CreateCompositorFrameSink( frame_sink_id_, std::move(compositor_frame_sink), std::move(client)); }
diff --git a/services/ui/ws2/user_activity_monitor.cc b/services/ui/ws2/user_activity_monitor.cc index 07d2f49..a2220061 100644 --- a/services/ui/ws2/user_activity_monitor.cc +++ b/services/ui/ws2/user_activity_monitor.cc
@@ -16,17 +16,18 @@ namespace ws2 { UserActivityMonitor::UserActivityMonitor( + aura::Env* env, std::unique_ptr<const base::TickClock> clock) - : now_clock_(std::move(clock)) { + : env_(env), now_clock_(std::move(clock)) { if (!now_clock_) now_clock_ = std::make_unique<base::DefaultTickClock>(); last_activity_ = now_clock_->NowTicks(); - aura::Env::GetInstance()->AddPreTargetHandler(this); + env_->AddPreTargetHandler(this); } UserActivityMonitor::~UserActivityMonitor() { - aura::Env::GetInstance()->RemovePreTargetHandler(this); + env_->RemovePreTargetHandler(this); } void UserActivityMonitor::AddBinding(
diff --git a/services/ui/ws2/user_activity_monitor.h b/services/ui/ws2/user_activity_monitor.h index ca8dae34..85f3159 100644 --- a/services/ui/ws2/user_activity_monitor.h +++ b/services/ui/ws2/user_activity_monitor.h
@@ -17,6 +17,10 @@ #include "services/ui/public/interfaces/user_activity_monitor.mojom.h" #include "ui/events/event_handler.h" +namespace aura { +class Env; +} + namespace ui { namespace ws2 { @@ -33,6 +37,7 @@ // |now_clock| is used to get the timestamp. If |now_clock| is nullptr, then // DefaultTickClock is used. explicit UserActivityMonitor( + aura::Env* env, std::unique_ptr<const base::TickClock> now_clock = nullptr); ~UserActivityMonitor() override; @@ -61,6 +66,8 @@ void OnActivityObserverDisconnected(mojom::UserActivityObserver* observer); void OnIdleObserverDisconnected(mojom::UserIdleObserver* observer); + aura::Env* env_; + mojo::BindingSet<mojom::UserActivityMonitor> bindings_; std::unique_ptr<const base::TickClock> now_clock_;
diff --git a/services/ui/ws2/user_activity_monitor_unittest.cc b/services/ui/ws2/user_activity_monitor_unittest.cc index c0032b4..9e4cd0d 100644 --- a/services/ui/ws2/user_activity_monitor_unittest.cc +++ b/services/ui/ws2/user_activity_monitor_unittest.cc
@@ -106,7 +106,7 @@ env_ = aura::Env::CreateInstance(aura::Env::Mode::LOCAL); TaskRunnerTestBase::SetUp(); monitor_ = std::make_unique<UserActivityMonitor>( - task_runner()->DeprecatedGetMockTickClock()); + env_.get(), task_runner()->DeprecatedGetMockTickClock()); } std::unique_ptr<aura::Env> env_;
diff --git a/services/ui/ws2/window_service.cc b/services/ui/ws2/window_service.cc index 9bc55fd..7978057 100644 --- a/services/ui/ws2/window_service.cc +++ b/services/ui/ws2/window_service.cc
@@ -33,12 +33,14 @@ WindowServiceDelegate* delegate, std::unique_ptr<GpuInterfaceProvider> gpu_interface_provider, aura::client::FocusClient* focus_client, - bool decrement_client_ids) + bool decrement_client_ids, + aura::Env* env) : delegate_(delegate), + env_(env ? env : aura::Env::GetInstance()), gpu_interface_provider_(std::move(gpu_interface_provider)), screen_provider_(std::make_unique<ScreenProvider>()), focus_client_(focus_client), - user_activity_monitor_(std::make_unique<UserActivityMonitor>()), + user_activity_monitor_(std::make_unique<UserActivityMonitor>(env_)), next_client_id_(decrement_client_ids ? kInitialClientIdDecrement : kInitialClientId), decrement_client_ids_(decrement_client_ids),
diff --git a/services/ui/ws2/window_service.h b/services/ui/ws2/window_service.h index 451f7465..7d0a5ffc 100644 --- a/services/ui/ws2/window_service.h +++ b/services/ui/ws2/window_service.h
@@ -30,6 +30,7 @@ #include "ui/base/mojo/clipboard.mojom.h" namespace aura { +class Env; class Window; namespace client { class FocusClient; @@ -74,7 +75,8 @@ WindowService(WindowServiceDelegate* delegate, std::unique_ptr<GpuInterfaceProvider> gpu_support, aura::client::FocusClient* focus_client, - bool decrement_client_ids = false); + bool decrement_client_ids = false, + aura::Env* env = nullptr); ~WindowService() override; // Gets the ServerWindow for |window|, creating if necessary. @@ -97,6 +99,8 @@ // Whether |window| hosts a remote client. static bool HasRemoteClient(const aura::Window* window); + aura::Env* env() { return env_; } + void AddObserver(WindowServiceObserver* observer); void RemoveObserver(WindowServiceObserver* observer); base::ObserverList<WindowServiceObserver>& observers() { return observers_; } @@ -168,6 +172,8 @@ WindowServiceDelegate* delegate_; + aura::Env* env_; + // GpuInterfaceProvider may be null in tests. std::unique_ptr<GpuInterfaceProvider> gpu_interface_provider_;
diff --git a/services/ui/ws2/window_tree.cc b/services/ui/ws2/window_tree.cc index baeb995..e7dc2dfa 100644 --- a/services/ui/ws2/window_tree.cc +++ b/services/ui/ws2/window_tree.cc
@@ -26,6 +26,7 @@ #include "services/ui/ws2/window_service_delegate.h" #include "services/ui/ws2/window_service_observer.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/client/screen_position_client.h" #include "ui/aura/client/transient_window_client.h" #include "ui/aura/env.h" #include "ui/aura/mus/os_exchange_data_provider_mus.h" @@ -530,7 +531,8 @@ window_data->transient_parent_id = transient_parent ? TransportIdForWindow(transient_parent) : kInvalidTransportId; - window_data->bounds = window->bounds(); + window_data->bounds = + IsTopLevel(window) ? window->GetBoundsInScreen() : window->bounds(); window_data->properties = window_service_->property_converter()->GetTransportProperties(window); window_data->visible = window->TargetVisibility(); @@ -604,8 +606,9 @@ const bool is_top_level = false; // WindowDelegateImpl deletes itself when |window| is destroyed. WindowDelegateImpl* window_delegate = new WindowDelegateImpl(); - std::unique_ptr<aura::Window> window_ptr = - std::make_unique<aura::Window>(window_delegate); + std::unique_ptr<aura::Window> window_ptr = std::make_unique<aura::Window>( + window_delegate, aura::client::WINDOW_TYPE_UNKNOWN, + window_service_->env()); window_delegate->set_window(window_ptr.get()); aura::Window* window = AddClientCreatedWindow(client_window_id, is_top_level, std::move(window_ptr)); @@ -1009,8 +1012,10 @@ } ServerWindow* server_window = ServerWindow::GetMayBeNull(window); + const gfx::Rect original_bounds = + IsTopLevel(window) ? window->GetBoundsInScreen() : window->bounds(); - if (window->bounds() == bounds && + if (original_bounds == bounds && server_window->local_surface_id() == local_surface_id) { return true; } @@ -1021,8 +1026,15 @@ if (IsLocalSurfaceIdAssignedByClient(window)) server_window->set_local_surface_id(local_surface_id); - const gfx::Rect original_bounds = window->bounds(); - window->SetBounds(bounds); + aura::client::ScreenPositionClient* screen_position_client = + aura::client::GetScreenPositionClient(window->GetRootWindow()); + if (IsTopLevel(window) && screen_position_client) { + display::Display dst_display = + display::Screen::GetScreen()->GetDisplayMatching(bounds); + screen_position_client->SetBounds(window, bounds, dst_display); + } else { + window->SetBounds(bounds); + } if (!change.window()) return true; // Return value doesn't matter if window destroyed. @@ -1732,7 +1744,7 @@ } if (source == ui::mojom::MoveLoopSource::MOUSE && - !aura::Env::GetInstance()->IsMouseButtonDown()) { + !window->env()->IsMouseButtonDown()) { DVLOG(1) << "PerformWindowMove failed (mouse not down)"; window_tree_client_->OnChangeCompleted(change_id, false); return;
diff --git a/services/ui/ws2/window_tree_unittest.cc b/services/ui/ws2/window_tree_unittest.cc index ce7d4c8..02914cf 100644 --- a/services/ui/ws2/window_tree_unittest.cc +++ b/services/ui/ws2/window_tree_unittest.cc
@@ -30,6 +30,7 @@ #include "ui/aura/window_tracker.h" #include "ui/events/test/event_generator.h" #include "ui/wm/core/capture_controller.h" +#include "ui/wm/core/default_screen_position_client.h" #include "ui/wm/core/focus_controller.h" #include "ui/wm/core/window_util.h" @@ -85,6 +86,38 @@ *result_value = actual_result; } +// A screen position client with a fixed screen offset applied via SetBounds. +class TestScreenPositionClient : public wm::DefaultScreenPositionClient { + public: + explicit TestScreenPositionClient(const gfx::Vector2d& offset) + : offset_(offset) {} + ~TestScreenPositionClient() override = default; + + // wm::DefaultScreenPositionClient: + void ConvertPointToScreen(const aura::Window* window, + gfx::PointF* point) override { + wm::DefaultScreenPositionClient::ConvertPointToScreen(window, point); + *point += offset_; + } + void ConvertPointFromScreen(const aura::Window* window, + gfx::PointF* point) override { + *point -= offset_; + wm::DefaultScreenPositionClient::ConvertPointFromScreen(window, point); + } + void SetBounds(aura::Window* window, + const gfx::Rect& bounds, + const display::Display& display) override { + EXPECT_EQ(display, display::Screen::GetScreen()->GetPrimaryDisplay()); + gfx::Rect offset_bounds = bounds; + offset_bounds.Offset(-offset_); + wm::DefaultScreenPositionClient::SetBounds(window, offset_bounds, display); + } + + private: + const gfx::Vector2d offset_; + DISALLOW_COPY_AND_ASSIGN(TestScreenPositionClient); +}; + TEST(WindowTreeTest, NewWindow) { WindowServiceTestSetup setup; EXPECT_TRUE(setup.changes()->empty()); @@ -136,15 +169,15 @@ setup.window_tree_test_helper()->NewTopLevelWindow(); setup.changes()->clear(); - const gfx::Rect bounds_from_client = gfx::Rect(1, 2, 300, 400); + const gfx::Rect bounds_from_client = gfx::Rect(100, 200, 300, 400); setup.window_tree_test_helper()->SetWindowBoundsWithAck( top_level, bounds_from_client, 2); - EXPECT_EQ(bounds_from_client, top_level->bounds()); + EXPECT_EQ(bounds_from_client, top_level->GetBoundsInScreen()); ASSERT_EQ(2u, setup.changes()->size()); { const Change& change = (*setup.changes())[0]; EXPECT_EQ(CHANGE_TYPE_NODE_BOUNDS_CHANGED, change.type); - EXPECT_EQ(top_level->bounds(), change.bounds2); + EXPECT_EQ(top_level->GetBoundsInScreen(), change.bounds2); EXPECT_TRUE(change.local_surface_id); setup.changes()->erase(setup.changes()->begin()); } @@ -179,6 +212,33 @@ // And because the layout manager changed the bounds the result is false. EXPECT_EQ("ChangeCompleted id=3 success=false", ChangeToDescription((*setup.changes())[1])); + setup.changes()->clear(); + + // Install a screen position client with a non-zero screen bounds offset. + gfx::Vector2d screen_offset(10, 20); + TestScreenPositionClient screen_position_client(screen_offset); + aura::client::SetScreenPositionClient(setup.aura_test_helper()->root_window(), + &screen_position_client); + + // Tests that top-level window bounds are set in screen coordinates. + setup.window_tree_test_helper()->SetWindowBoundsWithAck( + top_level, bounds_from_client, 4); + EXPECT_EQ(bounds_from_client, top_level->GetBoundsInScreen()); + EXPECT_EQ(bounds_from_client - screen_offset, top_level->bounds()); + ASSERT_EQ(2u, setup.changes()->size()); + { + const Change& change = (*setup.changes())[0]; + EXPECT_EQ(CHANGE_TYPE_NODE_BOUNDS_CHANGED, change.type); + EXPECT_EQ(top_level->GetBoundsInScreen(), change.bounds2); + EXPECT_TRUE(change.local_surface_id); + setup.changes()->erase(setup.changes()->begin()); + } + // See comments in WindowTree::SetBoundsImpl() for why this returns false. + EXPECT_EQ("ChangeCompleted id=4 success=false", + SingleChangeToDescription(*setup.changes())); + + aura::client::SetScreenPositionClient(setup.aura_test_helper()->root_window(), + nullptr); } TEST(WindowTreeTest, SetTopLevelWindowBoundsFailsForSameSize) {
diff --git a/services/video_capture/texture_virtual_device_mojo_adapter_unittest.cc b/services/video_capture/texture_virtual_device_mojo_adapter_unittest.cc index 4753d2b..587223cc 100644 --- a/services/video_capture/texture_virtual_device_mojo_adapter_unittest.cc +++ b/services/video_capture/texture_virtual_device_mojo_adapter_unittest.cc
@@ -79,9 +79,19 @@ ProducerSharesBufferHandle(kArbitraryBufferId2); base::RunLoop wait_loop; - EXPECT_CALL(*mock_receiver_1_, DoOnNewBuffer(kArbitraryBufferId1, _)); + int buffer_received_count = 0; + EXPECT_CALL(*mock_receiver_1_, DoOnNewBuffer(kArbitraryBufferId1, _)) + .WillOnce(InvokeWithoutArgs([&wait_loop, &buffer_received_count]() { + buffer_received_count++; + if (buffer_received_count == 2) + wait_loop.Quit(); + })); EXPECT_CALL(*mock_receiver_1_, DoOnNewBuffer(kArbitraryBufferId2, _)) - .WillOnce(InvokeWithoutArgs([&wait_loop]() { wait_loop.Quit(); })); + .WillOnce(InvokeWithoutArgs([&wait_loop, &buffer_received_count]() { + buffer_received_count++; + if (buffer_received_count == 2) + wait_loop.Quit(); + })); Receiver1Connects(); wait_loop.Run(); }
diff --git a/storage/browser/blob/blob_reader.h b/storage/browser/blob/blob_reader.h index 61beacb..947d13a 100644 --- a/storage/browser/blob/blob_reader.h +++ b/storage/browser/blob/blob_reader.h
@@ -191,7 +191,7 @@ int BytesReadCompleted(); // Returns a FileStreamReader for a blob item at |index|. - // If the item at |index| is not of file this returns NULL. + // If the item at |index| is not of file this returns nullptr. FileStreamReader* GetOrCreateFileReaderAtIndex(size_t index); // If the reader is null, then this basically performs a delete operation. void SetFileReaderAtIndex(size_t index,
diff --git a/storage/browser/blob/blob_url_request_job_factory.cc b/storage/browser/blob/blob_url_request_job_factory.cc index c8f8345d..270cc8f 100644 --- a/storage/browser/blob/blob_url_request_job_factory.cc +++ b/storage/browser/blob/blob_url_request_job_factory.cc
@@ -95,7 +95,7 @@ if (blob_data_handle) return blob_data_handle; if (!context_.get()) - return NULL; + return nullptr; // Support looking up based on uuid, the FeedbackExtensionAPI relies on this. // TODO(michaeln): Replace this use case and others like it with a BlobReader @@ -103,7 +103,7 @@ const std::string kPrefix("blob:uuid/"); if (!base::StartsWith(request->url().spec(), kPrefix, base::CompareCase::SENSITIVE)) - return NULL; + return nullptr; std::string uuid = request->url().spec().substr(kPrefix.length()); std::unique_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(uuid); BlobDataHandle* handle_ptr = handle.get();
diff --git a/storage/browser/blob/shareable_file_reference.cc b/storage/browser/blob/shareable_file_reference.cc index 9b5c5ce..e147ccfc 100644 --- a/storage/browser/blob/shareable_file_reference.cc +++ b/storage/browser/blob/shareable_file_reference.cc
@@ -72,7 +72,7 @@ const base::FilePath& path) { ShareableFileMap::iterator found = g_file_map.Get().Find(path); ShareableFileReference* reference = - (found == g_file_map.Get().End()) ? NULL : found->second; + (found == g_file_map.Get().End()) ? nullptr : found->second; return scoped_refptr<ShareableFileReference>(reference); } @@ -120,12 +120,12 @@ #if DCHECK_IS_ON() g_file_map.Get().AssertCalledOnValidSequence(); #endif // DCHECK_IS_ON() - scoped_file_.AddScopeOutCallback(std::move(callback), NULL); + scoped_file_.AddScopeOutCallback(std::move(callback), nullptr); } ShareableFileReference::ShareableFileReference(ScopedFile scoped_file) : scoped_file_(std::move(scoped_file)) { - DCHECK(g_file_map.Get().Find(path())->second == NULL); + DCHECK(g_file_map.Get().Find(path())->second == nullptr); } ShareableFileReference::~ShareableFileReference() {
diff --git a/storage/browser/blob/shareable_file_reference.h b/storage/browser/blob/shareable_file_reference.h index 7b935a0f..1e10c58 100644 --- a/storage/browser/blob/shareable_file_reference.h +++ b/storage/browser/blob/shareable_file_reference.h
@@ -26,7 +26,7 @@ }; // Returns a ShareableFileReference for the given path, if no reference - // for this path exists returns NULL. + // for this path exists returns nullptr. static scoped_refptr<ShareableFileReference> Get(const base::FilePath& path); // Returns a ShareableFileReference for the given path, creating a new @@ -43,7 +43,7 @@ // If there's a pre-existing reference for the path, the scope out policy // and scope-out-callbacks of the given |scoped_file| is ignored. // If the given scoped_file has an empty path (e.g. maybe already - // released) this returns NULL reference. + // released) this returns nullptr reference. // // TODO(kinuko): Make sure if this behavior is ok, we could alternatively // merge callbacks to the existing one.
diff --git a/storage/browser/fileapi/copy_or_move_file_validator.h b/storage/browser/fileapi/copy_or_move_file_validator.h index e1fe721..e2c05cc2 100644 --- a/storage/browser/fileapi/copy_or_move_file_validator.h +++ b/storage/browser/fileapi/copy_or_move_file_validator.h
@@ -41,7 +41,7 @@ public: virtual ~CopyOrMoveFileValidatorFactory() {} - // This method must always return a non-NULL validator. |src_url| is needed + // This method must always return a non-null validator. |src_url| is needed // in addition to |platform_path| because in the obfuscated file system // case, |platform_path| will be an obfuscated filename and extension. virtual CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
diff --git a/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc b/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc index 37ce98c5..2d1cd422 100644 --- a/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc +++ b/storage/browser/fileapi/copy_or_move_file_validator_unittest.cc
@@ -56,7 +56,7 @@ : origin_(origin), src_type_(src_type), dest_type_(dest_type) {} ~CopyOrMoveFileValidatorTestHelper() { - file_system_context_ = NULL; + file_system_context_ = nullptr; base::RunLoop().RunUntilIdle(); } @@ -64,7 +64,7 @@ ASSERT_TRUE(base_.CreateUniqueTempDir()); base::FilePath base_dir = base_.GetPath(); - file_system_context_ = CreateFileSystemContextForTesting(NULL, base_dir); + file_system_context_ = CreateFileSystemContextForTesting(nullptr, base_dir); // Set up TestFileSystemBackend to require CopyOrMoveFileValidator. storage::FileSystemBackend* test_file_system_backend =
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate.cc b/storage/browser/fileapi/copy_or_move_operation_delegate.cc index 3d66867..0756693 100644 --- a/storage/browser/fileapi/copy_or_move_operation_delegate.cc +++ b/storage/browser/fileapi/copy_or_move_operation_delegate.cc
@@ -224,7 +224,7 @@ return; } - // |validator_| is NULL when the destination filesystem does not do + // |validator_| is nullptr when the destination filesystem does not do // validation. if (!validator_) { // No validation is needed.
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc index f70d69c1..48684f6 100644 --- a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc +++ b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -186,10 +186,10 @@ base::test::ScopedTaskEnvironment::MainThreadType::IO) {} ~CopyOrMoveOperationTestHelper() { - file_system_context_ = NULL; + file_system_context_ = nullptr; quota_manager_proxy_->SimulateQuotaManagerDestroyed(); - quota_manager_ = NULL; - quota_manager_proxy_ = NULL; + quota_manager_ = nullptr; + quota_manager_proxy_ = nullptr; scoped_task_environment_.RunUntilIdle(); } @@ -208,7 +208,7 @@ quota_manager_ = new MockQuotaManager(false /* is_incognito */, base_dir, base::ThreadTaskRunnerHandle::Get().get(), - NULL /* special storage policy */); + nullptr /* special storage policy */); quota_manager_proxy_ = new MockQuotaManagerProxy( quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get()); file_system_context_ = @@ -252,13 +252,13 @@ int64_t GetSourceUsage() { int64_t usage = 0; - GetUsageAndQuota(src_type_, &usage, NULL); + GetUsageAndQuota(src_type_, &usage, nullptr); return usage; } int64_t GetDestUsage() { int64_t usage = 0; - GetUsageAndQuota(dest_type_, &usage, NULL); + GetUsageAndQuota(dest_type_, &usage, nullptr); return usage; }
diff --git a/storage/browser/fileapi/dragged_file_util.cc b/storage/browser/fileapi/dragged_file_util.cc index e9b432a..5ddd394 100644 --- a/storage/browser/fileapi/dragged_file_util.cc +++ b/storage/browser/fileapi/dragged_file_util.cc
@@ -69,7 +69,8 @@ if (url.path().empty()) { // The root directory case. // For now we leave three time fields (modified/accessed/creation time) - // NULL as it is not really clear what to be set for this virtual directory. + // nullptr as it is not really clear what to be set for this virtual + // directory. // TODO(kinuko): Maybe we want to set the time when this filesystem is // created (i.e. when the files/directories are dropped). file_info->is_directory = true;
diff --git a/storage/browser/fileapi/dragged_file_util_unittest.cc b/storage/browser/fileapi/dragged_file_util_unittest.cc index 7f0f5fe..994f0a04 100644 --- a/storage/browser/fileapi/dragged_file_util_unittest.cc +++ b/storage/browser/fileapi/dragged_file_util_unittest.cc
@@ -110,7 +110,7 @@ SimulateDropFiles(); file_system_context_ = CreateFileSystemContextForTesting( - NULL /* quota_manager */, partition_dir_.GetPath()); + nullptr /* quota_manager */, partition_dir_.GetPath()); isolated_context()->AddReference(filesystem_id_); } @@ -270,7 +270,7 @@ base::FilePath root = root_path().Append( kRootPaths[(root_path_index++) % arraysize(kRootPaths)]); toplevel_root_map_[toplevel] = root; - toplevels.AddPath(root.Append(path), NULL); + toplevels.AddPath(root.Append(path), nullptr); } SetUpOneFileSystemTestCase(toplevel_root_map_[toplevel], test_case);
diff --git a/storage/browser/fileapi/dump_file_system.cc b/storage/browser/fileapi/dump_file_system.cc index 03595909..d7c5930 100644 --- a/storage/browser/fileapi/dump_file_system.cc +++ b/storage/browser/fileapi/dump_file_system.cc
@@ -80,7 +80,7 @@ if (!base::DirectoryExists(origin_dir)) return; - SandboxDirectoryDatabase directory_db(origin_dir, NULL); + SandboxDirectoryDatabase directory_db(origin_dir, nullptr); SandboxDirectoryDatabase::FileId root_id; if (!directory_db.GetFileWithPath(StringToFilePath("/"), &root_id)) return; @@ -143,7 +143,7 @@ SandboxPrioritizedOriginDatabase::kPrimaryDirectory); } - SandboxOriginDatabase origin_db(file_system_dir, NULL); + SandboxOriginDatabase origin_db(file_system_dir, nullptr); base::FilePath origin_dir; if (!origin_db.HasOriginPath(origin_name)) { ShowMessageAndExit("Origin " + origin_name + " is not in " + @@ -165,7 +165,7 @@ } static void DumpFileSystem(const base::FilePath& file_system_dir) { - SandboxOriginDatabase origin_db(file_system_dir, NULL); + SandboxOriginDatabase origin_db(file_system_dir, nullptr); std::vector<SandboxOriginDatabase::OriginRecord> origins; origin_db.ListAllOrigins(&origins); for (size_t i = 0; i < origins.size(); i++) {
diff --git a/storage/browser/fileapi/external_mount_points_unittest.cc b/storage/browser/fileapi/external_mount_points_unittest.cc index 59be862..7e6007e 100644 --- a/storage/browser/fileapi/external_mount_points_unittest.cc +++ b/storage/browser/fileapi/external_mount_points_unittest.cc
@@ -37,76 +37,76 @@ const base::FilePath::CharType* const path; // Whether the mount point registration should succeed. bool success; - // Path returned by GetRegisteredPath. NULL if the method is expected to + // Path returned by GetRegisteredPath. nullptr if the method is expected to // fail. const base::FilePath::CharType* const registered_path; }; const TestCase kTestCases[] = { // Valid mount point. - { "test", DRIVE FPL("/foo/test"), true, DRIVE FPL("/foo/test") }, + {"test", DRIVE FPL("/foo/test"), true, DRIVE FPL("/foo/test")}, // Valid mount point with only one path component. - { "bbb", DRIVE FPL("/bbb"), true, DRIVE FPL("/bbb") }, + {"bbb", DRIVE FPL("/bbb"), true, DRIVE FPL("/bbb")}, // Existing mount point path is substring of the mount points path. - { "test11", DRIVE FPL("/foo/test11"), true, DRIVE FPL("/foo/test11") }, + {"test11", DRIVE FPL("/foo/test11"), true, DRIVE FPL("/foo/test11")}, // Path substring of an existing path. - { "test1", DRIVE FPL("/foo/test1"), true, DRIVE FPL("/foo/test1") }, + {"test1", DRIVE FPL("/foo/test1"), true, DRIVE FPL("/foo/test1")}, // Empty mount point name and path. - { "", DRIVE FPL(""), false, NULL }, + {"", DRIVE FPL(""), false, nullptr}, // Empty mount point name. - { "", DRIVE FPL("/ddd"), false, NULL }, + {"", DRIVE FPL("/ddd"), false, nullptr}, // Empty mount point path. - { "empty_path", FPL(""), true, FPL("") }, + {"empty_path", FPL(""), true, FPL("")}, // Name different from path's base name. - { "not_base_name", DRIVE FPL("/x/y/z"), true, DRIVE FPL("/x/y/z") }, + {"not_base_name", DRIVE FPL("/x/y/z"), true, DRIVE FPL("/x/y/z")}, // References parent. - { "invalid", DRIVE FPL("../foo/invalid"), false, NULL }, + {"invalid", DRIVE FPL("../foo/invalid"), false, nullptr}, // Relative path. - { "relative", DRIVE FPL("foo/relative"), false, NULL }, + {"relative", DRIVE FPL("foo/relative"), false, nullptr}, // Existing mount point path. - { "path_exists", DRIVE FPL("/foo/test"), false, NULL }, + {"path_exists", DRIVE FPL("/foo/test"), false, nullptr}, // Mount point with the same name exists. - { "test", DRIVE FPL("/foo/a/test_name_exists"), false, - DRIVE FPL("/foo/test") }, + {"test", DRIVE FPL("/foo/a/test_name_exists"), false, + DRIVE FPL("/foo/test")}, // Child of an existing mount point. - { "a1", DRIVE FPL("/foo/test/a"), false, NULL }, + {"a1", DRIVE FPL("/foo/test/a"), false, nullptr}, // Parent of an existing mount point. - { "foo1", DRIVE FPL("/foo"), false, NULL }, + {"foo1", DRIVE FPL("/foo"), false, nullptr}, // Bit bigger depth. - { "g", DRIVE FPL("/foo/a/b/c/d/e/f/g"), true, - DRIVE FPL("/foo/a/b/c/d/e/f/g") }, + {"g", DRIVE FPL("/foo/a/b/c/d/e/f/g"), true, + DRIVE FPL("/foo/a/b/c/d/e/f/g")}, // Sibling mount point (with similar name) exists. - { "ff", DRIVE FPL("/foo/a/b/c/d/e/ff"), true, - DRIVE FPL("/foo/a/b/c/d/e/ff") }, + {"ff", DRIVE FPL("/foo/a/b/c/d/e/ff"), true, + DRIVE FPL("/foo/a/b/c/d/e/ff")}, // Lexicographically last among existing mount points. - { "yyy", DRIVE FPL("/zzz/yyy"), true, DRIVE FPL("/zzz/yyy") }, + {"yyy", DRIVE FPL("/zzz/yyy"), true, DRIVE FPL("/zzz/yyy")}, // Parent of the lexicographically last mount point. - { "zzz1", DRIVE FPL("/zzz"), false, NULL }, + {"zzz1", DRIVE FPL("/zzz"), false, nullptr}, // Child of the lexicographically last mount point. - { "xxx1", DRIVE FPL("/zzz/yyy/xxx"), false, NULL }, + {"xxx1", DRIVE FPL("/zzz/yyy/xxx"), false, nullptr}, // Lexicographically first among existing mount points. - { "b", DRIVE FPL("/a/b"), true, DRIVE FPL("/a/b") }, + {"b", DRIVE FPL("/a/b"), true, DRIVE FPL("/a/b")}, // Parent of lexicographically first mount point. - { "a2", DRIVE FPL("/a"), false, NULL }, + {"a2", DRIVE FPL("/a"), false, nullptr}, // Child of lexicographically last mount point. - { "c1", DRIVE FPL("/a/b/c"), false, NULL }, + {"c1", DRIVE FPL("/a/b/c"), false, nullptr}, // Parent to all of the mount points. - { "root", DRIVE FPL("/"), false, NULL }, + {"root", DRIVE FPL("/"), false, nullptr}, // Path contains .. component. - { "funky", DRIVE FPL("/tt/fun/../funky"), false, NULL }, + {"funky", DRIVE FPL("/tt/fun/../funky"), false, nullptr}, // Windows separators. #if defined(FILE_PATH_USES_WIN_SEPARATORS) - { "win", DRIVE FPL("\\try\\separators\\win"), true, - DRIVE FPL("\\try\\separators\\win") }, - { "win1", DRIVE FPL("\\try/separators\\win1"), true, - DRIVE FPL("\\try/separators\\win1") }, - { "win2", DRIVE FPL("\\try/separators\\win"), false, NULL }, + {"win", DRIVE FPL("\\try\\separators\\win"), true, + DRIVE FPL("\\try\\separators\\win")}, + {"win1", DRIVE FPL("\\try/separators\\win1"), true, + DRIVE FPL("\\try/separators\\win1")}, + {"win2", DRIVE FPL("\\try/separators\\win"), false, nullptr}, #else - { "win", DRIVE FPL("\\separators\\win"), false, NULL }, - { "win1", DRIVE FPL("\\try/separators\\win1"), false, NULL }, + {"win", DRIVE FPL("\\separators\\win"), false, nullptr}, + {"win1", DRIVE FPL("\\try/separators\\win1"), false, nullptr}, #endif // Win separators, but relative path. - { "win2", DRIVE FPL("try\\separators\\win2"), false, NULL }, + {"win2", DRIVE FPL("try\\separators\\win2"), false, nullptr}, }; // Test adding mount points. @@ -124,7 +124,7 @@ // Test that final mount point presence state is as expected. for (size_t i = 0; i < arraysize(kTestCases); ++i) { base::FilePath found_path; - EXPECT_EQ(kTestCases[i].registered_path != NULL, + EXPECT_EQ(kTestCases[i].registered_path != nullptr, mount_points->GetRegisteredPath(kTestCases[i].name, &found_path)) << "Test case: " << i;
diff --git a/storage/browser/fileapi/file_system_backend.h b/storage/browser/fileapi/file_system_backend.h index cb81fd63..31afaaff 100644 --- a/storage/browser/fileapi/file_system_backend.h +++ b/storage/browser/fileapi/file_system_backend.h
@@ -83,7 +83,7 @@ virtual WatcherManager* GetWatcherManager(FileSystemType type) = 0; // Returns the specialized CopyOrMoveFileValidatorFactory for this backend - // and |type|. If |error_code| is File::FILE_OK and the result is NULL, + // and |type|. If |error_code| is File::FILE_OK and the result is nullptr, // then no validator is required. virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, base::File::Error* error_code) = 0; @@ -135,20 +135,20 @@ FileSystemContext* context) const = 0; // Returns the specialized FileSystemQuotaUtil for this backend. - // This could return NULL if this backend does not support quota. + // This could return nullptr if this backend does not support quota. virtual FileSystemQuotaUtil* GetQuotaUtil() = 0; - // Returns the update observer list for |type|. It may return NULL when no + // Returns the update observer list for |type|. It may return nullptr when no // observers are added. virtual const UpdateObserverList* GetUpdateObservers( FileSystemType type) const = 0; - // Returns the change observer list for |type|. It may return NULL when no + // Returns the change observer list for |type|. It may return nullptr when no // observers are added. virtual const ChangeObserverList* GetChangeObservers( FileSystemType type) const = 0; - // Returns the access observer list for |type|. It may return NULL when no + // Returns the access observer list for |type|. It may return nullptr when no // observers are added. virtual const AccessObserverList* GetAccessObservers( FileSystemType type) const = 0;
diff --git a/storage/browser/fileapi/file_system_context.cc b/storage/browser/fileapi/file_system_context.cc index bd051989..dd41383 100644 --- a/storage/browser/fileapi/file_system_context.cc +++ b/storage/browser/fileapi/file_system_context.cc
@@ -256,7 +256,7 @@ FileSystemContext::GetQuotaUtil(FileSystemType type) const { FileSystemBackend* backend = GetFileSystemBackend(type); if (!backend) - return NULL; + return nullptr; return backend->GetQuotaUtil(); } @@ -264,7 +264,7 @@ FileSystemType type) const { FileSystemBackend* backend = GetFileSystemBackend(type); if (!backend) - return NULL; + return nullptr; return backend->GetAsyncFileUtil(type); } @@ -275,7 +275,7 @@ *error_code = base::File::FILE_OK; FileSystemBackend* backend = GetFileSystemBackend(type); if (!backend) - return NULL; + return nullptr; return backend->GetCopyOrMoveFileValidatorFactory( type, error_code); } @@ -286,14 +286,14 @@ if (found != backend_map_.end()) return found->second; NOTREACHED() << "Unknown filesystem type: " << type; - return NULL; + return nullptr; } WatcherManager* FileSystemContext::GetWatcherManager( FileSystemType type) const { FileSystemBackend* backend = GetFileSystemBackend(type); if (!backend) - return NULL; + return nullptr; return backend->GetWatcherManager(type); } @@ -524,14 +524,14 @@ if (!url.is_valid()) { if (error_code) *error_code = base::File::FILE_ERROR_INVALID_URL; - return NULL; + return nullptr; } FileSystemBackend* backend = GetFileSystemBackend(url.type()); if (!backend) { if (error_code) *error_code = base::File::FILE_ERROR_FAILED; - return NULL; + return nullptr; } base::File::Error fs_error = base::File::FILE_OK;
diff --git a/storage/browser/fileapi/file_system_context.h b/storage/browser/fileapi/file_system_context.h index 24f576c..9fc8610 100644 --- a/storage/browser/fileapi/file_system_context.h +++ b/storage/browser/fileapi/file_system_context.h
@@ -108,8 +108,8 @@ // does). // // |external_mount_points| contains non-system external mount points available - // in the context. If not NULL, it will be used during URL cracking. - // |external_mount_points| may be NULL only on platforms different from + // in the context. If not nullptr, it will be used during URL cracking. + // |external_mount_points| may be nullptr only on platforms different from // ChromeOS (i.e. platforms that don't use external_mount_point_provider). // // |additional_backends| are added to the internal backend map @@ -134,7 +134,7 @@ bool DeleteDataForOriginOnFileTaskRunner(const GURL& origin_url); // Creates a new QuotaReservation for the given |origin_url| and |type|. - // Returns NULL if |type| does not support quota or reservation fails. + // Returns nullptr if |type| does not support quota or reservation fails. // This should be run on |default_file_task_runner_| and the returned value // should be destroyed on the runner. scoped_refptr<QuotaReservation> CreateQuotaReservationOnFileTaskRunner( @@ -149,7 +149,7 @@ void Shutdown(); // Returns a quota util for a given filesystem type. This may - // return NULL if the type does not support the usage tracking or + // return nullptr if the type does not support the usage tracking or // it is not a quota-managed storage. FileSystemQuotaUtil* GetQuotaUtil(FileSystemType type) const; @@ -157,23 +157,23 @@ AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) const; // Returns the appropriate CopyOrMoveFileValidatorFactory for the given - // |type|. If |error_code| is File::FILE_OK and the result is NULL, + // |type|. If |error_code| is File::FILE_OK and the result is nullptr, // then no validator is required. CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, base::File::Error* error_code) const; // Returns the file system backend instance for the given |type|. - // This may return NULL if it is given an invalid or unsupported filesystem + // This may return nullptr if it is given an invalid or unsupported filesystem // type. FileSystemBackend* GetFileSystemBackend( FileSystemType type) const; // Returns the watcher manager for the given |type|. - // This may return NULL if the type does not support watching. + // This may return nullptr if the type does not support watching. WatcherManager* GetWatcherManager(FileSystemType type) const; // Returns true for sandboxed filesystems. Currently this does - // the same as GetQuotaUtil(type) != NULL. (In an assumption that + // the same as GetQuotaUtil(type) != nullptr. (In an assumption that // all sandboxed filesystems must cooperate with QuotaManager so that // they can get deleted) bool IsSandboxFileSystem(FileSystemType type) const;
diff --git a/storage/browser/fileapi/file_system_context_unittest.cc b/storage/browser/fileapi/file_system_context_unittest.cc index d1d9059f..213db6e 100644 --- a/storage/browser/fileapi/file_system_context_unittest.cc +++ b/storage/browser/fileapi/file_system_context_unittest.cc
@@ -101,12 +101,12 @@ scoped_refptr<MockQuotaManager> mock_quota_manager_; }; -// It is not valid to pass NULL ExternalMountPoints to FileSystemContext on +// It is not valid to pass nullptr ExternalMountPoints to FileSystemContext on // ChromeOS. #if !defined(OS_CHROMEOS) TEST_F(FileSystemContextTest, NullExternalMountPoints) { scoped_refptr<FileSystemContext> file_system_context( - CreateFileSystemContextForTest(NULL)); + CreateFileSystemContextForTest(nullptr)); // Cracking system external mount and isolated mount points should work. std::string isolated_name = "root"; @@ -171,7 +171,7 @@ CreateFileSystemContextForTest(mount_points.get())); // Release a MountPoints reference created in the test. - mount_points = NULL; + mount_points = nullptr; // FileSystemContext should keep a reference to the |mount_points|, so it // should be able to resolve the URL.
diff --git a/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc index fd57b21..c7dac7e 100644 --- a/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc +++ b/storage/browser/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -133,7 +133,7 @@ special_storage_policy_ = new MockSpecialStoragePolicy; file_system_context_ = - CreateFileSystemContextForTesting(NULL, temp_dir_.GetPath()); + CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath()); file_system_context_->OpenFileSystem( GURL("http://remote/"), storage::kFileSystemTypeTemporary, @@ -145,8 +145,8 @@ void TearDown() override { // NOTE: order matters, request must die before delegate - request_.reset(NULL); - delegate_.reset(NULL); + request_.reset(nullptr); + delegate_.reset(nullptr); } void SetUpAutoMountContext(base::FilePath* mnt_point) { @@ -162,7 +162,8 @@ handlers.push_back(base::Bind(&TestAutoMountForURLRequest)); file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting( - NULL, std::move(additional_providers), handlers, temp_dir_.GetPath()); + nullptr, std::move(additional_providers), handlers, + temp_dir_.GetPath()); } void OnOpenFileSystem(const GURL& root_url, @@ -225,8 +226,9 @@ void EnsureFileExists(const base::StringPiece file_name) { base::FilePath path = base::FilePath().AppendASCII(file_name); std::unique_ptr<FileSystemOperationContext> context(NewOperationContext()); - ASSERT_EQ(base::File::FILE_OK, file_util()->EnsureFileExists( - context.get(), CreateURL(path), NULL)); + ASSERT_EQ( + base::File::FILE_OK, + file_util()->EnsureFileExists(context.get(), CreateURL(path), nullptr)); } void TruncateFile(const base::StringPiece file_name, int64_t length) { @@ -375,7 +377,7 @@ CreateDirectory("foo"); scoped_refptr<FileSystemContext> file_system_context = - CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.GetPath()); + CreateIncognitoFileSystemContextForTesting(nullptr, temp_dir_.GetPath()); TestRequestWithContext(CreateFileSystemURL("/"), file_system_context.get());
diff --git a/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc b/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc index 067efc3..444f2aef70 100644 --- a/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc +++ b/storage/browser/fileapi/file_system_file_stream_reader_unittest.cc
@@ -44,8 +44,8 @@ std::string* data, size_t size, int* result) { - ASSERT_TRUE(reader != NULL); - ASSERT_TRUE(result != NULL); + ASSERT_TRUE(reader != nullptr); + ASSERT_TRUE(result != nullptr); *result = net::OK; net::TestCompletionCallback callback; size_t total_bytes_read = 0; @@ -76,7 +76,7 @@ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); file_system_context_ = - CreateFileSystemContextForTesting(NULL, temp_dir_.GetPath()); + CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath()); file_system_context_->OpenFileSystem( GURL(kURLOrigin), storage::kFileSystemTypeTemporary, @@ -156,7 +156,7 @@ TEST_F(FileSystemFileStreamReaderTest, Empty) { const char kFileName[] = "empty"; - WriteFile(kFileName, NULL, 0, NULL); + WriteFile(kFileName, nullptr, 0, nullptr); std::unique_ptr<FileSystemFileStreamReader> reader( CreateFileReader(kFileName, 0, base::Time())); @@ -196,7 +196,7 @@ result = callback.WaitForResult(); ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result); - // With NULL expected modification time this should work. + // With nullptr expected modification time this should work. reader.reset(CreateFileReader(kTestFileName, 0, base::Time())); result = reader->GetLength(callback.callback()); if (result == net::ERR_IO_PENDING) @@ -238,7 +238,7 @@ ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result); ASSERT_EQ(0U, data.size()); - // With NULL expected modification time this should work. + // With nullptr expected modification time this should work. data.clear(); reader.reset(CreateFileReader(kTestFileName, 0, base::Time())); ReadFromReader(reader.get(), &data, kTestDataSize, &result);
diff --git a/storage/browser/fileapi/file_system_operation.h b/storage/browser/fileapi/file_system_operation.h index 55a613a..34754e5c 100644 --- a/storage/browser/fileapi/file_system_operation.h +++ b/storage/browser/fileapi/file_system_operation.h
@@ -15,6 +15,7 @@ #include "base/files/file_path.h" #include "base/process/process.h" #include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "storage/browser/blob/blob_reader.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/storage_browser_export.h" @@ -22,10 +23,6 @@ class Time; } -namespace net { -class URLRequest; -} - namespace storage { class ShareableFileReference; } @@ -106,7 +103,7 @@ // snapshot file. It can be set to let the chromium backend take // care of the life time of the snapshot file. Otherwise (if the returned // file does not require any handling) the implementation can just - // return NULL. In a more complex case, the implementaiton can manage + // return nullptr. In a more complex case, the implementation can manage // the lifetime of the snapshot file on its own (e.g. by its cache system) // but also can be notified via the reference when the file becomes no // longer necessary in the javascript world. @@ -321,10 +318,10 @@ virtual void Remove(const FileSystemURL& path, bool recursive, const StatusCallback& callback) = 0; - // Writes the data read from |blob_request| using |writer_delegate|. + // Writes the data read from |blob_reader| using |writer_delegate|. virtual void Write(const FileSystemURL& url, std::unique_ptr<FileWriterDelegate> writer_delegate, - std::unique_ptr<net::URLRequest> blob_request, + std::unique_ptr<BlobReader> blob_reader, const WriteCallback& callback) = 0; // Truncates a file at |path| to |length|. If |length| is larger than
diff --git a/storage/browser/fileapi/file_system_operation_impl.cc b/storage/browser/fileapi/file_system_operation_impl.cc index d2d05d2..d43cf07e 100644 --- a/storage/browser/fileapi/file_system_operation_impl.cc +++ b/storage/browser/fileapi/file_system_operation_impl.cc
@@ -191,12 +191,12 @@ void FileSystemOperationImpl::Write( const FileSystemURL& url, std::unique_ptr<FileWriterDelegate> writer_delegate, - std::unique_ptr<net::URLRequest> blob_request, + std::unique_ptr<BlobReader> blob_reader, const WriteCallback& callback) { DCHECK(SetPendingOperationType(kOperationWrite)); file_writer_delegate_ = std::move(writer_delegate); file_writer_delegate_->Start( - std::move(blob_request), + std::move(blob_reader), base::Bind(&FileSystemOperationImpl::DidWrite, weak_factory_.GetWeakPtr(), url, callback)); } @@ -377,7 +377,7 @@ std::unique_ptr<FileSystemOperationContext> operation_context) : file_system_context_(file_system_context), operation_context_(std::move(operation_context)), - async_file_util_(NULL), + async_file_util_(nullptr), pending_operation_(kOperationNone), weak_factory_(this) { weak_ptr_ = weak_factory_.GetWeakPtr();
diff --git a/storage/browser/fileapi/file_system_operation_impl.h b/storage/browser/fileapi/file_system_operation_impl.h index d253862..c113e996 100644 --- a/storage/browser/fileapi/file_system_operation_impl.h +++ b/storage/browser/fileapi/file_system_operation_impl.h
@@ -64,7 +64,7 @@ const StatusCallback& callback) override; void Write(const FileSystemURL& url, std::unique_ptr<FileWriterDelegate> writer_delegate, - std::unique_ptr<net::URLRequest> blob_request, + std::unique_ptr<BlobReader> blob_reader, const WriteCallback& callback) override; void Truncate(const FileSystemURL& url, int64_t length,
diff --git a/storage/browser/fileapi/file_system_operation_impl_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_unittest.cc index 7352c9c..293423f 100644 --- a/storage/browser/fileapi/file_system_operation_impl_unittest.cc +++ b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -73,7 +73,7 @@ quota_manager_ = new MockQuotaManager(false /* is_incognito */, base_dir, base::ThreadTaskRunnerHandle::Get().get(), - NULL /* special storage policy */); + nullptr /* special storage policy */); quota_manager_proxy_ = new MockQuotaManagerProxy( quota_manager(), base::ThreadTaskRunnerHandle::Get().get()); sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get()); @@ -85,8 +85,8 @@ void TearDown() override { // Let the client go away before dropping a ref of the quota manager proxy. quota_manager_proxy()->SimulateQuotaManagerDestroyed(); - quota_manager_ = NULL; - quota_manager_proxy_ = NULL; + quota_manager_ = nullptr; + quota_manager_proxy_ = nullptr; sandbox_file_system_.TearDown(); } @@ -265,7 +265,7 @@ int64_t ComputePathCost(const FileSystemURL& url) { int64_t base_usage; - GetUsageAndQuota(&base_usage, NULL); + GetUsageAndQuota(&base_usage, nullptr); AsyncFileTestHelper::CreateFile( sandbox_file_system_.file_system_context(), url); @@ -274,13 +274,13 @@ change_observer()->ResetCount(); int64_t total_usage; - GetUsageAndQuota(&total_usage, NULL); + GetUsageAndQuota(&total_usage, nullptr); return total_usage - base_usage; } void GrantQuotaForCurrentUsage() { int64_t usage; - GetUsageAndQuota(&usage, NULL); + GetUsageAndQuota(&usage, nullptr); quota_manager()->SetQuota(sandbox_file_system_.origin(), sandbox_file_system_.storage_type(), usage); @@ -288,13 +288,13 @@ int64_t GetUsage() { int64_t usage = 0; - GetUsageAndQuota(&usage, NULL); + GetUsageAndQuota(&usage, nullptr); return usage; } void AddQuota(int64_t quota_delta) { int64_t quota; - GetUsageAndQuota(NULL, "a); + GetUsageAndQuota(nullptr, "a); quota_manager()->SetQuota(sandbox_file_system_.origin(), sandbox_file_system_.storage_type(), quota + quota_delta); @@ -834,7 +834,7 @@ FileSystemURL dest_dir(CreateDirectory("dest")); int64_t before_usage; - GetUsageAndQuota(&before_usage, NULL); + GetUsageAndQuota(&before_usage, nullptr); // Check that the file copied and corresponding usage increased. EXPECT_EQ( @@ -844,7 +844,7 @@ EXPECT_EQ(1, change_observer()->create_file_count()); EXPECT_TRUE(FileExists("dest/file")); int64_t after_usage; - GetUsageAndQuota(&after_usage, NULL); + GetUsageAndQuota(&after_usage, nullptr); EXPECT_GT(after_usage, before_usage); // Compare contents of src and copied file. @@ -1206,7 +1206,7 @@ // The FileSystemOpration implementation does not create a // shareable file reference. - EXPECT_EQ(NULL, shareable_file_ref()); + EXPECT_EQ(nullptr, shareable_file_ref()); } TEST_F(FileSystemOperationImplTest,
diff --git a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc index a7c51e0..70b2bfb5 100644 --- a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc +++ b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -73,7 +73,7 @@ quota_manager_ = new MockQuotaManager(false /* is_incognito */, dir_.GetPath(), base::ThreadTaskRunnerHandle::Get().get(), - NULL /* special storage policy */); + nullptr /* special storage policy */); virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file")); file_system_context_ = CreateFileSystemContextForTesting( @@ -90,8 +90,8 @@ } void TearDown() override { - quota_manager_ = NULL; - file_system_context_ = NULL; + quota_manager_ = nullptr; + file_system_context_ = nullptr; base::RunLoop().RunUntilIdle(); } @@ -178,9 +178,9 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteSuccess) { ScopedTextBlob blob(url_request_context(), "blob-id:success", "Hello, world!\n"); - file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), - blob.GetBlobDataHandle(), 0, RecordWriteCallback()); + file_system_context_->operation_runner()->Write(URLForPath(virtual_path_), + blob.GetBlobDataHandle(), 0, + RecordWriteCallback()); base::RunLoop().Run(); EXPECT_EQ(14, bytes_written()); @@ -192,9 +192,9 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) { ScopedTextBlob blob(url_request_context(), "blob_id:zero", ""); - file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), - blob.GetBlobDataHandle(), 0, RecordWriteCallback()); + file_system_context_->operation_runner()->Write(URLForPath(virtual_path_), + blob.GetBlobDataHandle(), 0, + RecordWriteCallback()); base::RunLoop().Run(); EXPECT_EQ(0, bytes_written()); @@ -204,11 +204,11 @@ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); } -TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) { +TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlob) { std::unique_ptr<storage::BlobDataHandle> null_handle; - file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), std::move(null_handle), - 0, RecordWriteCallback()); + file_system_context_->operation_runner()->Write(URLForPath(virtual_path_), + std::move(null_handle), 0, + RecordWriteCallback()); base::RunLoop().Run(); EXPECT_EQ(0, bytes_written()); @@ -222,7 +222,6 @@ ScopedTextBlob blob(url_request_context(), "blob_id:writeinvalidfile", "It\'ll not be written."); file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))), blob.GetBlobDataHandle(), 0, RecordWriteCallback()); base::RunLoop().Run(); @@ -242,9 +241,9 @@ ScopedTextBlob blob(url_request_context(), "blob:writedir", "It\'ll not be written, too."); - file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_dir_path), - blob.GetBlobDataHandle(), 0, RecordWriteCallback()); + file_system_context_->operation_runner()->Write(URLForPath(virtual_dir_path), + blob.GetBlobDataHandle(), 0, + RecordWriteCallback()); base::RunLoop().Run(); EXPECT_EQ(0, bytes_written()); @@ -262,9 +261,9 @@ ScopedTextBlob blob(url_request_context(), "blob:success", "Hello, world!\n"); quota_manager_->SetQuota( kOrigin, FileSystemTypeToQuotaStorageType(kFileSystemType), 10); - file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), - blob.GetBlobDataHandle(), 0, RecordWriteCallback()); + file_system_context_->operation_runner()->Write(URLForPath(virtual_path_), + blob.GetBlobDataHandle(), 0, + RecordWriteCallback()); base::RunLoop().Run(); EXPECT_EQ(10, bytes_written()); @@ -277,9 +276,9 @@ TEST_F(FileSystemOperationImplWriteTest, TestImmediateCancelSuccessfulWrite) { ScopedTextBlob blob(url_request_context(), "blob:success", "Hello, world!\n"); FileSystemOperationRunner::OperationID id = - file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(virtual_path_), - blob.GetBlobDataHandle(), 0, RecordWriteCallback()); + file_system_context_->operation_runner()->Write(URLForPath(virtual_path_), + blob.GetBlobDataHandle(), + 0, RecordWriteCallback()); file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback()); // We use RunAllPendings() instead of Run() here, because we won't dispatch // callbacks after Cancel() is issued (so no chance to Quit) nor do we need @@ -301,7 +300,6 @@ "It\'ll not be written."); FileSystemOperationRunner::OperationID id = file_system_context_->operation_runner()->Write( - &url_request_context(), URLForPath(base::FilePath(FILE_PATH_LITERAL("nonexist"))), blob.GetBlobDataHandle(), 0, RecordWriteCallback()); file_system_context_->operation_runner()->Cancel(id, RecordCancelCallback());
diff --git a/storage/browser/fileapi/file_system_operation_runner.cc b/storage/browser/fileapi/file_system_operation_runner.cc index 51c4066..62f62a0 100644 --- a/storage/browser/fileapi/file_system_operation_runner.cc +++ b/storage/browser/fileapi/file_system_operation_runner.cc
@@ -237,7 +237,6 @@ } OperationID FileSystemOperationRunner::Write( - const net::URLRequestContext* url_request_context, const FileSystemURL& url, std::unique_ptr<storage::BlobDataHandle> blob, int64_t offset, @@ -264,12 +263,12 @@ std::unique_ptr<FileWriterDelegate> writer_delegate(new FileWriterDelegate( std::move(writer), url.mount_option().flush_policy())); - std::unique_ptr<net::URLRequest> blob_request( - storage::BlobProtocolHandler::CreateBlobRequest( - std::move(blob), url_request_context, writer_delegate.get())); + std::unique_ptr<BlobReader> blob_reader; + if (blob) + blob_reader = blob->CreateReader(); PrepareForWrite(id, url); - operation_raw->Write(url, std::move(writer_delegate), std::move(blob_request), + operation_raw->Write(url, std::move(writer_delegate), std::move(blob_reader), base::Bind(&FileSystemOperationRunner::DidWrite, weak_ptr_, id, callback)); return id; @@ -377,7 +376,7 @@ base::AutoReset<bool> beginning(&is_beginning_operation_, true); if (!operation_raw) { DidCreateSnapshot(id, callback, error, base::File::Info(), base::FilePath(), - NULL); + nullptr); return id; } PrepareForRead(id, url);
diff --git a/storage/browser/fileapi/file_system_operation_runner.h b/storage/browser/fileapi/file_system_operation_runner.h index f298e11..cf21797 100644 --- a/storage/browser/fileapi/file_system_operation_runner.h +++ b/storage/browser/fileapi/file_system_operation_runner.h
@@ -21,10 +21,6 @@ #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/storage_browser_export.h" -namespace net { -class URLRequestContext; -} - namespace storage { class FileSystemURL; @@ -114,9 +110,7 @@ const StatusCallback& callback); // Writes contents of |blob_url| to |url| at |offset|. - // |url_request_context| is used to read contents in |blob|. - OperationID Write(const net::URLRequestContext* url_request_context, - const FileSystemURL& url, + OperationID Write(const FileSystemURL& url, std::unique_ptr<storage::BlobDataHandle> blob, int64_t offset, const WriteCallback& callback);
diff --git a/storage/browser/fileapi/file_system_quota_client_unittest.cc b/storage/browser/fileapi/file_system_quota_client_unittest.cc index 9676d04..a6dc424 100644 --- a/storage/browser/fileapi/file_system_quota_client_unittest.cc +++ b/storage/browser/fileapi/file_system_quota_client_unittest.cc
@@ -52,7 +52,7 @@ void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); file_system_context_ = - CreateFileSystemContextForTesting(NULL, data_dir_.GetPath()); + CreateFileSystemContextForTesting(nullptr, data_dir_.GetPath()); } struct TestFile { @@ -252,7 +252,7 @@ TEST_F(FileSystemQuotaClientTest, NoFileTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); @@ -264,8 +264,8 @@ TEST_F(FileSystemQuotaClientTest, OneFileTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {false, "foo", 4921, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {false, "foo", 4921, kDummyURL1, kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( @@ -280,9 +280,9 @@ TEST_F(FileSystemQuotaClientTest, TwoFilesTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {false, "foo", 10310, kDummyURL1, kTemporary}, - {false, "bar", 41, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {false, "foo", 10310, kDummyURL1, kTemporary}, + {false, "bar", 41, kDummyURL1, kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( @@ -297,10 +297,10 @@ TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {false, "foo", 0, kDummyURL1, kTemporary}, - {false, "bar", 0, kDummyURL1, kTemporary}, - {false, "baz", 0, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {false, "foo", 0, kDummyURL1, kTemporary}, + {false, "bar", 0, kDummyURL1, kTemporary}, + {false, "baz", 0, kDummyURL1, kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( @@ -315,10 +315,10 @@ TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {true, "dirtest", 0, kDummyURL1, kTemporary}, - {false, "dirtest/foo", 11921, kDummyURL1, kTemporary}, - {false, "bar", 4814, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {true, "dirtest", 0, kDummyURL1, kTemporary}, + {false, "dirtest/foo", 11921, kDummyURL1, kTemporary}, + {false, "bar", 4814, kDummyURL1, kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( @@ -333,14 +333,14 @@ TEST_F(FileSystemQuotaClientTest, MultiTypeTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {true, "dirtest", 0, kDummyURL1, kTemporary}, - {false, "dirtest/foo", 133, kDummyURL1, kTemporary}, - {false, "bar", 14, kDummyURL1, kTemporary}, - {true, NULL, 0, kDummyURL1, kPersistent}, - {true, "dirtest", 0, kDummyURL1, kPersistent}, - {false, "dirtest/foo", 193, kDummyURL1, kPersistent}, - {false, "bar", 9, kDummyURL1, kPersistent}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {true, "dirtest", 0, kDummyURL1, kTemporary}, + {false, "dirtest/foo", 133, kDummyURL1, kTemporary}, + {false, "bar", 14, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kPersistent}, + {true, "dirtest", 0, kDummyURL1, kPersistent}, + {false, "dirtest/foo", 193, kDummyURL1, kPersistent}, + {false, "bar", 9, kDummyURL1, kPersistent}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost_temporary = @@ -361,22 +361,22 @@ TEST_F(FileSystemQuotaClientTest, MultiDomainTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {true, "dir1", 0, kDummyURL1, kTemporary}, - {false, "dir1/foo", 1331, kDummyURL1, kTemporary}, - {false, "bar", 134, kDummyURL1, kTemporary}, - {true, NULL, 0, kDummyURL1, kPersistent}, - {true, "dir2", 0, kDummyURL1, kPersistent}, - {false, "dir2/foo", 1903, kDummyURL1, kPersistent}, - {false, "bar", 19, kDummyURL1, kPersistent}, - {true, NULL, 0, kDummyURL2, kTemporary}, - {true, "dom", 0, kDummyURL2, kTemporary}, - {false, "dom/fan", 1319, kDummyURL2, kTemporary}, - {false, "bar", 113, kDummyURL2, kTemporary}, - {true, NULL, 0, kDummyURL2, kPersistent}, - {true, "dom", 0, kDummyURL2, kPersistent}, - {false, "dom/fan", 2013, kDummyURL2, kPersistent}, - {false, "baz", 18, kDummyURL2, kPersistent}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {true, "dir1", 0, kDummyURL1, kTemporary}, + {false, "dir1/foo", 1331, kDummyURL1, kTemporary}, + {false, "bar", 134, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kPersistent}, + {true, "dir2", 0, kDummyURL1, kPersistent}, + {false, "dir2/foo", 1903, kDummyURL1, kPersistent}, + {false, "bar", 19, kDummyURL1, kPersistent}, + {true, nullptr, 0, kDummyURL2, kTemporary}, + {true, "dom", 0, kDummyURL2, kTemporary}, + {false, "dom/fan", 1319, kDummyURL2, kTemporary}, + {false, "bar", 113, kDummyURL2, kTemporary}, + {true, nullptr, 0, kDummyURL2, kPersistent}, + {true, "dom", 0, kDummyURL2, kPersistent}, + {false, "dom/fan", 2013, kDummyURL2, kPersistent}, + {false, "baz", 18, kDummyURL2, kPersistent}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost_temporary1 = @@ -407,9 +407,9 @@ TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {false, "foo", 11, kDummyURL1, kTemporary}, - {false, "bar", 22, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {false, "foo", 11, kDummyURL1, kTemporary}, + {false, "bar", 22, kDummyURL1, kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost = ComputeFilePathsCostForOriginAndType( @@ -437,9 +437,9 @@ TEST_F(FileSystemQuotaClientTest, GetOriginsForType) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {true, NULL, 0, kDummyURL2, kTemporary}, - {true, NULL, 0, kDummyURL3, kPersistent}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL2, kTemporary}, + {true, nullptr, 0, kDummyURL3, kPersistent}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); @@ -462,11 +462,11 @@ const char* kURL4 = "http://foo2.com/"; const char* kURL5 = "http://foo.com:2/"; const TestFile kFiles[] = { - {true, NULL, 0, kURL1, kTemporary}, - {true, NULL, 0, kURL2, kTemporary}, - {true, NULL, 0, kURL3, kTemporary}, - {true, NULL, 0, kURL4, kTemporary}, - {true, NULL, 0, kURL5, kPersistent}, + {true, nullptr, 0, kURL1, kTemporary}, + {true, nullptr, 0, kURL2, kTemporary}, + {true, nullptr, 0, kURL3, kTemporary}, + {true, nullptr, 0, kURL4, kTemporary}, + {true, nullptr, 0, kURL5, kPersistent}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); @@ -485,8 +485,8 @@ TEST_F(FileSystemQuotaClientTest, IncognitoTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(true)); const TestFile kFiles[] = { - {true, NULL, 0, kDummyURL1, kTemporary}, - {false, "foo", 10, kDummyURL1, kTemporary}, + {true, nullptr, 0, kDummyURL1, kTemporary}, + {false, "foo", 10, kDummyURL1, kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); @@ -505,20 +505,20 @@ TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) { std::unique_ptr<FileSystemQuotaClient> quota_client(NewQuotaClient(false)); const TestFile kFiles[] = { - {true, NULL, 0, "http://foo.com/", kTemporary}, - {false, "a", 1, "http://foo.com/", kTemporary}, - {true, NULL, 0, "https://foo.com/", kTemporary}, - {false, "b", 2, "https://foo.com/", kTemporary}, - {true, NULL, 0, "http://foo.com/", kPersistent}, - {false, "c", 4, "http://foo.com/", kPersistent}, - {true, NULL, 0, "http://bar.com/", kTemporary}, - {false, "d", 8, "http://bar.com/", kTemporary}, - {true, NULL, 0, "http://bar.com/", kPersistent}, - {false, "e", 16, "http://bar.com/", kPersistent}, - {true, NULL, 0, "https://bar.com/", kPersistent}, - {false, "f", 32, "https://bar.com/", kPersistent}, - {true, NULL, 0, "https://bar.com/", kTemporary}, - {false, "g", 64, "https://bar.com/", kTemporary}, + {true, nullptr, 0, "http://foo.com/", kTemporary}, + {false, "a", 1, "http://foo.com/", kTemporary}, + {true, nullptr, 0, "https://foo.com/", kTemporary}, + {false, "b", 2, "https://foo.com/", kTemporary}, + {true, nullptr, 0, "http://foo.com/", kPersistent}, + {false, "c", 4, "http://foo.com/", kPersistent}, + {true, nullptr, 0, "http://bar.com/", kTemporary}, + {false, "d", 8, "http://bar.com/", kTemporary}, + {true, nullptr, 0, "http://bar.com/", kPersistent}, + {false, "e", 16, "http://bar.com/", kPersistent}, + {true, nullptr, 0, "https://bar.com/", kPersistent}, + {false, "f", 32, "https://bar.com/", kPersistent}, + {true, nullptr, 0, "https://bar.com/", kTemporary}, + {false, "g", 64, "https://bar.com/", kTemporary}, }; InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles)); const int64_t file_paths_cost_temporary_foo_https =
diff --git a/storage/browser/fileapi/file_system_url_request_job.cc b/storage/browser/fileapi/file_system_url_request_job.cc index a271317..152d67f 100644 --- a/storage/browser/fileapi/file_system_url_request_job.cc +++ b/storage/browser/fileapi/file_system_url_request_job.cc
@@ -86,7 +86,7 @@ DCHECK_NE(dest_size, 0); DCHECK_GE(remaining_bytes_, 0); - if (reader_.get() == NULL) + if (reader_.get() == nullptr) return net::ERR_FAILED; if (remaining_bytes_ < dest_size)
diff --git a/storage/browser/fileapi/file_system_url_request_job_unittest.cc b/storage/browser/fileapi/file_system_url_request_job_unittest.cc index 2caef9d..4e64cef 100644 --- a/storage/browser/fileapi/file_system_url_request_job_unittest.cc +++ b/storage/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -139,7 +139,7 @@ // We use the main thread so that we can get the root path synchronously. // TODO(adamk): Run this on the FILE thread we've created as well. file_system_context_ = - CreateFileSystemContextForTesting(NULL, temp_dir_.GetPath()); + CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath()); file_system_context_->OpenFileSystem( GURL("http://remote/"), storage::kFileSystemTypeTemporary, @@ -168,7 +168,8 @@ handlers.push_back(base::BindRepeating(&TestAutoMountForURLRequest)); file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting( - NULL, std::move(additional_providers), handlers, temp_dir_.GetPath()); + nullptr, std::move(additional_providers), handlers, + temp_dir_.GetPath()); ASSERT_EQ(static_cast<int>(sizeof(kTestFileData)) - 1, base::WriteFile(mnt_point.AppendASCII("foo"), kTestFileData, @@ -204,12 +205,12 @@ } void TestRequest(const GURL& url) { - TestRequestHelper(url, NULL, true, file_system_context_.get()); + TestRequestHelper(url, nullptr, true, file_system_context_.get()); } void TestRequestWithContext(const GURL& url, FileSystemContext* file_system_context) { - TestRequestHelper(url, NULL, true, file_system_context); + TestRequestHelper(url, nullptr, true, file_system_context); } void TestRequestWithHeaders(const GURL& url, @@ -218,7 +219,7 @@ } void TestRequestNoRun(const GURL& url) { - TestRequestHelper(url, NULL, false, file_system_context_.get()); + TestRequestHelper(url, nullptr, false, file_system_context_.get()); } void CreateDirectory(const base::StringPiece& dir_name) { @@ -419,7 +420,7 @@ // Creates a new filesystem context for incognito mode. scoped_refptr<FileSystemContext> file_system_context = - CreateIncognitoFileSystemContextForTesting(NULL, temp_dir_.GetPath()); + CreateIncognitoFileSystemContextForTesting(nullptr, temp_dir_.GetPath()); // The request should return NOT_FOUND error if it's in incognito mode. TestRequestWithContext(CreateFileSystemURL("file"),
diff --git a/storage/browser/fileapi/file_writer_delegate.cc b/storage/browser/fileapi/file_writer_delegate.cc index 9237aeb..7a64139b 100644 --- a/storage/browser/fileapi/file_writer_delegate.cc +++ b/storage/browser/fileapi/file_writer_delegate.cc
@@ -40,16 +40,35 @@ FileWriterDelegate::~FileWriterDelegate() = default; -void FileWriterDelegate::Start(std::unique_ptr<net::URLRequest> request, +void FileWriterDelegate::Start(std::unique_ptr<BlobReader> blob_reader, const DelegateWriteCallback& write_callback) { write_callback_ = write_callback; - request_ = std::move(request); - request_->Start(); + + if (!blob_reader) { + OnReadError(base::File::FILE_ERROR_FAILED); + return; + } + + blob_reader_ = std::move(blob_reader); + BlobReader::Status status = blob_reader_->CalculateSize(base::BindOnce( + &FileWriterDelegate::OnDidCalculateSize, weak_factory_.GetWeakPtr())); + switch (status) { + case BlobReader::Status::NET_ERROR: + OnDidCalculateSize(blob_reader_->net_error()); + return; + case BlobReader::Status::DONE: + OnDidCalculateSize(net::OK); + return; + case BlobReader::Status::IO_PENDING: + // Do nothing. + return; + } + NOTREACHED(); } void FileWriterDelegate::Cancel() { - // Destroy the request and invalidate weak ptrs to prevent pending callbacks. - request_.reset(); + // Destroy the reader and invalidate weak ptrs to prevent pending callbacks. + blob_reader_ = nullptr; weak_factory_.InvalidateWeakPtrs(); const int status = file_stream_writer_->Cancel( @@ -63,53 +82,21 @@ } } -void FileWriterDelegate::OnReceivedRedirect( - net::URLRequest* request, - const net::RedirectInfo& redirect_info, - bool* defer_redirect) { - NOTREACHED(); - OnReadError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnAuthRequired(net::URLRequest* request, - net::AuthChallengeInfo* auth_info) { - NOTREACHED(); - OnReadError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnCertificateRequested( - net::URLRequest* request, - net::SSLCertRequestInfo* cert_request_info) { - NOTREACHED(); - OnReadError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnSSLCertificateError(net::URLRequest* request, - const net::SSLInfo& ssl_info, - bool fatal) { - NOTREACHED(); - OnReadError(base::File::FILE_ERROR_SECURITY); -} - -void FileWriterDelegate::OnResponseStarted(net::URLRequest* request, - int net_error) { +void FileWriterDelegate::OnDidCalculateSize(int net_error) { DCHECK_NE(net::ERR_IO_PENDING, net_error); - DCHECK_EQ(request_.get(), request); - if (net_error != net::OK || request->GetResponseCode() != 200) { - OnReadError(base::File::FILE_ERROR_FAILED); + if (net_error != net::OK) { + OnReadError(NetErrorToFileError(net_error)); return; } Read(); } -void FileWriterDelegate::OnReadCompleted(net::URLRequest* request, - int bytes_read) { +void FileWriterDelegate::OnReadCompleted(int bytes_read) { DCHECK_NE(net::ERR_IO_PENDING, bytes_read); - DCHECK_EQ(request_.get(), request); if (bytes_read < 0) { - OnReadError(base::File::FILE_ERROR_FAILED); + OnReadError(NetErrorToFileError(bytes_read)); return; } OnDataReceived(bytes_read); @@ -117,17 +104,24 @@ void FileWriterDelegate::Read() { bytes_written_ = 0; - bytes_read_ = request_->Read(io_buffer_.get(), io_buffer_->size()); - if (bytes_read_ == net::ERR_IO_PENDING) - return; - - if (bytes_read_ >= 0) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&FileWriterDelegate::OnDataReceived, - weak_factory_.GetWeakPtr(), bytes_read_)); - } else { - OnReadError(base::File::FILE_ERROR_FAILED); + BlobReader::Status status = + blob_reader_->Read(io_buffer_.get(), io_buffer_->size(), &bytes_read_, + base::BindOnce(&FileWriterDelegate::OnReadCompleted, + weak_factory_.GetWeakPtr())); + switch (status) { + case BlobReader::Status::NET_ERROR: + OnReadCompleted(blob_reader_->net_error()); + return; + case BlobReader::Status::DONE: + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&FileWriterDelegate::OnReadCompleted, + weak_factory_.GetWeakPtr(), bytes_read_)); + return; + case BlobReader::Status::IO_PENDING: + // Do nothing. + return; } + NOTREACHED(); } void FileWriterDelegate::OnDataReceived(int bytes_read) { @@ -195,8 +189,8 @@ return; } - // Destroy the request and invalidate weak ptrs to prevent pending callbacks. - request_.reset(); + // Destroy the reader and invalidate weak ptrs to prevent pending callbacks. + blob_reader_.reset(); weak_factory_.InvalidateWeakPtrs(); if (writing_started_) @@ -206,8 +200,8 @@ } void FileWriterDelegate::OnWriteError(base::File::Error error) { - // Destroy the request and invalidate weak ptrs to prevent pending callbacks. - request_.reset(); + // Destroy the reader and invalidate weak ptrs to prevent pending callbacks. + blob_reader_.reset(); weak_factory_.InvalidateWeakPtrs(); // Errors when writing are not recoverable, so don't bother flushing.
diff --git a/storage/browser/fileapi/file_writer_delegate.h b/storage/browser/fileapi/file_writer_delegate.h index ed134c18..3671c3b 100644 --- a/storage/browser/fileapi/file_writer_delegate.h +++ b/storage/browser/fileapi/file_writer_delegate.h
@@ -16,7 +16,7 @@ #include "base/time/time.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" -#include "net/url_request/url_request.h" +#include "storage/browser/blob/blob_reader.h" #include "storage/browser/storage_browser_export.h" namespace storage { @@ -24,7 +24,7 @@ class FileStreamWriter; enum class FlushPolicy; -class STORAGE_EXPORT FileWriterDelegate : public net::URLRequest::Delegate { +class STORAGE_EXPORT FileWriterDelegate { public: enum WriteProgressStatus { SUCCESS_IO_PENDING, @@ -40,9 +40,9 @@ FileWriterDelegate(std::unique_ptr<FileStreamWriter> file_writer, FlushPolicy flush_policy); - ~FileWriterDelegate() override; + virtual ~FileWriterDelegate(); - void Start(std::unique_ptr<net::URLRequest> request, + void Start(std::unique_ptr<BlobReader> blob_reader, const DelegateWriteCallback& write_callback); // Cancels the current write operation. This will synchronously or @@ -50,29 +50,15 @@ // deleting this). void Cancel(); - void OnReceivedRedirect(net::URLRequest* request, - const net::RedirectInfo& redirect_info, - bool* defer_redirect) override; - void OnAuthRequired(net::URLRequest* request, - net::AuthChallengeInfo* auth_info) override; - void OnCertificateRequested( - net::URLRequest* request, - net::SSLCertRequestInfo* cert_request_info) override; - void OnSSLCertificateError(net::URLRequest* request, - const net::SSLInfo& ssl_info, - bool fatal) override; - void OnResponseStarted(net::URLRequest* request, int net_error) override; - void OnReadCompleted(net::URLRequest* request, int bytes_read) override; - protected: // Virtual for tests. virtual void OnDataReceived(int bytes_read); private: - void OnGetFileInfoAndStartRequest(std::unique_ptr<net::URLRequest> request, - base::File::Error error, - const base::File::Info& file_info); + void OnDidCalculateSize(int net_error); + void Read(); + void OnReadCompleted(int bytes_read); void Write(); void OnDataWritten(int write_response); void OnReadError(base::File::Error error); @@ -101,7 +87,7 @@ base::File::Error saved_read_error_ = base::File::FILE_OK; scoped_refptr<net::IOBufferWithSize> io_buffer_; scoped_refptr<net::DrainableIOBuffer> cursor_; - std::unique_ptr<net::URLRequest> request_; + std::unique_ptr<BlobReader> blob_reader_; base::WeakPtrFactory<FileWriterDelegate> weak_factory_;
diff --git a/storage/browser/fileapi/file_writer_delegate_unittest.cc b/storage/browser/fileapi/file_writer_delegate_unittest.cc index 2839396..eb78e5f 100644 --- a/storage/browser/fileapi/file_writer_delegate_unittest.cc +++ b/storage/browser/fileapi/file_writer_delegate_unittest.cc
@@ -14,9 +14,9 @@ #include "base/location.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "net/base/io_buffer.h" #include "net/base/request_priority.h" @@ -27,6 +27,8 @@ #include "net/url_request/url_request_job.h" #include "net/url_request/url_request_job_factory.h" #include "net/url_request/url_request_status.h" +#include "storage/browser/blob/blob_data_builder.h" +#include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_quota_util.h" #include "storage/browser/fileapi/file_writer_delegate.h" @@ -92,7 +94,9 @@ class FileWriterDelegateTest : public PlatformTest { public: - FileWriterDelegateTest() = default; + FileWriterDelegateTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO) {} protected: void SetUp() override; @@ -146,157 +150,57 @@ return base::BindRepeating(&Result::DidWrite, base::Unretained(result)); } - // Creates and sets up a FileWriterDelegate for writing the given |blob_url|, - // and creates a new FileWriterDelegate for the file. + // Creates and sets up a FileWriterDelegate for writing the given + // |blob_content|, and creates a new FileWriterDelegate for the file. void PrepareForWrite(const char* test_file_path, - const GURL& blob_url, int64_t offset, int64_t allowed_growth) { file_writer_delegate_ = CreateWriterDelegate(test_file_path, offset, allowed_growth); - request_ = empty_context_.CreateRequest(blob_url, net::DEFAULT_PRIORITY, - file_writer_delegate_.get(), - TRAFFIC_ANNOTATION_FOR_TESTS); + } + + std::unique_ptr<storage::BlobDataHandle> CreateBlob( + const std::string& contents) { + auto builder = std::make_unique<storage::BlobDataBuilder>("blob-uuid"); + builder->AppendData(contents); + return blob_context_->AddFinishedBlob(std::move(builder)); } // This should be alive until the very end of this instance. - base::MessageLoopForIO loop_; + base::test::ScopedTaskEnvironment scoped_task_environment_; scoped_refptr<storage::FileSystemContext> file_system_context_; + std::unique_ptr<storage::BlobStorageContext> blob_context_; - net::URLRequestContext empty_context_; std::unique_ptr<FileWriterDelegate> file_writer_delegate_; - std::unique_ptr<net::URLRequest> request_; - std::unique_ptr<BlobURLRequestJobFactory> job_factory_; base::ScopedTempDir dir_; - - static const char* content_; }; -const char* FileWriterDelegateTest::content_ = NULL; - -namespace { - -static std::string g_content; - -class FileWriterDelegateTestJob : public net::URLRequestJob { - public: - FileWriterDelegateTestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& content) - : net::URLRequestJob(request, network_delegate), - content_(content), - remaining_bytes_(content.length()), - cursor_(0), - weak_factory_(this) {} - - void Start() override { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&FileWriterDelegateTestJob::NotifyHeadersComplete, - weak_factory_.GetWeakPtr())); - } - - int ReadRawData(net::IOBuffer* buf, int buf_size) override { - if (remaining_bytes_ < buf_size) - buf_size = remaining_bytes_; - - for (int i = 0; i < buf_size; ++i) - buf->data()[i] = content_[cursor_++]; - remaining_bytes_ -= buf_size; - - return buf_size; - } - - void GetResponseInfo(net::HttpResponseInfo* info) override { - const char kStatus[] = "HTTP/1.1 200 OK\0"; - const size_t kStatusLen = arraysize(kStatus); - - info->headers = - new net::HttpResponseHeaders(std::string(kStatus, kStatusLen)); - } - - protected: - ~FileWriterDelegateTestJob() override = default; - - private: - std::string content_; - int remaining_bytes_; - int cursor_; - - base::WeakPtrFactory<FileWriterDelegateTestJob> weak_factory_; -}; - -class BlobURLRequestJobFactory : public net::URLRequestJobFactory { - public: - explicit BlobURLRequestJobFactory(const char** content_data) - : content_data_(content_data) { - } - - net::URLRequestJob* MaybeCreateJobWithProtocolHandler( - const std::string& scheme, - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { - return new FileWriterDelegateTestJob(request, network_delegate, - *content_data_); - } - - net::URLRequestJob* MaybeInterceptRedirect( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const GURL& location) const override { - return nullptr; - } - - net::URLRequestJob* MaybeInterceptResponse( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { - return nullptr; - } - - bool IsHandledProtocol(const std::string& scheme) const override { - return scheme == "blob"; - } - - bool IsSafeRedirectTarget(const GURL& location) const override { - return true; - } - - private: - const char** content_data_; - - DISALLOW_COPY_AND_ASSIGN(BlobURLRequestJobFactory); -}; - -} // namespace (anonymous) - void FileWriterDelegateTest::SetUp() { ASSERT_TRUE(dir_.CreateUniqueTempDir()); file_system_context_ = - CreateFileSystemContextForTesting(NULL, dir_.GetPath()); + CreateFileSystemContextForTesting(nullptr, dir_.GetPath()); ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateFile(file_system_context_.get(), GetFileSystemURL("test"))); - job_factory_ = std::make_unique<BlobURLRequestJobFactory>(&content_); - empty_context_.set_job_factory(job_factory_.get()); + blob_context_ = std::make_unique<storage::BlobStorageContext>(); } void FileWriterDelegateTest::TearDown() { - file_system_context_ = NULL; + file_system_context_ = nullptr; base::RunLoop().RunUntilIdle(); } TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimit) { - const GURL kBlobURL("blob:nolimit"); - content_ = kData; + auto blob = CreateBlob(kData); - PrepareForWrite("test", kBlobURL, 0, std::numeric_limits<int64_t>::max()); + PrepareForWrite("test", 0, std::numeric_limits<int64_t>::max()); Result result; ASSERT_EQ(0, usage()); - file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result)); + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status()); @@ -309,14 +213,13 @@ } TEST_F(FileWriterDelegateTest, WriteSuccessWithJustQuota) { - const GURL kBlobURL("blob:just"); - content_ = kData; + auto blob = CreateBlob(kData); const int64_t kAllowedGrowth = kDataSize; - PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth); + PrepareForWrite("test", 0, kAllowedGrowth); Result result; ASSERT_EQ(0, usage()); - file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result)); + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status()); file_writer_delegate_.reset(); @@ -329,14 +232,13 @@ } TEST_F(FileWriterDelegateTest, DISABLED_WriteFailureByQuota) { - const GURL kBlobURL("blob:failure"); - content_ = kData; + auto blob = CreateBlob(kData); const int64_t kAllowedGrowth = kDataSize - 1; - PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth); + PrepareForWrite("test", 0, kAllowedGrowth); Result result; ASSERT_EQ(0, usage()); - file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result)); + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status()); file_writer_delegate_.reset(); @@ -350,14 +252,13 @@ } TEST_F(FileWriterDelegateTest, WriteZeroBytesSuccessfullyWithZeroQuota) { - const GURL kBlobURL("blob:zero"); - content_ = ""; + auto blob = CreateBlob(""); int64_t kAllowedGrowth = 0; - PrepareForWrite("test", kBlobURL, 0, kAllowedGrowth); + PrepareForWrite("test", 0, kAllowedGrowth); Result result; ASSERT_EQ(0, usage()); - file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result)); + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status()); file_writer_delegate_.reset(); @@ -372,29 +273,24 @@ TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) { std::unique_ptr<FileWriterDelegate> file_writer_delegate2; - std::unique_ptr<net::URLRequest> request2; ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateFile(file_system_context_.get(), GetFileSystemURL("test2"))); - const GURL kBlobURL("blob:nolimitconcurrent"); - const GURL kBlobURL2("blob:nolimitconcurrent2"); - content_ = kData; + auto blob = CreateBlob(kData); - PrepareForWrite("test", kBlobURL, 0, std::numeric_limits<int64_t>::max()); + PrepareForWrite("test", 0, std::numeric_limits<int64_t>::max()); // Create another FileWriterDelegate for concurrent write. file_writer_delegate2 = CreateWriterDelegate("test2", 0, std::numeric_limits<int64_t>::max()); - request2 = empty_context_.CreateRequest(kBlobURL2, net::DEFAULT_PRIORITY, - file_writer_delegate2.get(), - TRAFFIC_ANNOTATION_FOR_TESTS); Result result, result2; ASSERT_EQ(0, usage()); - file_writer_delegate_->Start(std::move(request_), GetWriteCallback(&result)); - file_writer_delegate2->Start(std::move(request2), GetWriteCallback(&result2)); + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); + file_writer_delegate2->Start(blob->CreateReader(), + GetWriteCallback(&result2)); base::RunLoop().Run(); if (result.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING || result2.write_status() == FileWriterDelegate::SUCCESS_IO_PENDING) @@ -415,19 +311,18 @@ } TEST_F(FileWriterDelegateTest, WritesWithQuotaAndOffset) { - const GURL kBlobURL("blob:failure-with-updated-quota"); - content_ = kData; + auto blob = CreateBlob(kData); // Writing kDataSize (=45) bytes data while allowed_growth is 100. int64_t offset = 0; int64_t allowed_growth = 100; ASSERT_LT(kDataSize, allowed_growth); - PrepareForWrite("test", kBlobURL, offset, allowed_growth); + PrepareForWrite("test", offset, allowed_growth); { Result result; ASSERT_EQ(0, usage()); - file_writer_delegate_->Start(std::move(request_), + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status()); @@ -442,11 +337,11 @@ // Trying to overwrite kDataSize bytes data while allowed_growth is 20. offset = 0; allowed_growth = 20; - PrepareForWrite("test", kBlobURL, offset, allowed_growth); + PrepareForWrite("test", offset, allowed_growth); { Result result; - file_writer_delegate_->Start(std::move(request_), + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); EXPECT_EQ(kDataSize, usage()); @@ -460,11 +355,11 @@ // allowed_growth is 55. offset = 25; allowed_growth = 55; - PrepareForWrite("test", kBlobURL, offset, allowed_growth); + PrepareForWrite("test", offset, allowed_growth); { Result result; - file_writer_delegate_->Start(std::move(request_), + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status()); @@ -479,12 +374,12 @@ // Trying to overwrite 45 bytes data while allowed_growth is -20. offset = 0; allowed_growth = -20; - PrepareForWrite("test", kBlobURL, offset, allowed_growth); + PrepareForWrite("test", offset, allowed_growth); int64_t pre_write_usage = GetFileSizeOnDisk("test"); { Result result; - file_writer_delegate_->Start(std::move(request_), + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::SUCCESS_COMPLETED, result.write_status()); @@ -501,11 +396,11 @@ const int kOverlap = 20; offset = pre_write_usage - kOverlap; allowed_growth = 10; - PrepareForWrite("test", kBlobURL, offset, allowed_growth); + PrepareForWrite("test", offset, allowed_growth); { Result result; - file_writer_delegate_->Start(std::move(request_), + file_writer_delegate_->Start(blob->CreateReader(), GetWriteCallback(&result)); base::RunLoop().Run(); ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status()); @@ -518,53 +413,4 @@ } } -class InterruptedFileWriterDelegate : public FileWriterDelegate { - public: - InterruptedFileWriterDelegate( - std::unique_ptr<storage::FileStreamWriter> file_writer, - storage::FlushPolicy flush_policy) - : FileWriterDelegate(std::move(file_writer), flush_policy) {} - ~InterruptedFileWriterDelegate() override = default; - - void OnDataReceived(int bytes_read) override { - // The base class will respond to OnDataReceived by performing an - // asynchronous write. Schedule a task now that will execute before the - // write completes which terminates the URLRequestJob. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(IgnoreResult(&net::URLRequest::Cancel), - base::Unretained(request_))); - FileWriterDelegate::OnDataReceived(bytes_read); - } - - void set_request(net::URLRequest* request) { request_ = request; } - - private: - // The request is owned by the base class as a private member. - net::URLRequest* request_ = nullptr; -}; - -TEST_F(FileWriterDelegateTest, ReadFailureDuringAsyncWrite) { - const GURL kBlobURL("blob:async-fail"); - content_ = kData; - - auto writer = CreateWriter("test", 0, std::numeric_limits<int64_t>::max()); - auto file_writer_delegate = std::make_unique<InterruptedFileWriterDelegate>( - std::move(writer), storage::FlushPolicy::FLUSH_ON_COMPLETION); - auto request = empty_context_.CreateRequest(kBlobURL, net::DEFAULT_PRIORITY, - file_writer_delegate.get(), - TRAFFIC_ANNOTATION_FOR_TESTS); - file_writer_delegate->set_request(request.get()); - - Result result; - file_writer_delegate->Start(std::move(request), GetWriteCallback(&result)); - base::RunLoop().Run(); - - ASSERT_EQ(FileWriterDelegate::ERROR_WRITE_STARTED, result.write_status()); - file_writer_delegate_.reset(); - - // The write should still have flushed. - ASSERT_EQ(kDataSize, usage()); - EXPECT_EQ(GetFileSizeOnDisk("test"), usage()); -} - } // namespace content
diff --git a/storage/browser/fileapi/isolated_context_unittest.cc b/storage/browser/fileapi/isolated_context_unittest.cc index ec8eab8..990a67c4 100644 --- a/storage/browser/fileapi/isolated_context_unittest.cc +++ b/storage/browser/fileapi/isolated_context_unittest.cc
@@ -127,7 +127,7 @@ std::string id2 = isolated_context()->RegisterFileSystemForPath( kFileSystemTypeNativeLocal, std::string(), - base::FilePath(DRIVE FPL("/foo")), NULL); + base::FilePath(DRIVE FPL("/foo")), nullptr); // Make sure the GetDraggedFileInfo returns false for both ones. ASSERT_FALSE(isolated_context()->GetDraggedFileInfo(id2, &toplevels)); @@ -139,11 +139,11 @@ // Try registering three more file systems for the same path as id2. std::string id3 = isolated_context()->RegisterFileSystemForPath( - kFileSystemTypeNativeLocal, std::string(), path, NULL); + kFileSystemTypeNativeLocal, std::string(), path, nullptr); std::string id4 = isolated_context()->RegisterFileSystemForPath( - kFileSystemTypeNativeLocal, std::string(), path, NULL); + kFileSystemTypeNativeLocal, std::string(), path, nullptr); std::string id5 = isolated_context()->RegisterFileSystemForPath( - kFileSystemTypeNativeLocal, std::string(), path, NULL); + kFileSystemTypeNativeLocal, std::string(), path, nullptr); // Remove file system for id4. isolated_context()->AddReference(id4); @@ -283,7 +283,8 @@ // that has no corresponding platform directory. base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_); ASSERT_TRUE(isolated_context()->CrackVirtualPath( - virtual_path, &cracked_id, NULL, NULL, &cracked_path, &cracked_option)); + virtual_path, &cracked_id, nullptr, nullptr, &cracked_path, + &cracked_option)); ASSERT_EQ(FPL(""), cracked_path.value()); ASSERT_EQ(id_, cracked_id); @@ -292,7 +293,8 @@ virtual_path = isolated_context()->CreateVirtualRootPath( id_).AppendASCII("foo"); ASSERT_FALSE(isolated_context()->CrackVirtualPath( - virtual_path, &cracked_id, NULL, NULL, &cracked_path, &cracked_option)); + virtual_path, &cracked_id, nullptr, nullptr, &cracked_path, + &cracked_option)); } TEST_F(IsolatedContextTest, CanHandleURL) { @@ -353,7 +355,7 @@ std::string cracked_inner_id; FileSystemMountOption cracked_option; ASSERT_TRUE(isolated_context()->CrackVirtualPath( - whole_virtual_path, &cracked_id, NULL, &cracked_inner_id, + whole_virtual_path, &cracked_id, nullptr, &cracked_inner_id, &cracked_path, &cracked_option)); ASSERT_EQ(database_fsid, cracked_id); ASSERT_EQ(test_virtual_path, cracked_path);
diff --git a/storage/browser/fileapi/isolated_file_system_backend.cc b/storage/browser/fileapi/isolated_file_system_backend.cc index 84c7665..13eb8a3 100644 --- a/storage/browser/fileapi/isolated_file_system_backend.cc +++ b/storage/browser/fileapi/isolated_file_system_backend.cc
@@ -82,12 +82,12 @@ default: NOTREACHED(); } - return NULL; + return nullptr; } WatcherManager* IsolatedFileSystemBackend::GetWatcherManager( FileSystemType type) { - return NULL; + return nullptr; } CopyOrMoveFileValidatorFactory* @@ -95,7 +95,7 @@ FileSystemType type, base::File::Error* error_code) { DCHECK(error_code); *error_code = base::File::FILE_OK; - return NULL; + return nullptr; } FileSystemOperation* IsolatedFileSystemBackend::CreateFileSystemOperation( @@ -143,22 +143,22 @@ FileSystemQuotaUtil* IsolatedFileSystemBackend::GetQuotaUtil() { // No quota support. - return NULL; + return nullptr; } const UpdateObserverList* IsolatedFileSystemBackend::GetUpdateObservers( FileSystemType type) const { - return NULL; + return nullptr; } const ChangeObserverList* IsolatedFileSystemBackend::GetChangeObservers( FileSystemType type) const { - return NULL; + return nullptr; } const AccessObserverList* IsolatedFileSystemBackend::GetAccessObservers( FileSystemType type) const { - return NULL; + return nullptr; } } // namespace storage
diff --git a/storage/browser/fileapi/local_file_stream_reader_unittest.cc b/storage/browser/fileapi/local_file_stream_reader_unittest.cc index 7516d84..208a7d72 100644 --- a/storage/browser/fileapi/local_file_stream_reader_unittest.cc +++ b/storage/browser/fileapi/local_file_stream_reader_unittest.cc
@@ -38,8 +38,8 @@ void ReadFromReader(LocalFileStreamReader* reader, std::string* data, size_t size, int* result) { - ASSERT_TRUE(reader != NULL); - ASSERT_TRUE(result != NULL); + ASSERT_TRUE(reader != nullptr); + ASSERT_TRUE(result != nullptr); *result = net::OK; net::TestCompletionCallback callback; size_t total_bytes_read = 0; @@ -186,7 +186,7 @@ result = callback.WaitForResult(); ASSERT_EQ(net::ERR_UPLOAD_FILE_CHANGED, result); - // With NULL expected modification time this should work. + // With nullptr expected modification time this should work. reader.reset(CreateFileReader(test_path(), 0, base::Time())); result = reader->GetLength(callback.callback()); if (result == net::ERR_IO_PENDING) @@ -246,7 +246,7 @@ EXPECT_EQ(net::OK, result); EXPECT_EQ(kTestData, data); - // And with NULL expected modification time this should work. + // And with nullptr expected modification time this should work. data.clear(); reader.reset(CreateFileReader(test_path(), 0, base::Time())); ReadFromReader(reader.get(), &data, kTestDataSize, &result);
diff --git a/storage/browser/fileapi/local_file_stream_writer.cc b/storage/browser/fileapi/local_file_stream_writer.cc index 1e8d0f87..ed6c584e 100644 --- a/storage/browser/fileapi/local_file_stream_writer.cc +++ b/storage/browser/fileapi/local_file_stream_writer.cc
@@ -131,7 +131,7 @@ if (result != net::OK) { has_pending_operation_ = false; - stream_impl_.reset(NULL); + stream_impl_.reset(nullptr); error_callback.Run(result); return; }
diff --git a/storage/browser/fileapi/local_file_util_unittest.cc b/storage/browser/fileapi/local_file_util_unittest.cc index 8a3bc288..b0b58e6 100644 --- a/storage/browser/fileapi/local_file_util_unittest.cc +++ b/storage/browser/fileapi/local_file_util_unittest.cc
@@ -51,11 +51,11 @@ void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); file_system_context_ = - CreateFileSystemContextForTesting(NULL, data_dir_.GetPath()); + CreateFileSystemContextForTesting(nullptr, data_dir_.GetPath()); } void TearDown() override { - file_system_context_ = NULL; + file_system_context_ = nullptr; base::RunLoop().RunUntilIdle(); }
diff --git a/storage/browser/fileapi/obfuscated_file_util.cc b/storage/browser/fileapi/obfuscated_file_util.cc index 03f80cf..49f5f3cb8 100644 --- a/storage/browser/fileapi/obfuscated_file_util.cc +++ b/storage/browser/fileapi/obfuscated_file_util.cc
@@ -874,7 +874,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DestroyDirectoryDatabase(origin, type_string); - const base::FilePath origin_path = GetDirectoryForOrigin(origin, false, NULL); + const base::FilePath origin_path = + GetDirectoryForOrigin(origin, false, nullptr); if (origin_path.empty()) return true; @@ -1197,7 +1198,7 @@ std::string key = GetDirectoryDatabaseKey( url.origin(), CallGetTypeStringForURL(url)); if (key.empty()) - return NULL; + return nullptr; auto iter = directories_.find(key); if (iter != directories_.end()) { @@ -1210,7 +1211,7 @@ if (error != base::File::FILE_OK) { LOG(WARNING) << "Failed to get origin+type directory: " << url.DebugString() << " error:" << error; - return NULL; + return nullptr; } MarkUsed(); directories_[key] =
diff --git a/storage/browser/fileapi/obfuscated_file_util.h b/storage/browser/fileapi/obfuscated_file_util.h index 748d30e..ce12c819 100644 --- a/storage/browser/fileapi/obfuscated_file_util.h +++ b/storage/browser/fileapi/obfuscated_file_util.h
@@ -282,7 +282,7 @@ std::string GetDirectoryDatabaseKey(const GURL& origin, const std::string& type_string); - // This returns NULL if |create| flag is false and a filesystem does not + // This returns nullptr if |create| flag is false and a filesystem does not // exist for the given |url|. // For read operations |create| should be false. SandboxDirectoryDatabase* GetDirectoryDatabase(const FileSystemURL& url,
diff --git a/storage/browser/fileapi/obfuscated_file_util_unittest.cc b/storage/browser/fileapi/obfuscated_file_util_unittest.cc index fb67043..1fecb7a3 100644 --- a/storage/browser/fileapi/obfuscated_file_util_unittest.cc +++ b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -192,7 +192,7 @@ } void TearDown() override { - quota_manager_ = NULL; + quota_manager_ = nullptr; scoped_task_environment_.RunUntilIdle(); sandbox_file_system_.TearDown(); } @@ -248,7 +248,7 @@ storage::SpecialStoragePolicy* storage_policy) { return std::unique_ptr<ObfuscatedFileUtil>( ObfuscatedFileUtil::CreateForTesting(storage_policy, data_dir_path(), - NULL)); + nullptr)); } ObfuscatedFileUtil* ofu() { @@ -300,7 +300,7 @@ } bool PathExists(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); base::File::Info file_info; base::FilePath platform_path; base::File::Error error = ofu()->GetFileInfo( @@ -330,7 +330,7 @@ } void CheckFileAndCloseHandle(const FileSystemURL& url, base::File file) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); base::FilePath local_path; EXPECT_EQ(base::File::FILE_OK, ofu()->GetLocalFilePath(context.get(), url, &local_path)); @@ -357,7 +357,7 @@ base::File::Info file_info1; EXPECT_EQ(length, GetSize(data_path)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), url, &file_info1, &data_path)); EXPECT_EQ(data_path, local_path); @@ -370,12 +370,12 @@ EXPECT_EQ(length, file_info1.size); EXPECT_LE(file_info0.last_modified, file_info1.last_modified); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, length * 2)); EXPECT_EQ(length * 2, GetSize(data_path)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 0)); EXPECT_EQ(0, GetSize(data_path)); @@ -389,7 +389,7 @@ std::set<base::FilePath::StringType>::const_iterator iter; for (iter = files.begin(); iter != files.end(); ++iter) { bool created = true; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), FileSystemURLAppend(root_url, *iter), @@ -397,7 +397,7 @@ ASSERT_FALSE(created); } for (iter = directories.begin(); iter != directories.end(); ++iter) { - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_TRUE(DirectoryExists( FileSystemURLAppend(root_url, *iter))); } @@ -473,7 +473,7 @@ std::set<base::FilePath::StringType>::iterator iter; for (iter = files->begin(); iter != files->end(); ++iter) { bool created = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), FileSystemURLAppend(root_url, *iter), @@ -483,7 +483,7 @@ for (iter = directories->begin(); iter != directories->end(); ++iter) { bool exclusive = true; bool recursive = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), FileSystemURLAppend(root_url, *iter), @@ -499,7 +499,7 @@ std::unique_ptr<FileSystemOperationContext> context; std::vector<filesystem::mojom::DirectoryEntry> entries; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, AsyncFileTestHelper::ReadDirectory( file_system_context(), root_url, &entries)); @@ -523,7 +523,7 @@ base::Time last_access_time = base::Time::Now(); base::Time last_modified_time = base::Time::Now(); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Touch(context.get(), url, last_access_time, last_modified_time)); @@ -531,7 +531,7 @@ EXPECT_TRUE(change_observer()->HasNoChange()); base::FilePath local_path; base::File::Info file_info; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo( context.get(), url, &file_info, &local_path)); // We compare as time_t here to lower our resolution, to avoid false @@ -539,14 +539,14 @@ // representation and back. EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); last_modified_time += base::TimeDelta::FromHours(1); last_access_time += base::TimeDelta::FromHours(14); EXPECT_EQ(base::File::FILE_OK, ofu()->Touch(context.get(), url, last_access_time, last_modified_time)); EXPECT_TRUE(change_observer()->HasNoChange()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), url, &file_info, &local_path)); EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT()); @@ -572,7 +572,7 @@ std::unique_ptr<FileSystemOperationContext> context; if (overwrite) { - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); bool created = false; EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), dest_url, &created)); @@ -587,14 +587,14 @@ ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()); if (!overwrite) { // Verify that file creation requires sufficient quota for the path. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(path_cost + src_file_length - 1); EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, ofu()->CopyInForeignFile(context.get(), src_file_path, dest_url)); } - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(path_cost + src_file_length); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyInForeignFile(context.get(), @@ -603,7 +603,7 @@ EXPECT_TRUE(PathExists(dest_url)); EXPECT_FALSE(DirectoryExists(dest_url)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); base::File::Info file_info; base::FilePath data_path; EXPECT_EQ(base::File::FILE_OK, @@ -618,17 +618,17 @@ } void ClearTimestamp(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Touch(context.get(), url, base::Time(), base::Time())); EXPECT_EQ(base::Time(), GetModifiedTime(url)); } base::Time GetModifiedTime(const FileSystemURL& url) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); base::FilePath data_path; base::File::Info file_info; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), url, &file_info, &data_path)); EXPECT_TRUE(change_observer()->HasNoChange()); @@ -649,19 +649,19 @@ const FileSystemURL dest_file_url( FileSystemURLAppendUTF8(dest_dir_url, "fuga")); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), src_dir_url, true, true)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), dest_dir_url, true, true)); bool created = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_file_url, &created)); if (overwrite) { - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), dest_file_url, &created)); @@ -669,7 +669,7 @@ ClearTimestamp(src_dir_url); ClearTimestamp(dest_dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyOrMoveFile(context.get(), src_file_url, dest_file_url, @@ -684,9 +684,9 @@ void MaybeDropDatabasesAliveCaseTestBody() { std::unique_ptr<ObfuscatedFileUtil> file_util = - CreateObfuscatedFileUtil(NULL); + CreateObfuscatedFileUtil(nullptr); file_util->InitOriginDatabase(GURL(), true /*create*/); - ASSERT_TRUE(file_util->origin_database_ != NULL); + ASSERT_TRUE(file_util->origin_database_ != nullptr); // Callback to Drop DB is called while ObfuscatedFileUtilTest is // still alive. @@ -694,7 +694,7 @@ file_util->MarkUsed(); scoped_task_environment_.RunUntilIdle(); - ASSERT_TRUE(file_util->origin_database_ == NULL); + ASSERT_TRUE(file_util->origin_database_ == nullptr); } void MaybeDropDatabasesAlreadyDeletedCaseTestBody() { @@ -702,7 +702,7 @@ // doesn't cause a crash for use after free. { std::unique_ptr<ObfuscatedFileUtil> file_util = - CreateObfuscatedFileUtil(NULL); + CreateObfuscatedFileUtil(nullptr); file_util->InitOriginDatabase(GURL(), true /*create*/); file_util->db_flush_delay_seconds_ = 0; file_util->MarkUsed(); @@ -722,7 +722,7 @@ // Create DirectoryDatabase for isolated origin. SandboxDirectoryDatabase* db = file_util->GetDirectoryDatabase(url, true /* create */); - ASSERT_TRUE(db != NULL); + ASSERT_TRUE(db != nullptr); // Destory it. file_util->DestroyDirectoryDatabase( @@ -740,7 +740,7 @@ // Create DirectoryDatabase for isolated origin. SandboxDirectoryDatabase* db = file_util->GetDirectoryDatabase(url, true /* create */); - ASSERT_TRUE(db != NULL); + ASSERT_TRUE(db != nullptr); ASSERT_EQ(1U, file_util->directories_.size()); // Remove isolated. @@ -829,14 +829,14 @@ TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { FileSystemURL url = CreateURLFromUTF8("fake/file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE; base::File file = ofu()->CreateOrOpen(context.get(), url, file_flags); EXPECT_FALSE(file.IsValid()); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->DeleteFile(context.get(), url)); @@ -845,14 +845,14 @@ EXPECT_TRUE(change_observer()->HasNoChange()); // Verify that file creation requires sufficient quota for the path. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); file = ofu()->CreateOrOpen(context.get(), url, file_flags); EXPECT_FALSE(file.IsValid()); ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, file.error_details()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(url.path())); file = ofu()->CreateOrOpen(context.get(), url, file_flags); @@ -862,7 +862,7 @@ CheckFileAndCloseHandle(url, std::move(file)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); base::FilePath local_path; EXPECT_EQ(base::File::FILE_OK, ofu()->GetLocalFilePath(context.get(), url, &local_path)); @@ -870,7 +870,7 @@ // Verify that deleting a file isn't stopped by zero quota, and that it frees // up quote from its path. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(0); EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url)); EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); @@ -878,7 +878,7 @@ EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()), context->allowed_bytes_growth()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); bool exclusive = true; bool recursive = true; FileSystemURL directory_url = CreateURLFromUTF8( @@ -890,7 +890,7 @@ // The oepration created 3 directories recursively. EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); file = ofu()->CreateOrOpen(context.get(), url, file_flags); ASSERT_TRUE(file.IsValid()); ASSERT_TRUE(file.created()); @@ -898,12 +898,12 @@ CheckFileAndCloseHandle(url, std::move(file)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetLocalFilePath(context.get(), url, &local_path)); EXPECT_TRUE(base::PathExists(local_path)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url)); EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); EXPECT_FALSE(base::PathExists(local_path)); @@ -915,29 +915,29 @@ TEST_F(ObfuscatedFileUtilTest, TestTruncate) { bool created = false; FileSystemURL url = CreateURLFromUTF8("file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->Truncate(context.get(), url, 4)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); ASSERT_TRUE(created); EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); base::FilePath local_path; EXPECT_EQ(base::File::FILE_OK, ofu()->GetLocalFilePath(context.get(), url, &local_path)); EXPECT_EQ(0, GetSize(local_path)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 10)); EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); EXPECT_EQ(10, GetSize(local_path)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 1)); EXPECT_EQ(1, GetSize(local_path)); EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); @@ -1007,13 +1007,13 @@ TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { FileSystemURL url = CreateURLFromUTF8("fake/file"); bool created = false; - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->EnsureFileExists(context.get(), url, &created)); EXPECT_TRUE(change_observer()->HasNoChange()); // Verify that file creation requires sufficient quota for the path. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); url = CreateURLFromUTF8("test file"); created = false; context->set_allowed_bytes_growth( @@ -1023,7 +1023,7 @@ ASSERT_FALSE(created); EXPECT_TRUE(change_observer()->HasNoChange()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(url.path())); ASSERT_EQ(base::File::FILE_OK, @@ -1033,7 +1033,7 @@ CheckFileAndCloseHandle(url, base::File()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); ASSERT_FALSE(created); @@ -1041,7 +1041,7 @@ // Also test in a subdirectory. url = CreateURLFromUTF8("path/to/file.txt"); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); bool exclusive = true; bool recursive = true; EXPECT_EQ(base::File::FILE_OK, @@ -1050,7 +1050,7 @@ // 2 directories: path/ and path/to. EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); ASSERT_TRUE(created); @@ -1060,7 +1060,7 @@ } TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool exclusive = false; bool recursive = false; @@ -1068,17 +1068,17 @@ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->DeleteDirectory(context.get(), url)); FileSystemURL root = CreateURLFromUTF8(std::string()); EXPECT_FALSE(DirectoryExists(url)); EXPECT_FALSE(PathExists(url)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); exclusive = false; recursive = true; EXPECT_EQ(base::File::FILE_OK, @@ -1088,16 +1088,16 @@ EXPECT_TRUE(DirectoryExists(url)); EXPECT_TRUE(PathExists(url)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root)); EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url))); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), FileSystemURLDirName(url))); // Can't remove a non-empty directory. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, ofu()->DeleteDirectory(context.get(), FileSystemURLDirName(url))); @@ -1112,21 +1112,21 @@ EXPECT_FALSE(file_info.is_symbolic_link); // Same create again should succeed, since exclusive is false. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); EXPECT_TRUE(change_observer()->HasNoChange()); exclusive = true; recursive = true; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_EXISTS, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); EXPECT_TRUE(change_observer()->HasNoChange()); // Verify that deleting a directory isn't stopped by zero quota, and that it // frees up quota from its path. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(0); EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url)); EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); @@ -1138,7 +1138,7 @@ EXPECT_FALSE(DirectoryExists(url)); EXPECT_FALSE(PathExists(url)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(context.get(), url, &file_info, &local_path)); @@ -1146,14 +1146,14 @@ // Verify that file creation requires sufficient quota for the path. exclusive = true; recursive = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); EXPECT_TRUE(change_observer()->HasNoChange()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(url.path())); EXPECT_EQ(base::File::FILE_OK, @@ -1165,7 +1165,7 @@ exclusive = true; recursive = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_EXISTS, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); EXPECT_TRUE(change_observer()->HasNoChange()); @@ -1173,7 +1173,7 @@ exclusive = true; recursive = false; url = CreateURLFromUTF8("foo"); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_EXISTS, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); EXPECT_TRUE(change_observer()->HasNoChange()); @@ -1185,7 +1185,7 @@ exclusive = true; recursive = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); @@ -1195,14 +1195,14 @@ exclusive = true; recursive = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_EXISTS, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool exclusive = true; bool recursive = true; FileSystemURL url = CreateURLFromUTF8("directory/to/use"); @@ -1221,7 +1221,7 @@ TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) { FileSystemURL url = CreateURLFromUTF8("file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool created = false; ASSERT_EQ(base::File::FILE_OK, @@ -1238,7 +1238,7 @@ TEST_F(ObfuscatedFileUtilTest, TestTouch) { FileSystemURL url = CreateURLFromUTF8("file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); base::Time last_access_time = base::Time::Now(); base::Time last_modified_time = base::Time::Now(); @@ -1249,7 +1249,7 @@ last_modified_time)); // OK, now create it. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); bool created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); @@ -1257,7 +1257,7 @@ TestTouchHelper(url, true); // Now test a directory: - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); bool exclusive = true; bool recursive = false; url = CreateURLFromUTF8("dir"); @@ -1268,7 +1268,7 @@ TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) { FileSystemURL url = CreateURLFromUTF8("fake/file"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); url = CreateURLFromUTF8("file name"); context->set_allowed_bytes_growth(5); @@ -1296,7 +1296,7 @@ path_cost += ObfuscatedFileUtil::ComputeFilePathCost( base::FilePath(*iter)); } - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(1024); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); @@ -1306,7 +1306,7 @@ TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) { FileSystemURL source_url = CreateURLFromUTF8("path0.txt"); FileSystemURL dest_url = CreateURLFromUTF8("path1.txt"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool is_copy_not_move = false; EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, @@ -1314,7 +1314,7 @@ FileSystemOperation::OPTION_NONE, is_copy_not_move)); EXPECT_TRUE(change_observer()->HasNoChange()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); is_copy_not_move = true; EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, @@ -1324,7 +1324,7 @@ source_url = CreateURLFromUTF8("dir/dir/file"); bool exclusive = true; bool recursive = true; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), FileSystemURLDirName(source_url), @@ -1336,7 +1336,7 @@ FileSystemOperation::OPTION_NONE, is_copy_not_move)); EXPECT_TRUE(change_observer()->HasNoChange()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); is_copy_not_move = true; EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, @@ -1360,45 +1360,45 @@ test_case.dest_path); SCOPED_TRACE(testing::Message() << "\t cause_overwrite " << test_case.cause_overwrite); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool exclusive = false; bool recursive = true; FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path); FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), FileSystemURLDirName(source_url), exclusive, recursive)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), FileSystemURLDirName(dest_url), exclusive, recursive)); bool created = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), source_url, &created)); ASSERT_TRUE(created); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), source_url, kSourceLength)); if (test_case.cause_overwrite) { - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), dest_url, &created)); ASSERT_TRUE(created); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), dest_url, kDestLength)); } - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, FileSystemOperation::OPTION_NONE, @@ -1407,7 +1407,7 @@ if (test_case.is_copy_not_move) { base::File::Info file_info; base::FilePath local_path; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), source_url, &file_info, &local_path)); @@ -1417,7 +1417,7 @@ } else { base::File::Info file_info; base::FilePath local_path; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->GetFileInfo(context.get(), source_url, &file_info, &local_path)); @@ -1437,7 +1437,7 @@ TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) { FileSystemURL src_url = CreateURLFromUTF8("src path"); FileSystemURL dest_url = CreateURLFromUTF8("destination path"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); @@ -1449,7 +1449,7 @@ EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path())); EXPECT_EQ(base::File::FILE_OK, @@ -1457,7 +1457,7 @@ FileSystemOperation::OPTION_NONE, is_copy)); // Copy, with overwrite. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(0); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, @@ -1467,21 +1467,21 @@ TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) { FileSystemURL src_url = CreateURLFromUTF8("src path"); FileSystemURL dest_url = CreateURLFromUTF8("destination path"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); bool is_copy = false; // Move, rename, no overwrite. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1); EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - ObfuscatedFileUtil::ComputeFilePathCost(src_url.path())); @@ -1489,12 +1489,12 @@ ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, FileSystemOperation::OPTION_NONE, is_copy)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); // Move, rename, with overwrite. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(0); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, @@ -1503,7 +1503,7 @@ TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) { FileSystemURL src_url = CreateURLFromUTF8("src path"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); bool created = false; ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); @@ -1511,7 +1511,7 @@ bool exclusive = true; bool recursive = false; FileSystemURL dir_url = CreateURLFromUTF8("directory path"); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), dir_url, exclusive, recursive)); @@ -1522,7 +1522,7 @@ bool is_copy = false; int64_t allowed_bytes_growth = -1000; // Over quota, this should still work. // Move, no rename, no overwrite. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(allowed_bytes_growth); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, @@ -1530,10 +1530,10 @@ EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth()); // Move, no rename, with overwrite. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); ASSERT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_url, &created)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); context->set_allowed_bytes_growth(allowed_bytes_growth); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, @@ -1550,7 +1550,7 @@ } TEST_F(ObfuscatedFileUtilTest, TestEnumerator) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); FileSystemURL src_url = CreateURLFromUTF8("source dir"); bool exclusive = true; bool recursive = false; @@ -1669,7 +1669,7 @@ } TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); int64_t expected_quota = 0; @@ -1724,14 +1724,14 @@ bool created = false; // Create a non-empty file. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), kPath1, &created)); EXPECT_TRUE(created); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), kPath1, 10)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo( context.get(), kPath1, &file_info, &data_path)); @@ -1742,18 +1742,18 @@ // Try to get file info of broken file. EXPECT_FALSE(PathExists(kPath1)); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), kPath1, &created)); EXPECT_TRUE(created); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo( context.get(), kPath1, &file_info, &data_path)); EXPECT_EQ(0, file_info.size); // Make another broken file to |kPath2|. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), kPath2, &created)); EXPECT_TRUE(created); @@ -1762,7 +1762,7 @@ ofu()->DestroyDirectoryDatabase(origin(), type_string()); // Repair broken |kPath1|. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->Touch(context.get(), kPath1, base::Time::Now(), base::Time::Now())); @@ -1771,14 +1771,14 @@ EXPECT_TRUE(created); // Copy from sound |kPath1| to broken |kPath2|. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2, FileSystemOperation::OPTION_NONE, true /* copy */)); ofu()->DestroyDirectoryDatabase(origin(), type_string()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); base::File file = ofu()->CreateOrOpen(context.get(), kPath1, base::File::FLAG_READ | base::File::FLAG_CREATE); @@ -1800,7 +1800,7 @@ for (size_t i = 0; i < arraysize(kPath); ++i) { bool created = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), kPath[i], &created)); EXPECT_TRUE(created); @@ -1825,7 +1825,7 @@ } TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); // Create working directory. @@ -1836,7 +1836,7 @@ FileSystemURL url(FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_file")); bool created = false; ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); EXPECT_TRUE(created); @@ -1845,7 +1845,7 @@ // non create case. created = true; ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); EXPECT_FALSE(created); @@ -1853,12 +1853,12 @@ // fail case. url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir"); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), url, false, false)); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, ofu()->EnsureFileExists(context.get(), url, &created)); EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); @@ -1866,7 +1866,7 @@ // CreateOrOpen, create case. url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file"); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); base::File file = ofu()->CreateOrOpen(context.get(), url, base::File::FLAG_CREATE | base::File::FLAG_WRITE); @@ -1878,7 +1878,7 @@ // open case. ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); file = ofu()->CreateOrOpen(context.get(), url, base::File::FLAG_OPEN | base::File::FLAG_WRITE); EXPECT_TRUE(file.IsValid()); @@ -1888,7 +1888,7 @@ // fail case ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); file = ofu()->CreateOrOpen(context.get(), url, base::File::FLAG_CREATE | base::File::FLAG_WRITE); EXPECT_FALSE(file.IsValid()); @@ -1900,7 +1900,7 @@ url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir"); FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir")); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), subdir_url, true /* exclusive */, true /* recursive */)); @@ -1911,7 +1911,7 @@ subdir_url = FileSystemURLAppendUTF8(url, "subdir2"); ClearTimestamp(dir_url); ClearTimestamp(url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), subdir_url, true /* exclusive */, true /* recursive */)); @@ -1921,7 +1921,7 @@ // fail case. url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir"); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_EXISTS, ofu()->CreateDirectory(context.get(), url, true /* exclusive */, true /* recursive */)); @@ -1931,17 +1931,17 @@ url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file"); FileSystemURL src_path = FileSystemURLAppendUTF8( dir_url, "CopyInForeignFile_src_file"); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), src_path, &created)); EXPECT_TRUE(created); base::FilePath src_local_path; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path)); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CopyInForeignFile(context.get(), src_local_path, @@ -1950,7 +1950,7 @@ } TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) { - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); // Create working directory. @@ -1961,20 +1961,20 @@ FileSystemURL url = FileSystemURLAppendUTF8( dir_url, "DeleteFile_file"); bool created = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); EXPECT_TRUE(created); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url)); EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); // fail case. ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, ofu()->DeleteFile(context.get(), url)); EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); @@ -1982,28 +1982,28 @@ // DeleteDirectory, fail case. url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir"); FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta")); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), url, true, true)); created = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), file_path, &created)); EXPECT_TRUE(created); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, ofu()->DeleteDirectory(context.get(), url)); EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); // delete case. - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), file_path)); ClearTimestamp(dir_url); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url)); EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); } @@ -2024,40 +2024,40 @@ FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar"); FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz"); - std::unique_ptr<FileSystemOperationContext> context(NewContext(NULL)); + std::unique_ptr<FileSystemOperationContext> context(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), dir, false, false)); bool created = false; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->EnsureFileExists(context.get(), url1, &created)); EXPECT_TRUE(created); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), url2, false, false)); base::FilePath file_path; - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->GetLocalFilePath(context.get(), url1, &file_path)); EXPECT_FALSE(file_path.empty()); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); EXPECT_EQ(base::File::FILE_OK, ofu()->Touch(context.get(), url1, base::Time::Now() + base::TimeDelta::FromHours(1), base::Time())); - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); std::unique_ptr<storage::FileSystemFileUtil::AbstractFileEnumerator> file_enum(ofu()->CreateFileEnumerator(context.get(), dir, false)); int count = 0; base::FilePath file_path_each; while (!(file_path_each = file_enum->Next()).empty()) { - context.reset(NewContext(NULL)); + context.reset(NewContext(nullptr)); base::File::Info file_info; base::FilePath file_path; EXPECT_EQ(base::File::FILE_OK,
diff --git a/storage/browser/fileapi/plugin_private_file_system_backend.cc b/storage/browser/fileapi/plugin_private_file_system_backend.cc index 0b09b989..44cc5cc 100644 --- a/storage/browser/fileapi/plugin_private_file_system_backend.cc +++ b/storage/browser/fileapi/plugin_private_file_system_backend.cc
@@ -106,7 +106,7 @@ special_storage_policy, base_path_, env_override, base::Bind(&FileSystemIDToPluginMap::GetPluginIDForURL, base::Owned(plugin_map_)), - std::set<std::string>(), NULL))); + std::set<std::string>(), nullptr))); } PluginPrivateFileSystemBackend::~PluginPrivateFileSystemBackend() { @@ -163,7 +163,7 @@ WatcherManager* PluginPrivateFileSystemBackend::GetWatcherManager( FileSystemType type) { - return NULL; + return nullptr; } CopyOrMoveFileValidatorFactory* @@ -172,7 +172,7 @@ base::File::Error* error_code) { DCHECK(error_code); *error_code = base::File::FILE_OK; - return NULL; + return nullptr; } FileSystemOperation* PluginPrivateFileSystemBackend::CreateFileSystemOperation( @@ -345,17 +345,17 @@ const UpdateObserverList* PluginPrivateFileSystemBackend::GetUpdateObservers( FileSystemType type) const { - return NULL; + return nullptr; } const ChangeObserverList* PluginPrivateFileSystemBackend::GetChangeObservers( FileSystemType type) const { - return NULL; + return nullptr; } const AccessObserverList* PluginPrivateFileSystemBackend::GetAccessObservers( FileSystemType type) const { - return NULL; + return nullptr; } ObfuscatedFileUtil* PluginPrivateFileSystemBackend::obfuscated_file_util() {
diff --git a/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc b/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc index f4794ff..79dfbec 100644 --- a/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc +++ b/storage/browser/fileapi/plugin_private_file_system_backend_unittest.cc
@@ -50,8 +50,8 @@ protected: void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); - context_ = CreateFileSystemContextForTesting(NULL /* quota_manager_proxy */, - data_dir_.GetPath()); + context_ = CreateFileSystemContextForTesting( + nullptr /* quota_manager_proxy */, data_dir_.GetPath()); } FileSystemURL CreateURL(const GURL& root_url, const std::string& relative) { @@ -222,8 +222,8 @@ context_.get(), file2, AsyncFileTestHelper::kDontCheckSize)); // Delete data for kOrigin1. - error = backend()->DeleteOriginDataOnFileTaskRunner( - context_.get(), NULL, kOrigin1, kType); + error = backend()->DeleteOriginDataOnFileTaskRunner(context_.get(), nullptr, + kOrigin1, kType); EXPECT_EQ(base::File::FILE_OK, error); // Confirm 'foo' in kOrigin1 is deleted.
diff --git a/storage/browser/fileapi/quota/quota_backend_impl_unittest.cc b/storage/browser/fileapi/quota/quota_backend_impl_unittest.cc index e4023ecc..9367fe8 100644 --- a/storage/browser/fileapi/quota/quota_backend_impl_unittest.cc +++ b/storage/browser/fileapi/quota/quota_backend_impl_unittest.cc
@@ -46,7 +46,7 @@ class MockQuotaManagerProxy : public storage::QuotaManagerProxy { public: MockQuotaManagerProxy() - : QuotaManagerProxy(NULL, NULL), + : QuotaManagerProxy(nullptr, nullptr), storage_modified_count_(0), usage_(0), quota_(0) {} @@ -101,7 +101,7 @@ ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); in_memory_env_ = leveldb_chrome::NewMemEnv("quota"); file_util_.reset(ObfuscatedFileUtil::CreateForTesting( - NULL, data_dir_.GetPath(), in_memory_env_.get())); + nullptr, data_dir_.GetPath(), in_memory_env_.get())); backend_.reset(new QuotaBackendImpl(file_task_runner(), file_util_.get(), &file_system_usage_cache_, quota_manager_proxy_.get())); @@ -109,7 +109,7 @@ void TearDown() override { backend_.reset(); - quota_manager_proxy_ = NULL; + quota_manager_proxy_ = nullptr; file_util_.reset(); base::RunLoop().RunUntilIdle(); } @@ -119,7 +119,7 @@ storage::FileSystemType type) { ASSERT_TRUE( file_util_->InitOriginDatabase(origin.GetURL(), true /* create */)); - ASSERT_TRUE(file_util_->origin_database_ != NULL); + ASSERT_TRUE(file_util_->origin_database_ != nullptr); std::string type_string = SandboxFileSystemBackendDelegate::GetTypeString(type);
diff --git a/storage/browser/fileapi/quota/quota_reservation_manager_unittest.cc b/storage/browser/fileapi/quota/quota_reservation_manager_unittest.cc index 06c97e0..1e73a3a 100644 --- a/storage/browser/fileapi/quota/quota_reservation_manager_unittest.cc +++ b/storage/browser/fileapi/quota/quota_reservation_manager_unittest.cc
@@ -255,7 +255,7 @@ EXPECT_EQ(3, fake_backend()->on_disk_usage()); EXPECT_EQ(3 + 5, fake_backend()->on_memory_usage()); - reservation = NULL; + reservation = nullptr; EXPECT_EQ(3, fake_backend()->on_memory_usage()); } @@ -289,7 +289,7 @@ fake_backend()->on_memory_usage()); EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, fake_backend()->on_disk_usage()); - reservation = NULL; + reservation = nullptr; EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, fake_backend()->on_disk_usage()); } @@ -333,10 +333,10 @@ fake_backend()->on_memory_usage()); EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_disk_usage()); - reservation1 = NULL; + reservation1 = nullptr; EXPECT_EQ(kInitialFileSize + 10 + 20 + 3, fake_backend()->on_memory_usage()); - reservation2 = NULL; + reservation2 = nullptr; EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_memory_usage()); } @@ -357,13 +357,13 @@ reservation1->OnClientCrash(); writer.ClearWithoutUsageReport(); } - reservation1 = NULL; + reservation1 = nullptr; EXPECT_EQ(kInitialFileSize + 10, GetFileSize(file_path())); EXPECT_EQ(kInitialFileSize + 15 + 20, fake_backend()->on_memory_usage()); EXPECT_EQ(kInitialFileSize + 10, fake_backend()->on_disk_usage()); - reservation2 = NULL; + reservation2 = nullptr; EXPECT_EQ(kInitialFileSize + 10, fake_backend()->on_memory_usage()); }
diff --git a/storage/browser/fileapi/sandbox_directory_database_unittest.cc b/storage/browser/fileapi/sandbox_directory_database_unittest.cc index fb294e7..dfaf01ed 100644 --- a/storage/browser/fileapi/sandbox_directory_database_unittest.cc +++ b/storage/browser/fileapi/sandbox_directory_database_unittest.cc
@@ -51,7 +51,7 @@ // Call CloseDatabase() to avoid having multiple database instances for // single directory at once. CloseDatabase(); - db_.reset(new SandboxDirectoryDatabase(path(), NULL)); + db_.reset(new SandboxDirectoryDatabase(path(), nullptr)); } void CloseDatabase() { @@ -105,7 +105,7 @@ db_.reset(); ASSERT_TRUE(base::DeleteFile(path(), true /* recursive */)); ASSERT_TRUE(base::CreateDirectory(path())); - db_.reset(new SandboxDirectoryDatabase(path(), NULL)); + db_.reset(new SandboxDirectoryDatabase(path(), nullptr)); } bool RepairDatabase() { @@ -524,10 +524,10 @@ TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_Consistent) { FileId dir_id; - CreateFile(0, FPL("foo"), FPL("hoge"), NULL); + CreateFile(0, FPL("foo"), FPL("hoge"), nullptr); CreateDirectory(0, FPL("bar"), &dir_id); - CreateFile(dir_id, FPL("baz"), FPL("fuga"), NULL); - CreateFile(dir_id, FPL("fizz"), FPL("buzz"), NULL); + CreateFile(dir_id, FPL("baz"), FPL("fuga"), nullptr); + CreateFile(dir_id, FPL("fizz"), FPL("buzz"), nullptr); EXPECT_TRUE(db()->IsFileSystemConsistent()); } @@ -535,17 +535,17 @@ TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_BackingMultiEntry) { const base::FilePath::CharType kBackingFileName[] = FPL("the celeb"); - CreateFile(0, FPL("foo"), kBackingFileName, NULL); + CreateFile(0, FPL("foo"), kBackingFileName, nullptr); EXPECT_TRUE(db()->IsFileSystemConsistent()); ASSERT_TRUE(base::DeleteFile(path().Append(kBackingFileName), false)); - CreateFile(0, FPL("bar"), kBackingFileName, NULL); + CreateFile(0, FPL("bar"), kBackingFileName, nullptr); EXPECT_FALSE(db()->IsFileSystemConsistent()); } TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_FileLost) { const base::FilePath::CharType kBackingFileName[] = FPL("hoge"); - CreateFile(0, FPL("foo"), kBackingFileName, NULL); + CreateFile(0, FPL("foo"), kBackingFileName, nullptr); EXPECT_TRUE(db()->IsFileSystemConsistent()); ASSERT_TRUE(base::DeleteFile(path().Append(kBackingFileName), false)); @@ -553,7 +553,7 @@ } TEST_F(SandboxDirectoryDatabaseTest, TestConsistencyCheck_OrphanFile) { - CreateFile(0, FPL("foo"), FPL("hoge"), NULL); + CreateFile(0, FPL("foo"), FPL("hoge"), nullptr); EXPECT_TRUE(db()->IsFileSystemConsistent()); @@ -601,7 +601,7 @@ FileId dir2_id; CreateDirectory(0, FPL("foo"), &dir1_id); CreateDirectory(dir1_id, FPL("bar"), &dir2_id); - CreateFile(dir2_id, FPL("baz"), FPL("fizz/buzz"), NULL); + CreateFile(dir2_id, FPL("baz"), FPL("fizz/buzz"), nullptr); EXPECT_TRUE(db()->IsFileSystemConsistent()); DeleteHierarchyLink(dir2_id); // Delete link from |dir1_id| to |dir2_id|. @@ -612,7 +612,7 @@ base::FilePath::StringType kFileName = FPL("bar"); FileId file_id_prev; - CreateFile(0, FPL("foo"), FPL("hoge"), NULL); + CreateFile(0, FPL("foo"), FPL("hoge"), nullptr); CreateFile(0, kFileName, FPL("fuga"), &file_id_prev); const base::FilePath kDatabaseDirectory = @@ -633,8 +633,8 @@ TEST_F(SandboxDirectoryDatabaseTest, TestRepairDatabase_Failure) { base::FilePath::StringType kFileName = FPL("bar"); - CreateFile(0, FPL("foo"), FPL("hoge"), NULL); - CreateFile(0, kFileName, FPL("fuga"), NULL); + CreateFile(0, FPL("foo"), FPL("hoge"), nullptr); + CreateFile(0, kFileName, FPL("fuga"), nullptr); const base::FilePath kDatabaseDirectory = path().Append(kDirectoryDatabaseName); @@ -655,7 +655,7 @@ base::FilePath::StringType kFileName = FPL("bar"); FileId file_id_prev; - CreateFile(0, FPL("foo"), FPL("hoge"), NULL); + CreateFile(0, FPL("foo"), FPL("hoge"), nullptr); CreateFile(0, kFileName, FPL("fuga"), &file_id_prev); const base::FilePath kDatabaseDirectory =
diff --git a/storage/browser/fileapi/sandbox_file_system_backend.cc b/storage/browser/fileapi/sandbox_file_system_backend.cc index 9b38f2f..15b8a73 100644 --- a/storage/browser/fileapi/sandbox_file_system_backend.cc +++ b/storage/browser/fileapi/sandbox_file_system_backend.cc
@@ -53,12 +53,12 @@ // Set quota observers. delegate_->RegisterQuotaUpdateObserver(storage::kFileSystemTypeTemporary); - delegate_->AddFileAccessObserver( - storage::kFileSystemTypeTemporary, delegate_->quota_observer(), NULL); + delegate_->AddFileAccessObserver(storage::kFileSystemTypeTemporary, + delegate_->quota_observer(), nullptr); delegate_->RegisterQuotaUpdateObserver(storage::kFileSystemTypePersistent); - delegate_->AddFileAccessObserver( - storage::kFileSystemTypePersistent, delegate_->quota_observer(), NULL); + delegate_->AddFileAccessObserver(storage::kFileSystemTypePersistent, + delegate_->quota_observer(), nullptr); } void SandboxFileSystemBackend::ResolveURL(const FileSystemURL& url, @@ -87,7 +87,7 @@ WatcherManager* SandboxFileSystemBackend::GetWatcherManager( FileSystemType type) { - return NULL; + return nullptr; } CopyOrMoveFileValidatorFactory* @@ -96,7 +96,7 @@ base::File::Error* error_code) { DCHECK(error_code); *error_code = base::File::FILE_OK; - return NULL; + return nullptr; } FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( @@ -110,7 +110,7 @@ std::unique_ptr<FileSystemOperationContext> operation_context = delegate_->CreateFileSystemOperationContext(url, context, error_code); if (!operation_context) - return NULL; + return nullptr; SpecialStoragePolicy* policy = delegate_->special_storage_policy(); if (policy && policy->IsStorageUnlimited(url.origin()))
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc index fedd1918..94c63c3 100644 --- a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc +++ b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
@@ -479,7 +479,7 @@ std::map<FileSystemType, UpdateObserverList>::const_iterator iter = update_observers_.find(type); if (iter == update_observers_.end()) - return NULL; + return nullptr; return &iter->second; } @@ -488,7 +488,7 @@ std::map<FileSystemType, ChangeObserverList>::const_iterator iter = change_observers_.find(type); if (iter == change_observers_.end()) - return NULL; + return nullptr; return &iter->second; } @@ -497,7 +497,7 @@ std::map<FileSystemType, AccessObserverList>::const_iterator iter = access_observers_.find(type); if (iter == access_observers_.end()) - return NULL; + return nullptr; return &iter->second; } @@ -704,12 +704,9 @@ storage::SpecialStoragePolicy* special_storage_policy, const base::FilePath& file_system_directory, leveldb::Env* env_override) { - return new ObfuscatedFileUtil(special_storage_policy, - file_system_directory, - env_override, - base::Bind(&GetTypeStringForURL), - GetKnownTypeStrings(), - NULL); + return new ObfuscatedFileUtil(special_storage_policy, file_system_directory, + env_override, base::Bind(&GetTypeStringForURL), + GetKnownTypeStrings(), nullptr); } } // namespace storage
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc b/storage/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc index cf49cd91..c8dce44 100644 --- a/storage/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc +++ b/storage/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
@@ -42,7 +42,7 @@ nullptr, base::ThreadTaskRunnerHandle::Get().get()); delegate_.reset(new storage::SandboxFileSystemBackendDelegate( quota_manager_proxy_.get(), base::ThreadTaskRunnerHandle::Get().get(), - data_dir_.GetPath(), NULL /* special_storage_policy */, + data_dir_.GetPath(), nullptr /* special_storage_policy */, CreateAllowFileAccessOptions(), nullptr /* env_override */)); }
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc b/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc index 4f0017f..a5b3df8 100644 --- a/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc +++ b/storage/browser/fileapi/sandbox_file_system_backend_unittest.cc
@@ -258,10 +258,9 @@ for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) { SCOPED_TRACE(testing::Message() << "RootPath (create=false) #" << i << " " << kRootPathTestCases[i].expected_path); - EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url), - kRootPathTestCases[i].type, - storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, - NULL)); + EXPECT_FALSE(GetRootPath( + GURL(kRootPathTestCases[i].origin_url), kRootPathTestCases[i].type, + storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, nullptr)); } } @@ -272,10 +271,9 @@ for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) { SCOPED_TRACE(testing::Message() << "RootPath (incognito) #" << i << " " << kRootPathTestCases[i].expected_path); - EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url), - kRootPathTestCases[i].type, - storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, - NULL)); + EXPECT_FALSE(GetRootPath( + GURL(kRootPathTestCases[i].origin_url), kRootPathTestCases[i].type, + storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, nullptr)); } } @@ -287,7 +285,7 @@ EXPECT_FALSE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url), kRootPathFileURITestCases[i].type, storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, - NULL)); + nullptr)); } }
diff --git a/storage/browser/fileapi/sandbox_origin_database_unittest.cc b/storage/browser/fileapi/sandbox_origin_database_unittest.cc index e2675a76..d89ebb28 100644 --- a/storage/browser/fileapi/sandbox_origin_database_unittest.cc +++ b/storage/browser/fileapi/sandbox_origin_database_unittest.cc
@@ -42,7 +42,7 @@ EXPECT_FALSE(base::PathExists(kFSDir)); EXPECT_TRUE(base::CreateDirectory(kFSDir)); - SandboxOriginDatabase database(kFSDir, NULL); + SandboxOriginDatabase database(kFSDir, nullptr); std::string origin("origin"); EXPECT_FALSE(database.HasOriginPath(origin)); @@ -72,7 +72,7 @@ EXPECT_FALSE(base::PathExists(kFSDir)); EXPECT_TRUE(base::CreateDirectory(kFSDir)); - SandboxOriginDatabase database(kFSDir, NULL); + SandboxOriginDatabase database(kFSDir, nullptr); std::string origin0("origin0"); std::string origin1("origin1"); @@ -100,7 +100,7 @@ EXPECT_FALSE(base::PathExists(kFSDir)); EXPECT_TRUE(base::CreateDirectory(kFSDir)); - SandboxOriginDatabase database(kFSDir, NULL); + SandboxOriginDatabase database(kFSDir, nullptr); std::string origin("origin"); EXPECT_FALSE(database.HasOriginPath(origin)); @@ -128,7 +128,7 @@ EXPECT_FALSE(base::PathExists(kFSDir)); EXPECT_TRUE(base::CreateDirectory(kFSDir)); - SandboxOriginDatabase database(kFSDir, NULL); + SandboxOriginDatabase database(kFSDir, nullptr); std::string origin("origin"); EXPECT_FALSE(database.HasOriginPath(origin)); @@ -157,7 +157,7 @@ std::vector<SandboxOriginDatabase::OriginRecord> origins; - SandboxOriginDatabase database(kFSDir, NULL); + SandboxOriginDatabase database(kFSDir, nullptr); EXPECT_TRUE(database.ListAllOrigins(&origins)); EXPECT_TRUE(origins.empty()); origins.clear(); @@ -214,7 +214,7 @@ }; std::unique_ptr<SandboxOriginDatabase> database( - new SandboxOriginDatabase(kFSDir, NULL)); + new SandboxOriginDatabase(kFSDir, nullptr)); for (size_t i = 0; i < arraysize(kOrigins); ++i) { base::FilePath path; EXPECT_FALSE(database->HasOriginPath(kOrigins[i])); @@ -243,7 +243,7 @@ CorruptDatabase(kDBDir, leveldb::kLogFile, -1, 1); base::FilePath path; - database.reset(new SandboxOriginDatabase(kFSDir, NULL)); + database.reset(new SandboxOriginDatabase(kFSDir, nullptr)); std::vector<SandboxOriginDatabase::OriginRecord> origins_in_db; EXPECT_TRUE(database->ListAllOrigins(&origins_in_db)); @@ -284,7 +284,7 @@ base::FilePath path; std::unique_ptr<SandboxOriginDatabase> database( - new SandboxOriginDatabase(kFSDir, NULL)); + new SandboxOriginDatabase(kFSDir, nullptr)); EXPECT_FALSE(database->HasOriginPath(kOrigin)); EXPECT_TRUE(database->GetPathForOrigin(kOrigin, &path)); EXPECT_FALSE(path.empty()); @@ -294,7 +294,7 @@ DeleteDatabaseFile(kDBDir, kLevelDBFileTypes[i]); - database.reset(new SandboxOriginDatabase(kFSDir, NULL)); + database.reset(new SandboxOriginDatabase(kFSDir, nullptr)); std::vector<SandboxOriginDatabase::OriginRecord> origins_in_db; EXPECT_TRUE(database->ListAllOrigins(&origins_in_db));
diff --git a/storage/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc b/storage/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc index e21f418..5e1a106e 100644 --- a/storage/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc +++ b/storage/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc
@@ -22,7 +22,7 @@ const std::string kOrigin1("origin1"); const std::string kOrigin2("origin2"); - SandboxPrioritizedOriginDatabase database(dir.GetPath(), NULL); + SandboxPrioritizedOriginDatabase database(dir.GetPath(), nullptr); // Set the kOrigin1 as a parimary origin. EXPECT_TRUE(database.InitializePrimaryOrigin(kOrigin1)); @@ -76,7 +76,7 @@ const std::string kOrigin1("origin1"); const std::string kOrigin2("origin2"); - SandboxPrioritizedOriginDatabase database(dir.GetPath(), NULL); + SandboxPrioritizedOriginDatabase database(dir.GetPath(), nullptr); EXPECT_TRUE(database.GetPrimaryOrigin().empty()); @@ -105,7 +105,7 @@ const std::string kOrigin1("origin1"); const std::string kData("foo"); - SandboxPrioritizedOriginDatabase database(dir.GetPath(), NULL); + SandboxPrioritizedOriginDatabase database(dir.GetPath(), nullptr); EXPECT_TRUE(database.GetPrimaryOrigin().empty()); @@ -149,7 +149,7 @@ // Initialize the directory with two origins using the regular // SandboxOriginDatabase. { - SandboxOriginDatabase database_old(dir.GetPath(), NULL); + SandboxOriginDatabase database_old(dir.GetPath(), nullptr); base::FilePath old_db_path = database_old.GetDatabasePath(); EXPECT_FALSE(base::PathExists(old_db_path)); @@ -177,7 +177,7 @@ } // Re-open the directory using sandboxPrioritizedOriginDatabase. - SandboxPrioritizedOriginDatabase database(dir.GetPath(), NULL); + SandboxPrioritizedOriginDatabase database(dir.GetPath(), nullptr); // Set the kOrigin1 as a parimary origin. // (Trying to initialize another origin should fail).
diff --git a/storage/browser/fileapi/task_runner_bound_observer_list.h b/storage/browser/fileapi/task_runner_bound_observer_list.h index a244b6a..4dad36c4 100644 --- a/storage/browser/fileapi/task_runner_bound_observer_list.h +++ b/storage/browser/fileapi/task_runner_bound_observer_list.h
@@ -39,7 +39,7 @@ virtual ~TaskRunnerBoundObserverList() {} // Returns a new observer list with given observer. - // It is valid to give NULL as |runner_to_notify|, and in that case + // It is valid to give nullptr as |runner_to_notify|, and in that case // notifications are dispatched on the current runner. // Note that this is a const method and does NOT change 'this' observer // list but returns a new list.
diff --git a/storage/browser/fileapi/transient_file_util.cc b/storage/browser/fileapi/transient_file_util.cc index 892776cd..fd0a24f 100644 --- a/storage/browser/fileapi/transient_file_util.cc +++ b/storage/browser/fileapi/transient_file_util.cc
@@ -47,7 +47,7 @@ ScopedFile::DELETE_ON_SCOPE_OUT, context->task_runner()); scoped_file.AddScopeOutCallback( - base::BindOnce(&RevokeFileSystem, url.filesystem_id()), NULL); + base::BindOnce(&RevokeFileSystem, url.filesystem_id()), nullptr); return scoped_file; }
diff --git a/storage/browser/fileapi/transient_file_util_unittest.cc b/storage/browser/fileapi/transient_file_util_unittest.cc index 922419d..0567b32 100644 --- a/storage/browser/fileapi/transient_file_util_unittest.cc +++ b/storage/browser/fileapi/transient_file_util_unittest.cc
@@ -29,14 +29,14 @@ void SetUp() override { file_system_context_ = CreateFileSystemContextForTesting( - NULL, base::FilePath(FILE_PATH_LITERAL("dummy"))); + nullptr, base::FilePath(FILE_PATH_LITERAL("dummy"))); transient_file_util_.reset(new storage::TransientFileUtil); ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); } void TearDown() override { - file_system_context_ = NULL; + file_system_context_ = nullptr; base::RunLoop().RunUntilIdle(); }
diff --git a/storage/browser/quota/client_usage_tracker.cc b/storage/browser/quota/client_usage_tracker.cc index afda0ed..732fe4a 100644 --- a/storage/browser/quota/client_usage_tracker.cc +++ b/storage/browser/quota/client_usage_tracker.cc
@@ -159,7 +159,7 @@ delta); // Notify the usage monitor that usage has changed. The storage monitor may - // be NULL during tests. + // be nullptr during tests. if (storage_monitor_) { StorageObserver::Filter filter(type_, origin); storage_monitor_->NotifyUsageChange(filter, delta);
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc index e759bcf4..9103809e 100644 --- a/storage/browser/quota/quota_database.cc +++ b/storage/browser/quota/quota_database.cc
@@ -38,7 +38,7 @@ const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped"; bool VerifyValidQuotaConfig(const char* key) { - return (key != NULL && + return (key != nullptr && (!strcmp(key, QuotaDatabase::kDesiredAvailableSpaceKey) || !strcmp(key, QuotaDatabase::kTemporaryQuotaOverrideKey))); }
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc index c42503d..ff4774d 100644 --- a/storage/browser/quota/quota_database_unittest.cc +++ b/storage/browser/quota/quota_database_unittest.cc
@@ -154,7 +154,7 @@ std::set<GURL> exceptions; GURL origin; - EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, NULL, &origin)); + EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); EXPECT_TRUE(origin.is_empty()); const GURL kOrigin1("http://a/"); @@ -174,7 +174,7 @@ EXPECT_TRUE(db.SetOriginLastAccessTime(kOrigin4, kPersistent, base::Time::FromInternalValue(40))); - EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, NULL, &origin)); + EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); EXPECT_EQ(kOrigin1.spec(), origin.spec()); // Test that unlimited origins are exluded from eviction, but @@ -192,15 +192,15 @@ EXPECT_EQ(kOrigin3.spec(), origin.spec()); exceptions.insert(kOrigin1); - EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, NULL, &origin)); + EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); EXPECT_EQ(kOrigin2.spec(), origin.spec()); exceptions.insert(kOrigin2); - EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, NULL, &origin)); + EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); EXPECT_EQ(kOrigin3.spec(), origin.spec()); exceptions.insert(kOrigin3); - EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, NULL, &origin)); + EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); EXPECT_TRUE(origin.is_empty()); EXPECT_TRUE( @@ -211,12 +211,12 @@ // Querying again to see if the deletion has worked. exceptions.clear(); - EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, NULL, &origin)); + EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); EXPECT_EQ(kOrigin2.spec(), origin.spec()); exceptions.insert(kOrigin1); exceptions.insert(kOrigin2); - EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, NULL, &origin)); + EXPECT_TRUE(db.GetLRUOrigin(kTemporary, exceptions, nullptr, &origin)); EXPECT_TRUE(origin.is_empty()); } @@ -466,7 +466,7 @@ private: template <typename Iterator> void AssignQuotaTable(sql::Database* db, Iterator itr, Iterator end) { - ASSERT_NE(db, (sql::Database*)NULL); + ASSERT_NE(db, (sql::Database*)nullptr); for (; itr != end; ++itr) { const char* kSql = "INSERT INTO HostQuotaTable" @@ -485,7 +485,7 @@ template <typename Iterator> void AssignOriginInfoTable(sql::Database* db, Iterator itr, Iterator end) { - ASSERT_NE(db, (sql::Database*)NULL); + ASSERT_NE(db, (sql::Database*)nullptr); for (; itr != end; ++itr) { const char* kSql = "INSERT INTO OriginInfoTable"
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc index 59c97c9..41a92cc 100644 --- a/storage/browser/quota/quota_manager.cc +++ b/storage/browser/quota/quota_manager.cc
@@ -1138,7 +1138,7 @@ } QuotaManager::~QuotaManager() { - proxy_->manager_ = NULL; + proxy_->manager_ = nullptr; for (auto* client : clients_) client->OnQuotaManagerDestroyed(); if (database_) @@ -1228,11 +1228,11 @@ case StorageType::kSyncable: return syncable_usage_tracker_.get(); case StorageType::kQuotaNotManaged: - return NULL; + return nullptr; case StorageType::kUnknown: NOTREACHED(); } - return NULL; + return nullptr; } void QuotaManager::GetCachedOrigins(
diff --git a/storage/browser/quota/quota_manager_proxy.h b/storage/browser/quota/quota_manager_proxy.h index b3ab592..32b3292 100644 --- a/storage/browser/quota/quota_manager_proxy.h +++ b/storage/browser/quota/quota_manager_proxy.h
@@ -59,7 +59,7 @@ UsageAndQuotaCallback callback); // This method may only be called on the IO thread. - // It may return NULL if the manager has already been deleted. + // It may return nullptr if the manager has already been deleted. QuotaManager* quota_manager() const; protected:
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc index 5412489..174a262 100644 --- a/storage/browser/quota/quota_manager_unittest.cc +++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -98,7 +98,7 @@ void TearDown() override { // Make sure the quota manager cleans up correctly. - quota_manager_ = NULL; + quota_manager_ = nullptr; scoped_task_environment_.RunUntilIdle(); } @@ -288,7 +288,7 @@ } void GetCachedOrigins(StorageType type, std::set<GURL>* origins) { - ASSERT_TRUE(origins != NULL); + ASSERT_TRUE(origins != nullptr); origins->clear(); quota_manager_->GetCachedOrigins(type, origins); } @@ -611,7 +611,7 @@ } TEST_F(QuotaManagerTest, GetUsage_EmptyClient) { - RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem)); + RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem)); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); @@ -983,7 +983,7 @@ DeleteOriginData(GURL("http://bar.com/"), kTemp, kAllClients); // Nuke before waiting for callbacks. - set_quota_manager(NULL); + set_quota_manager(nullptr); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kErrorAbort, status()); } @@ -1155,7 +1155,7 @@ } TEST_F(QuotaManagerTest, GetAndSetPerststentHostQuota) { - RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem)); + RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem)); GetPersistentHostQuota("foo.com"); scoped_task_environment_.RunUntilIdle(); @@ -1182,7 +1182,7 @@ } TEST_F(QuotaManagerTest, GetAndSetPersistentUsageAndQuota) { - RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem)); + RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem)); GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm); scoped_task_environment_.RunUntilIdle(); @@ -1212,7 +1212,7 @@ } TEST_F(QuotaManagerTest, GetSyncableQuota) { - RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem)); + RegisterClient(CreateClient(nullptr, 0, QuotaClient::kFileSystem)); // Pre-condition check: available disk space (for testing) is less than // the default quota for syncable storage. @@ -1302,7 +1302,7 @@ RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kPerm); // Nuke before waiting for callbacks. - set_quota_manager(NULL); + set_quota_manager(nullptr); scoped_task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kErrorAbort, status()); }
diff --git a/storage/browser/quota/quota_task.cc b/storage/browser/quota/quota_task.cc index 8e10a880..b7266c4 100644 --- a/storage/browser/quota/quota_task.cc +++ b/storage/browser/quota/quota_task.cc
@@ -43,7 +43,7 @@ void QuotaTask::Abort() { DCHECK(original_task_runner_->BelongsToCurrentThread()); - observer_ = NULL; + observer_ = nullptr; Aborted(); }
diff --git a/storage/browser/quota/storage_monitor_unittest.cc b/storage/browser/quota/storage_monitor_unittest.cc index 0ffb6b1f..e633d22 100644 --- a/storage/browser/quota/storage_monitor_unittest.cc +++ b/storage/browser/quota/storage_monitor_unittest.cc
@@ -118,7 +118,8 @@ const StorageObserver::Event* GetPendingEvent( const StorageObserverList& observer_list) { return observer_list.notification_timer_.IsRunning() - ? &observer_list.pending_event_ : NULL; + ? &observer_list.pending_event_ + : nullptr; } const StorageObserver::Event* GetPendingEvent( @@ -169,7 +170,7 @@ void TearDown() override { // This ensures the quota manager is destroyed correctly. - quota_manager_ = NULL; + quota_manager_ = nullptr; scoped_task_environment_.RunUntilIdle(); } @@ -200,7 +201,7 @@ observer_list.OnStorageChange(event); EXPECT_EQ(1, mock_observer.EventCount()); EXPECT_EQ(event, mock_observer.LastEvent()); - EXPECT_EQ(NULL, GetPendingEvent(observer_list)); + EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); // Verify that the next event is pending. @@ -219,7 +220,7 @@ observer_list.OnStorageChange(event); EXPECT_EQ(2, mock_observer.EventCount()); EXPECT_EQ(event, mock_observer.LastEvent()); - EXPECT_EQ(NULL, GetPendingEvent(observer_list)); + EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); // Remove the observer. @@ -228,7 +229,7 @@ observer_list.RemoveObserver(&mock_observer); observer_list.OnStorageChange(event); EXPECT_EQ(2, mock_observer.EventCount()); - EXPECT_EQ(NULL, GetPendingEvent(observer_list)); + EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); } // Test dispatching events to multiple observers. @@ -258,7 +259,7 @@ EXPECT_EQ(1, mock_observer2.EventCount()); EXPECT_EQ(event, mock_observer1.LastEvent()); EXPECT_EQ(event, mock_observer2.LastEvent()); - EXPECT_EQ(NULL, GetPendingEvent(observer_list)); + EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); // Fake the last notification time so that observer1 will receive the next @@ -281,7 +282,7 @@ EXPECT_EQ(2, mock_observer2.EventCount()); EXPECT_EQ(event, mock_observer1.LastEvent()); EXPECT_EQ(event, mock_observer2.LastEvent()); - EXPECT_EQ(NULL, GetPendingEvent(observer_list)); + EXPECT_EQ(nullptr, GetPendingEvent(observer_list)); EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); } @@ -365,7 +366,7 @@ EXPECT_EQ(1, mock_observer2.EventCount()); EXPECT_EQ(expected_event, mock_observer2.LastEvent()); EXPECT_TRUE(host_observers.is_initialized()); - EXPECT_EQ(NULL, GetPendingEvent(host_observers)); + EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); // Verify that both observers will receive events after a usage change. @@ -377,7 +378,7 @@ EXPECT_EQ(2, mock_observer2.EventCount()); EXPECT_EQ(expected_event, mock_observer1.LastEvent()); EXPECT_EQ(expected_event, mock_observer2.LastEvent()); - EXPECT_EQ(NULL, GetPendingEvent(host_observers)); + EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); // Verify that the addition of a third observer only causes an event to be @@ -429,7 +430,7 @@ host_observers.NotifyUsageChange(params.filter, 9438); EXPECT_EQ(0, mock_observer.EventCount()); EXPECT_FALSE(host_observers.is_initialized()); - EXPECT_EQ(NULL, GetPendingEvent(host_observers)); + EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); // Now ensure that quota manager returns a good status. @@ -456,7 +457,7 @@ host_observers.NotifyUsageChange(params.filter, 7645); EXPECT_EQ(0, mock_observer.EventCount()); EXPECT_FALSE(host_observers.is_initialized()); - EXPECT_EQ(NULL, GetPendingEvent(host_observers)); + EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); // Simulate notifying |host_observers| of a usage change before initialization @@ -467,7 +468,7 @@ host_observers.NotifyUsageChange(params.filter, kDelta); EXPECT_EQ(0, mock_observer.EventCount()); EXPECT_FALSE(host_observers.is_initialized()); - EXPECT_EQ(NULL, GetPendingEvent(host_observers)); + EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); // Simulate an asynchronous callback from QuotaManager. @@ -477,7 +478,7 @@ EXPECT_EQ(1, mock_observer.EventCount()); EXPECT_EQ(expected_event, mock_observer.LastEvent()); EXPECT_TRUE(host_observers.is_initialized()); - EXPECT_EQ(NULL, GetPendingEvent(host_observers)); + EXPECT_EQ(nullptr, GetPendingEvent(host_observers)); EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); } @@ -534,7 +535,7 @@ class StorageMonitorTest : public StorageTestWithManagerBase { public: StorageMonitorTest() - : storage_monitor_(NULL), + : storage_monitor_(nullptr), params1_(StorageType::kTemporary, GURL(kDefaultOrigin), base::TimeDelta::FromHours(1), @@ -630,17 +631,15 @@ false, data_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get().get(), storage_policy_.get(), storage::GetQuotaSettingsFunc()); - client_ = new MockStorageClient(quota_manager_->proxy(), - NULL, - QuotaClient::kFileSystem, - 0); + client_ = new MockStorageClient(quota_manager_->proxy(), nullptr, + QuotaClient::kFileSystem, 0); quota_manager_->proxy()->RegisterClient(client_); } void TearDown() override { // This ensures the quota manager is destroyed correctly. - quota_manager_ = NULL; + quota_manager_ = nullptr; scoped_task_environment_.RunUntilIdle(); }
diff --git a/storage/browser/quota/usage_tracker_unittest.cc b/storage/browser/quota/usage_tracker_unittest.cc index 3e641b8a..48ea323 100644 --- a/storage/browser/quota/usage_tracker_unittest.cc +++ b/storage/browser/quota/usage_tracker_unittest.cc
@@ -140,7 +140,7 @@ usage_tracker_(GetUsageTrackerList(), StorageType::kTemporary, storage_policy_.get(), - NULL) {} + nullptr) {} ~UsageTrackerTest() override = default;
diff --git a/storage/browser/test/async_file_test_helper.h b/storage/browser/test/async_file_test_helper.h index 41e7978..fcdc0856 100644 --- a/storage/browser/test/async_file_test_helper.h +++ b/storage/browser/test/async_file_test_helper.h
@@ -99,7 +99,8 @@ static bool DirectoryExists(storage::FileSystemContext* context, const storage::FileSystemURL& url); - // Returns usage and quota. It's valid to pass NULL to |usage| and/or |quota|. + // Returns usage and quota. It's valid to pass nullptr to |usage| and/or + // |quota|. static blink::mojom::QuotaStatusCode GetUsageAndQuota( storage::QuotaManager* quota_manager, const GURL& origin,
diff --git a/storage/browser/test/mock_quota_manager_proxy.cc b/storage/browser/test/mock_quota_manager_proxy.cc index 410fb4f4..048b2afd 100644 --- a/storage/browser/test/mock_quota_manager_proxy.cc +++ b/storage/browser/test/mock_quota_manager_proxy.cc
@@ -16,7 +16,7 @@ storage_modified_count_(0), last_notified_type_(blink::mojom::StorageType::kUnknown), last_notified_delta_(0), - registered_client_(NULL) {} + registered_client_(nullptr) {} void MockQuotaManagerProxy::RegisterClient(QuotaClient* client) { DCHECK(!registered_client_); @@ -28,7 +28,7 @@ // We cannot call this in the destructor as the client (indirectly) // holds a refptr of the proxy. registered_client_->OnQuotaManagerDestroyed(); - registered_client_ = NULL; + registered_client_ = nullptr; } }
diff --git a/storage/browser/test/mock_quota_manager_proxy.h b/storage/browser/test/mock_quota_manager_proxy.h index 976b9dc..d2f41293f 100644 --- a/storage/browser/test/mock_quota_manager_proxy.h +++ b/storage/browser/test/mock_quota_manager_proxy.h
@@ -22,7 +22,7 @@ class MockQuotaManagerProxy : public QuotaManagerProxy { public: - // It is ok to give NULL to |quota_manager|. + // It is ok to give nullptr to |quota_manager|. MockQuotaManagerProxy(MockQuotaManager* quota_manager, base::SingleThreadTaskRunner* task_runner);
diff --git a/storage/browser/test/mock_quota_manager_unittest.cc b/storage/browser/test/mock_quota_manager_unittest.cc index 9fc112d..4ffb207 100644 --- a/storage/browser/test/mock_quota_manager_unittest.cc +++ b/storage/browser/test/mock_quota_manager_unittest.cc
@@ -53,7 +53,7 @@ void TearDown() override { // Make sure the quota manager cleans up correctly. - manager_ = NULL; + manager_ = nullptr; base::RunLoop().RunUntilIdle(); }
diff --git a/storage/browser/test/sandbox_file_system_test_helper.cc b/storage/browser/test/sandbox_file_system_test_helper.cc index a1b4f0a..cc2d38cb 100644 --- a/storage/browser/test/sandbox_file_system_test_helper.cc +++ b/storage/browser/test/sandbox_file_system_test_helper.cc
@@ -31,19 +31,17 @@ SandboxFileSystemTestHelper::SandboxFileSystemTestHelper( const GURL& origin, storage::FileSystemType type) - : origin_(origin), type_(type), file_util_(NULL) { -} + : origin_(origin), type_(type), file_util_(nullptr) {} SandboxFileSystemTestHelper::SandboxFileSystemTestHelper() : origin_(GURL("http://foo.com")), type_(storage::kFileSystemTypeTemporary), - file_util_(NULL) { -} + file_util_(nullptr) {} SandboxFileSystemTestHelper::~SandboxFileSystemTestHelper() = default; void SandboxFileSystemTestHelper::SetUp(const base::FilePath& base_dir) { - SetUp(base_dir, NULL); + SetUp(base_dir, nullptr); } void SandboxFileSystemTestHelper::SetUp( @@ -63,7 +61,7 @@ } void SandboxFileSystemTestHelper::TearDown() { - file_system_context_ = NULL; + file_system_context_ = nullptr; base::RunLoop().RunUntilIdle(); } @@ -132,13 +130,13 @@ void SandboxFileSystemTestHelper::AddFileChangeObserver( storage::FileChangeObserver* observer) { file_system_context_->sandbox_delegate()->AddFileChangeObserver( - type_, observer, NULL); + type_, observer, nullptr); } void SandboxFileSystemTestHelper::AddFileUpdateObserver( storage::FileUpdateObserver* observer) { file_system_context_->sandbox_delegate()->AddFileUpdateObserver( - type_, observer, NULL); + type_, observer, nullptr); } storage::FileSystemUsageCache* SandboxFileSystemTestHelper::usage_cache() {
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index e28f745..2b86716 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -1480,6 +1480,54 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "NRD91N", + "device_type": "bullhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -3883,6 +3931,34 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_type": "coho", + "os": "Android" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -5451,6 +5527,34 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_type": "gce_x86", + "os": "Android" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices"
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 8e833fe..7bfac0e 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -1336,6 +1336,52 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -3946,6 +3992,53 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84Z", + "device_type": "flo", + "os": "Android" + } + ], + "expiration": 10800, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -6668,6 +6761,54 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY48I", + "device_type": "hammerhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -9431,6 +9572,54 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY49B", + "device_type": "flo", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 120, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -12223,6 +12412,53 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -14925,6 +15161,53 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MRA58Z", + "device_type": "flo", + "os": "Android" + } + ], + "expiration": 10800, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -18014,6 +18297,52 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -20687,6 +21016,52 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 7e92952..6af67d37 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -524,6 +524,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -1146,6 +1157,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests",
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index b96d80f..31cc347 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -203,6 +203,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -866,6 +877,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -1672,6 +1694,22 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Windows-10-15063" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -2820,6 +2858,22 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Windows-10-15063" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -3956,6 +4010,22 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Windows-10-15063" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -5586,6 +5656,52 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -8331,6 +8447,52 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -10393,6 +10555,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -11052,6 +11225,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -11681,6 +11865,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -12320,6 +12515,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -12969,6 +13175,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -13530,6 +13747,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -13939,7 +14167,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -14098,6 +14327,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -14650,6 +14890,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -15310,6 +15561,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -15970,6 +16232,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -16630,6 +16903,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -17290,6 +17574,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -17950,6 +18245,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -18610,6 +18916,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -19270,6 +19587,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -19930,6 +20258,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -20590,6 +20929,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -21252,6 +21602,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -22029,6 +22390,22 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Windows-10" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index fb27fde8..b37e3a1 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -441,6 +441,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -850,7 +861,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -1044,6 +1056,9 @@ } }, { + "args": [ + "--extra-browser-args=--disable-gpu" + ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", "swarming": { @@ -1054,7 +1069,7 @@ }, { "args": [ - "--extra-browser-args=--enable-features=VizDisplayCompositor" + "--extra-browser-args=--enable-features=VizDisplayCompositor --disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests_viz", @@ -2096,6 +2111,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -2941,7 +2967,8 @@ "--remote=127.0.0.1", "--remote-ssh-port=9222", "--skip=telemetry.internal.app.android_app_unittest.AndroidAppTest.testWebView", - "--skip=telemetry.internal.backends.browser_backend_unittest.BrowserBackendIntegrationTest.testSmokeIsBrowserRunningReturnFalse" + "--skip=telemetry.internal.backends.browser_backend_unittest.BrowserBackendIntegrationTest.testSmokeIsBrowserRunningReturnFalse", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -3481,6 +3508,17 @@ "test": "content_browsertests" }, { + "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { "swarming": { "can_use_on_swarming_builders": true }, @@ -3746,6 +3784,17 @@ "test": "content_browsertests" }, { + "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { "swarming": { "can_use_on_swarming_builders": true }, @@ -4163,6 +4212,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -4692,7 +4752,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -4935,6 +4996,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -5464,7 +5536,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -5694,6 +5767,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend,ViewsBrowserWindows", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor,ViewsBrowserWindows" ], "name": "viz_content_browsertests",
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index b668a584..22df7c2 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -131,6 +131,17 @@ "test": "content_browsertests" }, { + "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { "swarming": { "can_use_on_swarming_builders": true }, @@ -436,6 +447,17 @@ "test": "content_browsertests" }, { + "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { "swarming": { "can_use_on_swarming_builders": true }, @@ -1029,6 +1051,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -1562,7 +1595,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -1824,6 +1858,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -2320,7 +2365,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -2551,6 +2597,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -2980,7 +3037,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -3379,6 +3437,22 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -4287,7 +4361,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index c8f79c3..bc2fddf5 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -124,6 +124,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -536,7 +547,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -718,6 +730,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -1130,7 +1153,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -1427,6 +1451,23 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -2223,7 +2264,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -2424,6 +2466,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -2823,7 +2876,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -2843,7 +2897,6 @@ { "alternate_swarming_dimensions": [ { - "gpu": "8086:0a2e", "os": "Mac-10.12.6" } ], @@ -2860,7 +2913,6 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "8086:0a2e", "os": "Mac-10.13" } ], @@ -3018,6 +3070,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -3420,7 +3483,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests",
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 35ffe13..e85584ae 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -825,6 +825,52 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "perfetto_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-surface-synchronization", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -2926,6 +2972,19 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*", + "--test-launcher-batch-limit=1", + "--test-launcher-print-test-stdio=always" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor", "--test-launcher-batch-limit=1", "--test-launcher-print-test-stdio=always" @@ -3788,6 +3847,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -4467,6 +4537,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -5087,6 +5168,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -5705,6 +5797,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--site-per-process" ], "name": "site_per_process_content_browsertests", @@ -6273,6 +6376,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -6776,6 +6890,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests",
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 4907f30..ae099bac 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -1793,7 +1793,7 @@ "hard_timeout": 25200, "ignore_task_failure": false, "io_timeout": 1800, - "shards": 5, + "shards": 26, "upload_test_results": true }, "trigger_script": {
diff --git a/testing/buildbot/chromium.swarm.json b/testing/buildbot/chromium.swarm.json index 15a97646..528b87c 100644 --- a/testing/buildbot/chromium.swarm.json +++ b/testing/buildbot/chromium.swarm.json
@@ -713,7 +713,8 @@ "args": [ "--browser=cros-chrome", "--remote=variable_chromeos_device_hostname", - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 4e1b640..7ed58c7 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -190,6 +190,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -689,7 +700,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -922,6 +934,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor", "--disable-features=WebRTC-H264WithOpenH264FFmpeg" ], @@ -1536,6 +1559,17 @@ "test": "content_browsertests" }, { + "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { "swarming": { "can_use_on_swarming_builders": true }, @@ -2030,7 +2064,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "experiment_percentage": 100, "isolate_name": "telemetry_unittests", @@ -2252,6 +2287,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -2736,7 +2782,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -2984,6 +3031,17 @@ }, { "args": [ + "--enable-features=TracingPerfettoBackend", + "--gtest_filter=TracingControllerTest.*" + ], + "name": "perfetto_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=VizDisplayCompositor" ], "name": "viz_content_browsertests", @@ -3497,7 +3555,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests",
diff --git a/testing/buildbot/client.v8.chromium.json b/testing/buildbot/client.v8.chromium.json index ec53bc6d..100360d 100644 --- a/testing/buildbot/client.v8.chromium.json +++ b/testing/buildbot/client.v8.chromium.json
@@ -244,7 +244,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests", @@ -487,7 +488,8 @@ }, { "args": [ - "--jobs=1" + "--jobs=1", + "--extra-browser-args=--disable-gpu" ], "isolate_name": "telemetry_unittests", "name": "telemetry_unittests",
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index 0ed1fa5..91874ae8 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -216,10 +216,6 @@ -PredictorBrowserTest.SubframeInitiatesPreconnects -PredictorBrowserTest.SubframeLearning -# Variations appending not working when network service is enabled. -# http://crbug.com/857165 --VariationsHttpHeadersBrowserTest.TestStrippingHeadersFromSubresourceRequest - # https://crbug.com/773295 # Remove this test when there are no more clients left that use URLFetcher. -VariationsHttpHeadersBrowserTest.TestStrippingHeadersFromInternalRequest
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index 0b09f26..e4dffe12 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -21,16 +21,11 @@ -PreviewsStateBrowserTest.ShouldEnableLoFiModeReload -PreviewsStateBrowserTest.ShouldEnableLoFiModeReloadDisableLoFi --AsyncResourceHandlerBrowserTest/AsyncResourceHandlerBrowserTest.UploadProgress* - # services/network/url_loader.cc should handle failure in # URLLoaderImpl::OnResponseBodyStreamRead(). Note this is flaky, so it will pass # sometimes. -SRC_ClearKey/EncryptedMediaTest.FrameSizeChangeVideo/0 -# Cross-origin request to file:// URL should be blocked. crbug.com/759230 --BrowserSideNavigationBrowserDisableWebSecurityTest.ValidateBaseUrlForDataUrl - # https://crbug.com/846352: CORB/NetworkService: Remove # CrossSiteDocumentResourceHandler while preserving test coverage - the tests # below can be probably removed altogether once NetworkService ships and the
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index ee0365b0..acab9b2 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1649,7 +1649,6 @@ # TODO(crbug.com/853356): Switch this to 10.13. 'use_multi_dimension_trigger_script': True, 'alternate_swarming_dimensions': [{ - 'gpu': '8086:0a2e', 'os': 'Mac-10.12.6', }], @@ -1658,7 +1657,6 @@ 'swarming': { 'dimension_sets': [ { - 'gpu': '8086:0a2e', 'os': 'Mac-10.13', }, ],
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 7847c5ff..6ebd10e 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -449,6 +449,9 @@ # Always fails. '--skip=telemetry.internal.app.android_app_unittest.AndroidAppTest.testWebView', '--skip=telemetry.internal.backends.browser_backend_unittest.BrowserBackendIntegrationTest.testSmokeIsBrowserRunningReturnFalse', + # Disable GPU compositing, telemetry_unittests runs on VMs. + # https://crbug.com/871955 + '--extra-browser-args=--disable-gpu', ], 'swarming': { 'hard_timeout': 1200, @@ -476,6 +479,9 @@ '--browser=cros-chrome', '--remote=variable_chromeos_device_hostname', '--jobs=1', + # Disable GPU compositing, telemetry_unittests runs on VMs. + # https://crbug.com/871955 + '--extra-browser-args=--disable-gpu', ], 'swarming': { 'idempotent': False, # https://crbug.com/549140 @@ -565,6 +571,13 @@ 'shards': 3, }, }, + 'perfetto_content_browsertests': { + 'args': [ + '--enable-features=TracingPerfettoBackend', + '--gtest_filter=TracingControllerTest.*', + ], + 'test': 'content_browsertests', + }, 'services_unittests': {}, 'shell_dialogs_unittests': {}, 'skia_unittests': {}, @@ -858,6 +871,9 @@ 'telemetry_unittests': { 'args': [ '--jobs=1', + # Disable GPU compositing, telemetry_unittests runs on VMs. + # https://crbug.com/871955 + '--extra-browser-args=--disable-gpu', ], 'swarming': { 'idempotent': False, # https://crbug.com/549140 @@ -896,6 +912,9 @@ 'telemetry_unittests': { 'args': [ '--jobs=1', + # Disable GPU compositing, telemetry_unittests runs on VMs. + # https://crbug.com/871955 + '--extra-browser-args=--disable-gpu', ], 'swarming': { 'idempotent': False, # https://crbug.com/549140 @@ -1653,6 +1672,9 @@ 'isolate_name': 'telemetry_unittests', 'args': [ '--extra-browser-args=--enable-features=VizDisplayCompositor', + # Disable GPU compositing, telemetry_unittests runs on VMs. + # https://crbug.com/871955 + '--extra-browser-args=--disable-gpu', ], 'swarming': { 'idempotent': False, # https://crbug.com/549140 @@ -1660,6 +1682,11 @@ }, }, 'telemetry_unittests': { + 'args': [ + # Disable GPU compositing, telemetry_unittests runs on VMs. + # https://crbug.com/871955 + '--extra-browser-args=--disable-gpu', + ], 'swarming': { 'idempotent': False, # https://crbug.com/549140 'shards': 4,
diff --git a/third_party/WebKit/LayoutTests/.gitattributes b/third_party/WebKit/LayoutTests/.gitattributes index 7617434..b5982ab 100644 --- a/third_party/WebKit/LayoutTests/.gitattributes +++ b/third_party/WebKit/LayoutTests/.gitattributes
@@ -141,6 +141,7 @@ http/tests/security/isolatedWorld/resources/userGestureEvents-second-window.html -crlf http/tests/security/isolatedWorld/userGestureEvents.html -crlf http/tests/security/resources/empty-svg.php -crlf +media/controls/*.mht -crlf media/track/captions-webvtt/captions-multiline-lf.vtt -crlf mhtml/*.mht -crlf platform/win/fast/events/panScroll-event-fired.html -crlf
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 01a8fc81..3c5fb56 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -70,11 +70,8 @@ crbug.com/591099 css3/flexbox/line-wrapping.html [ Failure ] crbug.com/591099 css3/flexbox/scrollbars-auto.html [ Failure ] crbug.com/714962 css3/masking/clip-path-reference-box-inline.html [ Failure ] -crbug.com/591099 editing/inserting/insert-character-in-first-letter-crash.html [ Crash ] crbug.com/591099 editing/selection/continuations-with-move-caret-to-boundary.html [ Failure Pass ] crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ] -crbug.com/591099 editing/text-iterator/first-letter-word-boundary.html [ Crash ] -crbug.com/591099 editing/text-iterator/read-past-cloned-first-letter.html [ Crash ] crbug.com/591099 external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html [ Pass ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures.worker.html [ Timeout ] crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_AES-CBC.worker.html [ Timeout ] @@ -423,10 +420,6 @@ crbug.com/807708 fast/css-intrinsic-dimensions/width-avoid-floats.html [ Failure ] crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Pass ] crbug.com/591099 fast/css/case-transform.html [ Failure ] -crbug.com/591099 fast/css/first-letter-block-form-controls-crash.html [ Crash ] -crbug.com/591099 fast/css/first-letter-capitalized-edit-select-crash.html [ Crash ] -crbug.com/591099 fast/css/first-letter-crash-document-disposal.html [ Crash ] -crbug.com/591099 fast/css/first-letter-text-fragment-crash.html [ Crash ] crbug.com/835484 fast/css/focus-ring-continuations.html [ Failure ] crbug.com/835484 fast/css/focus-ring-recursive-continuations.html [ Failure ] crbug.com/835484 fast/css/focus-ring-recursive-inlines.html [ Failure ] @@ -449,7 +442,6 @@ crbug.com/591099 fast/overflow/recompute-overflow-of-layout-root-container.html [ Failure ] crbug.com/591099 fast/replaced/table-replaced-element.html [ Failure ] crbug.com/591099 fast/ruby/position-after.html [ Failure ] -crbug.com/591099 fast/ruby/ruby-first-letter.html [ Crash ] crbug.com/591099 fast/scrolling/content-box-smaller-than-scrollbar.html [ Failure ] crbug.com/591099 fast/scrolling/jquery-rtl-scroll-type.html [ Failure ] crbug.com/591099 fast/scrolling/scrollbar-tickmarks-hittest.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index b998fe3..dcbfebf 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2704,6 +2704,19 @@ crbug.com/870526 external/wpt/push-api/idlharness.https.any.serviceworker.html [ Skip ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/svg/text/reftests/text-inline-size-007.svg [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-inline-size-005.svg [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-multiline-002.svg [ Failure ] +crbug.com/626703 [ Linux Win ] external/wpt/svg/text/reftests/text-multiline-003.svg [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-inline-size-201.svg [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-inline-size-001.svg [ Failure ] +crbug.com/626703 external/wpt/svg/painting/reftests/markers-orient-001.svg [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-inline-size-002.svg [ Failure ] +crbug.com/626703 external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-inline-size-006.svg [ Failure ] +crbug.com/626703 [ Linux Win ] external/wpt/svg/text/reftests/text-inline-size-003.svg [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-multiline-001.svg [ Failure ] +crbug.com/626703 external/wpt/svg/text/reftests/text-inline-size-101.svg [ Failure ] crbug.com/626703 [ Linux Win ] external/wpt/css/css-contain/contain-size-025.html [ Failure ] crbug.com/626703 external/wpt/css/css-contain/contain-paint-clip-016.html [ Failure ] crbug.com/626703 external/wpt/css/css-contain/contain-layout-cell-001.html [ Failure ] @@ -3035,7 +3048,6 @@ crbug.com/626703 external/wpt/css/css-transitions/transition-property-025.html [ Skip ] crbug.com/626703 external/wpt/css/css-transitions/transition-property-013.html [ Skip ] crbug.com/626703 external/wpt/payment-request/show-method-postmessage-manual.https.html [ Skip ] -crbug.com/626703 external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html [ Skip ] crbug.com/626703 external/wpt/css/css-writing-modes/available-size-019.html [ Failure ] crbug.com/626703 external/wpt/payment-request/change-shipping-option-select-last-manual.https.html [ Skip ] crbug.com/626703 external/wpt/payment-request/show-method-optional-promise-rejects-manual.https.html [ Skip ] @@ -3289,7 +3301,6 @@ crbug.com/648295 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-twice.html [ Timeout ] crbug.com/626703 external/wpt/svg/linking/reftests/href-filter-element.html [ Failure ] -crbug.com/642912 external/wpt/wasm/wasm_indexeddb_test.https.html [ Failure ] crbug.com/642912 external/wpt/wasm/wasm_local_iframe_test.html [ Failure ] crbug.com/642912 external/wpt/wasm/wasm_serialization_tests.html [ Failure ] crbug.com/642912 external/wpt/wasm/wasm_service_worker_test.https.html [ Failure ] @@ -3977,6 +3988,7 @@ crbug.com/626703 [ Win7 ] external/wpt/domxpath/xml_xpath_runner.html [ Timeout Pass ] crbug.com/746128 [ Win7 Debug ] media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure ] +crbug.com/746128 [ Mac ] media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure Pass ] crbug.com/746128 [ Win7 Debug ] virtual/new-remote-playback-pipeline/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure ] crbug.com/746128 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html [ Failure Pass ] @@ -4520,6 +4532,7 @@ # Sheriff 2018-04-13 crbug.com/832842 [ Win7 Linux ] virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure ] +crbug.com/832842 [ Mac ] virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ] crbug.com/833655 [ Linux ] media/controls/closed-captions-dynamic-update.html [ Skip ] crbug.com/833655 [ Linux ] virtual/new-remote-playback-pipeline/media/controls/closed-captions-dynamic-update.html [ Skip ] crbug.com/833655 [ Linux ] virtual/video-surface-layer/media/controls/closed-captions-dynamic-update.html [ Skip ] @@ -4746,7 +4759,6 @@ crbug.com/824539 [ Android ] editing/selection/previous-line-position.html [ Failure ] crbug.com/824539 [ Android ] editing/style/block-styles-007.html [ Failure ] crbug.com/824539 [ Android ] external/wpt/bluetooth/requestDevice/canonicalizeFilter/no-arguments.https.html [ Crash Failure ] -crbug.com/824539 [ Android ] external/wpt/dom/historical.html [ Failure ] crbug.com/824539 [ Android ] external/wpt/gamepad/idlharness.html [ Failure ] crbug.com/824539 [ Android ] external/wpt/input-events/idlharness.html [ Failure ] crbug.com/824539 [ Android ] external/wpt/web-animations/timing-model/animations/finishing-an-animation.html [ Failure ] @@ -4867,12 +4879,20 @@ # Flaky middleClinkAutoscroll increased flakiness on Mac crbug.com/851090 [ Mac ] fast/events/middleClickAutoscroll-click-hyperlink.html [ Failure Pass ] -crbug.com/851090 [ Mac ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-nested-divs.html [ Failure Pass ] -crbug.com/851090 [ Mac ] fast/events/middleClickAutoscroll-nested-divs.html [ Failure Pass ] +crbug.com/851090 [ Mac ] virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-nested-divs.html [ Failure Pass Timeout ] +crbug.com/851090 [ Mac ] fast/events/middleClickAutoscroll-nested-divs.html [ Failure Pass Timeout ] crbug.com/851090 [ Mac ] virtual/user-activation-v2/fast/events/autoscroll-over-scrollbar.html [ Failure Pass ] -# Sherrif 2018-08-08 +# Sheriff 2018-08-08 crbug.com/871105 [ Linux ] svg/dom/remove-use-target-element-indirectly.html [ Pass Crash ] crbug.com/872025 [ Mac Linux ] fast/css-grid-layout/crash-large-positions.html [ Pass Timeout ] crbug.com/871416 fast/spatial-navigation/snav-stay-in-overflow-div.html [ Pass Failure ] crbug.com/872242 [ Mac ] fast/events/autoscroll-over-scrollbar.html [ Pass Failure ] + +# Only passes on bots with GPUs. +crbug.com/871445 [ Mac ] http/tests/media/video-load-metadata-decode-error.html [ Timeout ] + +# Sheriff 2018-08-09 +crbug.com/872635 [ Mac ] fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Failure Pass ] +crbug.com/872705 [ Mac ] virtual/mouseevent_fractional/fast/events/autoscroll-over-scrollbar.html [ Failure Pass ] +crbug.com/872705 [ Mac ] virtual/mouseevent_fractional/fast/events/recorded-keydown-event.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers-expected.txt b/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers-expected.txt index 722793b..0a00cef 100644 --- a/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers-expected.txt +++ b/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers-expected.txt
@@ -7,5 +7,5 @@ Overflow scroll with inline child: PASS did not repaint when unexpected Overflow hidden: -PASS repainted when expected +PASS did not repaint when unexpected
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html b/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html index b9ef429..d5a56eb 100644 --- a/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html +++ b/third_party/WebKit/LayoutTests/compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html
@@ -100,7 +100,7 @@ async function testOverflowHidden() { container.style.overflow = "hidden"; - var result = await testScrollRepaint("Overflow hidden", true, container); + var result = testScrollRepaint("Overflow hidden", false, container); container.style.overflow = "scroll"; return result; }
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index a8654db..c58001e 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -5245,12 +5245,6 @@ {} ] ], - "payment-request/payment-request-canmakepayment-method-manual.https.html": [ - [ - "/payment-request/payment-request-canmakepayment-method-manual.https.html", - {} - ] - ], "payment-request/payment-response/complete-method-manual.https.html": [ [ "/payment-request/payment-response/complete-method-manual.https.html", @@ -53059,6 +53053,18 @@ {} ] ], + "css/css-pseudo/first-letter-and-sibling-display-change.html": [ + [ + "/css/css-pseudo/first-letter-and-sibling-display-change.html", + [ + [ + "/css/css-pseudo/first-letter-block-to-inline-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-pseudo/first-letter-block-to-inline.html": [ [ "/css/css-pseudo/first-letter-block-to-inline.html", @@ -58507,6 +58513,18 @@ {} ] ], + "css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html": [ + [ + "/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html", + [ + [ + "/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/overflow-wrap/word-wrap-001.html": [ [ "/css/css-text/overflow-wrap/word-wrap-001.html", @@ -96771,6 +96789,18 @@ {} ] ], + "svg/painting/reftests/markers-orient-001.svg": [ + [ + "/svg/painting/reftests/markers-orient-001.svg", + [ + [ + "/svg/painting/reftests/markers-orient-001-ref.svg", + "==" + ] + ], + {} + ] + ], "svg/painting/reftests/paint-context-001.svg": [ [ "/svg/painting/reftests/paint-context-001.svg", @@ -97191,6 +97221,138 @@ {} ] ], + "svg/text/reftests/text-inline-size-001.svg": [ + [ + "/svg/text/reftests/text-inline-size-001.svg", + [ + [ + "/svg/text/reftests/text-inline-size-001-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-inline-size-002.svg": [ + [ + "/svg/text/reftests/text-inline-size-002.svg", + [ + [ + "/svg/text/reftests/text-inline-size-002-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-inline-size-003.svg": [ + [ + "/svg/text/reftests/text-inline-size-003.svg", + [ + [ + "/svg/text/reftests/text-inline-size-003-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-inline-size-005.svg": [ + [ + "/svg/text/reftests/text-inline-size-005.svg", + [ + [ + "/svg/text/reftests/text-inline-size-005-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-inline-size-006.svg": [ + [ + "/svg/text/reftests/text-inline-size-006.svg", + [ + [ + "/svg/text/reftests/text-inline-size-006-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-inline-size-007.svg": [ + [ + "/svg/text/reftests/text-inline-size-007.svg", + [ + [ + "/svg/text/reftests/text-inline-size-007-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-inline-size-101.svg": [ + [ + "/svg/text/reftests/text-inline-size-101.svg", + [ + [ + "/svg/text/reftests/text-inline-size-101-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-inline-size-201.svg": [ + [ + "/svg/text/reftests/text-inline-size-201.svg", + [ + [ + "/svg/text/reftests/text-inline-size-201-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-multiline-001.svg": [ + [ + "/svg/text/reftests/text-multiline-001.svg", + [ + [ + "/svg/text/reftests/text-multiline-001-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-multiline-002.svg": [ + [ + "/svg/text/reftests/text-multiline-002.svg", + [ + [ + "/svg/text/reftests/text-multiline-002-ref.svg", + "==" + ] + ], + {} + ] + ], + "svg/text/reftests/text-multiline-003.svg": [ + [ + "/svg/text/reftests/text-multiline-003.svg", + [ + [ + "/svg/text/reftests/text-multiline-003-ref.svg", + "==" + ] + ], + {} + ] + ], "svg/text/reftests/textpath-shape-001.svg": [ [ "/svg/text/reftests/textpath-shape-001.svg", @@ -104377,11 +104539,26 @@ {} ] ], + "background-fetch/idlharness.https.any-expected.txt": [ + [ + {} + ] + ], "background-fetch/idlharness.https.any.serviceworker-expected.txt": [ [ {} ] ], + "background-fetch/idlharness.https.any.sharedworker-expected.txt": [ + [ + {} + ] + ], + "background-fetch/idlharness.https.any.worker-expected.txt": [ + [ + {} + ] + ], "background-fetch/resources/feature-name.txt": [ [ {} @@ -128732,6 +128909,11 @@ {} ] ], + "css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html": [ + [ + {} + ] + ], "css/css-text/support/1x1-green.png": [ [ {} @@ -153262,11 +153444,6 @@ {} ] ], - "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt": [ - [ - {} - ] - ], "html/infrastructure/urls/interfaces-for-url-manipulation/.gitkeep": [ [ {} @@ -158977,11 +159154,6 @@ {} ] ], - "html/webappapis/scripting/events/event-handler-processing-algorithm-error/window-synthetic-event-expected.txt": [ - [ - {} - ] - ], "html/webappapis/scripting/events/messageevent-constructor.https-expected.txt": [ [ {} @@ -170027,6 +170199,11 @@ {} ] ], + "svg/painting/reftests/markers-orient-001-ref.svg": [ + [ + {} + ] + ], "svg/painting/reftests/paint-context-001-ref.svg": [ [ {} @@ -170197,6 +170374,61 @@ {} ] ], + "svg/text/reftests/text-inline-size-001-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-inline-size-002-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-inline-size-003-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-inline-size-005-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-inline-size-006-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-inline-size-007-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-inline-size-101-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-inline-size-201-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-multiline-001-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-multiline-002-ref.svg": [ + [ + {} + ] + ], + "svg/text/reftests/text-multiline-003-ref.svg": [ + [ + {} + ] + ], "svg/text/reftests/textpath-shape-001-ref.svg": [ [ {} @@ -170227,6 +170459,11 @@ {} ] ], + "svg/types/scripted/event-handler-all-document-element-events-expected.txt": [ + [ + {} + ] + ], "svg/types/scripted/resources/SVGLengthList-helper.js": [ [ {} @@ -171077,6 +171314,66 @@ {} ] ], + "wasm/jsapi/assertions.js": [ + [ + {} + ] + ], + "wasm/jsapi/bad-imports.js": [ + [ + {} + ] + ], + "wasm/jsapi/interface.any-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/interface.any.worker-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/memory/constructor.any-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/memory/constructor.any.worker-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/module/customSections.any-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/module/customSections.any.worker-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/table/constructor.any-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/table/constructor.any.worker-expected.txt": [ + [ + {} + ] + ], + "wasm/jsapi/wasm-constants.js": [ + [ + {} + ] + ], + "wasm/jsapi/wasm-module-builder.js": [ + [ + {} + ] + ], "wasm/resources/blank.html": [ [ {} @@ -171102,16 +171399,6 @@ {} ] ], - "wasm/wasm_idb_worker.js": [ - [ - {} - ] - ], - "wasm/wasm_indexeddb_test.js": [ - [ - {} - ] - ], "wasm/wasm_serialization_tests.js": [ [ {} @@ -175432,6 +175719,11 @@ {} ] ], + "workers/modules/dedicated-worker-import-referrer-expected.txt": [ + [ + {} + ] + ], "workers/modules/dedicated-worker-options-credentials.html.headers": [ [ {} @@ -175902,6 +176194,21 @@ {} ] ], + "worklets/animation-worklet-referrer.https-expected.txt": [ + [ + {} + ] + ], + "worklets/layout-worklet-referrer.https-expected.txt": [ + [ + {} + ] + ], + "worklets/paint-worklet-referrer.https-expected.txt": [ + [ + {} + ] + ], "worklets/resources/addmodule-window.html": [ [ {} @@ -183937,14 +184244,6 @@ {} ] ], - "IndexedDB/wasm-module-value.html": [ - [ - "/IndexedDB/wasm-module-value.html", - { - "timeout": "long" - } - ] - ], "IndexedDB/writer-starvation.htm": [ [ "/IndexedDB/writer-starvation.htm", @@ -185113,22 +185412,22 @@ {} ] ], - "background-fetch/idlharness.any.js": [ + "background-fetch/idlharness.https.any.js": [ [ - "/background-fetch/idlharness.any.html", - {} - ], - [ - "/background-fetch/idlharness.any.sharedworker.html", - {} - ], - [ - "/background-fetch/idlharness.any.worker.html", + "/background-fetch/idlharness.https.any.html", {} ], [ "/background-fetch/idlharness.https.any.serviceworker.html", {} + ], + [ + "/background-fetch/idlharness.https.any.sharedworker.html", + {} + ], + [ + "/background-fetch/idlharness.https.any.worker.html", + {} ] ], "background-fetch/mixed-content-and-allowed-schemes.https.window.js": [ @@ -201699,6 +201998,12 @@ {} ] ], + "dom/inert/inert-does-not-match-disabled-selector.html": [ + [ + "/dom/inert/inert-does-not-match-disabled-selector.html", + {} + ] + ], "dom/interface-objects.html": [ [ "/dom/interface-objects.html", @@ -201851,9 +202156,9 @@ {} ] ], - "dom/nodes/Document-URL.sub.html": [ + "dom/nodes/Document-URL.html": [ [ - "/dom/nodes/Document-URL.sub.html", + "/dom/nodes/Document-URL.html", {} ] ], @@ -215896,19 +216201,27 @@ "html/browsers/the-window-object/window-open-noopener.html": [ [ "/html/browsers/the-window-object/window-open-noopener.html?_parent", - {} + { + "timeout": "long" + } ], [ "/html/browsers/the-window-object/window-open-noopener.html?_self", - {} + { + "timeout": "long" + } ], [ "/html/browsers/the-window-object/window-open-noopener.html?_top", - {} + { + "timeout": "long" + } ], [ "/html/browsers/the-window-object/window-open-noopener.html?indexed", - {} + { + "timeout": "long" + } ] ], "html/browsers/the-window-object/window-properties.https.html": [ @@ -216935,6 +217248,52 @@ {} ] ], + "html/editing/focus/inert/inert-does-not-match-disabled-selector.html": [ + [ + "/html/editing/focus/inert/inert-does-not-match-disabled-selector.html", + {} + ] + ], + "html/editing/focus/inert/inert-in-shadow-dom.html": [ + [ + "/html/editing/focus/inert/inert-in-shadow-dom.html", + {} + ] + ], + "html/editing/focus/inert/inert-inlines.html": [ + [ + "/html/editing/focus/inert/inert-inlines.html", + { + "testdriver": true + } + ] + ], + "html/editing/focus/inert/inert-label-focus.html": [ + [ + "/html/editing/focus/inert/inert-label-focus.html", + { + "testdriver": true + } + ] + ], + "html/editing/focus/inert/inert-node-is-uneditable.html": [ + [ + "/html/editing/focus/inert/inert-node-is-uneditable.html", + {} + ] + ], + "html/editing/focus/inert/inert-node-is-unfocusable.html": [ + [ + "/html/editing/focus/inert/inert-node-is-unfocusable.html", + {} + ] + ], + "html/editing/focus/inert/inert-node-is-unselectable.html": [ + [ + "/html/editing/focus/inert/inert-node-is-unselectable.html", + {} + ] + ], "html/editing/focus/processing-model/focus-fixup-rule-one-no-dialogs.html": [ [ "/html/editing/focus/processing-model/focus-fixup-rule-one-no-dialogs.html", @@ -217173,9 +217532,15 @@ {} ] ], - "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml": [ + "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.html": [ [ - "/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml", + "/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.html", + {} + ] + ], + "html/infrastructure/urls/dynamic-changes-to-base-urls/historical.sub.xhtml": [ + [ + "/html/infrastructure/urls/dynamic-changes-to-base-urls/historical.sub.xhtml", {} ] ], @@ -217357,6 +217722,18 @@ {} ] ], + "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-face.html": [ + [ + "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-face.html", + {} + ] + ], + "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-size.html": [ + [ + "/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-size.html", + {} + ] + ], "html/rendering/non-replaced-elements/tables/form-in-tables-xhtml.xhtml": [ [ "/html/rendering/non-replaced-elements/tables/form-in-tables-xhtml.xhtml", @@ -226743,9 +227120,9 @@ {} ] ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html": [ + "html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html": [ [ - "/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html", + "/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html", {} ] ], @@ -227011,6 +227388,18 @@ {} ] ], + "intersection-observer/initial-observation-with-threshold.html": [ + [ + "/intersection-observer/initial-observation-with-threshold.html", + {} + ] + ], + "intersection-observer/inline-client-rect.html": [ + [ + "/intersection-observer/inline-client-rect.html", + {} + ] + ], "intersection-observer/isIntersecting-change-events.html": [ [ "/intersection-observer/isIntersecting-change-events.html", @@ -229773,22 +230162,22 @@ {} ] ], - "notifications/idlharness.any.js": [ + "notifications/idlharness.https.any.js": [ [ - "/notifications/idlharness.any.html", - {} - ], - [ - "/notifications/idlharness.any.sharedworker.html", - {} - ], - [ - "/notifications/idlharness.any.worker.html", + "/notifications/idlharness.https.any.html", {} ], [ "/notifications/idlharness.https.any.serviceworker.html", {} + ], + [ + "/notifications/idlharness.https.any.sharedworker.html", + {} + ], + [ + "/notifications/idlharness.https.any.worker.html", + {} ] ], "notifications/instance.html": [ @@ -239609,6 +239998,14 @@ } ] ], + "payment-request/payment-request-canmakepayment-method.https.html": [ + [ + "/payment-request/payment-request-canmakepayment-method.https.html", + { + "testdriver": true + } + ] + ], "payment-request/payment-request-constructor-crash.https.html": [ [ "/payment-request/payment-request-constructor-crash.https.html", @@ -240207,22 +240604,22 @@ {} ] ], - "push-api/idlharness.any.js": [ + "push-api/idlharness.https.any.js": [ [ - "/push-api/idlharness.any.html", - {} - ], - [ - "/push-api/idlharness.any.sharedworker.html", - {} - ], - [ - "/push-api/idlharness.any.worker.html", + "/push-api/idlharness.https.any.html", {} ], [ "/push-api/idlharness.https.any.serviceworker.html", {} + ], + [ + "/push-api/idlharness.https.any.sharedworker.html", + {} + ], + [ + "/push-api/idlharness.https.any.worker.html", + {} ] ], "quirks/blocks-ignore-line-height.html": [ @@ -253727,6 +254124,12 @@ {} ] ], + "svg/types/scripted/event-handler-all-document-element-events.svg": [ + [ + "/svg/types/scripted/event-handler-all-document-element-events.svg", + {} + ] + ], "touch-events/historical.html": [ [ "/touch-events/historical.html", @@ -254809,9 +255212,163 @@ {} ] ], - "wasm/wasm_indexeddb_test.https.html": [ + "wasm/jsapi/constructor/instantiate-bad-imports.any.js": [ [ - "/wasm/wasm_indexeddb_test.https.html", + "/wasm/jsapi/constructor/instantiate-bad-imports.any.html", + {} + ], + [ + "/wasm/jsapi/constructor/instantiate-bad-imports.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/constructor/instantiate-bad-imports.any.worker.html", + {} + ] + ], + "wasm/jsapi/instance/constructor-bad-imports.any.js": [ + [ + "/wasm/jsapi/instance/constructor-bad-imports.any.html", + {} + ], + [ + "/wasm/jsapi/instance/constructor-bad-imports.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/instance/constructor-bad-imports.any.worker.html", + {} + ] + ], + "wasm/jsapi/instance/constructor.any.js": [ + [ + "/wasm/jsapi/instance/constructor.any.html", + {} + ], + [ + "/wasm/jsapi/instance/constructor.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/instance/constructor.any.worker.html", + {} + ] + ], + "wasm/jsapi/interface.any.js": [ + [ + "/wasm/jsapi/interface.any.html", + {} + ], + [ + "/wasm/jsapi/interface.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/interface.any.worker.html", + {} + ] + ], + "wasm/jsapi/memory/constructor.any.js": [ + [ + "/wasm/jsapi/memory/constructor.any.html", + {} + ], + [ + "/wasm/jsapi/memory/constructor.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/memory/constructor.any.worker.html", + {} + ] + ], + "wasm/jsapi/module/constructor.any.js": [ + [ + "/wasm/jsapi/module/constructor.any.html", + {} + ], + [ + "/wasm/jsapi/module/constructor.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/module/constructor.any.worker.html", + {} + ] + ], + "wasm/jsapi/module/customSections.any.js": [ + [ + "/wasm/jsapi/module/customSections.any.html", + {} + ], + [ + "/wasm/jsapi/module/customSections.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/module/customSections.any.worker.html", + {} + ] + ], + "wasm/jsapi/module/exports.any.js": [ + [ + "/wasm/jsapi/module/exports.any.html", + {} + ], + [ + "/wasm/jsapi/module/exports.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/module/exports.any.worker.html", + {} + ] + ], + "wasm/jsapi/module/imports.any.js": [ + [ + "/wasm/jsapi/module/imports.any.html", + {} + ], + [ + "/wasm/jsapi/module/imports.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/module/imports.any.worker.html", + {} + ] + ], + "wasm/jsapi/table/constructor.any.js": [ + [ + "/wasm/jsapi/table/constructor.any.html", + {} + ], + [ + "/wasm/jsapi/table/constructor.any.js", + { + "jsshell": true + } + ], + [ + "/wasm/jsapi/table/constructor.any.worker.html", {} ] ], @@ -257283,6 +257840,12 @@ {} ] ], + "webrtc/RTCIceTransport-extension.https.html": [ + [ + "/webrtc/RTCIceTransport-extension.https.html", + {} + ] + ], "webrtc/RTCIceTransport.html": [ [ "/webrtc/RTCIceTransport.html", @@ -269330,6 +269893,54 @@ "/css/selectors/selection-image-001-noref.html", {} ] + ], + "svg/text/visualtests/text-inline-size-001-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-001-visual.svg", + {} + ] + ], + "svg/text/visualtests/text-inline-size-002-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-002-visual.svg", + {} + ] + ], + "svg/text/visualtests/text-inline-size-003-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-003-visual.svg", + {} + ] + ], + "svg/text/visualtests/text-inline-size-005-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-005-visual.svg", + {} + ] + ], + "svg/text/visualtests/text-inline-size-006-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-006-visual.svg", + {} + ] + ], + "svg/text/visualtests/text-inline-size-007-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-007-visual.svg", + {} + ] + ], + "svg/text/visualtests/text-inline-size-101-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-101-visual.svg", + {} + ] + ], + "svg/text/visualtests/text-inline-size-201-visual.svg": [ + [ + "/svg/text/visualtests/text-inline-size-201-visual.svg", + {} + ] ] }, "wdspec": { @@ -275366,10 +275977,6 @@ "092b2e56b4f3ca71e36fc0b7e2892535b37b7c3a", "support" ], - "IndexedDB/wasm-module-value.html": [ - "71f4f3082028829ba17edcbc7fa7382d45109a30", - "testharness" - ], "IndexedDB/writer-starvation.htm": [ "76b34c6324cb5191aee56de0fd94e6132e65f15a", "testharness" @@ -276998,10 +277605,6 @@ "0cfe805f5e3fe9ccaf7b3c25a061cc583e8bc38c", "support" ], - "background-fetch/idlharness.any.js": [ - "5c0eebc307b9cdb534003593248b03004352dacd", - "testharness" - ], "background-fetch/idlharness.any.sharedworker-expected.txt": [ "5d9b1fd7b67c0d0c557564e28e261b58d73aa78a", "support" @@ -277010,10 +277613,26 @@ "5d9b1fd7b67c0d0c557564e28e261b58d73aa78a", "support" ], + "background-fetch/idlharness.https.any-expected.txt": [ + "adddfe5d5f620053d14c361792757c618b8469b1", + "support" + ], + "background-fetch/idlharness.https.any.js": [ + "5c0eebc307b9cdb534003593248b03004352dacd", + "testharness" + ], "background-fetch/idlharness.https.any.serviceworker-expected.txt": [ "92d77448b72d6220ad7b2d3a6b23534c99bdc9e5", "support" ], + "background-fetch/idlharness.https.any.sharedworker-expected.txt": [ + "aad3232c9459c4b4eb604e3d852f0fd78346fe3b", + "support" + ], + "background-fetch/idlharness.https.any.worker-expected.txt": [ + "aad3232c9459c4b4eb604e3d852f0fd78346fe3b", + "support" + ], "background-fetch/mixed-content-and-allowed-schemes.https.window.js": [ "5c8d022ff16664199c2c0f7c33df883653b4f254", "testharness" @@ -315591,7 +316210,7 @@ "reftest" ], "css/css-grid/grid-layout-properties.html": [ - "d30ee96245cf3d25bffc64347a4ee60bfb2b2049", + "951c53679990e675e492c201a93f1812e8026d53", "testharness" ], "css/css-grid/grid-model/display-grid.html": [ @@ -320002,6 +320621,10 @@ "5a7a51802925bda01fbb62c8635a0e3205683e51", "reftest" ], + "css/css-pseudo/first-letter-and-sibling-display-change.html": [ + "fe8b6b71faa344223eaa4ed781b39699e6f194b0", + "reftest" + ], "css/css-pseudo/first-letter-block-to-inline-ref.html": [ "1c8ca71127b09dc729377b71b102bed8095aa249", "support" @@ -325430,6 +326053,10 @@ "ae7abc617493b9e2c9313215a3f38b77c37d9450", "reftest" ], + "css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html": [ + "ef77c1be79979b43f753a3f5abbefbd50002887e", + "reftest" + ], "css/css-text/overflow-wrap/reference/overflow-wrap-break-word-001-ref.html": [ "0b16a0bdb25ddd647ad96dd82e3430274667ee87", "support" @@ -325454,6 +326081,10 @@ "3686ae6a0e278a970b861c165f0f840df302db70", "support" ], + "css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html": [ + "f70011433ebe5f0df3040aa5d92a34f1e6ab9229", + "support" + ], "css/css-text/overflow-wrap/word-wrap-001.html": [ "8bafc4d48bbfee1e6c465a95b29792ba33c30346", "reftest" @@ -345027,7 +345658,7 @@ "testharness" ], "css/cssom/interfaces-expected.txt": [ - "9e7e2c9027e8ece2d166cf3c6c2593e9530845a7", + "defaf5702e2b46cdb55dd2356e8a6bc53d54f3dc", "support" ], "css/cssom/interfaces.html": [ @@ -352223,11 +352854,15 @@ "support" ], "dom/historical-expected.txt": [ - "428a35a1e289a8bea86f1b5c37aeb145e67c4d9b", + "26e3bf886379fb6329c7c1beb95a44bc3ee4cdf9", "support" ], "dom/historical.html": [ - "291d078c4424d0491aeab7524d350eab7304f989", + "9015b79acc45e480c8f9abc60ab18e2bc1afd2df", + "testharness" + ], + "dom/inert/inert-does-not-match-disabled-selector.html": [ + "9622a2f3fcac6a11dd215fea94e41e4365abec27", "testharness" ], "dom/interface-objects.html": [ @@ -352362,8 +352997,8 @@ "4442c3a7aba3d1a9ead2a08d312dd221c0bade90", "support" ], - "dom/nodes/Document-URL.sub.html": [ - "1b04398f6f5657ca4ed97d41de565fe52e1853e2", + "dom/nodes/Document-URL.html": [ + "e06e90d138edbc592c317862dd83e8caf2b63af1", "testharness" ], "dom/nodes/Document-adoptNode.html": [ @@ -353379,7 +354014,7 @@ "testharness" ], "dom/nodes/rootNode.html": [ - "9e57a68d7e39fcee75bdfb737de93bd6b6236b3a", + "2cd3ea5d30ccb63c8ed122647928cf676ac95f34", "testharness" ], "dom/nodes/selectors.js": [ @@ -362375,7 +363010,7 @@ "testharness" ], "html/browsers/the-window-object/window-open-noopener.html": [ - "ee8d53b12b8034d1c0ede3b2c6516a345890915e", + "dc96e4c9c8c64ffd8fdf722383ccdfdcbcc58afb", "testharness" ], "html/browsers/the-window-object/window-open-noopener_indexed-expected.txt": [ @@ -367742,6 +368377,34 @@ "c8f4cb0441b482664a145b534edee487beda31c2", "testharness" ], + "html/editing/focus/inert/inert-does-not-match-disabled-selector.html": [ + "fbf2f33c8f043061328f1723dc0078781879f02f", + "testharness" + ], + "html/editing/focus/inert/inert-in-shadow-dom.html": [ + "2a25ceb0137bda8059ffdaef0596b42f68a30f48", + "testharness" + ], + "html/editing/focus/inert/inert-inlines.html": [ + "c534eaa5e2a22ac9648d7770c4b0d195fa3f9866", + "testharness" + ], + "html/editing/focus/inert/inert-label-focus.html": [ + "df5e73f0bc6275287e3b0eb97a3369a679b57117", + "testharness" + ], + "html/editing/focus/inert/inert-node-is-uneditable.html": [ + "f8d9482452deb9a031fb5bfd86d86bdf75e14316", + "testharness" + ], + "html/editing/focus/inert/inert-node-is-unfocusable.html": [ + "6fabb47b5fe7bc25f5be019c1669a34fdf1b91a3", + "testharness" + ], + "html/editing/focus/inert/inert-node-is-unselectable.html": [ + "1f5052ab3af3a2c230b07d82679281baddbe5135", + "testharness" + ], "html/editing/focus/processing-model/focus-fixup-rule-one-no-dialogs.html": [ "270a8c31ce78e9ae07d8169367224051baf91fd8", "testharness" @@ -368350,12 +369013,12 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], - "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt": [ - "8862b9460b11b6afbd81d9382ff79375d4f69f70", - "support" + "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.html": [ + "1bbcedf0374aa43765b097ce3dc62b48523b6778", + "testharness" ], - "html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml": [ - "ed3aa629bb438b285cc30761f526e76bad8c01b8", + "html/infrastructure/urls/dynamic-changes-to-base-urls/historical.sub.xhtml": [ + "2b66626e70fc73f0efc1b0cd578fb82b9f24f181", "testharness" ], "html/infrastructure/urls/interfaces-for-url-manipulation/.gitkeep": [ @@ -369082,6 +369745,14 @@ "f5ec83d4ee5ce80ae40a5fe12269d4c7c6c9d91a", "support" ], + "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-face.html": [ + "caf73b26a03b47d19668850e11c97b9e085ccf9c", + "testharness" + ], + "html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-size.html": [ + "61e138ed126a194f002ba187e8d68bbba51f2c6e", + "testharness" + ], "html/rendering/non-replaced-elements/quotes/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -379358,10 +380029,6 @@ "23db12066d01404453425499bbc1c85e293375cc", "testharness" ], - "html/webappapis/scripting/events/event-handler-processing-algorithm-error/window-synthetic-event-expected.txt": [ - "f28915679bf718c5e71d2f36cb0de26c04275564", - "support" - ], "html/webappapis/scripting/events/event-handler-processing-algorithm-error/window-synthetic-event.html": [ "a779db7beb4c5f52bde9131b7648b6efab2f8000", "testharness" @@ -379802,7 +380469,7 @@ "8f141c495c1b4444c8e25ba57924d7917f97d1b9", "testharness" ], - "html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html": [ + "html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html": [ "d87ec96d53353fc63b9d3db4775414c6335cdd2d", "testharness" ], @@ -381014,6 +381681,14 @@ "6cbea44f209e59ea0b901b0fe1cec7ac1aee0b64", "testharness" ], + "intersection-observer/initial-observation-with-threshold.html": [ + "1f3b96b7b22f1926eda6ba602ca1585aa96fc9db", + "testharness" + ], + "intersection-observer/inline-client-rect.html": [ + "5ef7203a189e693e49b8ce52cfb29f8fa76be2d4", + "testharness" + ], "intersection-observer/isIntersecting-change-events.html": [ "6def578601e9fb21f2ffd5412a83036353b7647a", "testharness" @@ -381531,7 +382206,7 @@ "testharness" ], "media-source/mediasource-changetype-util.js": [ - "a886523b16f314c6988fc734dacfd9568b707c27", + "b4e57994dbc5c2862e548156d114d8110f09f006", "support" ], "media-source/mediasource-changetype.html": [ @@ -381731,7 +382406,7 @@ "testharness" ], "media-source/mediasource-util.js": [ - "72b8c59a8eb6ed9f672eac1ba237e19d0d6fc4fa", + "8de08141e7839f1e41cc6ac98d45afa2e57fceed", "support" ], "media-source/mp3/sound_5.mp3": [ @@ -384194,10 +384869,6 @@ "5c3baf5da0b37791d9ae35033c04d0fcf5a1b318", "support" ], - "notifications/idlharness.any.js": [ - "c140ff43dc93d45d611941edfdb92b42be11ba87", - "testharness" - ], "notifications/idlharness.any.sharedworker-expected.txt": [ "cc3279f611cbe6e08909ef7f00e5ac151629699c", "support" @@ -384206,6 +384877,10 @@ "cc3279f611cbe6e08909ef7f00e5ac151629699c", "support" ], + "notifications/idlharness.https.any.js": [ + "c140ff43dc93d45d611941edfdb92b42be11ba87", + "testharness" + ], "notifications/idlharness.https.any.serviceworker-expected.txt": [ "a0511ee3c37e878f62bf0c9e3893230210d275ac", "support" @@ -391359,17 +392034,17 @@ "support" ], "payment-request/payment-request-abort-method.https.html": [ - "a9d811dc41487ba7a8e5d55319574364b93362aa", + "033fb8ae8710acf8870a7ff7b36aa3d33ec86e0b", "testharness" ], - "payment-request/payment-request-canmakepayment-method-manual.https.html": [ - "20edcf57236087023cf7379cec4a4ab3b57f3155", - "manual" - ], "payment-request/payment-request-canmakepayment-method.https-expected.txt": [ - "edf4b9aedbdc74041e2aa49d77eaa177954f0f80", + "1192dd5e77f9cb197c30ebc22d8271759db8d1e2", "support" ], + "payment-request/payment-request-canmakepayment-method.https.html": [ + "e2c13d3485bca29d28558ca4664745ae286bab6c", + "testharness" + ], "payment-request/payment-request-constructor-crash.https.html": [ "383d1c3f9505ee63d504bee87e13efa90ba49f3d", "testharness" @@ -391419,11 +392094,11 @@ "testharness" ], "payment-request/payment-request-show-method.https.html": [ - "5d3272b142ce55347400f8890cf406dd77804654", + "132a07918e43418e3da3b26128146ea9606fb8b9", "testharness" ], "payment-request/payment-response/complete-method-manual.https.html": [ - "218d966b1dbf064e56010101e71fc4489c34cb45", + "7ead47f96f3b45cb446b967d129d2704047a85c2", "manual" ], "payment-request/payment-response/helpers.js": [ @@ -392558,10 +393233,6 @@ "d1559a52f07fcb9f06d6d70c140665463d17c215", "support" ], - "push-api/idlharness.any.js": [ - "72864ef8db9789fc58ec0de4dfc84249f9368ff1", - "testharness" - ], "push-api/idlharness.any.sharedworker-expected.txt": [ "7b4ac8ca15e6888027a19c5e5bdef7e0109968bf", "support" @@ -392570,6 +393241,10 @@ "7b4ac8ca15e6888027a19c5e5bdef7e0109968bf", "support" ], + "push-api/idlharness.https.any.js": [ + "72864ef8db9789fc58ec0de4dfc84249f9368ff1", + "testharness" + ], "quirks/META.yml": [ "0214c11aec63acf1b5ae247cff64b440ff8b4bfe", "support" @@ -402987,7 +403662,7 @@ "testharness" ], "service-workers/service-worker/interfaces-sw.https-expected.txt": [ - "8c5191a644ac762a4a5bb66c6f70b5900a3e557c", + "ff5c91c7d58511fab3e2c6900e69a49dd063426b", "support" ], "service-workers/service-worker/interfaces-sw.https.html": [ @@ -403891,7 +404566,7 @@ "support" ], "service-workers/service-worker/resources/interfaces-worker.sub.js": [ - "cd067da4cc6683916037aaf13d71f6309f04460b", + "612ace7df6de8514c4175ab0b3f72b85541cfe14", "support" ], "service-workers/service-worker/resources/invalid-blobtype-iframe.https.html": [ @@ -407182,6 +407857,14 @@ "d8e578f5422229b37676ecdc7146488ac0865eaf", "reftest" ], + "svg/painting/reftests/markers-orient-001-ref.svg": [ + "be7bd408a33c09630027aa03f8fbde81d70cdf65", + "support" + ], + "svg/painting/reftests/markers-orient-001.svg": [ + "97f819fac348b0124e92b38b14939179fcd07443", + "reftest" + ], "svg/painting/reftests/paint-context-001-ref.svg": [ "d7e12d36f0b3168c677edf95ce401b3e1e5eccbe", "support" @@ -407530,6 +408213,94 @@ "2976a4812636c4515cc5e2c633b17c47bee392ab", "testharness" ], + "svg/text/reftests/text-inline-size-001-ref.svg": [ + "01f9695fa0965609348eada7c058fc1942b81b24", + "support" + ], + "svg/text/reftests/text-inline-size-001.svg": [ + "c99160d090e23f53d404e3dff127cdfae7f971cc", + "reftest" + ], + "svg/text/reftests/text-inline-size-002-ref.svg": [ + "e60c2d19f59d25acb8bf6cac063d0060ff0656fd", + "support" + ], + "svg/text/reftests/text-inline-size-002.svg": [ + "44b683fa1c34daac7e49763bcc108976fbb94ae8", + "reftest" + ], + "svg/text/reftests/text-inline-size-003-ref.svg": [ + "5301e3cc45e4948f38df96a482afcbc4188d939f", + "support" + ], + "svg/text/reftests/text-inline-size-003.svg": [ + "76c25b7386d160fb2f21a8f9cd40b3e1590a40ba", + "reftest" + ], + "svg/text/reftests/text-inline-size-005-ref.svg": [ + "6f0a98878263f20824b99a40dca45201a2d55243", + "support" + ], + "svg/text/reftests/text-inline-size-005.svg": [ + "91a6a50635b5dfe981a83509c13d62a7c333d76b", + "reftest" + ], + "svg/text/reftests/text-inline-size-006-ref.svg": [ + "4fa3dcc4eeb69cf64e82dd8f397c73c693eb51fb", + "support" + ], + "svg/text/reftests/text-inline-size-006.svg": [ + "50addd6be8ecb405a6b15821907605cad9b1d9d4", + "reftest" + ], + "svg/text/reftests/text-inline-size-007-ref.svg": [ + "6d210fbd1f98bad5563e1328fcf03b0311eb33f3", + "support" + ], + "svg/text/reftests/text-inline-size-007.svg": [ + "614537e68a70bdacfd206096ffa0c07f04f78797", + "reftest" + ], + "svg/text/reftests/text-inline-size-101-ref.svg": [ + "58ba7fcd16c1d044386ff9e221847c589111867e", + "support" + ], + "svg/text/reftests/text-inline-size-101.svg": [ + "2a6be86c0522e430de9b84ab299f4e26c6e7a8cf", + "reftest" + ], + "svg/text/reftests/text-inline-size-201-ref.svg": [ + "b80c4cfc11af6dd6ede27ec232a5dabf1de8f5f4", + "support" + ], + "svg/text/reftests/text-inline-size-201.svg": [ + "5bb85fc9de79fb3ef741f8f1215911e590fc1462", + "reftest" + ], + "svg/text/reftests/text-multiline-001-ref.svg": [ + "79dfad6caf2c10047e436f4bcdccebe0753c3b02", + "support" + ], + "svg/text/reftests/text-multiline-001.svg": [ + "cdff010d68d308bd248cb834d4edc4a3af17036f", + "reftest" + ], + "svg/text/reftests/text-multiline-002-ref.svg": [ + "66252b5a763750c9bfb7fe9082a6b960c408bd40", + "support" + ], + "svg/text/reftests/text-multiline-002.svg": [ + "07154a1b549e1cf0eb79b356a06ce6de727fddc0", + "reftest" + ], + "svg/text/reftests/text-multiline-003-ref.svg": [ + "da35a5f4c3defee2b3e63418ee5a062e1b40e517", + "support" + ], + "svg/text/reftests/text-multiline-003.svg": [ + "9151f583f6d6f94108b1dd5006a5037a874d9ac3", + "reftest" + ], "svg/text/reftests/textpath-shape-001-ref.svg": [ "6206cb07df0e750a9a2c2e805e3ac2334309e493", "support" @@ -407546,6 +408317,38 @@ "621b7e7b6799868067acf594d0248e13747830ce", "reftest" ], + "svg/text/visualtests/text-inline-size-001-visual.svg": [ + "3f324503faf0196fd9b76cba93c546c720e90f72", + "visual" + ], + "svg/text/visualtests/text-inline-size-002-visual.svg": [ + "8613452e81a6f73d902d5c1dad7a5c7909ccf3fe", + "visual" + ], + "svg/text/visualtests/text-inline-size-003-visual.svg": [ + "01d02938853ce250f0520393be3ae9cbefda03da", + "visual" + ], + "svg/text/visualtests/text-inline-size-005-visual.svg": [ + "170e7c5ee4e67887f13396774d987e52db6bb843", + "visual" + ], + "svg/text/visualtests/text-inline-size-006-visual.svg": [ + "7c5f9da911188f8a69c1aaa0a158a4f606b2953c", + "visual" + ], + "svg/text/visualtests/text-inline-size-007-visual.svg": [ + "408166290fa6573c8ce4f59a19d5564834df39c8", + "visual" + ], + "svg/text/visualtests/text-inline-size-101-visual.svg": [ + "5af35c0e9058fb4dd8a8e0ca4548bddca3466607", + "visual" + ], + "svg/text/visualtests/text-inline-size-201-visual.svg": [ + "282f01657cde99a323dcabf54f0cdae31eb905fa", + "visual" + ], "svg/types/elements/SVGGeometryElement-rect-expected.txt": [ "11b91f560c70bef8436895f6dbdba30de551863a", "support" @@ -407706,6 +408509,14 @@ "9e1f6ab25b99d75df4c885bf7cdaf9226d8c8bd4", "testharness" ], + "svg/types/scripted/event-handler-all-document-element-events-expected.txt": [ + "2ab110e137c7348dbbf99f6ef2739c82596abaf4", + "support" + ], + "svg/types/scripted/event-handler-all-document-element-events.svg": [ + "31761c9745e806bc527cd884c0559d454246d225", + "testharness" + ], "svg/types/scripted/resources/SVGLengthList-helper.js": [ "e0cfabfa40e50ef2c25602563862caba72dd469e", "support" @@ -409154,6 +409965,94 @@ "acdf9d22c042ea3b2637c14b1576b4c8ffb4e97a", "support" ], + "wasm/jsapi/assertions.js": [ + "4238583700450eb53b439a4be94ff645f15839f9", + "support" + ], + "wasm/jsapi/bad-imports.js": [ + "62d79e19598c7851b2167bafa67e40240c75c9b7", + "support" + ], + "wasm/jsapi/constructor/instantiate-bad-imports.any.js": [ + "3982f34f1f1519f6e68a59b8774af32f320ec24e", + "testharness" + ], + "wasm/jsapi/instance/constructor-bad-imports.any.js": [ + "d9e24eb66edb923586d25d825d829b20c72911d0", + "testharness" + ], + "wasm/jsapi/instance/constructor.any.js": [ + "9dedd497a1301a845b942c9d97592ff83ba3f0f4", + "testharness" + ], + "wasm/jsapi/interface.any-expected.txt": [ + "a1723fbf04327441898ca6112811c22c3390ccbd", + "support" + ], + "wasm/jsapi/interface.any.js": [ + "41f922170f108339a1e08e66a6c287c30c1dd3d6", + "testharness" + ], + "wasm/jsapi/interface.any.worker-expected.txt": [ + "a1723fbf04327441898ca6112811c22c3390ccbd", + "support" + ], + "wasm/jsapi/memory/constructor.any-expected.txt": [ + "497370aa424101b8f9d62640bad7a09923774fb3", + "support" + ], + "wasm/jsapi/memory/constructor.any.js": [ + "caa0e9f80a446a25de82489b82cc03f660512b04", + "testharness" + ], + "wasm/jsapi/memory/constructor.any.worker-expected.txt": [ + "497370aa424101b8f9d62640bad7a09923774fb3", + "support" + ], + "wasm/jsapi/module/constructor.any.js": [ + "babdaa3936a89f9cad43f28ed3a5d66b9bd13dda", + "testharness" + ], + "wasm/jsapi/module/customSections.any-expected.txt": [ + "62e01c278bc0b238519a38285a13d7f042289f26", + "support" + ], + "wasm/jsapi/module/customSections.any.js": [ + "477202fdc215f2746dc4b247d0c0783b980edead", + "testharness" + ], + "wasm/jsapi/module/customSections.any.worker-expected.txt": [ + "62e01c278bc0b238519a38285a13d7f042289f26", + "support" + ], + "wasm/jsapi/module/exports.any.js": [ + "b066152fea1877694e1cabae12bf606b3c50dcd1", + "testharness" + ], + "wasm/jsapi/module/imports.any.js": [ + "149d8661b3eb6ab68199574ce33ea9784103e517", + "testharness" + ], + "wasm/jsapi/table/constructor.any-expected.txt": [ + "17c0c0892ac7feafe063b7877df31a1bace514f3", + "support" + ], + "wasm/jsapi/table/constructor.any.js": [ + "351c99d612d5a07ce781fc5937ca3f2e82c6c3dd", + "testharness" + ], + "wasm/jsapi/table/constructor.any.worker-expected.txt": [ + "17c0c0892ac7feafe063b7877df31a1bace514f3", + "support" + ], + "wasm/jsapi/wasm-constants.js": [ + "6aba4f5fb4127cd56e1381bfb18204edde41abb2", + "support" + ], + "wasm/jsapi/wasm-module-builder.js": [ + "d989de51de5092642de1ea9a1d2d9edc0e605031", + "support" + ], "wasm/resources/blank.html": [ "0ddb4f1cf84729ed673295719ec58a3e5d600a12", "support" @@ -409174,18 +410073,6 @@ "d1b8ad09830985a5ce9ac0fe0f88b6d68eb7f012", "support" ], - "wasm/wasm_idb_worker.js": [ - "3f8a0a4736251c836009b9281dd9a46d0b612235", - "support" - ], - "wasm/wasm_indexeddb_test.https.html": [ - "2fcd9de0de5291930f331b25ee98e1c92490ab6a", - "testharness" - ], - "wasm/wasm_indexeddb_test.js": [ - "e202fc90095365ce4d19e3ff3f2423e93d2f979b", - "support" - ], "wasm/wasm_local_iframe_test.html": [ "e7b86a731b7cf7c122a1e37118cebce7342291fc", "testharness" @@ -411726,6 +412613,10 @@ "6f89b973ca7770bcb02f054c7f82326d003df8f3", "support" ], + "webrtc/RTCIceTransport-extension.https.html": [ + "7124d5112bf71807172936c1a0a0b9fd4b3484cd", + "testharness" + ], "webrtc/RTCIceTransport.html": [ "1b593c8ed167fd998195a2e2051bc489473f1bf4", "testharness" @@ -411775,7 +412666,7 @@ "testharness" ], "webrtc/RTCPeerConnection-constructor-expected.txt": [ - "690546c17c47d54083cb7735187db8d8a83b816a", + "9570ac1a99bcd14328d77804b8a78d74a391ec3c", "support" ], "webrtc/RTCPeerConnection-constructor.html": [ @@ -412255,7 +413146,7 @@ "support" ], "webrtc/idlharness.https.window-expected.txt": [ - "fc927276b7994269703a563bc0c90e9976da1b2b", + "488e238f27c07937793f97474e41f3cf50e29589", "support" ], "webrtc/idlharness.https.window.js": [ @@ -417530,8 +418421,12 @@ "1f5a6dcb95464a46817c2b6ad09af6f64d53f128", "testharness" ], + "workers/modules/dedicated-worker-import-referrer-expected.txt": [ + "849c2ffb7101b181e27bec999df756e4f8a3a992", + "support" + ], "workers/modules/dedicated-worker-import-referrer.html": [ - "9495c1f58acf7062267fd59e682541950a659731", + "c41d89774837e4816b197e2b2b93bee23fc42cb4", "testharness" ], "workers/modules/dedicated-worker-import.any.js": [ @@ -418138,6 +419033,10 @@ "6e92613e720ac1fa1cdec91665cc1ca68a6e0bc8", "testharness" ], + "worklets/animation-worklet-referrer.https-expected.txt": [ + "a4fdf44bc0ae720bce19cc1d5252908615514c12", + "support" + ], "worklets/animation-worklet-referrer.https.html": [ "7c6e4a94815093e9353d184b877046ad7627bae9", "testharness" @@ -418162,6 +419061,10 @@ "33cf33b95b66020e10fef9515fce2956c27b75ba", "testharness" ], + "worklets/layout-worklet-referrer.https-expected.txt": [ + "a4fdf44bc0ae720bce19cc1d5252908615514c12", + "support" + ], "worklets/layout-worklet-referrer.https.html": [ "3de86e7b122d6e8403858279e280d7e6ea5af389", "testharness" @@ -418182,6 +419085,10 @@ "a1a5fe53abb00fe37c7688032038110a67f988ee", "testharness" ], + "worklets/paint-worklet-referrer.https-expected.txt": [ + "a4fdf44bc0ae720bce19cc1d5252908615514c12", + "support" + ], "worklets/paint-worklet-referrer.https.html": [ "86e7c0fe4de0764a7064ed22eef2b66ab09d4a62", "testharness" @@ -418275,15 +419182,15 @@ "support" ], "worklets/resources/referrer-checker.py": [ - "3de9f5d0d90e5c360edd453a539cc2b83f45d42e", + "930c113063cfa5b0c2e5097761c82a443ff85ddf", "support" ], "worklets/resources/referrer-tests.js": [ - "e072f492d6aa19866245b357a623c60ec3382c9a", + "bfa2e28259a44abf3aac6be528e51976c9ff782d", "support" ], "worklets/resources/referrer-window.html": [ - "5900ef7037397bc3eb956b97c40cfd7a3a12c95f", + "adfb1c116fedb6396f970ed8072ee73edfc755fc", "support" ], "worklets/resources/service-worker-interception-tests.js": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/wasm-module-value.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/wasm-module-value.html deleted file mode 100644 index 9fcfd780..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/wasm-module-value.html +++ /dev/null
@@ -1,109 +0,0 @@ -<!doctype html> -<meta charset="utf8"> -<meta name="timeout" content="long"> -<title>IndexedDB: WebAssembly module values</title> -<link rel="help" href="https://w3c.github.io/IndexedDB/"> -<link rel="help" href="https://webassembly.github.io/spec/"> -<link rel="author" href="pwnall@chromium.org" title="Victor Costan"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="support-promises.js"></script> -<script> -'use strict'; - -// Binary representation for a WASM module that exports an "inc" function. -// -// This test covers storing WASM modules in IndexedDB. Its failure should only -// be debugged if WASM specification tests pass. To this end, the test does not -// use the WASM module builder helpers, trading off WASM debuggability in return -// for having the WASM wire bytes listed explicitly in the test body. Having the -// wire bytes spelled out can be helpful when debugging IndexedDB failures. -let wasm_module_bytes = new Uint8Array([ - 0x00, 0x61, 0x73, 0x6d, // Magic. - 0x01, 0x00, 0x00, 0x00, // Version. - 0x01, 0x06, 0x01, // Type section - 6 bytes, 1 entry - 0x60, 0x01, 0x7f, 0x01, 0x7f, // Type 0. Function: (i32) -> (i32) - 0x03, 0x02, 0x01, // Function section - 2 bytes, 1 entry - 0x00, // Function 0: Type 0 - 0x07, 0x07, 0x01, // Export section - 7 bytes, 1 entry - 0x03, 0x69, 0x6e, 0x63, // Export 1. { name: "inc" - 0x00, 0x00, // desc: function 0 } - 0x0a, 0x09, 0x01, // Code section: 9 bytes, 1 entry - 0x07, 0x00, // Function 1: 7 code bytes, 0 locals - 0x20, 0x00, // getlocal 0 - 0x41, 0x01, // i32.const 1 - 0x6a, // i32.add - 0x0b, // end -]); - -promise_test(async testCase => { - const wasm_module = await WebAssembly.compile(wasm_module_bytes.buffer); - - const database = await createDatabase(testCase, (database, transaction) => { - const store = database.createObjectStore('store'); - store.put(wasm_module, 'key1'); - }); - - const result = await new Promise((resolve, reject) => { - const transaction = database.transaction(['store'], 'readonly'); - const store = transaction.objectStore('store'); - const request = store.get('key1'); - request.onsuccess = (event) => resolve(event.target.result); - request.onerror = (event) => reject(event.target.error); - }); - - database.close(); - - const instance = await WebAssembly.instantiate(result); - assert_equals( - instance.exports['inc'](42), 43, 'inc should increment its argument'); -}, 'WebAssembly module as an IndexedDB value'); - -promise_test(async testCase => { - const wasm_module = await WebAssembly.compile(wasm_module_bytes.buffer); - - const database = await createDatabase(testCase, (database, transaction) => { - const store = database.createObjectStore('store'); - store.put({ module: wasm_module }, 'key1'); - }); - - const result = await new Promise((resolve, reject) => { - const transaction = database.transaction(['store'], 'readonly'); - const store = transaction.objectStore('store'); - const request = store.get('key1'); - request.onsuccess = (event) => resolve(event.target.result); - request.onerror = (event) => reject(event.target.error); - }); - - database.close(); - - const instance = await WebAssembly.instantiate(result.module); - assert_equals( - instance.exports['inc'](42), 43, 'inc should increment its argument'); -}, 'WebAssembly module in a JavaScript object IndexedDB value'); - -promise_test(async testCase => { - const wasm_module = await WebAssembly.compile(wasm_module_bytes.buffer); - - const database = await createDatabase(testCase, (database, transaction) => { - const store = database.createObjectStore('store', { keyPath: 'key' }); - store.put({ key: 'key1', module: wasm_module }); - }); - - const result = await new Promise((resolve, reject) => { - const transaction = database.transaction(['store'], 'readonly'); - const store = transaction.objectStore('store'); - const request = store.get('key1'); - request.onsuccess = (event) => resolve(event.target.result); - request.onerror = (event) => reject(event.target.error); - }); - - database.close(); - - assert_equals('key1', result.key); - const instance = await WebAssembly.instantiate(result.module); - assert_equals( - instance.exports['inc'](42), 43, 'inc should increment its argument'); -}, 'WebAssembly module in an IndexedDB value with an inline key'); - -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any-expected.txt new file mode 100644 index 0000000..79ea026 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any-expected.txt
@@ -0,0 +1,62 @@ +This is a testharness.js-based test. +PASS background-fetch interfaces +PASS Partial interface ServiceWorkerGlobalScope: original interface defined +PASS Partial interface ServiceWorkerRegistration: original interface defined +PASS BackgroundFetchManager interface: existence and properties of interface object +PASS BackgroundFetchManager interface object length +PASS BackgroundFetchManager interface object name +PASS BackgroundFetchManager interface: existence and properties of interface prototype object +PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchManager interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchManager interface: operation fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions) +PASS BackgroundFetchManager interface: operation get(DOMString) +PASS BackgroundFetchManager interface: operation getIds() +PASS BackgroundFetchRegistration interface: existence and properties of interface object +PASS BackgroundFetchRegistration interface object length +PASS BackgroundFetchRegistration interface object name +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchRegistration interface: attribute id +PASS BackgroundFetchRegistration interface: attribute uploadTotal +PASS BackgroundFetchRegistration interface: attribute uploaded +PASS BackgroundFetchRegistration interface: attribute downloadTotal +PASS BackgroundFetchRegistration interface: attribute downloaded +FAIL BackgroundFetchRegistration interface: attribute activeFetches assert_true: The prototype object must have a property "activeFetches" expected true got false +PASS BackgroundFetchRegistration interface: attribute onprogress +PASS BackgroundFetchRegistration interface: operation abort() +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation values() assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +PASS BackgroundFetchFetch interface: existence and properties of interface object +PASS BackgroundFetchFetch interface object length +PASS BackgroundFetchFetch interface object name +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchFetch interface: attribute request +PASS BackgroundFetchEvent interface: existence and properties of interface object +PASS BackgroundFetchSettledEvent interface: existence and properties of interface object +PASS BackgroundFetchSettledFetches interface: existence and properties of interface object +PASS BackgroundFetchSettledFetch interface: existence and properties of interface object +PASS BackgroundFetchUpdateEvent interface: existence and properties of interface object +PASS BackgroundFetchClickEvent interface: existence and properties of interface object +PASS ServiceWorkerRegistration interface: attribute backgroundFetch +PASS ServiceWorkerGlobalScope interface: existence and properties of interface object +PASS ExtendableEvent interface: existence and properties of interface object +PASS WorkerGlobalScope interface: existence and properties of interface object +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.js similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.js rename to third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.js
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.sharedworker-expected.txt new file mode 100644 index 0000000..a7a6e7dd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.sharedworker-expected.txt
@@ -0,0 +1,61 @@ +This is a testharness.js-based test. +PASS background-fetch interfaces +PASS Partial interface ServiceWorkerGlobalScope: original interface defined +PASS Partial interface ServiceWorkerRegistration: original interface defined +PASS BackgroundFetchManager interface: existence and properties of interface object +PASS BackgroundFetchManager interface object length +PASS BackgroundFetchManager interface object name +PASS BackgroundFetchManager interface: existence and properties of interface prototype object +PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchManager interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchManager interface: operation fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions) +PASS BackgroundFetchManager interface: operation get(DOMString) +PASS BackgroundFetchManager interface: operation getIds() +PASS BackgroundFetchRegistration interface: existence and properties of interface object +PASS BackgroundFetchRegistration interface object length +PASS BackgroundFetchRegistration interface object name +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchRegistration interface: attribute id +PASS BackgroundFetchRegistration interface: attribute uploadTotal +PASS BackgroundFetchRegistration interface: attribute uploaded +PASS BackgroundFetchRegistration interface: attribute downloadTotal +PASS BackgroundFetchRegistration interface: attribute downloaded +FAIL BackgroundFetchRegistration interface: attribute activeFetches assert_true: The prototype object must have a property "activeFetches" expected true got false +PASS BackgroundFetchRegistration interface: attribute onprogress +PASS BackgroundFetchRegistration interface: operation abort() +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation values() assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +PASS BackgroundFetchFetch interface: existence and properties of interface object +PASS BackgroundFetchFetch interface object length +PASS BackgroundFetchFetch interface object name +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchFetch interface: attribute request +PASS BackgroundFetchEvent interface: existence and properties of interface object +PASS BackgroundFetchSettledEvent interface: existence and properties of interface object +PASS BackgroundFetchSettledFetches interface: existence and properties of interface object +PASS BackgroundFetchSettledFetch interface: existence and properties of interface object +PASS BackgroundFetchUpdateEvent interface: existence and properties of interface object +PASS BackgroundFetchClickEvent interface: existence and properties of interface object +PASS ServiceWorkerRegistration interface: attribute backgroundFetch +PASS ServiceWorkerGlobalScope interface: existence and properties of interface object +PASS ExtendableEvent interface: existence and properties of interface object +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.worker-expected.txt new file mode 100644 index 0000000..a7a6e7dd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.worker-expected.txt
@@ -0,0 +1,61 @@ +This is a testharness.js-based test. +PASS background-fetch interfaces +PASS Partial interface ServiceWorkerGlobalScope: original interface defined +PASS Partial interface ServiceWorkerRegistration: original interface defined +PASS BackgroundFetchManager interface: existence and properties of interface object +PASS BackgroundFetchManager interface object length +PASS BackgroundFetchManager interface object name +PASS BackgroundFetchManager interface: existence and properties of interface prototype object +PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchManager interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchManager interface: operation fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions) +PASS BackgroundFetchManager interface: operation get(DOMString) +PASS BackgroundFetchManager interface: operation getIds() +PASS BackgroundFetchRegistration interface: existence and properties of interface object +PASS BackgroundFetchRegistration interface object length +PASS BackgroundFetchRegistration interface object name +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchRegistration interface: attribute id +PASS BackgroundFetchRegistration interface: attribute uploadTotal +PASS BackgroundFetchRegistration interface: attribute uploaded +PASS BackgroundFetchRegistration interface: attribute downloadTotal +PASS BackgroundFetchRegistration interface: attribute downloaded +FAIL BackgroundFetchRegistration interface: attribute activeFetches assert_true: The prototype object must have a property "activeFetches" expected true got false +PASS BackgroundFetchRegistration interface: attribute onprogress +PASS BackgroundFetchRegistration interface: operation abort() +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetches interface: operation values() assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +FAIL BackgroundFetchActiveFetch interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing +PASS BackgroundFetchFetch interface: existence and properties of interface object +PASS BackgroundFetchFetch interface object length +PASS BackgroundFetchFetch interface object name +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's "constructor" property +PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's @@unscopables property +PASS BackgroundFetchFetch interface: attribute request +PASS BackgroundFetchEvent interface: existence and properties of interface object +PASS BackgroundFetchSettledEvent interface: existence and properties of interface object +PASS BackgroundFetchSettledFetches interface: existence and properties of interface object +PASS BackgroundFetchSettledFetch interface: existence and properties of interface object +PASS BackgroundFetchUpdateEvent interface: existence and properties of interface object +PASS BackgroundFetchClickEvent interface: existence and properties of interface object +PASS ServiceWorkerRegistration interface: attribute backgroundFetch +PASS ServiceWorkerGlobalScope interface: existence and properties of interface object +PASS ExtendableEvent interface: existence and properties of interface object +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-layout-properties.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-layout-properties.html index 249c4a7..fcc2ce3b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-layout-properties.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-layout-properties.html
@@ -94,7 +94,7 @@ '<line-names>': ['[a] auto [b] auto [c]', '[a] 50px [b] 50px [c] 50px'], '<track-size>.auto': ['auto', '50px 50px 50px'], '<track-size>.<track-breadth>.<length>': ['100px', '100px 50px 50px'], - '<track-size>.<track-breadth>.<percentage>': ['100%', '50px 50px 50px'], + '<track-size>.<track-breadth>.<percentage>': ['100%', '150px 50px 50px'], '<track-size>.<track-breadth>.<flex>': ['1fr', '50px 50px 50px'], '<track-size>.<track-breadth>.min-content': ['min-content', '50px 50px 50px'], '<track-size>.<track-breadth>.max-content': ['max-content', '50px 50px 50px'],
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html new file mode 100644 index 0000000..d1af28ff --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text Test: overflow-wrap: break-word and intrinsic sizing</title> +<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org/"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#overflow-wrap-property"> +<meta name="flags" content="ahem"> +<link rel="match" href="reference/overflow-wrap-min-content-size-003-ref.html"> +<meta name="assert" content="overflow-wrap:break-word breaks at edge of inline elements."> +<style> +#wrapper { + width: 0px; + font: 16px / 1 Ahem; + overflow-wrap: break-word; + color: green; +} +#test { + float: left; +} +#reference { + position: absolute; + width: 16px; + height: 128px; + background: red; + z-index: -1; +} +</style> + +<p>Test passes if there is a vertical green bar below. +<div id="wrapper"> + <div id="reference"></div> + <div id="test"><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span><span>X</span></div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html new file mode 100644 index 0000000..a71b3a34d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-003-ref.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text Test reference</title> +<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/"> +<link rel="author" title="Mozilla" href="https://www.mozilla.org/"> +<meta name="flags" content="ahem"> +<style> +#wrapper { + width: 0px; + font: 16px / 1 Ahem; + color: green; +} +#test { + float: left; +} +#reference { + position: absolute; + width: 16px; + height: 128px; + background: red; + z-index: -1; +} +</style> + +<p>Test passes if there is a vertical green bar below. +<div id="wrapper"> + <div id="reference"></div> + <div id="test">X<br>X<br>X<br>X<br>X<br>X<br>X<br>X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt index fbc962c5..18388c8 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 377 tests; 322 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 377 tests; 323 PASS, 54 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Test driver PASS Partial interface Document: original interface defined PASS Partial interface Window: original interface defined @@ -38,7 +38,7 @@ PASS StyleSheet interface: attribute title PASS StyleSheet interface: attribute media PASS StyleSheet interface: attribute disabled -FAIL CSSStyleSheet interface: existence and properties of interface object assert_throws: interface object didn't throw TypeError when called as a constructor function "function () { [native code] }" did not throw +PASS CSSStyleSheet interface: existence and properties of interface object PASS CSSStyleSheet interface object length PASS CSSStyleSheet interface object name PASS CSSStyleSheet interface: existence and properties of interface prototype object
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/historical-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/historical-expected.txt index fdfba77..2c0959b7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/historical-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/historical-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 74 tests; 70 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 75 tests; 71 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Historical DOM features must be removed: DOMConfiguration PASS Historical DOM features must be removed: DOMCursor FAIL Historical DOM features must be removed: DOMError assert_equals: expected (undefined) undefined but got (function) function "function DOMError() { [native code] }" @@ -34,6 +34,7 @@ PASS Historical DOM features must be removed: cssElementMap PASS Historical DOM features must be removed: async PASS document.load +PASS XMLDocument.load PASS DOMImplementation.getFeature() must be nuked. PASS Historical DOM features must be removed: schemaTypeInfo PASS Historical DOM features must be removed: setIdAttribute
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/historical.html b/third_party/WebKit/LayoutTests/external/wpt/dom/historical.html index b45bebf..921fa07b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/historical.html +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/historical.html
@@ -67,6 +67,12 @@ }, "document.load"); test(function() { + // https://github.com/whatwg/html/commit/523f7a8773d2ab8a1eb0da6510651e8c5d2a7531 + var doc = document.implementation.createDocument(null, null, null); + assert_false("load" in doc); +}, "XMLDocument.load"); + +test(function() { assert_equals(document.implementation["getFeature"], undefined) }, "DOMImplementation.getFeature() must be nuked.")
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.sub.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.html similarity index 88% rename from third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.sub.html rename to third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.html index 8e960110..242def1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.sub.html +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Document-URL.html
@@ -12,7 +12,7 @@ this.add_cleanup(function() { document.body.removeChild(iframe); }); iframe.onload = this.step_func_done(function() { assert_equals(iframe.contentDocument.URL, - "http://{{host}}:{{ports[http][0]}}/common/blank.html"); + location.origin + "/common/blank.html"); }); }) </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/rootNode.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/rootNode.html index 66343e7..784831d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/rootNode.html +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/rootNode.html
@@ -11,6 +11,20 @@ <script> test(function () { + var shadowHost = document.createElement('div'); + document.body.appendChild(shadowHost); + + var shadowRoot = shadowHost.attachShadow({mode: 'open'}); + shadowRoot.innerHTML = '<div class="shadowChild">content</div>'; + + var shadowChild = shadowRoot.querySelector('.shadowChild'); + assert_equals(shadowChild.getRootNode({composed: true}), document, "getRootNode() must return context object's shadow-including root if options's composed is true"); + assert_equals(shadowChild.getRootNode({composed: false}), shadowRoot, "getRootNode() must return context object's root if options's composed is false"); + assert_equals(shadowChild.getRootNode(), shadowRoot, "getRootNode() must return context object's root if options's composed is default false"); + +}, "getRootNode() must return context object's shadow-including root if options's composed is true, and context object's root otherwise"); + +test(function () { var element = document.createElement('div'); assert_equals(element.getRootNode(), element, 'getRootNode() on an element without a parent must return the element itself');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html index 7d1d430c..52560537 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html
@@ -6,6 +6,7 @@ <meta name="variant" content="?_self"> <meta name="variant" content="?_parent"> <meta name="variant" content="?_top"> +<meta name=timeout content=long> <script src=/resources/testharness.js></script> <script src=/resources/testharnessreport.js></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt deleted file mode 100644 index 755a2ea7..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -This is a testharness.js-based test. -FAIL The 'href' attribute of the 'a' element assert_equals: The 'href' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'href' attribute of the 'link' element assert_equals: The 'href' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'href' attribute of the 'area' element assert_equals: The 'href' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'cite' attribute of the 'q' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'cite' attribute of the 'blockquote' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'cite' attribute of the 'ins' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'cite' attribute of the 'del' element assert_equals: The 'cite' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'src' attribute of the 'img' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'src' attribute of the 'embed' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'src' attribute of the 'video' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'src' attribute of the 'iframe' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'src' attribute of the 'script' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'src' attribute of the 'source' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'src' attribute of the 'track' element assert_equals: The 'src' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'action' attribute of the 'form' element assert_equals: The 'action' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'data' attribute of the 'object' element assert_equals: The 'data' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL The 'formaction' attribute of the 'button' element assert_equals: The 'formAction' attribute is incorrect. expected "http://www.web-platform.test:8001/test.txt" but got "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -FAIL Change the base URL must effect the descendant elements only assert_not_equals: The inner element must be effected. got disallowed value "http://web-platform.test:8001/html/infrastructure/urls/dynamic-changes-to-base-urls/test.txt" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.html b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.html new file mode 100644 index 0000000..ce65f392 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>HTML Test: Dynamic changes to base URLs</title> +<link rel="author" title="Intel" href="http://www.intel.com/"/> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#dynamic-changes-to-base-urls" /> +<base href="" id="base"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="div" style="display:none"></div> +<script> + var div = document.getElementById("div"), + base = document.getElementById("base"), + url = document.location.href; + + var testData = [ + {elements: ["a", "link", "area"], set: "href", get: "href"}, + {elements: ["q", "blockquote", "ins", "del"], set: "cite", get: "cite"}, + {elements: ["audio", "input", "img", "embed", "video", "iframe", "script", "source", "track"], set: "src", get: "src"}, + {elements: ["form"], set: "action", get: "action"}, + {elements: ["object"], set: "data", get: "data"}, + {elements: ["button"], set: "formAction", get: "formAction"} + ]; + + for (var i in testData) { + var item = testData[i]; + for (var j in item.elements) { + test(function () { + var ele = document.createElement(item.elements[j]); + + ele.setAttribute(item.set, "test.txt"); + div.appendChild(ele); + + base.setAttribute("href", ""); + assert_equals(ele[item.get], url.substr(0, url.lastIndexOf("/")) +"/test.txt", "The '" + item.get + "' attribute is incorrect."); + base.setAttribute("href", "http://{{domains[www]}}:{{ports[http][0]}}"); + assert_equals(ele[item.get], "http://{{domains[www]}}:{{ports[http][0]}}/test.txt", "The '" + item.get + "' attribute is incorrect."); + }, "The '" + item.set + "' attribute of the '" + item.elements[j] + "' element"); + } + } +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/historical.sub.xhtml similarity index 74% rename from third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml rename to third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/historical.sub.xhtml index 7302ed6..1be7a7c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml +++ b/third_party/WebKit/LayoutTests/external/wpt/html/infrastructure/urls/dynamic-changes-to-base-urls/historical.sub.xhtml
@@ -2,9 +2,9 @@ <!DOCTYPE html> <html id="h" xmlns="http://www.w3.org/1999/xhtml" xml:base=""> <head> - <title>HTML Test: Dynamic changes to base URLs</title> + <title>Historical xml:base must be removed</title> <link rel="author" title="Intel" href="http://www.intel.com/"/> - <link rel="help" href="https://html.spec.whatwg.org/multipage/#dynamic-changes-to-base-urls" /> + <link rel="help" href="https://github.com/whatwg/html/pull/84/files" /> <script src="/resources/testharness.js" id="s1"></script> <script src="/resources/testharnessreport.js"></script> </head> @@ -20,7 +20,7 @@ var testData = [ {elements: ["a", "link", "area"], set: "href", get: "href"}, {elements: ["q", "blockquote", "ins", "del"], set: "cite", get: "cite"}, - {elements: ["img", "embed", "video", "iframe", "script", "source", "track"], set: "src", get: "src"}, + {elements: ["audio", "input", "img", "embed", "video", "iframe", "script", "source", "track"], set: "src", get: "src"}, {elements: ["form"], set: "action", get: "action"}, {elements: ["object"], set: "data", get: "data"}, {elements: ["button"], set: "formaction", get: "formAction"} @@ -38,7 +38,7 @@ html.setAttribute("xml:base", ""); assert_equals(ele[item.get], url.substr(0, url.lastIndexOf("/")) +"/test.txt", "The '" + item.get + "' attribute is incorrect."); html.setAttribute("xml:base", "http://{{domains[www]}}:{{ports[http][0]}}"); - assert_equals(ele[item.get], "http://{{domains[www]}}:{{ports[http][0]}}/test.txt", "The '" + item.get + "' attribute is incorrect."); + assert_not_equals(ele[item.get], "http://{{domains[www]}}:{{ports[http][0]}}/test.txt", "The '" + item.get + "' attribute is incorrect."); }, "The '" + item.set + "' attribute of the '" + item.elements[j] + "' element"); } } @@ -50,9 +50,9 @@ div.setAttribute("xml:base", "http://{{domains[www2]}}:{{ports[http][0]}}"); assert_equals(s1.src, val1, "The outer element must not be effected."); - assert_not_equals(div.firstChild.href, val2, "The inner element must be effected."); - assert_equals(div.firstChild.href, "http://{{domains[www2]}}:{{ports[http][0]}}/test.txt"); - }, "Change the base URL must effect the descendant elements only"); + assert_equals(div.firstChild.href, val2, "The inner element must be effected."); + assert_not_equals(div.firstChild.href, "http://{{domains[www2]}}:{{ports[http][0]}}/test.txt"); + }, "Change the base URL must not effect the descendant elements"); ]]> </script> </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-face.html b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-face.html new file mode 100644 index 0000000..a37da3c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-face.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>font face</title> +<link rel="help" href="https://html.spec.whatwg.org/#the-font-element-text-decoration-color-quirk"> +<link rel="author" title="Intel" href="http://www.intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> + +const types = ["serif", "sans-serif", "cursive", "fantasy", "monospace"]; +for (let type of types) { + test(() => { + let elem = document.createElement("font"); + elem.setAttribute("face", type); + document.body.appendChild(elem); + let exp_type = window.getComputedStyle(elem, null).getPropertyValue("font-family"); + assert_equals(exp_type, type); + }, `font face attribute ${type} is correct`); +} + +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-size.html b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-size.html new file mode 100644 index 0000000..8e8b9f2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/phrasing-content-0/font-element-text-decoration-color/font-size.html
@@ -0,0 +1,103 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>font size</title> +<link rel="help" href="https://html.spec.whatwg.org/#the-font-element-text-decoration-color-quirk"> +<link rel="author" title="Intel" href="http://www.intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> + +<script> + +const modes = ["", "+", "-"]; +const values = ["0", "1", "2", "3", "4", "5", "6", "7", "8"]; +const rels = [ + ["1", "x-small"], + ["2", "small"], + ["3", "medium"], + ["4", "large"], + ["5", "x-large"], + ["6", "xx-large"], + ["7", "xxx-large"] +]; +let results = getCSSFontSize(rels); + +function cal(n) { + //If value is greater than 7, let it be 7 + //If value is less than 1, let it be 1 + return n > 7 ? 7 : (n < 1 ? 1 : n); +} + +function getRealInput(mode, value) { + switch(mode) { + case "+": + //If mode is relative-plus, then increment value by 3 + return cal(3 + parseInt(value)); + case "-": + // If mode is relative-minus, then let value be the result of subtracting value from 3 + return cal(3 - parseInt(value)); + default: + return cal(parseInt(value)); + } +} + +function getCSSFontSize(rels) { + let results = {}; + for (let [key, value] of rels) { + if (key == "7") { + //The 'xxx-large' value is a non-CSS value used here to indicate a font size 50% larger than 'xx-large'. + let size = parseInt(results["6"]) * 1.5; + results[key] = size.toString(); + return results; + } + let elem = document.createElement("span"); + document.body.appendChild(elem); + elem.setAttribute("style", `font-size: ${value}`); + let exp_size = window.getComputedStyle(elem, null).getPropertyValue("font-size"); + results[key] = exp_size.slice(0, -2); + } + return results; +} + +for (let mode of modes) { + for (let value of values) { + test(() => { + let size = getRealInput(mode, value); + let elem = document.createElement("font"); + elem.setAttribute("size", `${mode}${value}`); + document.body.appendChild(elem); + let exp_size = window.getComputedStyle(elem, null).getPropertyValue("font-size"); + assert_equals(exp_size.slice(0, -2), results[size]); + }, `font size attribute ${mode}${value} is correct`); + } +} + +test(() => { + let span_elem = document.createElement("span"); + document.body.appendChild(span_elem); + span_elem.setAttribute("style", "font-size: medium"); + let span_size = window.getComputedStyle(span_elem, null).getPropertyValue("font-size"); + + let font_elem = document.createElement("font"); + document.body.appendChild(font_elem); + let font_size = window.getComputedStyle(font_elem, null).getPropertyValue("font-size"); + assert_equals(font_size, span_size); + + font_elem.setAttribute("size", ""); + font_size = window.getComputedStyle(font_elem, null).getPropertyValue("font-size"); + assert_equals(font_size, span_size); + + font_elem.setAttribute("size", " "); + font_size = window.getComputedStyle(font_elem, null).getPropertyValue("font-size"); + assert_equals(font_size, span_size); + + font_elem.setAttribute("size", " 3"); + font_size = window.getComputedStyle(font_elem, null).getPropertyValue("font-size"); + assert_equals(font_size, span_size); + + font_elem.setAttribute("size", "3"); + font_size = window.getComputedStyle(font_elem, null).getPropertyValue("font-size"); + assert_equals(font_size, span_size); +}, "font size default value is 3"); + +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html rename to third_party/WebKit/LayoutTests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/initial-observation-with-threshold.html b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/initial-observation-with-threshold.html new file mode 100644 index 0000000..d677f0ee --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/intersection-observer/initial-observation-with-threshold.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/intersection-observer-test-utils.js"></script> + +<style> +pre, #log { + position: absolute; + top: 0; + left: 200px; +} +.spacer { + height: calc(100vh + 100px); +} +#root { + display: inline-block; + overflow-y: scroll; + height: 240px; + border: 3px solid black; +} +#target { + width: 100px; + height: 100px; + margin: 200px 0 0 0; + background-color: green; +} +</style> + +<div id="root"> + <div id="target"></div> +</div> + +<script> +var entries = []; +var root, target; + +runTestCycle(function() { + target = document.getElementById("target"); + assert_true(!!target, "target exists"); + root = document.getElementById("root"); + assert_true(!!root, "root exists"); + var observer = new IntersectionObserver(function(changes) { + entries = entries.concat(changes) + }, { root: root, threshold: [0.5] }); + observer.observe(target); + entries = entries.concat(observer.takeRecords()); + assert_equals(entries.length, 0, "No initial notifications."); + runTestCycle(step0, "First rAF"); +}, "First observation with a threshold."); + +function step0() { + root.scrollTop = 20; + runTestCycle(step1, "root.scrollTop = 20"); + checkLastEntry(entries, 0, [ 11, 111, 211, 311, 11, 111, 211, 251, 11, 111, 11, 251, false]); +} + +function step1() { + checkLastEntry(entries, 1, [ 11, 111, 191, 291, 11, 111, 191, 251, 11, 111, 11, 251, true]); +} +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/notifications/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/notifications/idlharness.https.any.js similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/notifications/idlharness.any.js rename to third_party/WebKit/LayoutTests/external/wpt/notifications/idlharness.https.any.js
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-abort-method.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-abort-method.https.html index d1f693a..522411b5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-abort-method.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-abort-method.https.html
@@ -15,7 +15,10 @@ explicit_timeout: true, }); const basicCard = Object.freeze({ supportedMethods: "basic-card" }); -const defaultMethods = Object.freeze([basicCard]); +const applePay = Object.freeze({ + supportedMethods: "https://apple.com/apple-pay", +}); +const defaultMethods = Object.freeze([basicCard, applePay]); const defaultDetails = Object.freeze({ total: { label: "Total", @@ -26,53 +29,53 @@ }, }); -window.onload = async () => { - promise_test(async t => { - // request is in "created" state +promise_test(async t => { + // request is in "created" state + const request = new PaymentRequest(defaultMethods, defaultDetails); + await promise_rejects(t, "InvalidStateError", request.abort()); +}, `Throws if the promise [[state]] is not "interactive"`); + +promise_test(async t => { + return test_driver.bless("show payment request", async () => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + const acceptPromise = request.show(); + try { + await request.abort(); + } catch (err) { + assert_unreached("Unexpected promise rejection: " + err.message); + } + await promise_rejects(t, "AbortError", acceptPromise); + // As request is now "closed", trying to show it will fail + await promise_rejects(t, "InvalidStateError", request.show()); + }); +}); + +promise_test(async t => { + return test_driver.bless("show payment request", async () => { + // request is in "created" state. const request = new PaymentRequest(defaultMethods, defaultDetails); await promise_rejects(t, "InvalidStateError", request.abort()); - }, `Throws if the promise [[state]] is not "interactive"`); - - const button = document.getElementById("button"); - - promise_test(async t => { - button.onclick = async () => { - const request = new PaymentRequest(defaultMethods, defaultDetails); - const acceptPromise = request.show(); - try { - await request.abort(); - } catch (err) { - assert_unreached("Unexpected promise rejection: " + err.message); - } - await promise_rejects(t, "AbortError", acceptPromise); - // As request is now "closed", trying to show it will fail - await promise_rejects(t, "InvalidStateError", request.show()); - }; - await test_driver.click(button); + // Call it again, for good measure. + await promise_rejects(t, "InvalidStateError", request.abort()); + // The request's state is "created", so let's show it + // which changes the state to "interactive.". + const acceptPromise = request.show(); + // Let's set request the state to "closed" by calling .abort() + try { + await request.abort(); + } catch (err) { + assert_unreached("Unexpected promise rejection: " + err.message); + } + // The request is now "closed", so... + await promise_rejects(t, "InvalidStateError", request.abort()); + await promise_rejects(t, "AbortError", acceptPromise); }); +}); - promise_test(async t => { - button.onclick = async () => { - // request is in "created" state. - const request = new PaymentRequest(defaultMethods, defaultDetails); - await promise_rejects(t, "InvalidStateError", request.abort()); - // Call it again, for good measure. - await promise_rejects(t, "InvalidStateError", request.abort()); - // The request's state is "created", so let's show it - // which changes the state to "interactive.". - const acceptPromise = request.show(); - // Let's set request the state to "closed" by calling .abort() - try { - await request.abort(); - } catch (err) { - assert_unreached("Unexpected promise rejection: " + err.message); - } - // The request is now "closed", so... - await promise_rejects(t, "InvalidStateError", request.abort()); - await promise_rejects(t, "AbortError", acceptPromise); - }; - await test_driver.click(button); - }); -}; +promise_test(async t => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + const promises = new Set([request.abort(), request.abort(), request.abort()]); + assert_equals(promises.size, 3, "Must have three unique objects"); +}, "Calling abort() multiple times is always a new object."); </script> -<button id="button"></button> +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https-expected.txt index 9269b3a3..0f09114 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https-expected.txt
@@ -1,10 +1,4 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Request failed -FAIL If request.[[state]] is "created", then return a promise that resolves to true for known method. assert_equals: if it throws, then it must be a NotAllowedError. expected "NotAllowedError" but got "UnknownError" -FAIL If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException. promise_test: Unhandled rejection with value: object "UnknownError: Request failed" -FAIL If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException. promise_test: Unhandled rejection with value: object "UnknownError: Request failed" -FAIL If payment method identifier and serialized parts are supported, resolve promise with true. promise_test: Unhandled rejection with value: object "UnknownError: Request failed" -FAIL If payment method identifier is unknown, resolve promise with false. assert_equals: if it throws, then it must be a NotAllowedError. expected "NotAllowedError" but got "UnknownError" -FAIL Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException. assert_equals: if it throws, then it must be a NotAllowedError. expected "NotAllowedError" but got "UnknownError" +FAIL Tests for PaymentRequest.canMakePayment() method Uncaught TypeError: Cannot set property 'click' of undefined Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html similarity index 76% rename from third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html rename to third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html index 5ea639b..617bd6e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html
@@ -4,12 +4,9 @@ <link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src='/resources/testdriver-vendor.js'></script> +<script src="/resources/testdriver.js"></script> <script> -setup({ - explicit_done: true, - explicit_timeout: true, -}); - const basicCard = Object.freeze({ supportedMethods: "basic-card" }); const defaultMethods = Object.freeze([basicCard]); const defaultDetails = Object.freeze({ @@ -124,14 +121,10 @@ } }, `Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.`); -function manualTest1(elem){ - elem.disabled = true; - - // NB: request.show has to be called outside of promise_test to ensure the - // user's click is still visible to PaymentRequest.show. - const request = new PaymentRequest(defaultMethods, defaultDetails); - const acceptPromise = request.show(); // Sets state to "interactive" - promise_test(async t => { +promise_test(t => { + return test_driver.bless("show payment request", async () => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + const acceptPromise = request.show(); // Sets state to "interactive" const canMakePaymentPromise = request.canMakePayment(); try { const result = await canMakePaymentPromise; @@ -147,18 +140,14 @@ } // The state should be "closed" await promise_rejects(t, "InvalidStateError", request.canMakePayment()); - }, elem.textContent.trim()); -} + }); +}, 'If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.'); -function manualTest2(elem){ - elem.disabled = true; - - // See above for why it's important for these lines to be outside of - // promise_test. - const request = new PaymentRequest(defaultMethods, defaultDetails); - const acceptPromise = request.show(); // The state is now "interactive" - acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools. - promise_test(async t => { +promise_test(t => { + return test_driver.bless("show payment request", async () => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + const acceptPromise = request.show(); // The state is now "interactive" + acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools. await request.abort(); // The state is now "closed" await promise_rejects(t, "InvalidStateError", request.canMakePayment()); try { @@ -174,28 +163,23 @@ "must be an InvalidStateError." ); } - }, elem.textContent.trim()); - done(); -} + }); +}, 'If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.'); + +test(() => { + const request = new PaymentRequest( + [{ supportedMethods: "basic-card" }], + defaultDetails + ); + const promises = new Set([ + request.canMakePayment(), + request.canMakePayment(), + request.canMakePayment(), + ]); + assert_equals(promises.size, 3, "Must have three unique objects"); +}, "Calling canMakePayment() multiple times is always a new object."); </script> -<h2>Tests for PaymentRequest.canMakePayment() method</h2> -<p> - Click on each button in sequence from top to bottom without refreshing the page. - No payment sheet will be shown, but the tests will run in the background. -</p> -<ol> - <li> - <button onclick="manualTest1(this)"> - If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException. - </button> - </li> - <li> - <button onclick="manualTest2(this)"> - If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException. - </button> - </li> -</ol> <small> If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a> and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/META.yml">suggested reviewers</a>.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-show-method.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-show-method.https.html index 38ab786b..c6e69d4c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-show-method.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-show-method.https.html
@@ -6,13 +6,11 @@ <script src="/resources/testharnessreport.js"></script> <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> -<button id="button"></button> <script> -'use strict'; -const button = document.getElementById("button"); +"use strict"; const defaultMethods = Object.freeze([ { supportedMethods: "basic-card" }, - { supportedMethods: "https://apple.com/apple-pay" } + { supportedMethods: "https://apple.com/apple-pay" }, ]); const defaultDetails = Object.freeze({ @@ -31,19 +29,18 @@ await promise_rejects(t, "SecurityError", acceptPromise); }, `Calling show() without being triggered by user interaction throws`); -promise_test(async t => { - button.onclick = async () => { +promise_test(t => { + return test_driver.bless("show payment request", async () => { const request = new PaymentRequest(defaultMethods, defaultDetails); const acceptPromise = request.show(); // Sets state to "interactive" await promise_rejects(t, "InvalidStateError", request.show()); await request.abort(); await promise_rejects(t, "AbortError", acceptPromise); - }; - await test_driver.click(button); + }); }, "Throws if the promise [[state]] is not 'created'."); -promise_test(async t => { - button.onclick = async () => { +promise_test(t => { + return test_driver.bless("show payment request", async () => { const request1 = new PaymentRequest(defaultMethods, defaultDetails); const request2 = new PaymentRequest(defaultMethods, defaultDetails); const acceptPromise1 = request1.show(); @@ -51,19 +48,33 @@ await promise_rejects(t, "AbortError", acceptPromise2); await request1.abort(); await promise_rejects(t, "AbortError", acceptPromise1); - }; - await test_driver.click(button); + }); }, `If the user agent's "payment request is showing" boolean is true, then return a promise rejected with an "AbortError" DOMException.`); -promise_test(async t => { - button.onclick = async () => { +promise_test(t => { + return test_driver.bless("show payment request", async () => { const request = new PaymentRequest( [{ supportedMethods: "this-is-not-supported" }], defaultDetails ); const acceptPromise = request.show(); await promise_rejects(t, "NotSupportedError", acceptPromise); - }; - await test_driver.click(button); + }); }, `If payment method consultation produces no supported method of payment, then return a promise rejected with a "NotSupportedError" DOMException.`); + +promise_test(t => { + return test_driver.bless("show payment request", async () => { + const request = new PaymentRequest( + [{ supportedMethods: "basic-card" }], + defaultDetails + ); + const promises = new Set([request.show(), request.show(), request.show()]); + await request.abort(); + assert_equals(promises.size, 3, "Must have three unique objects"); + }); +}, "Calling show() multiple times is always a new object."); </script> +<small> + If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a> + and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/META.yml">suggested reviewers</a>. +</small>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html index 64d5c53..a9da9ee 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-response/complete-method-manual.https.html
@@ -14,12 +14,13 @@ promise_test(async t => { try { // We .complete() as normal, using the passed test value - const promise = response.complete(result); - assert_true(promise instanceof Promise, "returns a promise"); + const completePromise = response.complete(result); + assert_true(completePromise instanceof Promise, "returns a promise"); // Immediately calling complete() again yields a rejected promise. - await promise_rejects(t, "InvalidStateError", response.complete(result)); + const invalidComplete = response.complete(result); + await promise_rejects(t, "InvalidStateError", invalidComplete); // but the original promise is unaffected - const returnedValue = await promise; + const returnedValue = await completePromise; assert_equals( returnedValue, undefined, @@ -27,12 +28,23 @@ ); // We now call .complete() again, to force an exception // because [[complete]] is true. - await promise_rejects(t, "InvalidStateError", response.complete(result)); + const afterComplete = response.complete(result); + await promise_rejects(t, "InvalidStateError", afterComplete); button.innerHTML = `✅ ${button.textContent}`; } catch (err) { button.innerHTML = `❌ ${button.textContent}`; assert_unreached("Unexpected exception: " + err.message); } + const allPromises = new Set([ + completePromise, + invalidComplete, + afterComplete, + ]); + assert_equals( + allPromises.length, + 3, + "Calling complete() multiple times is always a new object." + ); }, button.textContent.trim()); } </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.https.any.js similarity index 100% rename from third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.any.js rename to third_party/WebKit/LayoutTests/external/wpt/push-api/idlharness.https.any.js
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js index fdd9820..0ea7a2a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/testharness.js
@@ -650,7 +650,7 @@ /** * Returns a Promise that will resolve after the specified event or - * series of events has occured. + * series of events has occurred. * * @param options An optional options object. If the 'record' property * on this object has the value 'all', when the Promise @@ -1059,7 +1059,7 @@ function assert_array_approx_equals(actual, expected, epsilon, description) { /* - * Test if two primitive arrays are equal withing +/- epsilon + * Test if two primitive arrays are equal within +/- epsilon */ assert(actual.length === expected.length, "assert_array_approx_equals", description, @@ -1087,7 +1087,7 @@ function assert_approx_equals(actual, expected, epsilon, description) { /* - * Test if two primitive numbers are equal withing +/- epsilon + * Test if two primitive numbers are equal within +/- epsilon */ assert(typeof actual === "number", "assert_approx_equals", description,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-sw.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-sw.https-expected.txt index 79d93e8..16b331f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-sw.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-sw.https-expected.txt
@@ -3,6 +3,7 @@ PASS test setup (cache creation) FAIL Event constructors assert_equals: FetchEvent.isReload should not exist expected (undefined) undefined but got (boolean) false PASS xhr is not exposed +PASS URL.createObjectURL is not exposed FAIL ServiceWorker interface: existence and properties of interface object assert_own_property: self does not have own property "ServiceWorker" expected property "ServiceWorker" missing FAIL ServiceWorker interface object length assert_own_property: self does not have own property "ServiceWorker" expected property "ServiceWorker" missing FAIL ServiceWorker interface object name assert_own_property: self does not have own property "ServiceWorker" expected property "ServiceWorker" missing
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js index 10fe14d5..56bc8af4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js
@@ -93,3 +93,7 @@ test(() => { assert_false('XMLHttpRequest' in self); }, 'xhr is not exposed'); + +test(() => { + assert_false('createObjectURL' in self.URL); + }, 'URL.createObjectURL is not exposed')
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/markers-orient-001-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/markers-orient-001-ref.svg new file mode 100644 index 0000000..871003f3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/markers-orient-001-ref.svg
@@ -0,0 +1,48 @@ +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Marker: 'orient'</title> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("../fonts/FreeSans.woff") format("woff"); + } + text { + font-family: FreeSans, sans-serif; + text-anchor: middle; + fill: black; + } + #title { + font-size: 24px; + } + .label { + font-size: 18px; + } + </style> + + <defs> + <path id="triangle" d="m 0,0 0,-2.5 10,2.5 -10,2.5 z"/> + </defs> + + <g id="test-body-reference" style="fill:black"> + <path d="m 120,120 120,0 120,0" style="stroke:black;stroke-width:4px"/> + <path d="m 120,220 120,0 120,0" style="stroke:black;stroke-width:4px"/> + <path d="m 120,320 120,0 120,0" style="stroke:black;stroke-width:4px"/> + <use xlink:href="#triangle" transform="translate(120,120) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(240,120) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(360,120) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(120,220) scale(4,4) rotate(45)"/> + <use xlink:href="#triangle" transform="translate(240,220) scale(4,4) rotate(45)"/> + <use xlink:href="#triangle" transform="translate(360,220) scale(4,4) rotate(45)"/> + <use xlink:href="#triangle" transform="translate(120,320) scale(4,4) rotate(180)"/> + <use xlink:href="#triangle" transform="translate(240,320) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(360,320) scale(4,4)"/> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/markers-orient-001.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/markers-orient-001.svg new file mode 100644 index 0000000..55c2394 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/markers-orient-001.svg
@@ -0,0 +1,65 @@ +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Marker: 'orient'</title> + <html:link rel="author" + title="Tavmjong Bah" + href="http://tavmjong.free.fr"/> + <html:link rel="help" + href="https://www.w3.org/TR/SVG2/painting.html#OrientAttribute"/> + <html:link rel="match" href="markers-orient-001-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("../fonts/FreeSans.woff") format("woff"); + } + text { + font-family: FreeSans, sans-serif; + text-anchor: middle; + fill: black; + } + #title { + font-size: 24px; + } + .label { + font-size: 18px; + } + </style> + + <defs> + <path id="triangle" d="m 0,0 0,-2.5 10,2.5 -10,2.5 z"/> + <marker id="OrientAuto" style="overflow:visible" markerWidth="5" markerHeight="10"> + <use xlink:href="#triangle"/> + </marker> + <marker id="OrientFixed" style="overflow:visible" markerWidth="5" markerHeight="10" orient="45"> + <use xlink:href="#triangle"/> + </marker> + <marker id="OrientAutoReverse" style="overflow:visible" markerWidth="5" markerHeight="10" orient="auto-start-reverse"> + <use xlink:href="#triangle"/> + </marker> + </defs> + + <g id="reference" style="fill:red"> + <use xlink:href="#triangle" transform="translate(120,120) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(240,120) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(360,120) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(120,220) scale(4,4) rotate(45)"/> + <use xlink:href="#triangle" transform="translate(240,220) scale(4,4) rotate(45)"/> + <use xlink:href="#triangle" transform="translate(360,220) scale(4,4) rotate(45)"/> + <use xlink:href="#triangle" transform="translate(120,320) scale(4,4) rotate(180)"/> + <use xlink:href="#triangle" transform="translate(240,320) scale(4,4)"/> + <use xlink:href="#triangle" transform="translate(360,320) scale(4,4)"/> + </g> + <g id="test-body-content" font-size="16"> + <path d="m 120,120 120,0 120,0" style="stroke:black;stroke-width:4px;marker:url(#OrientAuto)"/> + <path d="m 120,220 120,0 120,0" style="stroke:black;stroke-width:4px;marker:url(#OrientFixed)"/> + <path d="m 120,320 120,0 120,0" style="stroke:black;stroke-width:4px;marker:url(#OrientAutoReverse)"/> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-001-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-001-ref.svg new file mode 100644 index 0000000..6abd21158 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-001-ref.svg
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 001</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px;fill:black"> + <g transform="translate(0,0)"> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="240" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <text style="text-anchor:end"> + <tspan x="400" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="400" y="134.8">adipisicing elit,</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-001.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-001.svg new file mode 100644 index 0000000..ae1a10d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-001.svg
@@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 001</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-001-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,60)"> + <text x="240" y="114.8" style="inline-size:320px;text-anchor:middle">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,120)"> + <text x="400" y="114.8" style="inline-size:320px;text-anchor:end">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-002-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-002-ref.svg new file mode 100644 index 0000000..66f771e3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-002-ref.svg
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text in Shape — 002</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px"> + <g transform="translate(0,0)"> + <text transform="translate(250,10) rotate(90)"> + <tspan x="90" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="90" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(80,0)"> + <text transform="translate(250,-40) rotate(90)" style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="240" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(160,0)"> + <text transform="translate(250,-90) rotate(90)" style="text-anchor:end"> + <tspan x="390" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="390" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-002.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-002.svg new file mode 100644 index 0000000..141909c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-002.svg
@@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text in Shape — 002</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-002-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;writing-mode:tb-rl"> + <g transform="translate(0,0)"> + <text x="140" y="100" style="inline-size:200px">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(80,0)"> + <text x="140" y="200" style="inline-size:200px;text-anchor:middle">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(160,0)"> + <text x="140" y="300" style="inline-size:200px;text-anchor:end">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-003-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-003-ref.svg new file mode 100644 index 0000000..289b92a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-003-ref.svg
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 003</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px;direction:rtl"> + <g transform="translate(0,0)"> + <text> + <tspan x="400" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="400" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="240" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <text style="text-anchor:end"> + <tspan x="80" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="80" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-003.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-003.svg new file mode 100644 index 0000000..9fcab5b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-003.svg
@@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 003</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-003-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;direction:rtl"> + <g transform="translate(0,0)"> + <text x="400" y="114.8" style="inline-size:320px">لكن لا بد أن أوضح لك أن كل هذه الأفكار المغلوطة حول استنكار</text> + </g> + <g transform="translate(0,60)"> + <text x="240" y="114.8" style="inline-size:320px;text-anchor:middle">لكن لا بد أن أوضح لك أن كل هذه الأفكار المغلوطة حول استنكار</text> + </g> + <g transform="translate(0,120)"> + <text x="80" y="114.8" style="inline-size:320px;text-anchor:end">لكن لا بد أن أوضح لك أن كل هذه الأفكار المغلوطة حول استنكار</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-005-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-005-ref.svg new file mode 100644 index 0000000..af756b6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-005-ref.svg
@@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 005</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px"> + <g transform="translate(0,0)"> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="149.6">adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor</tspan> + <tspan x="80" y="174.8">incididunt ut labore et dolore magna aliqua. Ut</tspan> + <tspan x="80" y="209.6">enim ad minim veniam, <tspan style="font-size:32px">quis</tspan> nostrud</tspan> + <tspan x="80" y="234.8">exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea</tspan> + <tspan x="80" y="254.8">commodo consequat.</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-005.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-005.svg new file mode 100644 index 0000000..e6a1d75 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-005.svg
@@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 005</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-005-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-height:1.25"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px" xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, <tspan style="font-size:2em">quis</tspan> nostrud exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea commodo consequat.</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-006-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-006-ref.svg new file mode 100644 index 0000000..9c32e841 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-006-ref.svg
@@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 006</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px"> + <g transform="translate(0,0)"> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="134.8">adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor</tspan> + <tspan x="80" y="154.8">incididunt ut labore et dolore magna aliqua. Ut</tspan> + <tspan x="80" y="174.8">enim ad minim veniam, <tspan style="font-size:32px">quis</tspan> nostrud</tspan> + <tspan x="80" y="194.8">exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea</tspan> + <tspan x="80" y="214.8">commodo consequat.</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-006.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-006.svg new file mode 100644 index 0000000..b84e3d5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-006.svg
@@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 006</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-006-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-height:1.25"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px">Lorem ipsum dolor sit amet, consectetur adipiscing <tspan style="font-size:32px;line-height:0">elit</tspan>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, <tspan style="font-size:2em;line-height:0">quis</tspan> nostrud exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea commodo consequat.</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-007-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-007-ref.svg new file mode 100644 index 0000000..1817851 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-007-ref.svg
@@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 006</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px"> + <g transform="translate(0,0)"> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="139.6">adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor</tspan> + <tspan x="80" y="159.6">incididunt ut labore et dolore magna aliqua. Ut</tspan> + <tspan x="80" y="184.4">enim ad minim veniam, <tspan style="font-size:32px">quis</tspan> nostrud</tspan> + <tspan x="80" y="204.4">exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea</tspan> + <tspan x="80" y="226.8">commodo consequat.</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-007.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-007.svg new file mode 100644 index 0000000..9d18b52 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-007.svg
@@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 006</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-007-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px;line-height:20px">Lorem ipsum dolor sit amet, consectetur adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, <tspan style="font-size:2em">quis</tspan> nostrud exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea commodo consequat.</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-101-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-101-ref.svg new file mode 100644 index 0000000..ab41dea --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-101-ref.svg
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 101</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px"> + <g transform="translate(0,0)"> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="240" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <text style="text-anchor:end"> + <tspan x="400" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="400" y="134.8">adipisicing elit,</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-101.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-101.svg new file mode 100644 index 0000000..fa8bf5ef --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-101.svg
@@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 101</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-101-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:66.66667%">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,60)"> + <text x="240" y="114.8" style="inline-size:66.66667%;text-anchor:middle">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,120)"> + <text x="400" y="114.8" style="inline-size:66.66667%;text-anchor:end">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-201-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-201-ref.svg new file mode 100644 index 0000000..b1eb7c7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-201-ref.svg
@@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text in Shape — 201</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px"> + <g transform="translate(0,0)"> + <text style="writing-mode:tb-rl"> + <tspan x="140" y="100">漢字</tspan> + <tspan x="140" y="132">Lorem ipsum</tspan> + <tspan x="140" y="227.7">漢字</tspan> + </text> + </g> + <g transform="translate(80,0)"> + <text transform="translate(250,-40) rotate(90)"> + <tspan x="140" y="110">漢字Lorem ipsum!漢字</tspan> + </text> + </g> + <g transform="translate(160,0)"> + <text transform="translate(250,-40) rotate(90)"> + <tspan x="140" y="110">漢字!لكن لا بد أن漢字</tspan> + </text> + </g> + <g transform="translate(240,0)"> + <text transform="translate(250,-40) rotate(90)" style="direction:rtl;text-anchor:end"> + <tspan x="140" y="110">漢字!لكن لا بد أن漢字</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-201.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-201.svg new file mode 100644 index 0000000..5ab3213 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-inline-size-201.svg
@@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text in Shape — 201</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <html:link rel="match" href="text-inline-size-201-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <!-- Lorem ipsum dolor sit amet, consectetur adipisicing elit, --> + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;writing-mode:tb-rl"> + <g transform="translate(0,0)"> + <text x="140" y="100" style="inline-size:200px">漢字Lorem ipsum!漢字</text> + </g> + <g transform="translate(80,0)" style="text-orientation:sideways"> + <text x="140" y="100" style="inline-size:200px">漢字Lorem ipsum!漢字</text> + </g> + <g transform="translate(160,0)" style="text-orientation:sideways"> + <text x="140" y="100" style="inline-size:200px">漢字!لكن لا بد أن漢字</text> + </g> + <g transform="translate(240,0)" style="direction:rtl;text-orientation:sideways"> + <text x="140" y="100" style="inline-size:200px">漢字!لكن لا بد أن漢字</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-001-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-001-ref.svg new file mode 100644 index 0000000..9238a88 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-001-ref.svg
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Multiline — 001</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px;fill:black"> + <g transform="translate(0,0)"> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="240" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <text style="text-anchor:end"> + <tspan x="400" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="400" y="134.8">adipisicing elit,</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-001.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-001.svg new file mode 100644 index 0000000..1272f56b0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-001.svg
@@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Multiline — 001</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#TextLayoutPreMultiline"/> + <html:link rel="match" href="text-multiline-001-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="white-space: pre-line">Lorem ipsum dolor sit amet, consectetur +adipisicing elit,</text> + </g> + <g transform="translate(0,60)"> + <text x="240" y="114.8" style="white-space: pre-line;text-anchor:middle">Lorem ipsum dolor sit amet, consectetur +adipisicing elit,</text> + </g> + <g transform="translate(0,120)"> + <text x="400" y="114.8" style="white-space: pre-line;text-anchor:end">Lorem ipsum dolor sit amet, consectetur + adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-002-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-002-ref.svg new file mode 100644 index 0000000..5ba04b7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-002-ref.svg
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Multiline — 002</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px"> + <g transform="translate(0,0)"> + <text transform="translate(250,10) rotate(90)"> + <tspan x="90" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="90" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(80,0)"> + <text transform="translate(250,-40) rotate(90)" style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="240" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(160,0)"> + <text transform="translate(250,-90) rotate(90)" style="text-anchor:end"> + <tspan x="390" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="390" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-002.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-002.svg new file mode 100644 index 0000000..e109351 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-002.svg
@@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Multiline — 002</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#TextLayoutPreMultiline"/> + <html:link rel="match" href="text-multiline-002-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;writing-mode:tb-rl"> + <g transform="translate(0,0)"> + <text x="140" y="100" style="white-space: pre-line">Lorem ipsum dolor sit amet, +consectetur adipisicing elit,</text> + </g> + <g transform="translate(80,0)"> + <text x="140" y="200" style="white-space: pre-line;text-anchor:middle">Lorem ipsum dolor sit amet, +consectetur adipisicing elit,</text> + </g> + <g transform="translate(160,0)"> + <text x="140" y="300" style="white-space: pre-line;text-anchor:end">Lorem ipsum dolor sit amet, +consectetur adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-003-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-003-ref.svg new file mode 100644 index 0000000..cbfce51b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-003-ref.svg
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Multiline — 003</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-reference" style="font-size:16px;direction:rtl"> + <g transform="translate(0,0)"> + <text> + <tspan x="400" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="400" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="240" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <text style="text-anchor:end"> + <tspan x="80" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="80" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-003.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-003.svg new file mode 100644 index 0000000..e52bb7705 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/reftests/text-multiline-003.svg
@@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Multiline — 003</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#TextLayoutPreMultiline"/> + <html:link rel="match" href="text-multiline-003-ref.svg" /> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;direction:rtl"> + <g transform="translate(0,0)"> + <text x="400" y="114.8" style="white-space: pre-line">لكن لا بد أن أوضح لك أن كل هذه الأفكار +المغلوطة حول استنكار</text> + </g> + <g transform="translate(0,60)"> + <text x="240" y="114.8" style="white-space: pre-line;text-anchor:middle">لكن لا بد أن أوضح لك أن كل هذه الأفكار +المغلوطة حول استنكار</text> + </g> + <g transform="translate(0,120)"> + <text x="80" y="114.8" style="white-space: pre-line;text-anchor:end">لكن لا بد أن أوضح لك أن كل هذه الأفكار +المغلوطة حول استنكار</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-001-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-001-visual.svg new file mode 100644 index 0000000..086bab3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-001-visual.svg
@@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 001</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 80,100 0,40 m 320,-40 0,40"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 001</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;fill:red"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <circle cx="80" cy="114.8" r="1,0" style="fill:lightblue"/> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <circle cx="240" cy="114.8" r="1,0" style="fill:lightblue"/> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="240" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <circle cx="400" cy="114.8" r="1,0" style="fill:lightblue"/> + <text style="text-anchor:end"> + <tspan x="400" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="400" y="134.8">adipisicing elit,</tspan> + </text> + </g> + </g> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;fill:green"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,60)"> + <text x="240" y="114.8" style="inline-size:320px;text-anchor:middle">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,120)"> + <text x="400" y="114.8" style="inline-size:320px;text-anchor:end">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-002-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-002-visual.svg new file mode 100644 index 0000000..7f58973c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-002-visual.svg
@@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text in Shape — 002</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 110,100 40,0 m -40,200 40,0"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 002</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;fill:red"> + <g transform="translate(0,0)"> + <text transform="translate(250,10) rotate(90)"> + <tspan x="90" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="90" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(80,0)"> + <text transform="translate(250,-40) rotate(90)" style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="240" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(160,0)"> + <text transform="translate(250,-90) rotate(90)" style="text-anchor:end"> + <tspan x="390" y="114.8">Lorem ipsum dolor sit amet,</tspan> + <tspan x="390" y="134.8">consectetur adipisicing elit,</tspan> + </text> + </g> + </g> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;writing-mode:tb-rl;fill:green"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text x="140" y="100" style="inline-size:200px">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(80,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text x="140" y="200" style="inline-size:200px;text-anchor:middle">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(160,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text x="140" y="300" style="inline-size:200px;text-anchor:end">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-003-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-003-visual.svg new file mode 100644 index 0000000..19bf0dc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-003-visual.svg
@@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 003</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 80,100 0,40 m 320,-40 0,40"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 003</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;direction:rtl;fill:red"> + <g transform="translate(0,0)"> + <text> + <tspan x="400" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="400" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="240" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <text style="text-anchor:end"> + <tspan x="80" y="114.8">لكن لا بد أن أوضح لك أن كل هذه الأفكار</tspan> + <tspan x="80" y="134.8">المغلوطة حول استنكار</tspan> + </text> + </g> + </g> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;direction:rtl;fill:green"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text x="400" y="114.8" style="inline-size:320px">لكن لا بد أن أوضح لك أن كل هذه الأفكار المغلوطة حول استنكار</text> + </g> + <g transform="translate(0,60)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text x="240" y="114.8" style="inline-size:320px;text-anchor:middle">لكن لا بد أن أوضح لك أن كل هذه الأفكار المغلوطة حول استنكار</text> + </g> + <g transform="translate(0,120)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text x="80" y="114.8" style="inline-size:320px;text-anchor:end">لكن لا بد أن أوضح لك أن كل هذه الأفكار المغلوطة حول استنكار</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-005-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-005-visual.svg new file mode 100644 index 0000000..dab467e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-005-visual.svg
@@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 005</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 80,100 0,160 m 320,-160 0,160"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 005</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;fill:#ffeeee"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="149.6">adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor</tspan> + <tspan x="80" y="174.8">incididunt ut labore et dolore magna aliqua. Ut</tspan> + <tspan x="80" y="209.6">enim ad minim veniam, <tspan style="font-size:32px">quis</tspan> nostrud</tspan> + <tspan x="80" y="234.8">exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea</tspan> + <tspan x="80" y="254.8">commodo consequat.</tspan> + </text> + </g> + </g> + + <g id="test-body-content" style="font-size:16px;line-height:1.25;fill:green"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px" xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, <tspan style="font-size:2em">quis</tspan> nostrud exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea commodo consequat.</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-006-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-006-visual.svg new file mode 100644 index 0000000..427ff09 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-006-visual.svg
@@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 006</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 80,100 0,160 m 320,-160 0,160"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 006</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;fill:red"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="134.8">adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor</tspan> + <tspan x="80" y="154.8">incididunt ut labore et dolore magna aliqua. Ut</tspan> + <tspan x="80" y="174.8">enim ad minim veniam, <tspan style="font-size:32px">quis</tspan> nostrud</tspan> + <tspan x="80" y="194.8">exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea</tspan> + <tspan x="80" y="214.8">commodo consequat.</tspan> + </text> + </g> + </g> + + <g id="test-body-content" style="font-size:16px;line-height:1.25;fill:green"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px">Lorem ipsum dolor sit amet, consectetur adipiscing <tspan style="font-size:32px;line-height:0">elit</tspan>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, <tspan style="font-size:2em;line-height:0">quis</tspan> nostrud exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea commodo consequat.</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-007-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-007-visual.svg new file mode 100644 index 0000000..8bb078f9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-007-visual.svg
@@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 006</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 80,100 0,160 m 320,-160 0,160"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 007</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;fill:red"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="139.6">adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor</tspan> + <tspan x="80" y="159.6">incididunt ut labore et dolore magna aliqua. Ut</tspan> + <tspan x="80" y="184.4">enim ad minim veniam, <tspan style="font-size:32px">quis</tspan> nostrud</tspan> + <tspan x="80" y="204.4">exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea</tspan> + <tspan x="80" y="226.8">commodo consequat.</tspan> + </text> + </g> + </g> + + <g id="test-body-content" style="font-size:16px;fill:green"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:320px;line-height:20px">Lorem ipsum dolor sit amet, consectetur adipiscing <tspan style="font-size:32px">elit</tspan>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, <tspan style="font-size:2em">quis</tspan> nostrud exercitation ullamco laboris <tspan style="font-size:8px">nisi</tspan> ut aliquip ex ea commodo consequat.</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-101-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-101-visual.svg new file mode 100644 index 0000000..e1c5c416 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-101-visual.svg
@@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text: Inline Size — 101</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 80,100 0,40 m 320,-40 0,40"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 101</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;fill:red"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text> + <tspan x="80" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="80" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,60)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text style="text-anchor:middle"> + <tspan x="240" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="240" y="134.8">adipisicing elit,</tspan> + </text> + </g> + <g transform="translate(0,120)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text style="text-anchor:end"> + <tspan x="400" y="114.8">Lorem ipsum dolor sit amet, consectetur</tspan> + <tspan x="400" y="134.8">adipisicing elit,</tspan> + </text> + </g> + </g> + + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;fill:green"> + <g transform="translate(0,0)"> + <text x="80" y="114.8" style="inline-size:66.66667%">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,60)"> + <text x="240" y="114.8" style="inline-size:66.66667%;text-anchor:middle">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + <g transform="translate(0,120)"> + <text x="400" y="114.8" style="inline-size:66.66667%;text-anchor:end">Lorem ipsum dolor sit amet, consectetur adipisicing elit,</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-201-visual.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-201-visual.svg new file mode 100644 index 0000000..f2649ea --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/text/visualtests/text-inline-size-201-visual.svg
@@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg id="svg-root" + width="100%" height="100%" viewBox="0 0 480 360" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Text in Shape — 201</title> + <html:link rel="author" + title="Tavmjong Bah" + href="mailto:tavmjong@free.fr"/> + <html:link rel="reviewer" + title="NAME_OF_REVIEWER" + href="mailto:EMAIL OR http://CONTACT_PAGE" /> + <!-- YYYY-MM-DD --> + <html:link rel="help" + href="https://svgwg.org/svg2-draft/text.html#InlineSize"/> + <metadata class="flags">TOKENS</metadata> + <desc class="assert">TEST ASSERTION</desc> + </g> + + <style id="test-font" type="text/css"> + /* Standard Font (if needed). */ + @font-face { + font-family: FreeSans; + src: url("fonts/FreeSans.woff") format("woff"), + local("FreeSans"); + } + text { font-family: FreeSans, sans-serif } + </style> + + <style id="test-style" type="text/css"> + /* Style that is being tested (if needed). */ + text { font-family: FreeSans, sans-serif } + </style> + + <defs> + <path id="TestPath" d="m 110,100 40,0 m -40,200 40,0"/> + </defs> + + <text id="title" x="240" y="50" style="fill:black; font-size:24px; text-anchor:middle;">Text 'inline-size' — 201</text> + <a href="https://svgwg.org/svg2-draft/text.html#InlineSize"> + <text id="source" x="240" y="70" style="fill:black; font-size:12px; text-anchor:middle;">https://svgwg.org/svg2-draft/text.html#InlineSize</text> + </a> + + <g id="test-body-reference" style="font-size:16px;fill:red"> + <g transform="translate(0,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text style="writing-mode:tb-rl"> + <tspan x="140" y="100">漢字</tspan> + <tspan x="140" y="132">Lorem ipsum</tspan> + <tspan x="140" y="227.7">漢字</tspan> + </text> + </g> + <g transform="translate(80,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text transform="translate(250,-40) rotate(90)"> + <tspan x="140" y="110">漢字Lorem ipsum!漢字</tspan> + </text> + </g> + <g transform="translate(160,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text transform="translate(250,-40) rotate(90)"> + <tspan x="140" y="110">漢字!لكن لا بد أن漢字</tspan> + </text> + </g> + <g transform="translate(240,0)"> + <use xlink:href="#TestPath" style="fill:none;stroke:lightblue"/> + <text transform="translate(250,-40) rotate(90)" style="direction:rtl;text-anchor:end"> + <tspan x="140" y="110">漢字!لكن لا بد أن漢字</tspan> + </text> + </g> + </g> + + <!-- Lorem ipsum dolor sit amet, consectetur adipisicing elit, --> + <g id="test-body-content" style="font-size:16px;line-spacing:1.25;writing-mode:tb-rl;fill:green"> + <g transform="translate(0,0)"> + <text x="140" y="100" style="inline-size:200px">漢字Lorem ipsum!漢字</text> + </g> + <g transform="translate(80,0)" style="text-orientation:sideways"> + <text x="140" y="100" style="inline-size:200px">漢字Lorem ipsum!漢字</text> + </g> + <g transform="translate(160,0)" style="text-orientation:sideways"> + <text x="140" y="100" style="inline-size:200px">漢字!لكن لا بد أن漢字</text> + </g> + <g transform="translate(240,0)" style="direction:rtl;text-orientation:sideways"> + <text x="140" y="100" style="inline-size:200px">漢字!لكن لا بد أن漢字</text> + </g> + </g> + +</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events-expected.txt new file mode 100644 index 0000000..e60970b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events-expected.txt
@@ -0,0 +1,15 @@ +This is a testharness.js-based test. +FAIL oncut: DocumentAndElementEventHandlers must be on SVGElement not Element assert_true: SVGElement has an own property named "oncut" expected true got false +PASS oncut: the default value must be null +PASS oncut: the content attribute must be compiled into a function as the corresponding property +PASS oncut: the content attribute must execute when an event is dispatched +FAIL oncopy: DocumentAndElementEventHandlers must be on SVGElement not Element assert_true: SVGElement has an own property named "oncopy" expected true got false +PASS oncopy: the default value must be null +PASS oncopy: the content attribute must be compiled into a function as the corresponding property +PASS oncopy: the content attribute must execute when an event is dispatched +FAIL onpaste: DocumentAndElementEventHandlers must be on SVGElement not Element assert_true: SVGElement has an own property named "onpaste" expected true got false +PASS onpaste: the default value must be null +PASS onpaste: the content attribute must be compiled into a function as the corresponding property +PASS onpaste: the content attribute must execute when an event is dispatched +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events.svg new file mode 100644 index 0000000..fa813dd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/svg/types/scripted/event-handler-all-document-element-events.svg
@@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml"> + <title>DocumentAndElementEventHandlers</title> + <metadata> + <h:link rel="help" href="https://svgwg.org/svg2-draft/types.html#InterfaceSVGElement"/> + </metadata> + <h:script src="/resources/testharness.js"/> + <h:script src="/resources/testharnessreport.js"/> + <script><![CDATA[ + "use strict"; + setup({ explicit_done: true }); + + const names = ["oncut","oncopy","onpaste"]; + + for (const name of names) { + const withoutOn = name.substring(2); + + test(() => { + assert_true(SVGElement.prototype.hasOwnProperty(name), + `${SVGElement.prototype.constructor.name} has an own property named "${name}"`); + assert_false(name in Element.prototype, `Element.prototype must not contain a "${name}" property`); + }, `${name}: DocumentAndElementEventHandlers must be on SVGElement not Element`); + + test(() => { + const svgElement = document.createElementNS("http://www.w3.org/2000/svg", "g"); + + assert_equals(svgElement[name], null, + `The default value of the property is null for a ${svgElement.constructor.name} instance`); + }, `${name}: the default value must be null`); + + test(() => { + const el = document.createElementNS("http://www.w3.org/2000/svg", "g"); + el.setAttribute(name, `window.${name}Happened = true;`); + const compiledHandler = el[name]; + + assert_equals(typeof compiledHandler, "function", `The ${name} property must be a function`); + compiledHandler(); + assert_true(window[name + "Happened"], "Calling the handler must run the code"); + }, `${name}: the content attribute must be compiled into a function as the corresponding property`); + + test(() => { + const el = document.createElementNS("http://www.w3.org/2000/svg", "g"); + el.setAttribute(name, `window.${name}Happened2 = true;`); + + el.dispatchEvent(new Event(withoutOn)); + + assert_true(window[name + "Happened2"], "Dispatching an event must run the code"); + }, `${name}: the content attribute must execute when an event is dispatched`); + } + + done(); + ]]></script> +</svg> +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/assertions.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/assertions.js new file mode 100644 index 0000000..151a406 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/assertions.js
@@ -0,0 +1,17 @@ +function assert_function_name(fn, name, description) { + const propdesc = Object.getOwnPropertyDescriptor(fn, "name"); + assert_equals(typeof propdesc, "object", `${description} should have name property`); + assert_false(propdesc.writable, "writable", `${description} name should not be writable`); + assert_false(propdesc.enumerable, "enumerable", `${description} name should not be enumerable`); + assert_true(propdesc.configurable, "configurable", `${description} name should be configurable`); + assert_equals(propdesc.value, name, `${description} name should be ${name}`); +} + +function assert_function_length(fn, length, description) { + const propdesc = Object.getOwnPropertyDescriptor(fn, "length"); + assert_equals(typeof propdesc, "object", `${description} should have length property`); + assert_false(propdesc.writable, "writable", `${description} length should not be writable`); + assert_false(propdesc.enumerable, "enumerable", `${description} length should not be enumerable`); + assert_true(propdesc.configurable, "configurable", `${description} length should be configurable`); + assert_equals(propdesc.value, length, `${description} length should be ${length}`); +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/bad-imports.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/bad-imports.js new file mode 100644 index 0000000..f076baa --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/bad-imports.js
@@ -0,0 +1,140 @@ +function test_bad_imports(t) { + for (const value of [null, true, "", Symbol(), 1, 0.1, NaN]) { + t(`Non-object imports argument: ${format_value(value)}`, + new TypeError(), + builder => {}, + value); + } + + for (const value of [undefined, null, true, "", Symbol(), 1, 0.1, NaN]) { + const imports = { + "module": value, + }; + t(`Non-object module: ${format_value(value)}`, + new TypeError(), + builder => { + builder.addImport("module", "fn", kSig_v_v); + }, + value); + } + + t(`Missing imports argument`, + new TypeError(), + builder => { + builder.addImport("module", "fn", kSig_v_v); + }); + + for (const [value, name] of [[undefined, "undefined"], [{}, "empty object"], [{ "module\0": null }, "wrong property"]]) { + t(`Imports argument with missing property: ${name}`, + new TypeError(), + builder => { + builder.addImport("module", "fn", kSig_v_v); + }, + value); + } + + t(`Importing an i64 global`, + new WebAssembly.LinkError(), + builder => { + builder.addImportedGlobal("module", "global", kWasmI64); + }, + { + "module": { + "global": 0, + }, + }); + + for (const value of [undefined, null, true, "", Symbol(), 1, 0.1, NaN, {}]) { + t(`Importing a function with an incorrectly-typed value: ${format_value(value)}`, + new WebAssembly.LinkError(), + builder => { + builder.addImport("module", "fn", kSig_v_v); + }, + { + "module": { + "fn": value, + }, + }); + } + + const nonGlobals = [ + [undefined], + [null], + [true], + [""], + [Symbol()], + [{}, "plain object"], + [WebAssembly.Global, "WebAssembly.Global"], + [WebAssembly.Global.prototype, "WebAssembly.Global.prototype"], + [Object.create(WebAssembly.Global.prototype), "Object.create(WebAssembly.Global.prototype)"], + ]; + + for (const [value, name = format_value(value)] of nonGlobals) { + t(`Importing a global with an incorrectly-typed value: ${name}`, + new WebAssembly.LinkError(), + builder => { + builder.addImportedGlobal("module", "global", kWasmI32); + }, + { + "module": { + "global": value, + }, + }); + } + + const nonMemories = [ + [undefined], + [null], + [true], + [""], + [Symbol()], + [1], + [0.1], + [NaN], + [{}, "plain object"], + [WebAssembly.Memory, "WebAssembly.Memory"], + [WebAssembly.Memory.prototype, "WebAssembly.Memory.prototype"], + [Object.create(WebAssembly.Memory.prototype), "Object.create(WebAssembly.Memory.prototype)"], + ]; + + for (const [value, name = format_value(value)] of nonMemories) { + t(`Importing memory with an incorrectly-typed value: ${name}`, + new WebAssembly.LinkError(), + builder => { + builder.addImportedMemory("module", "memory", 0, 128); + }, + { + "module": { + "memory": value, + }, + }); + } + + const nonTables = [ + [undefined], + [null], + [true], + [""], + [Symbol()], + [1], + [0.1], + [NaN], + [{}, "plain object"], + [WebAssembly.Table, "WebAssembly.Table"], + [WebAssembly.Table.prototype, "WebAssembly.Table.prototype"], + [Object.create(WebAssembly.Table.prototype), "Object.create(WebAssembly.Table.prototype)"], + ]; + + for (const [value, name = format_value(value)] of nonTables) { + t(`Importing table with an incorrectly-typed value: ${name}`, + new WebAssembly.LinkError(), + builder => { + builder.addImportedTable("module", "table", 0, 128); + }, + { + "module": { + "table": value, + }, + }); + } +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/constructor/instantiate-bad-imports.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/constructor/instantiate-bad-imports.any.js new file mode 100644 index 0000000..8670029 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/constructor/instantiate-bad-imports.any.js
@@ -0,0 +1,23 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js +// META: script=/wasm/jsapi/bad-imports.js + +test_bad_imports((name, error, build, ...arguments) => { + promise_test(t => { + const builder = new WasmModuleBuilder(); + build(builder); + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + return promise_rejects(t, error, WebAssembly.instantiate(module, ...arguments)); + }, `WebAssembly.instantiate(module): ${name}`); +}); + +test_bad_imports((name, error, build, ...arguments) => { + promise_test(t => { + const builder = new WasmModuleBuilder(); + build(builder); + const buffer = builder.toBuffer(); + return promise_rejects(t, error, WebAssembly.instantiate(buffer, ...arguments)); + }, `WebAssembly.instantiate(buffer): ${name}`); +});
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/instance/constructor-bad-imports.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/instance/constructor-bad-imports.any.js new file mode 100644 index 0000000..24c51c1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/instance/constructor-bad-imports.any.js
@@ -0,0 +1,14 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js +// META: script=/wasm/jsapi/bad-imports.js + +test_bad_imports((name, error, build, ...arguments) => { + test(() => { + const builder = new WasmModuleBuilder(); + build(builder); + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + assert_throws(error, () => new WebAssembly.Instance(module, ...arguments)); + }, `new WebAssembly.Instance(module): ${name}`); +});
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/instance/constructor.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/instance/constructor.any.js new file mode 100644 index 0000000..93a3ffda --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/instance/constructor.any.js
@@ -0,0 +1,193 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js +// META: script=/wasm/jsapi/assertions.js + +function assert_exported_function(fn, { name, length }, description) { + assert_equals(Object.getPrototypeOf(fn), Function.prototype, + `${description}: prototype`); + + assert_function_name(fn, name, description); + assert_function_length(fn, length, description); +} + +function assert_Instance(instance, expected_exports) { + assert_equals(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype, + "prototype"); + assert_true(Object.isExtensible(instance), "extensible"); + + assert_equals(instance.exports, instance.exports, "exports should be idempotent"); + const exports = instance.exports; + + assert_equals(Object.getPrototypeOf(exports), null, "exports prototype"); + assert_false(Object.isExtensible(exports), "extensible exports"); + for (const [key, expected] of Object.entries(expected_exports)) { + const property = Object.getOwnPropertyDescriptor(exports, key); + assert_equals(typeof property, "object", `${key} should be present`); + assert_false(property.writable, `${key}: writable`); + assert_true(property.enumerable, `${key}: enumerable`); + assert_false(property.configurable, `${key}: configurable`); + const actual = property.value; + + switch (expected.kind) { + case "function": + assert_exported_function(actual, expected, `value of ${key}`); + break; + case "global": + assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype, + `value of ${key}: prototype`); + assert_equals(actual.value, expected.value, `value of ${key}: value`); + assert_equals(actual.valueOf(), expected.value, `value of ${key}: valueOf()`); + break; + case "memory": + assert_equals(Object.getPrototypeOf(actual), WebAssembly.Memory.prototype, + `value of ${key}: prototype`); + assert_equals(Object.getPrototypeOf(actual.buffer), ArrayBuffer.prototype, + `value of ${key}: prototype of buffer`); + assert_equals(actual.buffer.byteLength, 0x10000 * expected.size, `value of ${key}: size of buffer`); + const array = new Uint8Array(actual.buffer); + assert_equals(array[0], 0, `value of ${key}: first element of buffer`); + assert_equals(array[array.byteLength - 1], 0, `value of ${key}: last element of buffer`); + break; + case "table": + assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype, + `value of ${key}: prototype`); + assert_equals(actual.length, expected.length, `value of ${key}: length of table`); + break; + } + } +} + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_function_name(WebAssembly.Instance, "Instance", "WebAssembly.Instance"); +}, "name"); + +test(() => { + assert_function_length(WebAssembly.Instance, 1, "WebAssembly.Instance"); +}, "length"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Instance()); +}, "No arguments"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + assert_throws(new TypeError(), () => WebAssembly.Instance(module)); +}, "Calling"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const arguments = [ + [], + [undefined], + [{}], + ]; + for (const value of arguments) { + const instance = new WebAssembly.Instance(module, ...arguments); + assert_Instance(instance, {}); + } +}, "Empty module"); + +test(() => { + const builder = new WasmModuleBuilder(); + builder.addImportedGlobal("module", "global1", kWasmI32); + builder.addImportedGlobal("module", "global2", kWasmI32); + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + const order = []; + const imports = { + get module() { + order.push("module getter"); + return { + get global1() { + order.push("global1 getter"); + return 0; + }, + get global2() { + order.push("global2 getter"); + return 0; + }, + } + }, + }; + new WebAssembly.Instance(module, imports); + const expected = [ + "module getter", + "global1 getter", + "module getter", + "global2 getter", + ]; + assert_array_equals(order, expected); +}, "getter order for imports object"); + +test(() => { + const builder = new WasmModuleBuilder(); + + builder.addImport("module", "fn", kSig_v_v); + builder.addImportedGlobal("module", "global", kWasmI32); + builder.addImportedMemory("module", "memory", 0, 128); + builder.addImportedTable("module", "table", 0, 128); + + const buffer = builder.toBuffer(); + const module = new WebAssembly.Module(buffer); + const instance = new WebAssembly.Instance(module, { + "module": { + "fn": function() {}, + "global": 0, + "memory": new WebAssembly.Memory({ "initial": 64, maximum: 128 }), + "table": new WebAssembly.Table({ "element": "anyfunc", "initial": 64, maximum: 128 }), + }, + get "module2"() { + assert_unreached("Should not get modules that are not imported"); + }, + }); + assert_Instance(instance, {}); +}, "imports"); + +test(() => { + const builder = new WasmModuleBuilder(); + + builder + .addFunction("fn", kSig_v_d) + .addBody([ + kExprEnd + ]) + .exportFunc(); + builder + .addFunction("fn2", kSig_v_v) + .addBody([ + kExprEnd + ]) + .exportFunc(); + + builder.setFunctionTableLength(1); + builder.addExportOfKind("table", kExternalTable, 0); + + builder.addGlobal(kWasmI32, true) + .exportAs("global") + .init = 7; + builder.addGlobal(kWasmF64, true) + .exportAs("global2") + .init = 1.2; + + builder.addMemory(4, 8, true); + + const buffer = builder.toBuffer() + const module = new WebAssembly.Module(buffer); + + const instance = new WebAssembly.Instance(module, {}); + const expected = { + "fn": { "kind": "function", "name": "0", "length": 1 }, + "fn2": { "kind": "function", "name": "1", "length": 0 }, + "table": { "kind": "table", "length": 1 }, + "global": { "kind": "global", "value": 7 }, + "global2": { "kind": "global", "value": 1.2 }, + "memory": { "kind": "memory", "size": 4 }, + }; + assert_Instance(instance, expected); +}, "exports");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any-expected.txt new file mode 100644 index 0000000..5fdc3310 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any-expected.txt
@@ -0,0 +1,67 @@ +This is a testharness.js-based test. +Found 63 tests; 48 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS WebAssembly: property descriptor +PASS WebAssembly: constructing +PASS WebAssembly.Module: property descriptor +PASS WebAssembly.Module: prototype +PASS WebAssembly.Instance: property descriptor +PASS WebAssembly.Instance: prototype +PASS WebAssembly.Memory: property descriptor +PASS WebAssembly.Memory: prototype +PASS WebAssembly.Table: property descriptor +PASS WebAssembly.Table: prototype +PASS WebAssembly.Global: property descriptor +PASS WebAssembly.Global: prototype +PASS WebAssembly.CompileError: property descriptor +PASS WebAssembly.CompileError: prototype +PASS WebAssembly.LinkError: property descriptor +PASS WebAssembly.LinkError: prototype +PASS WebAssembly.RuntimeError: property descriptor +PASS WebAssembly.RuntimeError: prototype +FAIL WebAssembly.validate assert_true: enumerable expected true got false +PASS WebAssembly.validate: name +PASS WebAssembly.validate: length +FAIL WebAssembly.compile assert_true: enumerable expected true got false +PASS WebAssembly.compile: name +PASS WebAssembly.compile: length +FAIL WebAssembly.instantiate assert_true: enumerable expected true got false +PASS WebAssembly.instantiate: name +PASS WebAssembly.instantiate: length +FAIL WebAssembly.Module.exports assert_true: enumerable expected true got false +PASS WebAssembly.Module.exports: name +PASS WebAssembly.Module.exports: length +FAIL WebAssembly.Module.imports assert_true: enumerable expected true got false +PASS WebAssembly.Module.imports: name +PASS WebAssembly.Module.imports: length +FAIL WebAssembly.Module.customSections assert_true: enumerable expected true got false +PASS WebAssembly.Module.customSections: name +PASS WebAssembly.Module.customSections: length +FAIL WebAssembly.Instance.exports assert_true: enumerable expected true got false +PASS WebAssembly.Instance.exports: getter +PASS WebAssembly.Instance.exports: setter +FAIL WebAssembly.Memory.grow assert_true: enumerable expected true got false +PASS WebAssembly.Memory.grow: name +PASS WebAssembly.Memory.grow: length +FAIL WebAssembly.Memory.buffer assert_true: enumerable expected true got false +PASS WebAssembly.Memory.buffer: getter +PASS WebAssembly.Memory.buffer: setter +FAIL WebAssembly.Table.grow assert_true: enumerable expected true got false +PASS WebAssembly.Table.grow: name +PASS WebAssembly.Table.grow: length +FAIL WebAssembly.Table.get assert_true: enumerable expected true got false +PASS WebAssembly.Table.get: name +PASS WebAssembly.Table.get: length +FAIL WebAssembly.Table.set assert_true: enumerable expected true got false +PASS WebAssembly.Table.set: name +PASS WebAssembly.Table.set: length +FAIL WebAssembly.Table.length assert_true: enumerable expected true got false +PASS WebAssembly.Table.length: getter +PASS WebAssembly.Table.length: setter +FAIL WebAssembly.Global.valueOf assert_true: enumerable expected true got false +PASS WebAssembly.Global.valueOf: name +PASS WebAssembly.Global.valueOf: length +FAIL WebAssembly.Global.value assert_true: enumerable expected true got false +PASS WebAssembly.Global.value: getter +PASS WebAssembly.Global.value: setter +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any.js new file mode 100644 index 0000000..64c1f60d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any.js
@@ -0,0 +1,147 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/assertions.js + +function test_operations(object, object_name, operations) { + for (const [name, length] of operations) { + test(() => { + const propdesc = Object.getOwnPropertyDescriptor(object, name); + assert_equals(typeof propdesc, "object"); + assert_true(propdesc.writable, "writable"); + assert_true(propdesc.enumerable, "enumerable"); + assert_true(propdesc.configurable, "configurable"); + assert_equals(propdesc.value, WebAssembly[name]); + }, `${object_name}.${name}`); + + test(() => { + assert_function_name(object[name], name, `${object_name}.${name}`); + }, `${object_name}.${name}: name`); + + test(() => { + assert_function_length(object[name], length, `${object_name}.${name}`); + }, `${object_name}.${name}: length`); + } +} + +function test_attributes(object, object_name, attributes) { + for (const [name, mutable] of attributes) { + test(() => { + const propdesc = Object.getOwnPropertyDescriptor(object, name); + assert_equals(typeof propdesc, "object"); + assert_true(propdesc.enumerable, "enumerable"); + assert_true(propdesc.configurable, "configurable"); + }, `${object_name}.${name}`); + + test(() => { + const propdesc = Object.getOwnPropertyDescriptor(object, name); + assert_equals(typeof propdesc, "object"); + assert_equals(typeof propdesc.get, "function"); + assert_function_name(propdesc.get, "get " + name, `getter for "${name}"`); + assert_function_length(propdesc.get, 0, `getter for "${name}"`); + }, `${object_name}.${name}: getter`); + + test(() => { + const propdesc = Object.getOwnPropertyDescriptor(object, name); + assert_equals(typeof propdesc, "object"); + if (mutable) { + assert_equals(typeof propdesc.set, "function"); + assert_function_name(propdesc.set, "set " + name, `setter for "${name}"`); + assert_function_length(propdesc.set, 1, `setter for "${name}"`); + } else { + assert_equals(typeof propdesc.set, "undefined"); + } + }, `${object_name}.${name}: setter`); + } +} + +test(() => { + const propdesc = Object.getOwnPropertyDescriptor(this, "WebAssembly"); + assert_equals(typeof propdesc, "object"); + assert_true(propdesc.writable, "writable"); + assert_false(propdesc.enumerable, "enumerable"); + assert_true(propdesc.configurable, "configurable"); + assert_equals(propdesc.value, this.WebAssembly); +}, "WebAssembly: property descriptor"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly()); +}, "WebAssembly: constructing"); + +const interfaces = [ + "Module", + "Instance", + "Memory", + "Table", + "Global", + "CompileError", + "LinkError", + "RuntimeError", +]; + +for (const name of interfaces) { + test(() => { + const propdesc = Object.getOwnPropertyDescriptor(WebAssembly, name); + assert_equals(typeof propdesc, "object"); + assert_true(propdesc.writable, "writable"); + assert_false(propdesc.enumerable, "enumerable"); + assert_true(propdesc.configurable, "configurable"); + assert_equals(propdesc.value, WebAssembly[name]); + }, `WebAssembly.${name}: property descriptor`); + + test(() => { + const interface_object = WebAssembly[name]; + const interface_prototype_object = interface_object.prototype; + const propdesc = Object.getOwnPropertyDescriptor(interface_prototype_object, "constructor"); + assert_equals(typeof propdesc, "object"); + assert_true(propdesc.writable, "writable"); + assert_false(propdesc.enumerable, "enumerable"); + assert_true(propdesc.configurable, "configurable"); + assert_equals(propdesc.value, interface_object); + }, `WebAssembly.${name}: prototype`); +} + +test_operations(WebAssembly, "WebAssembly", [ + ["validate", 1], + ["compile", 1], + ["instantiate", 1], +]); + + +test_operations(WebAssembly.Module, "WebAssembly.Module", [ + ["exports", 1], + ["imports", 1], + ["customSections", 2], +]); + + +test_attributes(WebAssembly.Instance.prototype, "WebAssembly.Instance", [ + ["exports", false], +]); + + +test_operations(WebAssembly.Memory.prototype, "WebAssembly.Memory", [ + ["grow", 1], +]); + +test_attributes(WebAssembly.Memory.prototype, "WebAssembly.Memory", [ + ["buffer", false], +]); + + +test_operations(WebAssembly.Table.prototype, "WebAssembly.Table", [ + ["grow", 1], + ["get", 1], + ["set", 2], +]); + +test_attributes(WebAssembly.Table.prototype, "WebAssembly.Table", [ + ["length", false], +]); + + +test_operations(WebAssembly.Global.prototype, "WebAssembly.Global", [ + ["valueOf", 0], +]); + +test_attributes(WebAssembly.Global.prototype, "WebAssembly.Global", [ + ["value", true], +]);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any.worker-expected.txt new file mode 100644 index 0000000..5fdc3310 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/interface.any.worker-expected.txt
@@ -0,0 +1,67 @@ +This is a testharness.js-based test. +Found 63 tests; 48 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS WebAssembly: property descriptor +PASS WebAssembly: constructing +PASS WebAssembly.Module: property descriptor +PASS WebAssembly.Module: prototype +PASS WebAssembly.Instance: property descriptor +PASS WebAssembly.Instance: prototype +PASS WebAssembly.Memory: property descriptor +PASS WebAssembly.Memory: prototype +PASS WebAssembly.Table: property descriptor +PASS WebAssembly.Table: prototype +PASS WebAssembly.Global: property descriptor +PASS WebAssembly.Global: prototype +PASS WebAssembly.CompileError: property descriptor +PASS WebAssembly.CompileError: prototype +PASS WebAssembly.LinkError: property descriptor +PASS WebAssembly.LinkError: prototype +PASS WebAssembly.RuntimeError: property descriptor +PASS WebAssembly.RuntimeError: prototype +FAIL WebAssembly.validate assert_true: enumerable expected true got false +PASS WebAssembly.validate: name +PASS WebAssembly.validate: length +FAIL WebAssembly.compile assert_true: enumerable expected true got false +PASS WebAssembly.compile: name +PASS WebAssembly.compile: length +FAIL WebAssembly.instantiate assert_true: enumerable expected true got false +PASS WebAssembly.instantiate: name +PASS WebAssembly.instantiate: length +FAIL WebAssembly.Module.exports assert_true: enumerable expected true got false +PASS WebAssembly.Module.exports: name +PASS WebAssembly.Module.exports: length +FAIL WebAssembly.Module.imports assert_true: enumerable expected true got false +PASS WebAssembly.Module.imports: name +PASS WebAssembly.Module.imports: length +FAIL WebAssembly.Module.customSections assert_true: enumerable expected true got false +PASS WebAssembly.Module.customSections: name +PASS WebAssembly.Module.customSections: length +FAIL WebAssembly.Instance.exports assert_true: enumerable expected true got false +PASS WebAssembly.Instance.exports: getter +PASS WebAssembly.Instance.exports: setter +FAIL WebAssembly.Memory.grow assert_true: enumerable expected true got false +PASS WebAssembly.Memory.grow: name +PASS WebAssembly.Memory.grow: length +FAIL WebAssembly.Memory.buffer assert_true: enumerable expected true got false +PASS WebAssembly.Memory.buffer: getter +PASS WebAssembly.Memory.buffer: setter +FAIL WebAssembly.Table.grow assert_true: enumerable expected true got false +PASS WebAssembly.Table.grow: name +PASS WebAssembly.Table.grow: length +FAIL WebAssembly.Table.get assert_true: enumerable expected true got false +PASS WebAssembly.Table.get: name +PASS WebAssembly.Table.get: length +FAIL WebAssembly.Table.set assert_true: enumerable expected true got false +PASS WebAssembly.Table.set: name +PASS WebAssembly.Table.set: length +FAIL WebAssembly.Table.length assert_true: enumerable expected true got false +PASS WebAssembly.Table.length: getter +PASS WebAssembly.Table.length: setter +FAIL WebAssembly.Global.valueOf assert_true: enumerable expected true got false +PASS WebAssembly.Global.valueOf: name +PASS WebAssembly.Global.valueOf: length +FAIL WebAssembly.Global.value assert_true: enumerable expected true got false +PASS WebAssembly.Global.value: getter +PASS WebAssembly.Global.value: setter +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any-expected.txt new file mode 100644 index 0000000..884d6700 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any-expected.txt
@@ -0,0 +1,23 @@ +This is a testharness.js-based test. +PASS name +PASS length +PASS No arguments +PASS Calling +FAIL Empty descriptor assert_throws: function "() => new WebAssembly.Memory({})" did not throw +FAIL Undefined initial value in descriptor assert_throws: function "() => new WebAssembly.Memory({ "initial": undefined })" did not throw +FAIL Out-of-range initial value in descriptor: NaN assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" did not throw +FAIL Out-of-range maximum value in descriptor: NaN assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" did not throw +FAIL Out-of-range initial value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value 9223372036854775807 is above the upper bound 32767" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value 9223372036854775807 is above the upper bound 65536" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -1 assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -1 assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value 4294967296 is above the upper bound 32767" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value 4294967296 is above the upper bound 65536" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value 68719476736 is above the upper bound 32767" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value 68719476736 is above the upper bound 65536" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Proxy descriptor assert_unreached: Should not call [[HasProperty]] with maximum Reached unreachable code +PASS Prototype +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any.js new file mode 100644 index 0000000..33256f8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any.js
@@ -0,0 +1,71 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js +// META: script=/wasm/jsapi/assertions.js + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_function_name(WebAssembly.Memory, "Memory", "WebAssembly.Memory"); +}, "name"); + +test(() => { + assert_function_length(WebAssembly.Memory, 1, "WebAssembly.Memory"); +}, "length"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Memory()); +}, "No arguments"); + +test(() => { + const argument = { "initial": 0 }; + assert_throws(new TypeError(), () => WebAssembly.Memory(argument)); +}, "Calling"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Memory({})); +}, "Empty descriptor"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Memory({ "initial": undefined })); +}, "Undefined initial value in descriptor"); + +const outOfRangeValues = [ + NaN, + Infinity, + -Infinity, + -1, + 0x100000000, + 0x1000000000, +]; + +for (const value of outOfRangeValues) { + test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Memory({ "initial": value })); + }, `Out-of-range initial value in descriptor: ${format_value(value)}`); + + test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Memory({ "initial": 0, "maximum": value })); + }, `Out-of-range maximum value in descriptor: ${format_value(value)}`); +} + +test(() => { + const proxy = new Proxy({}, { + has(o, x) { + assert_unreached(`Should not call [[HasProperty]] with ${x}`); + }, + get(o, x) { + return 0; + }, + }); + new WebAssembly.Memory(proxy); +}, "Proxy descriptor"); + +test(() => { + const argument = { "initial": 0 }; + const memory = new WebAssembly.Memory(argument); + assert_equals(Object.getPrototypeOf(memory), WebAssembly.Memory.prototype); +}, "Prototype");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any.worker-expected.txt new file mode 100644 index 0000000..884d6700 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/memory/constructor.any.worker-expected.txt
@@ -0,0 +1,23 @@ +This is a testharness.js-based test. +PASS name +PASS length +PASS No arguments +PASS Calling +FAIL Empty descriptor assert_throws: function "() => new WebAssembly.Memory({})" did not throw +FAIL Undefined initial value in descriptor assert_throws: function "() => new WebAssembly.Memory({ "initial": undefined })" did not throw +FAIL Out-of-range initial value in descriptor: NaN assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" did not throw +FAIL Out-of-range maximum value in descriptor: NaN assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" did not throw +FAIL Out-of-range initial value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value 9223372036854775807 is above the upper bound 32767" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value 9223372036854775807 is above the upper bound 65536" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -1 assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -1 assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value 4294967296 is above the upper bound 32767" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value 4294967296 is above the upper bound 65536" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Memory({ "initial": value })" threw object "RangeError: WebAssembly.Memory(): Property value 68719476736 is above the upper bound 32767" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Memory({ "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Memory(): Property value 68719476736 is above the upper bound 65536" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Proxy descriptor assert_unreached: Should not call [[HasProperty]] with maximum Reached unreachable code +PASS Prototype +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/constructor.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/constructor.any.js new file mode 100644 index 0000000..0f5eecf9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/constructor.any.js
@@ -0,0 +1,35 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js +// META: script=/wasm/jsapi/assertions.js + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_function_name(WebAssembly.Module, "Module", "WebAssembly.Module"); +}, "name"); + +test(() => { + assert_function_length(WebAssembly.Module, 1, "WebAssembly.Module"); +}, "length"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Module()); +}, "No arguments"); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.Module(emptyModuleBinary)); +}, "Calling"); + +test(() => { + const buffer = new Uint8Array(); + assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer)); +}, "Empty buffer"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype); +}, "Prototype");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt new file mode 100644 index 0000000..b2e39b8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +FAIL Missing arguments assert_throws: function "() => WebAssembly.Module.customSections(module)" did not throw +PASS Non-Module arguments +PASS Branding +PASS Empty module +PASS Empty module: array caching +FAIL Custom sections WebAssembly.Module(): Wasm decoding failed: unexpected section: name @+33 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any.js new file mode 100644 index 0000000..146aa7fd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any.js
@@ -0,0 +1,104 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js + +function assert_ArrayBuffer(buffer, expected) { + assert_equals(Object.getPrototypeOf(buffer), ArrayBuffer.prototype, "Prototype"); + assert_array_equals(new Uint8Array(buffer), expected); +} + +function assert_sections(sections, expected) { + assert_true(Array.isArray(sections), "Should be array"); + assert_equals(Object.getPrototypeOf(sections), Array.prototype, "Prototype"); + + assert_equals(sections.length, expected.length); + for (let i = 0; i < expected.length; ++i) { + assert_ArrayBuffer(sections[i], expected[i]); + } +} + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.Module.customSections()); + const module = new WebAssembly.Module(emptyModuleBinary); + assert_throws(new TypeError(), () => WebAssembly.Module.customSections(module)); +}, "Missing arguments"); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.Module.customSections({}, "")); + assert_throws(new TypeError(), () => WebAssembly.Module.customSections("", "")); + assert_throws(new TypeError(), () => WebAssembly.Module.customSections(undefined, "")); + assert_throws(new TypeError(), () => WebAssembly.Module.customSections(null, "")); +}, "Non-Module arguments"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const fn = WebAssembly.Module.customSections; + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly.Module, + WebAssembly.Module.prototype, + ]; + for (const thisValue of thisValues) { + assert_sections(fn.call(thisValue, module, ""), []); + } +}, "Branding"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + assert_sections(WebAssembly.Module.customSections(module, ""), []); +}, "Empty module"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + assert_not_equals(WebAssembly.Module.customSections(module, ""), + WebAssembly.Module.customSections(module, "")); +}, "Empty module: array caching"); + +test(() => { + const bytes1 = [87, 101, 98, 65, 115, 115, 101, 109, 98, 108, 121]; + const bytes2 = [74, 83, 65, 80, 73]; + + const binary = new Binary; + binary.emit_section(kUnknownSectionCode, section => { + section.emit_string("name"); + section.emit_bytes(bytes1); + }); + binary.emit_section(kUnknownSectionCode, section => { + section.emit_string("name"); + section.emit_bytes(bytes2); + }); + binary.emit_section(kUnknownSectionCode, section => { + section.emit_string("foo"); + section.emit_bytes(bytes1); + }); + + const builder = new WasmModuleBuilder(); + builder.addExplicitSection(binary); + const buffer = builder.toBuffer() + const module = new WebAssembly.Module(buffer); + + assert_sections(WebAssembly.Module.customSections(module, "name"), [ + bytes1, + bytes2, + ]) + + assert_sections(WebAssembly.Module.customSections(module, "foo"), [ + bytes1, + ]) + + assert_sections(WebAssembly.Module.customSections(module, ""), []) + assert_sections(WebAssembly.Module.customSections(module, "\0"), []) + assert_sections(WebAssembly.Module.customSections(module, "name\0"), []) + assert_sections(WebAssembly.Module.customSections(module, "foo\0"), []) +}, "Custom sections");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt new file mode 100644 index 0000000..b2e39b8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +FAIL Missing arguments assert_throws: function "() => WebAssembly.Module.customSections(module)" did not throw +PASS Non-Module arguments +PASS Branding +PASS Empty module +PASS Empty module: array caching +FAIL Custom sections WebAssembly.Module(): Wasm decoding failed: unexpected section: name @+33 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/exports.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/exports.any.js new file mode 100644 index 0000000..c7ecdcf --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/exports.any.js
@@ -0,0 +1,121 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.Module.exports()); +}, "Missing arguments"); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.Module.exports({})); + assert_throws(new TypeError(), () => WebAssembly.Module.exports("")); + assert_throws(new TypeError(), () => WebAssembly.Module.exports(undefined)); + assert_throws(new TypeError(), () => WebAssembly.Module.exports(null)); +}, "Non-Module arguments"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const fn = WebAssembly.Module.exports; + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly.Module, + WebAssembly.Module.prototype, + ]; + for (const thisValue of thisValues) { + assert_array_equals(fn.call(thisValue, module), []); + } +}, "Branding"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const exports = WebAssembly.Module.exports(module); + assert_true(Array.isArray(exports)); +}, "Return type"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const exports = WebAssembly.Module.exports(module); + assert_true(Array.isArray(exports), "Should be array"); + assert_equals(Object.getPrototypeOf(exports), Array.prototype, "Prototype"); + assert_array_equals(exports, []); +}, "Empty module"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + assert_not_equals(WebAssembly.Module.exports(module), WebAssembly.Module.exports(module)); +}, "Empty module: array caching"); + +function assert_ModuleExportDescriptor(export_, expected) { + assert_equals(Object.getPrototypeOf(export_), Object.prototype, "Prototype"); + + const name = Object.getOwnPropertyDescriptor(export_, "name"); + assert_true(name.writable, "name: writable"); + assert_true(name.enumerable, "name: enumerable"); + assert_true(name.configurable, "name: configurable"); + assert_equals(name.value, expected.name); + + const kind = Object.getOwnPropertyDescriptor(export_, "kind"); + assert_true(kind.writable, "kind: writable"); + assert_true(kind.enumerable, "kind: enumerable"); + assert_true(kind.configurable, "kind: configurable"); + assert_equals(kind.value, expected.kind); +} + +test(() => { + const builder = new WasmModuleBuilder(); + + builder + .addFunction("fn", kSig_v_v) + .addBody([ + kExprEnd + ]) + .exportFunc(); + builder + .addFunction("fn2", kSig_v_v) + .addBody([ + kExprEnd + ]) + .exportFunc(); + + builder.setFunctionTableLength(1); + builder.addExportOfKind("table", kExternalTable, 0); + + builder.addGlobal(kWasmI32, true) + .exportAs("global") + .init = 7; + builder.addGlobal(kWasmF64, true) + .exportAs("global2") + .init = 1.2; + + builder.addMemory(0, 256, true); + + const buffer = builder.toBuffer() + const module = new WebAssembly.Module(buffer); + const exports = WebAssembly.Module.exports(module); + assert_true(Array.isArray(exports), "Should be array"); + assert_equals(Object.getPrototypeOf(exports), Array.prototype, "Prototype"); + + const expected = [ + { "kind": "function", "name": "fn" }, + { "kind": "function", "name": "fn2" }, + { "kind": "table", "name": "table" }, + { "kind": "global", "name": "global" }, + { "kind": "global", "name": "global2" }, + { "kind": "memory", "name": "memory" }, + ]; + assert_equals(exports.length, expected.length); + for (let i = 0; i < expected.length; ++i) { + assert_ModuleExportDescriptor(exports[i], expected[i]); + } +}, "exports");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/imports.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/imports.any.js new file mode 100644 index 0000000..522b262 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/module/imports.any.js
@@ -0,0 +1,105 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.Module.imports()); +}, "Missing arguments"); + +test(() => { + assert_throws(new TypeError(), () => WebAssembly.Module.imports({})); + assert_throws(new TypeError(), () => WebAssembly.Module.imports("")); + assert_throws(new TypeError(), () => WebAssembly.Module.imports(undefined)); + assert_throws(new TypeError(), () => WebAssembly.Module.imports(null)); +}, "Non-Module arguments"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const fn = WebAssembly.Module.imports; + const thisValues = [ + undefined, + null, + true, + "", + Symbol(), + 1, + {}, + WebAssembly.Module, + WebAssembly.Module.prototype, + ]; + for (const thisValue of thisValues) { + assert_array_equals(fn.call(thisValue, module), []); + } +}, "Branding"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const imports = WebAssembly.Module.imports(module); + assert_true(Array.isArray(imports)); +}, "Return type"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const imports = WebAssembly.Module.imports(module); + assert_true(Array.isArray(imports), "Should be array"); + assert_equals(Object.getPrototypeOf(imports), Array.prototype, "Prototype"); + assert_array_equals(imports, []); +}, "Empty module"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + assert_not_equals(WebAssembly.Module.imports(module), WebAssembly.Module.imports(module)); +}, "Empty module: array caching"); + +function assert_ModuleImportDescriptor(import_, expected) { + assert_equals(Object.getPrototypeOf(import_), Object.prototype, "Prototype"); + + const module = Object.getOwnPropertyDescriptor(import_, "module"); + assert_true(module.writable, "module: writable"); + assert_true(module.enumerable, "module: enumerable"); + assert_true(module.configurable, "module: configurable"); + assert_equals(module.value, expected.module); + + const name = Object.getOwnPropertyDescriptor(import_, "name"); + assert_true(name.writable, "name: writable"); + assert_true(name.enumerable, "name: enumerable"); + assert_true(name.configurable, "name: configurable"); + assert_equals(name.value, expected.name); + + const kind = Object.getOwnPropertyDescriptor(import_, "kind"); + assert_true(kind.writable, "kind: writable"); + assert_true(kind.enumerable, "kind: enumerable"); + assert_true(kind.configurable, "kind: configurable"); + assert_equals(kind.value, expected.kind); +} + +test(() => { + const builder = new WasmModuleBuilder(); + + builder.addImport("module", "fn", kSig_v_v); + builder.addImportedGlobal("module", "global", kWasmI32); + builder.addImportedMemory("module", "memory", 0, 128); + builder.addImportedTable("module", "table", 0, 128); + + const buffer = builder.toBuffer() + const module = new WebAssembly.Module(buffer); + const imports = WebAssembly.Module.imports(module); + assert_true(Array.isArray(imports), "Should be array"); + assert_equals(Object.getPrototypeOf(imports), Array.prototype, "Prototype"); + + const expected = [ + { "module": "module", "kind": "function", "name": "fn" }, + { "module": "module", "kind": "global", "name": "global" }, + { "module": "module", "kind": "memory", "name": "memory" }, + { "module": "module", "kind": "table", "name": "table" }, + ]; + assert_equals(imports.length, expected.length); + for (let i = 0; i < expected.length; ++i) { + assert_ModuleImportDescriptor(imports[i], expected[i]); + } +}, "imports");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any-expected.txt new file mode 100644 index 0000000..6592666 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any-expected.txt
@@ -0,0 +1,24 @@ +This is a testharness.js-based test. +PASS name +PASS length +PASS No arguments +PASS Calling +PASS Empty descriptor +FAIL Undefined initial value in descriptor assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined })" did not throw +PASS Undefined element value in descriptor +FAIL Out-of-range initial value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" did not throw +FAIL Out-of-range maximum value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" did not throw +FAIL Out-of-range initial value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Proxy descriptor assert_unreached: Should not call [[HasProperty]] with maximum Reached unreachable code +PASS Prototype +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any.js new file mode 100644 index 0000000..4aeac10 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any.js
@@ -0,0 +1,83 @@ +// META: global=jsshell +// META: script=/wasm/jsapi/wasm-constants.js +// META: script=/wasm/jsapi/wasm-module-builder.js +// META: script=/wasm/jsapi/assertions.js + +let emptyModuleBinary; +setup(() => { + emptyModuleBinary = new WasmModuleBuilder().toBuffer(); +}); + +test(() => { + assert_function_name(WebAssembly.Table, "Table", "WebAssembly.Table"); +}, "name"); + +test(() => { + assert_function_length(WebAssembly.Table, 1, "WebAssembly.Table"); +}, "length"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Table()); +}, "No arguments"); + +test(() => { + const argument = { "initial": 0 }; + assert_throws(new TypeError(), () => WebAssembly.Table(argument)); +}, "Calling"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Table({})); +}, "Empty descriptor"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined })); +}, "Undefined initial value in descriptor"); + +test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": undefined, "initial": 0 })); +}, "Undefined element value in descriptor"); + +const outOfRangeValues = [ + NaN, + Infinity, + -Infinity, + -1, + 0x100000000, + 0x1000000000, +]; + +for (const value of outOfRangeValues) { + test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": value })); + }, `Out-of-range initial value in descriptor: ${format_value(value)}`); + + test(() => { + assert_throws(new TypeError(), () => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })); + }, `Out-of-range maximum value in descriptor: ${format_value(value)}`); +} + +test(() => { + const proxy = new Proxy({}, { + has(o, x) { + assert_unreached(`Should not call [[HasProperty]] with ${x}`); + }, + get(o, x) { + switch (x) { + case "element": + return "anyfunc"; + case "initial": + case "maximum": + return 0; + default: + return undefined; + } + }, + }); + new WebAssembly.Table(proxy); +}, "Proxy descriptor"); + +test(() => { + const argument = { "element": "anyfunc", "initial": 0 }; + const table = new WebAssembly.Table(argument); + assert_equals(Object.getPrototypeOf(table), WebAssembly.Table.prototype); +}, "Prototype");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any.worker-expected.txt new file mode 100644 index 0000000..6592666 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/table/constructor.any.worker-expected.txt
@@ -0,0 +1,24 @@ +This is a testharness.js-based test. +PASS name +PASS length +PASS No arguments +PASS Calling +PASS Empty descriptor +FAIL Undefined initial value in descriptor assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": undefined })" did not throw +PASS Undefined element value in descriptor +FAIL Out-of-range initial value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" did not throw +FAIL Out-of-range maximum value in descriptor: NaN assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" did not throw +FAIL Out-of-range initial value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 9223372036854775807 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -Infinity assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -9223372036854775808 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: -1 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value -1 is below the lower bound 0" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 4294967296 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 4294967296 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range initial value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 10000000" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Out-of-range maximum value in descriptor: 68719476736 assert_throws: function "() => new WebAssembly.Table({ "element": "anyfunc", "initial": 0, "maximum": value })" threw object "RangeError: WebAssembly.Module(): Property value 68719476736 is above the upper bound 4294967295" ("RangeError") expected object "TypeError" ("TypeError") +FAIL Proxy descriptor assert_unreached: Should not call [[HasProperty]] with maximum Reached unreachable code +PASS Prototype +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/wasm-constants.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/wasm-constants.js new file mode 100644 index 0000000..f056f9c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/wasm-constants.js
@@ -0,0 +1,374 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-wasm + +function bytes() { + var buffer = new ArrayBuffer(arguments.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < arguments.length; i++) { + var val = arguments[i]; + if ((typeof val) == "string") val = val.charCodeAt(0); + view[i] = val | 0; + } + return buffer; +} + +// Header declaration constants +var kWasmH0 = 0; +var kWasmH1 = 0x61; +var kWasmH2 = 0x73; +var kWasmH3 = 0x6d; + +var kWasmV0 = 1; +var kWasmV1 = 0; +var kWasmV2 = 0; +var kWasmV3 = 0; + +var kHeaderSize = 8; +var kPageSize = 65536; + +function bytesWithHeader() { + var buffer = new ArrayBuffer(kHeaderSize + arguments.length); + var view = new Uint8Array(buffer); + view[0] = kWasmH0; + view[1] = kWasmH1; + view[2] = kWasmH2; + view[3] = kWasmH3; + view[4] = kWasmV0; + view[5] = kWasmV1; + view[6] = kWasmV2; + view[7] = kWasmV3; + for (var i = 0; i < arguments.length; i++) { + var val = arguments[i]; + if ((typeof val) == "string") val = val.charCodeAt(0); + view[kHeaderSize + i] = val | 0; + } + return buffer; +} + +let kDeclNoLocals = 0; + +// Section declaration constants +let kUnknownSectionCode = 0; +let kTypeSectionCode = 1; // Function signature declarations +let kImportSectionCode = 2; // Import declarations +let kFunctionSectionCode = 3; // Function declarations +let kTableSectionCode = 4; // Indirect function table and other tables +let kMemorySectionCode = 5; // Memory attributes +let kGlobalSectionCode = 6; // Global declarations +let kExportSectionCode = 7; // Exports +let kStartSectionCode = 8; // Start function declaration +let kElementSectionCode = 9; // Elements section +let kCodeSectionCode = 10; // Function code +let kDataSectionCode = 11; // Data segments +let kNameSectionCode = 12; // Name section (encoded as string) + +let kWasmFunctionTypeForm = 0x60; +let kWasmAnyFunctionTypeForm = 0x70; + +let kResizableMaximumFlag = 1; + +// Function declaration flags +let kDeclFunctionName = 0x01; +let kDeclFunctionImport = 0x02; +let kDeclFunctionLocals = 0x04; +let kDeclFunctionExport = 0x08; + +// Local types +let kWasmStmt = 0x40; +let kWasmI32 = 0x7f; +let kWasmI64 = 0x7e; +let kWasmF32 = 0x7d; +let kWasmF64 = 0x7c; +let kWasmS128 = 0x7b; + +let kExternalFunction = 0; +let kExternalTable = 1; +let kExternalMemory = 2; +let kExternalGlobal = 3; + +let kTableZero = 0; +let kMemoryZero = 0; + +// Useful signatures +let kSig_i_i = makeSig([kWasmI32], [kWasmI32]); +let kSig_l_l = makeSig([kWasmI64], [kWasmI64]); +let kSig_i_l = makeSig([kWasmI64], [kWasmI32]); +let kSig_i_ii = makeSig([kWasmI32, kWasmI32], [kWasmI32]); +let kSig_i_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]); +let kSig_d_dd = makeSig([kWasmF64, kWasmF64], [kWasmF64]); +let kSig_l_ll = makeSig([kWasmI64, kWasmI64], [kWasmI64]); +let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]); +let kSig_v_v = makeSig([], []); +let kSig_i_v = makeSig([], [kWasmI32]); +let kSig_l_v = makeSig([], [kWasmI64]); +let kSig_f_v = makeSig([], [kWasmF64]); +let kSig_d_v = makeSig([], [kWasmF64]); +let kSig_v_i = makeSig([kWasmI32], []); +let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []); +let kSig_v_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], []); +let kSig_v_l = makeSig([kWasmI64], []); +let kSig_v_d = makeSig([kWasmF64], []); +let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []); +let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []); +let kSig_s_v = makeSig([], [kWasmS128]); + +function makeSig(params, results) { + return {params: params, results: results}; +} + +function makeSig_v_x(x) { + return makeSig([x], []); +} + +function makeSig_v_xx(x) { + return makeSig([x, x], []); +} + +function makeSig_r_v(r) { + return makeSig([], [r]); +} + +function makeSig_r_x(r, x) { + return makeSig([x], [r]); +} + +function makeSig_r_xx(r, x) { + return makeSig([x, x], [r]); +} + +// Opcodes +let kExprUnreachable = 0x00; +let kExprNop = 0x01; +let kExprBlock = 0x02; +let kExprLoop = 0x03; +let kExprIf = 0x04; +let kExprElse = 0x05; +let kExprTry = 0x06; +let kExprCatch = 0x07; +let kExprThrow = 0x08; +let kExprEnd = 0x0b; +let kExprBr = 0x0c; +let kExprBrIf = 0x0d; +let kExprBrTable = 0x0e; +let kExprReturn = 0x0f; +let kExprCallFunction = 0x10; +let kExprCallIndirect = 0x11; +let kExprDrop = 0x1a; +let kExprSelect = 0x1b; +let kExprGetLocal = 0x20; +let kExprSetLocal = 0x21; +let kExprTeeLocal = 0x22; +let kExprGetGlobal = 0x23; +let kExprSetGlobal = 0x24; +let kExprI32Const = 0x41; +let kExprI64Const = 0x42; +let kExprF32Const = 0x43; +let kExprF64Const = 0x44; +let kExprI32LoadMem = 0x28; +let kExprI64LoadMem = 0x29; +let kExprF32LoadMem = 0x2a; +let kExprF64LoadMem = 0x2b; +let kExprI32LoadMem8S = 0x2c; +let kExprI32LoadMem8U = 0x2d; +let kExprI32LoadMem16S = 0x2e; +let kExprI32LoadMem16U = 0x2f; +let kExprI64LoadMem8S = 0x30; +let kExprI64LoadMem8U = 0x31; +let kExprI64LoadMem16S = 0x32; +let kExprI64LoadMem16U = 0x33; +let kExprI64LoadMem32S = 0x34; +let kExprI64LoadMem32U = 0x35; +let kExprI32StoreMem = 0x36; +let kExprI64StoreMem = 0x37; +let kExprF32StoreMem = 0x38; +let kExprF64StoreMem = 0x39; +let kExprI32StoreMem8 = 0x3a; +let kExprI32StoreMem16 = 0x3b; +let kExprI64StoreMem8 = 0x3c; +let kExprI64StoreMem16 = 0x3d; +let kExprI64StoreMem32 = 0x3e; +let kExprMemorySize = 0x3f; +let kExprGrowMemory = 0x40; +let kExprI32Eqz = 0x45; +let kExprI32Eq = 0x46; +let kExprI32Ne = 0x47; +let kExprI32LtS = 0x48; +let kExprI32LtU = 0x49; +let kExprI32GtS = 0x4a; +let kExprI32GtU = 0x4b; +let kExprI32LeS = 0x4c; +let kExprI32LeU = 0x4d; +let kExprI32GeS = 0x4e; +let kExprI32GeU = 0x4f; +let kExprI64Eqz = 0x50; +let kExprI64Eq = 0x51; +let kExprI64Ne = 0x52; +let kExprI64LtS = 0x53; +let kExprI64LtU = 0x54; +let kExprI64GtS = 0x55; +let kExprI64GtU = 0x56; +let kExprI64LeS = 0x57; +let kExprI64LeU = 0x58; +let kExprI64GeS = 0x59; +let kExprI64GeU = 0x5a; +let kExprF32Eq = 0x5b; +let kExprF32Ne = 0x5c; +let kExprF32Lt = 0x5d; +let kExprF32Gt = 0x5e; +let kExprF32Le = 0x5f; +let kExprF32Ge = 0x60; +let kExprF64Eq = 0x61; +let kExprF64Ne = 0x62; +let kExprF64Lt = 0x63; +let kExprF64Gt = 0x64; +let kExprF64Le = 0x65; +let kExprF64Ge = 0x66; +let kExprI32Clz = 0x67; +let kExprI32Ctz = 0x68; +let kExprI32Popcnt = 0x69; +let kExprI32Add = 0x6a; +let kExprI32Sub = 0x6b; +let kExprI32Mul = 0x6c; +let kExprI32DivS = 0x6d; +let kExprI32DivU = 0x6e; +let kExprI32RemS = 0x6f; +let kExprI32RemU = 0x70; +let kExprI32And = 0x71; +let kExprI32Ior = 0x72; +let kExprI32Xor = 0x73; +let kExprI32Shl = 0x74; +let kExprI32ShrS = 0x75; +let kExprI32ShrU = 0x76; +let kExprI32Rol = 0x77; +let kExprI32Ror = 0x78; +let kExprI64Clz = 0x79; +let kExprI64Ctz = 0x7a; +let kExprI64Popcnt = 0x7b; +let kExprI64Add = 0x7c; +let kExprI64Sub = 0x7d; +let kExprI64Mul = 0x7e; +let kExprI64DivS = 0x7f; +let kExprI64DivU = 0x80; +let kExprI64RemS = 0x81; +let kExprI64RemU = 0x82; +let kExprI64And = 0x83; +let kExprI64Ior = 0x84; +let kExprI64Xor = 0x85; +let kExprI64Shl = 0x86; +let kExprI64ShrS = 0x87; +let kExprI64ShrU = 0x88; +let kExprI64Rol = 0x89; +let kExprI64Ror = 0x8a; +let kExprF32Abs = 0x8b; +let kExprF32Neg = 0x8c; +let kExprF32Ceil = 0x8d; +let kExprF32Floor = 0x8e; +let kExprF32Trunc = 0x8f; +let kExprF32NearestInt = 0x90; +let kExprF32Sqrt = 0x91; +let kExprF32Add = 0x92; +let kExprF32Sub = 0x93; +let kExprF32Mul = 0x94; +let kExprF32Div = 0x95; +let kExprF32Min = 0x96; +let kExprF32Max = 0x97; +let kExprF32CopySign = 0x98; +let kExprF64Abs = 0x99; +let kExprF64Neg = 0x9a; +let kExprF64Ceil = 0x9b; +let kExprF64Floor = 0x9c; +let kExprF64Trunc = 0x9d; +let kExprF64NearestInt = 0x9e; +let kExprF64Sqrt = 0x9f; +let kExprF64Add = 0xa0; +let kExprF64Sub = 0xa1; +let kExprF64Mul = 0xa2; +let kExprF64Div = 0xa3; +let kExprF64Min = 0xa4; +let kExprF64Max = 0xa5; +let kExprF64CopySign = 0xa6; +let kExprI32ConvertI64 = 0xa7; +let kExprI32SConvertF32 = 0xa8; +let kExprI32UConvertF32 = 0xa9; +let kExprI32SConvertF64 = 0xaa; +let kExprI32UConvertF64 = 0xab; +let kExprI64SConvertI32 = 0xac; +let kExprI64UConvertI32 = 0xad; +let kExprI64SConvertF32 = 0xae; +let kExprI64UConvertF32 = 0xaf; +let kExprI64SConvertF64 = 0xb0; +let kExprI64UConvertF64 = 0xb1; +let kExprF32SConvertI32 = 0xb2; +let kExprF32UConvertI32 = 0xb3; +let kExprF32SConvertI64 = 0xb4; +let kExprF32UConvertI64 = 0xb5; +let kExprF32ConvertF64 = 0xb6; +let kExprF64SConvertI32 = 0xb7; +let kExprF64UConvertI32 = 0xb8; +let kExprF64SConvertI64 = 0xb9; +let kExprF64UConvertI64 = 0xba; +let kExprF64ConvertF32 = 0xbb; +let kExprI32ReinterpretF32 = 0xbc; +let kExprI64ReinterpretF64 = 0xbd; +let kExprF32ReinterpretI32 = 0xbe; +let kExprF64ReinterpretI64 = 0xbf; + +let kTrapUnreachable = 0; +let kTrapMemOutOfBounds = 1; +let kTrapDivByZero = 2; +let kTrapDivUnrepresentable = 3; +let kTrapRemByZero = 4; +let kTrapFloatUnrepresentable = 5; +let kTrapFuncInvalid = 6; +let kTrapFuncSigMismatch = 7; +let kTrapInvalidIndex = 8; + +let kTrapMsgs = [ + "unreachable", + "memory access out of bounds", + "divide by zero", + "divide result unrepresentable", + "remainder by zero", + "integer result unrepresentable", + "invalid function", + "function signature mismatch", + "invalid index into function table" +]; + +function assertTraps(trap, code) { + var threwException = true; + try { + if (typeof code === 'function') { + code(); + } else { + eval(code); + } + threwException = false; + } catch (e) { + assertEquals("object", typeof e); + assertEquals(kTrapMsgs[trap], e.message); + // Success. + return; + } + throw new MjsUnitAssertionError("Did not trap, expected: " + kTrapMsgs[trap]); +} + +function assertWasmThrows(value, code) { + assertEquals("number", typeof(value)); + try { + if (typeof code === 'function') { + code(); + } else { + eval(code); + } + } catch (e) { + assertEquals("number", typeof e); + assertEquals(value, e); + // Success. + return; + } + throw new MjsUnitAssertionError("Did not throw at all, expected: " + value); +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/wasm-module-builder.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/wasm-module-builder.js new file mode 100644 index 0000000..6e9284e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/wasm/jsapi/wasm-module-builder.js
@@ -0,0 +1,555 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Used for encoding f32 and double constants to bits. +let __buffer = new ArrayBuffer(8); +let byte_view = new Int8Array(__buffer); +let f32_view = new Float32Array(__buffer); +let f64_view = new Float64Array(__buffer); + +class Binary extends Array { + emit_u8(val) { + this.push(val); + } + + emit_u16(val) { + this.push(val & 0xff); + this.push((val >> 8) & 0xff); + } + + emit_u32(val) { + this.push(val & 0xff); + this.push((val >> 8) & 0xff); + this.push((val >> 16) & 0xff); + this.push((val >> 24) & 0xff); + } + + emit_u32v(val) { + while (true) { + let v = val & 0xff; + val = val >>> 7; + if (val == 0) { + this.push(v); + break; + } + this.push(v | 0x80); + } + } + + emit_bytes(data) { + for (let i = 0; i < data.length; i++) { + this.push(data[i] & 0xff); + } + } + + emit_string(string) { + // When testing illegal names, we pass a byte array directly. + if (string instanceof Array) { + this.emit_u32v(string.length); + this.emit_bytes(string); + return; + } + + // This is the hacky way to convert a JavaScript string to a UTF8 encoded + // string only containing single-byte characters. + let string_utf8 = unescape(encodeURIComponent(string)); + this.emit_u32v(string_utf8.length); + for (let i = 0; i < string_utf8.length; i++) { + this.emit_u8(string_utf8.charCodeAt(i)); + } + } + + emit_header() { + this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, + kWasmV0, kWasmV1, kWasmV2, kWasmV3); + } + + emit_section(section_code, content_generator) { + // Emit section name. + this.emit_u8(section_code); + // Emit the section to a temporary buffer: its full length isn't know yet. + let section = new Binary; + content_generator(section); + // Emit section length. + this.emit_u32v(section.length); + // Copy the temporary buffer. + this.push(...section); + } +} + +class WasmFunctionBuilder { + constructor(module, name, type_index) { + this.module = module; + this.name = name; + this.type_index = type_index; + this.body = []; + } + + exportAs(name) { + this.module.addExport(name, this.index); + return this; + } + + exportFunc() { + this.exportAs(this.name); + return this; + } + + addBody(body) { + this.body = body; + return this; + } + + addLocals(locals) { + this.locals = locals; + return this; + } + + end() { + return this.module; + } +} + +class WasmGlobalBuilder { + constructor(module, type, mutable) { + this.module = module; + this.type = type; + this.mutable = mutable; + this.init = 0; + } + + exportAs(name) { + this.module.exports.push({name: name, kind: kExternalGlobal, + index: this.index}); + return this; + } +} + +class WasmModuleBuilder { + constructor() { + this.types = []; + this.imports = []; + this.exports = []; + this.globals = []; + this.functions = []; + this.function_table = []; + this.function_table_length = 0; + this.function_table_inits = []; + this.segments = []; + this.explicit = []; + this.num_imported_funcs = 0; + this.num_imported_globals = 0; + return this; + } + + addStart(start_index) { + this.start_index = start_index; + return this; + } + + addMemory(min, max, exp) { + this.memory = {min: min, max: max, exp: exp}; + return this; + } + + addExplicitSection(bytes) { + this.explicit.push(bytes); + return this; + } + + addType(type) { + // TODO: canonicalize types? + this.types.push(type); + return this.types.length - 1; + } + + addGlobal(local_type, mutable) { + let glob = new WasmGlobalBuilder(this, local_type, mutable); + glob.index = this.globals.length + this.num_imported_globals; + this.globals.push(glob); + return glob; + } + + addFunction(name, type) { + let type_index = (typeof type) == "number" ? type : this.addType(type); + let func = new WasmFunctionBuilder(this, name, type_index); + func.index = this.functions.length + this.num_imported_funcs; + this.functions.push(func); + return func; + } + + addImport(module = "", name, type) { + let type_index = (typeof type) == "number" ? type : this.addType(type); + this.imports.push({module: module, name: name, kind: kExternalFunction, + type: type_index}); + return this.num_imported_funcs++; + } + + addImportedGlobal(module = "", name, type) { + let o = {module: module, name: name, kind: kExternalGlobal, type: type, + mutable: false} + this.imports.push(o); + return this.num_imported_globals++; + } + + addImportedMemory(module = "", name, initial = 0, maximum) { + let o = {module: module, name: name, kind: kExternalMemory, + initial: initial, maximum: maximum}; + this.imports.push(o); + return this; + } + + addImportedTable(module = "", name, initial, maximum) { + let o = {module: module, name: name, kind: kExternalTable, initial: initial, + maximum: maximum}; + this.imports.push(o); + } + + addExport(name, index) { + this.exports.push({name: name, kind: kExternalFunction, index: index}); + return this; + } + + addExportOfKind(name, kind, index) { + this.exports.push({name: name, kind: kind, index: index}); + return this; + } + + addDataSegment(addr, data, is_global = false) { + this.segments.push({addr: addr, data: data, is_global: is_global}); + return this.segments.length - 1; + } + + exportMemoryAs(name) { + this.exports.push({name: name, kind: kExternalMemory, index: 0}); + } + + addFunctionTableInit(base, is_global, array) { + this.function_table_inits.push({base: base, is_global: is_global, + array: array}); + if (!is_global) { + var length = base + array.length; + if (length > this.function_table_length) { + this.function_table_length = length; + } + } + return this; + } + + appendToTable(array) { + return this.addFunctionTableInit(this.function_table.length, false, array); + } + + setFunctionTableLength(length) { + this.function_table_length = length; + return this; + } + + toArray(debug = false) { + let binary = new Binary; + let wasm = this; + + // Add header + binary.emit_header(); + + // Add type section + if (wasm.types.length > 0) { + if (debug) print("emitting types @ " + binary.length); + binary.emit_section(kTypeSectionCode, section => { + section.emit_u32v(wasm.types.length); + for (let type of wasm.types) { + section.emit_u8(kWasmFunctionTypeForm); + section.emit_u32v(type.params.length); + for (let param of type.params) { + section.emit_u8(param); + } + section.emit_u32v(type.results.length); + for (let result of type.results) { + section.emit_u8(result); + } + } + }); + } + + // Add imports section + if (wasm.imports.length > 0) { + if (debug) print("emitting imports @ " + binary.length); + binary.emit_section(kImportSectionCode, section => { + section.emit_u32v(wasm.imports.length); + for (let imp of wasm.imports) { + section.emit_string(imp.module); + section.emit_string(imp.name || ''); + section.emit_u8(imp.kind); + if (imp.kind == kExternalFunction) { + section.emit_u32v(imp.type); + } else if (imp.kind == kExternalGlobal) { + section.emit_u32v(imp.type); + section.emit_u8(imp.mutable); + } else if (imp.kind == kExternalMemory) { + var has_max = (typeof imp.maximum) != "undefined"; + section.emit_u8(has_max ? 1 : 0); // flags + section.emit_u32v(imp.initial); // initial + if (has_max) section.emit_u32v(imp.maximum); // maximum + } else if (imp.kind == kExternalTable) { + section.emit_u8(kWasmAnyFunctionTypeForm); + var has_max = (typeof imp.maximum) != "undefined"; + section.emit_u8(has_max ? 1 : 0); // flags + section.emit_u32v(imp.initial); // initial + if (has_max) section.emit_u32v(imp.maximum); // maximum + } else { + throw new Error("unknown/unsupported import kind " + imp.kind); + } + } + }); + } + + // Add functions declarations + let has_names = false; + let names = false; + if (wasm.functions.length > 0) { + if (debug) print("emitting function decls @ " + binary.length); + binary.emit_section(kFunctionSectionCode, section => { + section.emit_u32v(wasm.functions.length); + for (let func of wasm.functions) { + has_names = has_names || (func.name != undefined && + func.name.length > 0); + section.emit_u32v(func.type_index); + } + }); + } + + // Add function_table. + if (wasm.function_table_length > 0) { + if (debug) print("emitting table @ " + binary.length); + binary.emit_section(kTableSectionCode, section => { + section.emit_u8(1); // one table entry + section.emit_u8(kWasmAnyFunctionTypeForm); + section.emit_u8(1); + section.emit_u32v(wasm.function_table_length); + section.emit_u32v(wasm.function_table_length); + }); + } + + // Add memory section + if (wasm.memory != undefined) { + if (debug) print("emitting memory @ " + binary.length); + binary.emit_section(kMemorySectionCode, section => { + section.emit_u8(1); // one memory entry + section.emit_u32v(kResizableMaximumFlag); + section.emit_u32v(wasm.memory.min); + section.emit_u32v(wasm.memory.max); + }); + } + + // Add global section. + if (wasm.globals.length > 0) { + if (debug) print ("emitting globals @ " + binary.length); + binary.emit_section(kGlobalSectionCode, section => { + section.emit_u32v(wasm.globals.length); + for (let global of wasm.globals) { + section.emit_u8(global.type); + section.emit_u8(global.mutable); + if ((typeof global.init_index) == "undefined") { + // Emit a constant initializer. + switch (global.type) { + case kWasmI32: + section.emit_u8(kExprI32Const); + section.emit_u32v(global.init); + break; + case kWasmI64: + section.emit_u8(kExprI64Const); + section.emit_u8(global.init); + break; + case kWasmF32: + section.emit_u8(kExprF32Const); + f32_view[0] = global.init; + section.emit_u8(byte_view[0]); + section.emit_u8(byte_view[1]); + section.emit_u8(byte_view[2]); + section.emit_u8(byte_view[3]); + break; + case kWasmF64: + section.emit_u8(kExprF64Const); + f64_view[0] = global.init; + section.emit_u8(byte_view[0]); + section.emit_u8(byte_view[1]); + section.emit_u8(byte_view[2]); + section.emit_u8(byte_view[3]); + section.emit_u8(byte_view[4]); + section.emit_u8(byte_view[5]); + section.emit_u8(byte_view[6]); + section.emit_u8(byte_view[7]); + break; + } + } else { + // Emit a global-index initializer. + section.emit_u8(kExprGetGlobal); + section.emit_u32v(global.init_index); + } + section.emit_u8(kExprEnd); // end of init expression + } + }); + } + + // Add export table. + var mem_export = (wasm.memory != undefined && wasm.memory.exp); + var exports_count = wasm.exports.length + (mem_export ? 1 : 0); + if (exports_count > 0) { + if (debug) print("emitting exports @ " + binary.length); + binary.emit_section(kExportSectionCode, section => { + section.emit_u32v(exports_count); + for (let exp of wasm.exports) { + section.emit_string(exp.name); + section.emit_u8(exp.kind); + section.emit_u32v(exp.index); + } + if (mem_export) { + section.emit_string("memory"); + section.emit_u8(kExternalMemory); + section.emit_u8(0); + } + }); + } + + // Add start function section. + if (wasm.start_index != undefined) { + if (debug) print("emitting start function @ " + binary.length); + binary.emit_section(kStartSectionCode, section => { + section.emit_u32v(wasm.start_index); + }); + } + + // Add table elements. + if (wasm.function_table_inits.length > 0) { + if (debug) print("emitting table @ " + binary.length); + binary.emit_section(kElementSectionCode, section => { + var inits = wasm.function_table_inits; + section.emit_u32v(inits.length); + section.emit_u8(0); // table index + + for (let init of inits) { + if (init.is_global) { + section.emit_u8(kExprGetGlobal); + } else { + section.emit_u8(kExprI32Const); + } + section.emit_u32v(init.base); + section.emit_u8(kExprEnd); + section.emit_u32v(init.array.length); + for (let index of init.array) { + section.emit_u32v(index); + } + } + }); + } + + // Add function bodies. + if (wasm.functions.length > 0) { + // emit function bodies + if (debug) print("emitting code @ " + binary.length); + binary.emit_section(kCodeSectionCode, section => { + section.emit_u32v(wasm.functions.length); + for (let func of wasm.functions) { + // Function body length will be patched later. + let local_decls = []; + let l = func.locals; + if (l != undefined) { + let local_decls_count = 0; + if (l.i32_count > 0) { + local_decls.push({count: l.i32_count, type: kWasmI32}); + } + if (l.i64_count > 0) { + local_decls.push({count: l.i64_count, type: kWasmI64}); + } + if (l.f32_count > 0) { + local_decls.push({count: l.f32_count, type: kWasmF32}); + } + if (l.f64_count > 0) { + local_decls.push({count: l.f64_count, type: kWasmF64}); + } + } + + let header = new Binary; + header.emit_u32v(local_decls.length); + for (let decl of local_decls) { + header.emit_u32v(decl.count); + header.emit_u8(decl.type); + } + + section.emit_u32v(header.length + func.body.length); + section.emit_bytes(header); + section.emit_bytes(func.body); + } + }); + } + + // Add data segments. + if (wasm.segments.length > 0) { + if (debug) print("emitting data segments @ " + binary.length); + binary.emit_section(kDataSectionCode, section => { + section.emit_u32v(wasm.segments.length); + for (let seg of wasm.segments) { + section.emit_u8(0); // linear memory index 0 + if (seg.is_global) { + // initializer is a global variable + section.emit_u8(kExprGetGlobal); + section.emit_u32v(seg.addr); + } else { + // initializer is a constant + section.emit_u8(kExprI32Const); + section.emit_u32v(seg.addr); + } + section.emit_u8(kExprEnd); + section.emit_u32v(seg.data.length); + section.emit_bytes(seg.data); + } + }); + } + + // Add any explicitly added sections + for (let exp of wasm.explicit) { + if (debug) print("emitting explicit @ " + binary.length); + binary.emit_bytes(exp); + } + + // Add function names. + if (has_names) { + if (debug) print("emitting names @ " + binary.length); + binary.emit_section(kUnknownSectionCode, section => { + section.emit_string("name"); + var count = wasm.functions.length + wasm.num_imported_funcs; + section.emit_u32v(count); + for (var i = 0; i < wasm.num_imported_funcs; i++) { + section.emit_u8(0); // empty string + section.emit_u8(0); // local names count == 0 + } + for (let func of wasm.functions) { + var name = func.name == undefined ? "" : func.name; + section.emit_string(name); + section.emit_u8(0); // local names count == 0 + } + }); + } + + return binary; + } + + toBuffer(debug = false) { + let bytes = this.toArray(debug); + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; i++) { + let val = bytes[i]; + if ((typeof val) == "string") val = val.charCodeAt(0); + view[i] = val | 0; + } + return new Uint8Array(buffer); + } + + instantiate(...args) { + let module = new WebAssembly.Module(this.toBuffer()); + let instance = new WebAssembly.Instance(module, ...args); + return instance; + } +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_idb_worker.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_idb_worker.js deleted file mode 100644 index 9d36d74..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_idb_worker.js +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -importScripts('/resources/testharness.js'); -importScripts('resources/load_wasm.js'); -importScripts('wasm_indexeddb_test.js'); - -onmessage = function(e) { - if (e.data.command === "load") { - loadFromIndexedDB(e.data.db_name) - .then(res => { - if (res === 2) postMessage("ok"); - else postMessage("error"); - }, - error => postMessage(error)); - } else if (e.data.command === "save") { - createAndSaveToIndexedDB(e.data.db_name) - .then((m) => { - postMessage("ok"); - }, - () => postMessage("error")); - } else { - postMessage("unknown message: " + e.data); - } -}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_indexeddb_test.https.html b/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_indexeddb_test.https.html deleted file mode 100644 index 320f046..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_indexeddb_test.https.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/common/get-host-info.sub.js"></script> -<script src="resources/load_wasm.js"></script> -<script src="wasm_indexeddb_test.js"></script> -</head> -<body> -<script> - promise_test(TestIndexedDBLoadStoreSecure, "serialize/deserialize to IndexedDB "); - promise_test(SaveToIDBAndLoadInWorker, "Save to IDB and load in worker"); - promise_test(SaveToIDBInWorkerAndLoadInMain, "Save in worker to IDB and load in window"); -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_indexeddb_test.js b/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_indexeddb_test.js deleted file mode 100644 index a5a582cd..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/wasm/wasm_indexeddb_test.js +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var db_name = "db_wasm_test"; -var obj_store = 'store'; -var module_key = 'my_module'; - -function createAndSaveToIndexedDB(db_name) { - return createWasmModule() - .then(mod => new Promise((resolve, reject) => { - var delete_request = indexedDB.deleteDatabase(db_name); - delete_request.onsuccess = function() { - var open_request = indexedDB.open(db_name); - open_request.onupgradeneeded = function() { - var db = open_request.result; - db.createObjectStore(obj_store); - }; - open_request.onsuccess = function() { - var db = open_request.result; - var tx = db.transaction(obj_store, 'readwrite'); - var store = tx.objectStore(obj_store); - try { - store.put(mod, module_key); - } catch(e) { - db.close(); - reject(e); - return; - } - tx.oncomplete = function() { - db.close(); - resolve(); - return; - }; - }; - }; - })); -} - -function loadFromIndexedDB(db_name) { - var open_request = indexedDB.open(db_name); - - return new Promise((resolve, reject) => { - open_request.onsuccess = function() { - var db = open_request.result; - var tx = db.transaction(obj_store); - var store = tx.objectStore(obj_store); - var get_request = store.get(module_key); - get_request.onsuccess = function() { - var mod = get_request.result; - db.close(); - assert_true(mod instanceof WebAssembly.Module); - try { - var instance = new WebAssembly.Instance(mod); - resolve(instance.exports.increment(1)); - } catch(e) { - reject(e); - } - }; - get_request.onerror = reject; - }; - }); -} - -function TestIndexedDBLoadStoreSecure() { - return createAndSaveToIndexedDB(db_name) - .then(() => loadFromIndexedDB(db_name)) - .then(res => assert_equals(res, 2), - error => assert_unreached(error)); -} - -function TestIndexedDBLoadStoreInsecure() { - return createAndSaveToIndexedDB(db_name) - .then(assert_unreached, - error => { - assert_true(error instanceof DOMException); - assert_equals(error.name, 'DataCloneError'); - }); -} - -function SaveToIDBAndLoadInWorker() { - return createAndSaveToIndexedDB(db_name) - .then(() => { - var worker = new Worker("wasm_idb_worker.js"); - return new Promise((resolve, reject) => { - worker.onmessage = function (event) { - if (typeof (event.data) == "string") { - resolve(event.data); - worker.terminate(); - worker = undefined; - } - }; - worker.postMessage({command: "load", db_name: db_name}); - }) - }) -.then(data => assert_equals(data, "ok"), - error => assert_unreached(error)); -} - -function SaveToIDBInWorkerAndLoadInMain() { - var worker = new Worker("wasm_idb_worker.js"); - var ret = new Promise((resolve, reject) => { - worker.onmessage = function (event) { - if (typeof (event.data) == "string") { - resolve(event.data); - worker.terminate(); - worker = undefined; - } - }; - }) - worker.postMessage({command: "save", db_name: db_name}); - return ret - .then(data => assert_equals(data, "ok"), - error => assert_unreached(error)) - .then(() => loadFromIndexedDB(db_name)) - .then(res => assert_equals(res, 2), - assert_unreached); -}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html new file mode 100644 index 0000000..1f7273f3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCIceTransport-extension.https.html
@@ -0,0 +1,34 @@ +<!doctype html> +<meta charset=utf-8> +<title>RTCIceTransport-extensions.https.html</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +'use strict'; + +// These tests are based on the following extension specification: +// https://w3c.github.io/webrtc-ice/ + +test(() => { + const iceTransport = new RTCIceTransport(); +}, 'RTCIceTransport constructor does not throw.'); + +test(() => { + const iceTransport = new RTCIceTransport(); + assert_equals(iceTransport.role, null, 'Expect role to be null'); + assert_equals(iceTransport.state, 'new', `Expect state to be 'new'`); + assert_equals(iceTransport.gatheringState, 'new', + `Expect gatheringState to be 'new'`); + assert_array_equals(iceTransport.getLocalCandidates(), [], + 'Expect no local candidates'); + assert_array_equals(iceTransport.getRemoteCandidates(), [], + 'Expect no remote candidates'); + assert_equals(iceTransport.getSelectedCandidatePair(), null, + 'Expect no selected candidate pair'); + assert_equals(iceTransport.getLocalParameters(), null, + 'Expect no local parameters'); + assert_equals(iceTransport.getRemoteParameters(), null, + 'Expect no remote parameters'); +}, 'RTCIceTransport initial properties are set.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-constructor-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-constructor-expected.txt index 6e5a466..a20bbe5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-constructor-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-constructor-expected.txt
@@ -13,10 +13,10 @@ PASS new RTCPeerConnection({ certificates: [null] }) PASS new RTCPeerConnection({ certificates: [undefined] }) PASS new RTCPeerConnection({ iceCandidatePoolSize: toNumberThrows }) -FAIL localDescription initial value assert_equals: expected null but got object "[object RTCSessionDescription]" +PASS localDescription initial value FAIL currentLocalDescription initial value assert_equals: expected (object) null but got (undefined) undefined FAIL pendingLocalDescription initial value assert_equals: expected (object) null but got (undefined) undefined -FAIL remoteDescription initial value assert_equals: expected null but got object "[object RTCSessionDescription]" +PASS remoteDescription initial value FAIL currentRemoteDescription initial value assert_equals: expected (object) null but got (undefined) undefined FAIL pendingRemoteDescription initial value assert_equals: expected (object) null but got (undefined) undefined PASS signalingState initial value
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt index 5c5f591..380e5aa3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -321,24 +321,24 @@ FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "getRemoteCertificates()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onstatechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onerror" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL RTCIceTransport interface: existence and properties of interface object assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface object length assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface object name assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute role assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute component assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute state assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute gatheringState assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getLocalCandidates() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getRemoteCandidates() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getSelectedCandidatePair() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getLocalParameters() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getRemoteParameters() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute onstatechange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute ongatheringstatechange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute onselectedcandidatepairchange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing +FAIL RTCIceTransport interface: existence and properties of interface object assert_equals: prototype of RTCIceTransport is not EventTarget expected function "function EventTarget() { [native code] }" but got function "function () { [native code] }" +PASS RTCIceTransport interface object length +PASS RTCIceTransport interface object name +FAIL RTCIceTransport interface: existence and properties of interface prototype object assert_equals: prototype of RTCIceTransport.prototype is not EventTarget.prototype expected object "[object EventTarget]" but got object "[object Object]" +PASS RTCIceTransport interface: existence and properties of interface prototype object's "constructor" property +PASS RTCIceTransport interface: existence and properties of interface prototype object's @@unscopables property +PASS RTCIceTransport interface: attribute role +FAIL RTCIceTransport interface: attribute component assert_true: The prototype object must have a property "component" expected true got false +PASS RTCIceTransport interface: attribute state +PASS RTCIceTransport interface: attribute gatheringState +PASS RTCIceTransport interface: operation getLocalCandidates() +PASS RTCIceTransport interface: operation getRemoteCandidates() +PASS RTCIceTransport interface: operation getSelectedCandidatePair() +PASS RTCIceTransport interface: operation getLocalParameters() +PASS RTCIceTransport interface: operation getRemoteParameters() +FAIL RTCIceTransport interface: attribute onstatechange assert_true: The prototype object must have a property "onstatechange" expected true got false +FAIL RTCIceTransport interface: attribute ongatheringstatechange assert_true: The prototype object must have a property "ongatheringstatechange" expected true got false +FAIL RTCIceTransport interface: attribute onselectedcandidatepairchange assert_true: The prototype object must have a property "onselectedcandidatepairchange" expected true got false FAIL RTCIceTransport must be primary interface of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined" FAIL Stringification of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "role" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import-referrer-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import-referrer-expected.txt new file mode 100644 index 0000000..033d418 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import-referrer-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +FAIL Same-origin top-level module script loading with "no-referrer" referrer policy assert_equals: expected "" but got "http://web-platform.test:8001/workers/modules/resources/new-worker-window.html" +FAIL Same-origin top-level module script loading with "origin" referrer policy assert_equals: expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/workers/modules/resources/new-worker-window.html" +PASS Same-origin top-level module script loading with "same-origin" referrer policy +FAIL Same-origin static import with "no-referrer" referrer policy. assert_equals: expected "" but got "http://web-platform.test:8001/workers/modules/resources/static-import-same-origin-referrer-checker-worker.js" +FAIL Same-origin static import with "origin" referrer policy. assert_equals: expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/workers/modules/resources/static-import-same-origin-referrer-checker-worker.js" +PASS Same-origin static import with "same-origin" referrer policy. +FAIL Cross-origin static import with "no-referrer" referrer policy. assert_equals: expected "" but got "http://web-platform.test:8001/workers/modules/resources/static-import-remote-origin-referrer-checker-worker.sub.js" +FAIL Cross-origin static import with "origin" referrer policy. assert_equals: expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/workers/modules/resources/static-import-remote-origin-referrer-checker-worker.sub.js" +FAIL Cross-origin static import with "same-origin" referrer policy. assert_equals: expected "" but got "http://web-platform.test:8001/workers/modules/resources/static-import-remote-origin-referrer-checker-worker.sub.js" +FAIL Same-origin dynamic import with "no-referrer" referrer policy. assert_equals: expected "" but got "http://web-platform.test:8001/workers/modules/resources/dynamic-import-same-origin-referrer-checker-worker.js" +FAIL Same-origin dynamic import with "origin" referrer policy. assert_equals: expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/workers/modules/resources/dynamic-import-same-origin-referrer-checker-worker.js" +PASS Same-origin dynamic import with "same-origin" referrer policy. +FAIL Cross-origin dynamic import with "no-referrer" referrer policy. assert_equals: expected "" but got "http://web-platform.test:8001/workers/modules/resources/dynamic-import-remote-origin-referrer-checker-worker.sub.js" +FAIL Cross-origin dynamic import with "origin" referrer policy. assert_equals: expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/workers/modules/resources/dynamic-import-remote-origin-referrer-checker-worker.sub.js" +FAIL Cross-origin dynamic import with "same-origin" referrer policy. assert_equals: expected "" but got "http://web-platform.test:8001/workers/modules/resources/dynamic-import-remote-origin-referrer-checker-worker.sub.js" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import-referrer.html b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import-referrer.html index e84b0ad..e13c0e2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import-referrer.html +++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import-referrer.html
@@ -12,11 +12,6 @@ return win; } -// Returns a URL string from the current path and the given relative path. -function createURLString(relative_path) { - return (new URL(relative_path, location.href)).href; -} - // Removes URL parameters from the given URL string and returns it. function removeParams(url_string) { if (!url_string) @@ -27,6 +22,23 @@ return url.href; } +// Generates a referrer given a fetchType, referrer policy, and a request URL +// (used to determine whether request is remote-origin or not). This function +// is used to generate expected referrers. +function generateExpectedReferrer(referrerURL, referrerPolicy, requestURL) { + let generatedReferrer = ""; + if (referrerPolicy === 'no-referrer') + generatedReferrer = ""; + else if (referrerPolicy === 'origin') + generatedReferrer = new URL('resources/' + referrerURL, location.href).origin + '/'; + else if (referrerPolicy === 'same-origin') + generatedReferrer = requestURL.includes('remote') ? "" : new URL('resources/' + referrerURL, location.href).href; + else + generatedReferrer = new URL('resources/' + referrerURL, location.href).href; + + return generatedReferrer; +} + // Runs a referrer policy test with the given settings. This opens a new window // that starts a dedicated worker. // @@ -36,16 +48,16 @@ // scriptURL: 'resources/referrer-checker.sub.js', // windowReferrerPolicy: 'no-referrer', // workerReferrerPolicy: 'same-origin', -// moduleGraphLevel: 'top-level' (or 'descendant') +// fetchType: 'top-level' or 'descendant-static' or 'descendant-dynamic' // }; // // - |scriptURL| is used for starting a new worker. -// - |windowReferrerPolicy| is set to the ReferrerPolicy HTTP header of the +// - |windowReferrerPolicy| is to set the ReferrerPolicy HTTP header of the // window. This policy should be applied to top-level worker module script // loading and static imports. -// - |workerReferrerPolicy| is set to the ReferrerPolicy HTTP header of the +// - |workerReferrerPolicy| is to set the ReferrerPolicy HTTP header of the // worker. This policy should be applied to dynamic imports. -// - |moduleGraphLevel| indicates a script whose referrer will be tested. +// - |fetchType| indicates a script whose referrer will be tested. function import_referrer_test(settings, description) { promise_test(async () => { let windowURL = 'resources/new-worker-window.html'; @@ -68,11 +80,30 @@ win.postMessage(scriptURL, '*'); const msgEvent = await new Promise(resolve => window.onmessage = resolve); + // Generate the expected referrer, given: + // - The fetchType of the test + // - Referrer URL to be used + // - Relevant referrer policy + // - Request URL let expectedReferrer; - if (settings.moduleGraphLevel == 'top-level') - expectedReferrer = createURLString('resources/new-worker-window.html'); - else - expectedReferrer = createURLString('resources/' + settings.scriptURL); + if (settings.fetchType === 'top-level') { + // Top-level worker requests have their outgoing referrers set given their + // containing window's URL and referrer policy. + expectedReferrer = generateExpectedReferrer('new-worker-window.html', settings.windowReferrerPolicy, settings.scriptURL); + } else if (settings.fetchType === 'descendant-static') { + // Static descendant script requests from a worker have their outgoing + // referrer set given their containing script's URL and containing + // window's referrer policy. + + // In the below cases, the referrer URL and the request URLs are the same + // because the initial request (for the top-level worker script) should + // act as the referrer for future descendant requests. + expectedReferrer = generateExpectedReferrer(settings.scriptURL, settings.windowReferrerPolicy, settings.scriptURL); + } else if (settings.fetchType === 'descendant-dynamic') { + // Dynamic descendant script requests from a worker have their outgoing + // referrer set given their containing script's URL and referrer policy. + expectedReferrer = generateExpectedReferrer(settings.scriptURL, settings.workerReferrerPolicy, settings.scriptURL); + } // Delete query parameters from the actual referrer to make it easy to match // it with the expected referrer. @@ -84,128 +115,129 @@ // Tests for top-level worker module script loading. // -// Top-level worker module script loading should obey the default referrer -// policy (not the window's referrer policy), and send the window's URL as a -// referrer. +// Top-level worker module scripts should inherit the containing window's +// referrer policy when using the containing window's URL as the referrer. // // [Current document] // --(open)--> [Window] whose referrer policy is |windowReferrerPolicy|. -// --(new Worker)--> [Worker] should be loaded with [Window]'s URL as a -// referrer regardless of |windowReferrerPolicy|. +// --(new Worker)--> [Worker] should respect [windowReferrerPolicy| when +// using [Window]'s URL as the referrer. import_referrer_test( { scriptURL: 'referrer-checker.py', windowReferrerPolicy: 'no-referrer', - moduleGraphLevel: 'top-level' }, + fetchType: 'top-level' }, 'Same-origin top-level module script loading with "no-referrer" referrer ' + 'policy'); import_referrer_test( { scriptURL: 'referrer-checker.py', windowReferrerPolicy: 'origin', - moduleGraphLevel: 'top-level' }, + fetchType: 'top-level' }, 'Same-origin top-level module script loading with "origin" referrer ' + 'policy'); import_referrer_test( { scriptURL: 'referrer-checker.py', windowReferrerPolicy: 'same-origin', - moduleGraphLevel: 'top-level' }, + fetchType: 'top-level' }, 'Same-origin top-level module script loading with "same-origin" referrer ' + 'policy'); // Tests for static imports. // -// Static imports should obey the default referrer policy, and send the worker's -// URL as a referrer. +// Static imports should inherit the containing window's referrer policy when +// using the containing module script's URL as the referrer. +// Note: This is subject to change in the future; see +// https://github.com/w3c/webappsec-referrer-policy/issues/111. // // [Current document] // --(open)--> [Window] whose referrer policy is |windowReferrerPolicy|. // --(new Worker)--> [Worker] -// --(static import)--> [Script] should be loaded with [Worker]'s URL as a -// referrer regardless of |windowReferrerPolicy|. +// --(static import)--> [Script] should respect |windowReferrerPolicy| when +// using [Worker]'s URL as the referrer. import_referrer_test( { scriptURL: 'static-import-same-origin-referrer-checker-worker.js', windowReferrerPolicy: 'no-referrer', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-static' }, 'Same-origin static import with "no-referrer" referrer policy.'); import_referrer_test( { scriptURL: 'static-import-same-origin-referrer-checker-worker.js', windowReferrerPolicy: 'origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-static' }, 'Same-origin static import with "origin" referrer policy.'); import_referrer_test( { scriptURL: 'static-import-same-origin-referrer-checker-worker.js', windowReferrerPolicy: 'same-origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-static' }, 'Same-origin static import with "same-origin" referrer policy.'); import_referrer_test( { scriptURL: 'static-import-remote-origin-referrer-checker-worker.sub.js', windowReferrerPolicy: 'no-referrer', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-static' }, 'Cross-origin static import with "no-referrer" referrer policy.'); import_referrer_test( { scriptURL: 'static-import-remote-origin-referrer-checker-worker.sub.js', windowReferrerPolicy: 'origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-static' }, 'Cross-origin static import with "origin" referrer policy.'); import_referrer_test( { scriptURL: 'static-import-remote-origin-referrer-checker-worker.sub.js', windowReferrerPolicy: 'same-origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-static' }, 'Cross-origin static import with "same-origin" referrer policy.'); // Tests for dynamic imports. // -// Dynamic imports should obey the default referrer policy (not the worker's -// referrer policy), and send the worker's URL as a referrer. +// Dynamic imports should inherit the containing script's referrer policy if +// set, and use the default referrer policy otherwise, when using the +// containing script's URL as the referrer. // // [Current document] // --(open)--> [Window] // --(new Worker)--> [Worker] whose referrer policy is |workerReferrerPolicy|. -// --(dynamic import)--> [Script] should be loaded with [Worker]'s URL as a -// referrer regardless of |workerReferrerPolicy|. +// --(dynamic import)--> [Script] should respect |workerReferrerPolicy| when +// using [Worker]'s URL as the referrer. import_referrer_test( { scriptURL: 'dynamic-import-same-origin-referrer-checker-worker.js', workerReferrerPolicy: 'no-referrer', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-dynamic' }, 'Same-origin dynamic import with "no-referrer" referrer policy.'); import_referrer_test( { scriptURL: 'dynamic-import-same-origin-referrer-checker-worker.js', workerReferrerPolicy: 'origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-dynamic' }, 'Same-origin dynamic import with "origin" referrer policy.'); import_referrer_test( { scriptURL: 'dynamic-import-same-origin-referrer-checker-worker.js', workerReferrerPolicy: 'same-origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-dynamic' }, 'Same-origin dynamic import with "same-origin" referrer policy.'); import_referrer_test( { scriptURL: 'dynamic-import-remote-origin-referrer-checker-worker.sub.js', workerReferrerPolicy: 'no-referrer', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-dynamic' }, 'Cross-origin dynamic import with "no-referrer" referrer policy.'); import_referrer_test( { scriptURL: 'dynamic-import-remote-origin-referrer-checker-worker.sub.js', workerReferrerPolicy: 'origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-dynamic' }, 'Cross-origin dynamic import with "origin" referrer policy.'); import_referrer_test( { scriptURL: 'dynamic-import-remote-origin-referrer-checker-worker.sub.js', workerReferrerPolicy: 'same-origin', - moduleGraphLevel: 'descendant' }, + fetchType: 'descendant-dynamic' }, 'Cross-origin dynamic import with "same-origin" referrer policy.'); - </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-referrer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-referrer.https-expected.txt new file mode 100644 index 0000000..ba0d50f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/animation-worklet-referrer.https-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +FAIL Importing a same-origin script from a page that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a page that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a page that has "origin" referrer policy should send only an origin as referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a page that has "origin" referrer policy should send only an origin as referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +PASS Importing a same-origin script from a page that has "same-origin" referrer policy should send referrer. +FAIL Importing a remote-origin script from a page that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a same-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a same-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a same-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a same-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +PASS Importing a same-origin script from a same-origin worklet script that has "same-origin" referrer policy should send referrer. +FAIL Importing a remote-origin script from a same-origin worklet script that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/layout-worklet-referrer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/worklets/layout-worklet-referrer.https-expected.txt new file mode 100644 index 0000000..ba0d50f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/layout-worklet-referrer.https-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +FAIL Importing a same-origin script from a page that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a page that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a page that has "origin" referrer policy should send only an origin as referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a page that has "origin" referrer policy should send only an origin as referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +PASS Importing a same-origin script from a page that has "same-origin" referrer policy should send referrer. +FAIL Importing a remote-origin script from a page that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a same-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a same-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a same-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a same-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +PASS Importing a same-origin script from a same-origin worklet script that has "same-origin" referrer policy should send referrer. +FAIL Importing a remote-origin script from a same-origin worklet script that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-referrer.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-referrer.https-expected.txt new file mode 100644 index 0000000..ba0d50f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/paint-worklet-referrer.https-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +FAIL Importing a same-origin script from a page that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a page that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a page that has "origin" referrer policy should send only an origin as referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a page that has "origin" referrer policy should send only an origin as referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +PASS Importing a same-origin script from a page that has "same-origin" referrer policy should send referrer. +FAIL Importing a remote-origin script from a page that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a same-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a same-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "no-referrer" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a same-origin script from a same-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a same-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "origin" referrer policy should send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +PASS Importing a same-origin script from a same-origin worklet script that has "same-origin" referrer policy should send referrer. +FAIL Importing a remote-origin script from a same-origin worklet script that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +FAIL Importing a remote-origin script from a remote-origin worklet script that has "same-origin" referrer policy should not send referrer. assert_equals: expected "RESOLVED" but got "The user aborted a request." +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-checker.py b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-checker.py index 3d9afb4..8f37983 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-checker.py +++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-checker.py
@@ -1,15 +1,24 @@ # Returns a valid response when request's |referrer| matches # |expected_referrer|. def main(request, response): - referrer = request.headers.get("referer", "") + # We want |referrer| to be the referrer header with no query params, + # because |expected_referrer| will not contain any query params, and + # thus cannot be compared with the actual referrer header if it were to + # contain query params. This works fine if the actual referrer has no + # query params too. + referrer = request.headers.get("referer", "").split("?")[0] + referrer_policy = request.GET.first("referrer_policy") expected_referrer = request.GET.first("expected_referrer", "") - response_headers = [("Content-Type", "text/javascript"), ("Access-Control-Allow-Origin", "*")] - # The expected referrer doesn't contain query params for simplification, so - # we check the referrer by startswith() here. - if (expected_referrer != "" and - referrer.startswith(expected_referrer + "?")): - return (200, response_headers, "") + if referrer_policy == "no-referrer" or referrer_policy == "origin": + if referrer == expected_referrer: + return (200, response_headers, "") + return (404, response_headers) + + if referrer_policy == "same-origin": + if referrer == expected_referrer: + return (200, response_headers, "") + return (404, response_headers) return (404, response_headers)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-tests.js b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-tests.js index e46f93db..01b8e2a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-tests.js +++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-tests.js
@@ -29,9 +29,7 @@ }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED')); } -// Runs a series of tests related to the referrer policy on a worklet. Referrer -// on worklet module loading should always be handled with the default referrer -// policy. +// Runs a series of tests related to the referrer policy on a worklet. // // Usage: // runReferrerTests("paint"); @@ -46,7 +44,7 @@ referrerPolicy: 'no-referrer', scriptOrigins: { topLevel: 'same' } }); }, 'Importing a same-origin script from a page that has "no-referrer" ' + - 'referrer policy.'); + 'referrer policy should not send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -54,7 +52,7 @@ referrerPolicy: 'no-referrer', scriptOrigins: { topLevel: 'remote' } }); }, 'Importing a remote-origin script from a page that has "no-referrer" ' + - 'referrer policy.'); + 'referrer policy should not send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -62,7 +60,7 @@ referrerPolicy: 'origin', scriptOrigins: { topLevel: 'same' } }); }, 'Importing a same-origin script from a page that has "origin" ' + - 'referrer policy.'); + 'referrer policy should send only an origin as referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -70,7 +68,7 @@ referrerPolicy: 'origin', scriptOrigins: { topLevel: 'remote' } }); }, 'Importing a remote-origin script from a page that has "origin" ' + - 'referrer policy.'); + 'referrer policy should send only an origin as referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -78,7 +76,7 @@ referrerPolicy: 'same-origin', scriptOrigins: { topLevel: 'same' } }); }, 'Importing a same-origin script from a page that has "same-origin" ' + - 'referrer policy.'); + 'referrer policy should send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -86,7 +84,7 @@ referrerPolicy: 'same-origin', scriptOrigins: { topLevel: 'remote' } }); }, 'Importing a remote-origin script from a page that has "same-origin" ' + - 'referrer policy.'); + 'referrer policy should not send referrer.'); // Tests for descendant script fetch ----------------------------------------- @@ -97,7 +95,7 @@ scriptOrigins: { topLevel: 'same', descendant: 'same' } }); }, 'Importing a same-origin script from a same-origin worklet script that ' + - 'has "no-referrer" referrer policy.'); + 'has "no-referrer" referrer policy should not send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -106,7 +104,7 @@ scriptOrigins: { topLevel: 'same', descendant: 'remote' } }); }, 'Importing a remote-origin script from a same-origin worklet script ' + - 'that has "no-referrer" referrer policy.'); + 'that has "no-referrer" referrer policy should not send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -115,7 +113,7 @@ scriptOrigins: { topLevel: 'remote', descendant: 'remote' } }); }, 'Importing a remote-origin script from a remote-origin worklet script ' + - 'that has "no-referrer" referrer policy.'); + 'that has "no-referrer" referrer policy should not send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -124,7 +122,7 @@ scriptOrigins: { topLevel: 'same', descendant: 'same' } }); }, 'Importing a same-origin script from a same-origin worklet script that ' + - 'has "origin" referrer policy.'); + 'has "origin" referrer policy should send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -133,7 +131,7 @@ scriptOrigins: { topLevel: 'same', descendant: 'remote' } }); }, 'Importing a remote-origin script from a same-origin worklet script ' + - 'that has "origin" referrer policy.'); + 'that has "origin" referrer policy should send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -142,7 +140,7 @@ scriptOrigins: { topLevel: 'remote', descendant: 'remote' } }); }, 'Importing a remote-origin script from a remote-origin worklet script ' + - 'that has "origin" referrer policy.'); + 'that has "origin" referrer policy should send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -151,7 +149,7 @@ scriptOrigins: { topLevel: 'same', descendant: 'same' } }); }, 'Importing a same-origin script from a same-origin worklet script that ' + - 'has "same-origin" referrer policy.'); + 'has "same-origin" referrer policy should send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -160,7 +158,7 @@ scriptOrigins: { topLevel: 'same', descendant: 'remote' } }); }, 'Importing a remote-origin script from a same-origin worklet script ' + - 'that has "same-origin" referrer policy.'); + 'that has "same-origin" referrer policy should not send referrer.'); promise_test(() => { return runReferrerTest({ workletType: workletType, @@ -169,5 +167,5 @@ scriptOrigins: { topLevel: 'remote', descendant: 'remote' } }); }, 'Importing a remote-origin script from a remote-origin worklet script ' + - 'that has "same-origin" referrer policy.'); + 'that has "same-origin" referrer policy should not send referrer.'); }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-window.html b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-window.html index 331db0793..4817f045 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-window.html +++ b/third_party/WebKit/LayoutTests/external/wpt/worklets/resources/referrer-window.html
@@ -48,30 +48,47 @@ assert_unreached('fetchType has an invalid value.'); } +function createExpectedReferrer( + importerURL, fetchType, referrerPolicy, scriptOrigins) { + if (referrerPolicy === 'no-referrer') + return ""; + if (referrerPolicy === 'same-origin') { + if (isDestinationCrossOrigin(fetchType, scriptOrigins)) + return ""; + // Delete query params to make it easier to match with an actual referrer in + // the referrer-checker.py. + const expectedReferrer = new URL(importerURL); + for (var key of expectedReferrer.searchParams.keys()) + expectedReferrer.searchParams.delete(key); + return expectedReferrer; + } + if (referrerPolicy === 'origin') + return (new URL(importerURL)).origin + '/'; + assert_unreached('referrerPolicy has an invalid value.'); +} + window.onmessage = e => { const workletType = e.data.workletType; const fetchType = e.data.fetchType; + const referrerPolicy = e.data.referrerPolicy; const scriptOrigins = e.data.scriptOrigins; let scriptURL; let expectedReferrer; if (fetchType === 'top-level') { scriptURL = createScriptURLForTopLevel(scriptOrigins.topLevel); - // The referrer of the top-level script should be this file. - // Delete query params to make it easier to match with an actual referrer in - // the referrer-checker.py. - expectedReferrer = new URL(location.href); - for (var key of expectedReferrer.searchParams.keys()) - expectedReferrer.searchParams.delete(key); + expectedReferrer = createExpectedReferrer( + location.href, fetchType, referrerPolicy, scriptOrigins); } else if (fetchType === 'descendant') { scriptURL = createScriptURLForDecendant(scriptOrigins); - // The referrer of the imported script should be the importer script. - expectedReferrer = scriptURL; + expectedReferrer = createExpectedReferrer( + scriptURL, fetchType, referrerPolicy, scriptOrigins); } else { assert_unreached('fetchType should be \'top-level\' or \'descendant\''); } const params = new URLSearchParams; + params.append('referrer_policy', referrerPolicy); params.append('expected_referrer', expectedReferrer); get_worklet(workletType).addModule(scriptURL + '?' + params)
diff --git a/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html b/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html index c0d358148..30e177e 100644 --- a/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html +++ b/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html
@@ -9,26 +9,6 @@ const redStyleTexts = [".red { color: red; }", ".red + span + span { color: red; }"]; test(() => { - const sheet = new CSSStyleSheet({title: "Red", disabled: true, media: "screen, print"}); - assert_equals(sheet.title, "Red"); - assert_equals(sheet.ownerNode, null); - assert_equals(sheet.ownerRule, null); - assert_equals(sheet.media.length, 2); - assert_equals(sheet.media.item(0), "screen"); - assert_equals(sheet.media.item(1), "print"); - assert_true(sheet.disabled); - assert_equals(sheet.cssRules.length, 0); - - sheet.insertRule(redStyleTexts[0]); - assert_equals(sheet.cssRules.length, 1); - assert_equals(sheet.cssRules[0].cssText, redStyleTexts[0]); - - sheet.insertRule(redStyleTexts[1]); - assert_equals(sheet.cssRules.length, 2); - assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]); -}, 'Empty CSSStyleSheet can be constructed using script'); - -test(() => { const sheet = document.createEmptyCSSStyleSheet({title: "Red", disabled: true, media: "screen, print"}); assert_equals(sheet.title, "Red"); assert_equals(sheet.ownerNode, null);
diff --git a/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt index 39d0f34..ee72f095 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/dom-constructors-expected.txt
@@ -74,7 +74,7 @@ PASS TryAllocate('CSSRuleList') is 'exception' PASS TryAllocate('CSSStyleDeclaration') is 'exception' PASS TryAllocate('CSSStyleRule') is 'exception' -FAIL TryAllocate('CSSStyleSheet') should be exception. Was [object CSSStyleSheet]. +PASS TryAllocate('CSSStyleSheet') is 'exception' PASS TryAllocate('DOMImplementation') is 'exception' PASS TryAllocate('HTMLCollection') is 'exception' PASS TryAllocate('MediaList') is 'exception'
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/unit/soft-context-menu.js b/third_party/WebKit/LayoutTests/http/tests/devtools/unit/soft-context-menu.js index 311ae06..6552c13 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/unit/soft-context-menu.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/unit/soft-context-menu.js
@@ -76,13 +76,14 @@ do { if (selection) selection += ' -> '; - if (subMenu._contextMenuElement === activeElement) + const focused = (subMenu._highlightedMenuItemElement || subMenu._contextMenuElement) === activeElement; + if (focused) selection += '['; if (subMenu._highlightedMenuItemElement) selection += subMenu._highlightedMenuItemElement.textContent.replace(/[^A-z0-9 ]/g, ''); else selection += 'null' - if (subMenu._contextMenuElement === activeElement) + if (focused) selection += ']'; } while (subMenu = subMenu._subMenu)
diff --git a/third_party/WebKit/LayoutTests/media/controls/offline-play-button-expected.html b/third_party/WebKit/LayoutTests/media/controls/offline-play-button-expected.html new file mode 100644 index 0000000..4aa0458 --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/controls/offline-play-button-expected.html
@@ -0,0 +1 @@ +<video controls>
diff --git a/third_party/WebKit/LayoutTests/media/controls/offline-play-button.mht b/third_party/WebKit/LayoutTests/media/controls/offline-play-button.mht new file mode 100644 index 0000000..f2a1bddb --- /dev/null +++ b/third_party/WebKit/LayoutTests/media/controls/offline-play-button.mht
@@ -0,0 +1,19 @@ +From: <Saved by Blink> +Snapshot-Content-Location: data:text/html,<video controls> +Subject: +Date: Wed, 8 Aug 2018 03:40:01 -0000 +MIME-Version: 1.0 +Content-Type: multipart/related; + type="text/html"; + boundary="----MultipartBoundary--vMHcSo6MOQ8bNqjzscEyfel3Kzz93I3pZg8BXOlrNK----" + + +------MultipartBoundary--vMHcSo6MOQ8bNqjzscEyfel3Kzz93I3pZg8BXOlrNK---- +Content-Type: text/html +Content-ID: <frame-EABF2B3BFD6D225D86B7362F1A016751@mhtml.blink> +Content-Transfer-Encoding: quoted-printable +Content-Location: data:text/html,<video controls> + +<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset= +=3Dwindows-1252"></head><body><video controls=3D""></video></body></html> +------MultipartBoundary--vMHcSo6MOQ8bNqjzscEyfel3Kzz93I3pZg8BXOlrNK------
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt index 7bbf22f1..c3830b6 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-absolute-layer-with-reflection-expected.txt
@@ -45,10 +45,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'", - "reason": "full" - }, - { "object": "LayoutBlockFlow (relative positioned) DIV class='relative reflected'", "reason": "geometry" },
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt index c3d8353..8f28c78 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
@@ -45,10 +45,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'", - "reason": "full" - }, - { "object": "LayoutBlockFlow (positioned) DIV class='absolute green reflected'", "reason": "geometry" },
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/document-flipped-blocks-writing-mode-scroll-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/document-flipped-blocks-writing-mode-scroll-expected.png similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/document-flipped-blocks-writing-mode-scroll-expected.png rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/document-flipped-blocks-writing-mode-scroll-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.png similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.png rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/fixed-img-src-change-after-scroll-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/iframe-scroll-repaint-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/iframe-scroll-repaint-expected.txt index 85d9057..f5ed717 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/iframe-scroll-repaint-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/iframe-scroll-repaint-expected.txt
@@ -1,9 +1,4 @@ { - "objectPaintInvalidations": [ - { - "object": "LayoutView #document", - "reason": "full" - } - ] + }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt index b0a29f0..13b1cfa 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -32,10 +32,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow DIV id='innerDiv'", - "reason": "full" - }, - { "object": "VerticalScrollbar", "reason": "scroll control" }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt index c971603..662ba22 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled-expected.txt
@@ -32,10 +32,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow DIV class='innerWrapper'", - "reason": "full" - }, - { "object": "LayoutBlockFlow DIV class='red'", "reason": "geometry" },
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt index 33e32fc..a688cc26 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-expected.txt
@@ -25,22 +25,11 @@ "paintInvalidations": [ { "object": "LayoutBlockFlow DIV id='scroller'", - "rect": [0, 0, 302, 302], - "reason": "full" - }, - { - "object": "LayoutBlockFlow DIV id='scroller'", "rect": [1, 201, 100, 100], "reason": "chunk appeared" } ] } - ], - "objectPaintInvalidations": [ - { - "object": "LayoutBlockFlow DIV id='scroller'", - "reason": "full" - } ] }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt index 88e6b62..922711a 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar-expected.txt
@@ -24,23 +24,12 @@ "backfaceVisibility": "hidden", "paintInvalidations": [ { - "object": "LayoutBlockFlow DIV id='scroller'", - "rect": [0, 0, 302, 302], - "reason": "full" - }, - { "object": "LayoutBlockFlow DIV id='target'", "rect": [1, 201, 100, 100], "reason": "chunk appeared" } ] } - ], - "objectPaintInvalidations": [ - { - "object": "LayoutBlockFlow DIV id='scroller'", - "reason": "full" - } ] }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt index 615ed6c9..5d81d66 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
@@ -18,11 +18,6 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutBlockFlow DIV class='scroller'", - "rect": [18, 60, 310, 200], - "reason": "full" - }, - { "object": "LayoutBlockFlow (positioned) DIV class='back'", "rect": [93, 125, 180, 100], "reason": "paint property change" @@ -77,10 +72,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow DIV class='scroller'", - "reason": "full" - }, - { "object": "VerticalScrollbar", "reason": "scroll control" }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt index b0a29f0..13b1cfa 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -32,10 +32,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow DIV id='innerDiv'", - "reason": "full" - }, - { "object": "VerticalScrollbar", "reason": "scroll control" }
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/overflow-scroll-local-background-text-color-change-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-local-background-text-color-change-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/overflow-scroll-local-background-text-color-change-expected.txt rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/overflow-scroll-local-background-text-color-change-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.png similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.png rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt index 958284e..06fd400 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer-expected.txt
@@ -45,10 +45,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'", - "reason": "full" - }, - { "object": "LayoutBlockFlow (positioned) DIV class='absolute green'", "reason": "geometry" },
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt index 511b1aa..d39a9c0 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-clipped-layer-expected.txt
@@ -32,10 +32,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'", - "reason": "full" - }, - { "object": "LayoutBlockFlow (relative positioned) DIV class='relative green'", "reason": "geometry" },
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt index 63c5448..bbaa509 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
@@ -45,10 +45,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'", - "reason": "full" - }, - { "object": "LayoutBlockFlow (positioned) DIV class='absolute green'", "reason": "geometry" },
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt index 7dc14b5..009a0e4f 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-in-transformed-layer-expected.txt
@@ -33,7 +33,7 @@ "objectPaintInvalidations": [ { "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped rotated'", - "reason": "full" + "reason": "style change" }, { "object": "LayoutBlockFlow (positioned) DIV class='absolute green'",
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.png b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.png similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.png rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt rename to third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt index 2b950e5f..3cef082d 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/scroll/scroll-with-transformed-parent-layer-expected.txt
@@ -29,12 +29,6 @@ } ] } - ], - "objectPaintInvalidations": [ - { - "object": "LayoutBlockFlow (positioned) DIV id='moveMe' class='absolute clipped'", - "reason": "full" - } ] }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt index 5727385..2a60c32 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-inside-table-cell-expected.txt
@@ -18,11 +18,6 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'", - "rect": [312, 112, 454, 469], - "reason": "full" - }, - { "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'", "rect": [314, 114, 435, 450], "reason": "paint property change" @@ -37,10 +32,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'", - "reason": "full" - }, - { "object": "HorizontalScrollbar", "reason": "scroll control" }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt index 179f292..e4529f2 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/scroll-relative-table-inside-table-cell-expected.txt
@@ -18,11 +18,6 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'", - "rect": [1112, 1312, 454, 469], - "reason": "full" - }, - { "object": "LayoutBlockFlow (relative positioned) DIV class='relative red'", "rect": [1114, 1314, 435, 450], "reason": "paint property change" @@ -50,10 +45,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutTableCell (relative positioned) TD id='cellToScroll' class='relative'", - "reason": "full" - }, - { "object": "HorizontalScrollbar", "reason": "scroll control" }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt index 10b246a..9675bc2 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -32,10 +32,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow DIV id='innerDiv'", - "reason": "full" - }, - { "object": "VerticalScrollbar", "reason": "scroll control" }
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt index 10b246a..9675bc2 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -32,10 +32,6 @@ ], "objectPaintInvalidations": [ { - "object": "LayoutBlockFlow DIV id='innerDiv'", - "reason": "full" - }, - { "object": "VerticalScrollbar", "reason": "scroll control" }
diff --git a/third_party/WebKit/LayoutTests/paint/masks/mask-change-crash.html b/third_party/WebKit/LayoutTests/paint/masks/mask-change-crash.html new file mode 100644 index 0000000..746ffcff --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/masks/mask-change-crash.html
@@ -0,0 +1,13 @@ +<!doctype HTML> +<script src="../../resources/run-after-layout-and-paint.js"></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> +async_test(t => { + runAfterLayoutAndPaint(t.step_func_done(() => { + target.style.webkitMaskImage = 'url(#foo)'; + })); +}); +</script> +Passes if it does not crash. +<textarea style="transform: translateX(1px)" id="target"></textarea>
diff --git a/third_party/WebKit/LayoutTests/platform/android/external/wpt/dom/historical-expected.txt b/third_party/WebKit/LayoutTests/platform/android/external/wpt/dom/historical-expected.txt deleted file mode 100644 index bf2c547..0000000 --- a/third_party/WebKit/LayoutTests/platform/android/external/wpt/dom/historical-expected.txt +++ /dev/null
@@ -1,76 +0,0 @@ -This is a testharness.js-based test. -Found 72 tests; 68 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS Historical DOM features must be removed: DOMConfiguration -FAIL Historical DOM features must be removed: DOMError assert_equals: expected (undefined) undefined but got (function) function "function DOMError() { [native code] }" -PASS Historical DOM features must be removed: DOMErrorHandler -PASS Historical DOM features must be removed: DOMImplementationList -PASS Historical DOM features must be removed: DOMImplementationSource -PASS Historical DOM features must be removed: DOMLocator -PASS Historical DOM features must be removed: DOMObject -PASS Historical DOM features must be removed: DOMSettableTokenList -PASS Historical DOM features must be removed: DOMUserData -PASS Historical DOM features must be removed: Entity -PASS Historical DOM features must be removed: EntityReference -PASS Historical DOM features must be removed: EventException -PASS Historical DOM features must be removed: NameList -PASS Historical DOM features must be removed: Notation -PASS Historical DOM features must be removed: TypeInfo -PASS Historical DOM features must be removed: UserDataHandler -PASS Historical DOM features must be removed: RangeException -PASS Historical DOM features must be removed: createEntityReference -FAIL Historical DOM features must be removed: xmlEncoding assert_equals: expected (undefined) undefined but got (object) null -FAIL Historical DOM features must be removed: xmlStandalone assert_equals: expected (undefined) undefined but got (boolean) false -FAIL Historical DOM features must be removed: xmlVersion assert_equals: expected (undefined) undefined but got (object) null -PASS Historical DOM features must be removed: strictErrorChecking -PASS Historical DOM features must be removed: domConfig -PASS Historical DOM features must be removed: normalizeDocument -PASS Historical DOM features must be removed: renameNode -PASS Historical DOM features must be removed: defaultCharset -PASS Historical DOM features must be removed: height -PASS Historical DOM features must be removed: width -PASS Historical DOM features must be removed: commands -PASS Historical DOM features must be removed: cssElementMap -PASS Historical DOM features must be removed: async -PASS document.load -PASS DOMImplementation.getFeature() must be nuked. -PASS Historical DOM features must be removed: schemaTypeInfo -PASS Historical DOM features must be removed: setIdAttribute -PASS Historical DOM features must be removed: setIdAttributeNS -PASS Historical DOM features must be removed: setIdAttributeNode -PASS Attr member must be nuked: schemaTypeInfo -PASS Attr member must be nuked: isId -PASS DocumentType member must be nuked: entities -PASS DocumentType member must be nuked: notations -PASS DocumentType member must be nuked: internalSubset -PASS Text member must be nuked: isElementContentWhitespace -PASS Text member must be nuked: replaceWholeText -PASS Node member must be nuked: hasAttributes -PASS Node member must be nuked: attributes -PASS Node member must be nuked: namespaceURI -PASS Node member must be nuked: prefix -PASS Node member must be nuked: localName -PASS Node member must be nuked: isSupported -PASS Node member must be nuked: getFeature -PASS Node member must be nuked: getUserData -PASS Node member must be nuked: setUserData -PASS Node member must be nuked: rootNode -PASS Window member must be nuked: attachEvent -PASS Event should not have this constant: MOUSEDOWN -PASS Event should not have this constant: MOUSEUP -PASS Event should not have this constant: MOUSEOVER -PASS Event should not have this constant: MOUSEOUT -PASS Event should not have this constant: MOUSEMOVE -PASS Event should not have this constant: MOUSEDRAG -PASS Event should not have this constant: CLICK -PASS Event should not have this constant: DBLCLICK -PASS Event should not have this constant: KEYDOWN -PASS Event should not have this constant: KEYUP -PASS Event should not have this constant: KEYPRESS -PASS Event should not have this constant: DRAGDROP -PASS Event should not have this constant: FOCUS -PASS Event should not have this constant: BLUR -PASS Event should not have this constant: SELECT -PASS Event should not have this constant: CHANGE -PASS Event.prototype should not have this property: getPreventDefault -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt index 7311d7db..0dd8fb6 100644 --- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -321,24 +321,24 @@ FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "getRemoteCertificates()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onstatechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onerror" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL RTCIceTransport interface: existence and properties of interface object assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface object length assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface object name assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute role assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute component assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute state assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute gatheringState assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getLocalCandidates() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getRemoteCandidates() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getSelectedCandidatePair() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getLocalParameters() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: operation getRemoteParameters() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute onstatechange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute ongatheringstatechange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing -FAIL RTCIceTransport interface: attribute onselectedcandidatepairchange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing +FAIL RTCIceTransport interface: existence and properties of interface object assert_equals: prototype of RTCIceTransport is not EventTarget expected function "function EventTarget() { [native code] }" but got function "function () { [native code] }" +PASS RTCIceTransport interface object length +PASS RTCIceTransport interface object name +FAIL RTCIceTransport interface: existence and properties of interface prototype object assert_equals: prototype of RTCIceTransport.prototype is not EventTarget.prototype expected object "[object EventTarget]" but got object "[object Object]" +PASS RTCIceTransport interface: existence and properties of interface prototype object's "constructor" property +PASS RTCIceTransport interface: existence and properties of interface prototype object's @@unscopables property +PASS RTCIceTransport interface: attribute role +FAIL RTCIceTransport interface: attribute component assert_true: The prototype object must have a property "component" expected true got false +PASS RTCIceTransport interface: attribute state +PASS RTCIceTransport interface: attribute gatheringState +PASS RTCIceTransport interface: operation getLocalCandidates() +PASS RTCIceTransport interface: operation getRemoteCandidates() +PASS RTCIceTransport interface: operation getSelectedCandidatePair() +PASS RTCIceTransport interface: operation getLocalParameters() +PASS RTCIceTransport interface: operation getRemoteParameters() +FAIL RTCIceTransport interface: attribute onstatechange assert_true: The prototype object must have a property "onstatechange" expected true got false +FAIL RTCIceTransport interface: attribute ongatheringstatechange assert_true: The prototype object must have a property "ongatheringstatechange" expected true got false +FAIL RTCIceTransport interface: attribute onselectedcandidatepairchange assert_true: The prototype object must have a property "onselectedcandidatepairchange" expected true got false FAIL RTCIceTransport must be primary interface of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined" FAIL Stringification of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined" FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "role" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index c763cbe0..30ed8b3 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -5425,6 +5425,17 @@ setter candidate setter sdpMLineIndex setter sdpMid +interface RTCIceTransport + attribute @@toStringTag + getter gatheringState + getter role + getter state + method constructor + method getLocalCandidates + method getLocalParameters + method getRemoteCandidates + method getRemoteParameters + method getSelectedCandidatePair interface RTCPeerConnection : EventTarget static method generateCertificate attribute @@toStringTag
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium index a48e31e..91d6d38 100644 --- a/third_party/abseil-cpp/README.chromium +++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@ License: Apache 2.0 License File: LICENSE Version: 0 -Revision: 8f612ebb152fb7e05643a2bcf78cb89a8c0641ad +Revision: bea85b52733022294eef108a2e42d77b616ddca2 Security Critical: yes Description:
diff --git a/third_party/abseil-cpp/WORKSPACE b/third_party/abseil-cpp/WORKSPACE index a7b1c139..e4a91197 100644 --- a/third_party/abseil-cpp/WORKSPACE +++ b/third_party/abseil-cpp/WORKSPACE
@@ -1,4 +1,6 @@ workspace(name = "com_google_absl") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + # Bazel toolchains http_archive( name = "bazel_toolchains", @@ -13,9 +15,9 @@ # GoogleTest/GoogleMock framework. Used by most unit-tests. http_archive( name = "com_google_googletest", - urls = ["https://github.com/google/googletest/archive/4e4df226fc197c0dda6e37f5c8c3845ca1e73a49.zip"], - strip_prefix = "googletest-4e4df226fc197c0dda6e37f5c8c3845ca1e73a49", - sha256 = "d4179caf54410968d1fff0b869e7d74803dd30209ee6645ccf1ca65ab6cf5e5a", + urls = ["https://github.com/google/googletest/archive/b4d4438df9479675a632b2f11125e57133822ece.zip"], # 2018-07-16 + strip_prefix = "googletest-b4d4438df9479675a632b2f11125e57133822ece", + sha256 = "5aaa5d566517cae711e2a3505ea9a6438be1b37fcaae0ebcb96ccba9aa56f23a", ) # Google benchmark. @@ -25,11 +27,3 @@ strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be", sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3", ) - -# RE2 regular-expression framework. Used by some unit-tests. -http_archive( - name = "com_googlesource_code_re2", - urls = ["https://github.com/google/re2/archive/6cf8ccd82dbaab2668e9b13596c68183c9ecd13f.zip"], - strip_prefix = "re2-6cf8ccd82dbaab2668e9b13596c68183c9ecd13f", - sha256 = "279a852219dbfc504501775596089d30e9c0b29664ce4128b0ac4c841471a16a", -)
diff --git a/third_party/abseil-cpp/absl/BUILD.bazel b/third_party/abseil-cpp/absl/BUILD.bazel index 439addbf..edd0274c 100644 --- a/third_party/abseil-cpp/absl/BUILD.bazel +++ b/third_party/abseil-cpp/absl/BUILD.bazel
@@ -18,11 +18,10 @@ licenses(["notice"]) # Apache 2.0 -config_setting( +load(":compiler_config_setting.bzl", "create_llvm_config") + +create_llvm_config( name = "llvm_compiler", - values = { - "compiler": "llvm", - }, visibility = [":__subpackages__"], )
diff --git a/third_party/abseil-cpp/absl/algorithm/container.h b/third_party/abseil-cpp/absl/algorithm/container.h index acddec48..6af8c097 100644 --- a/third_party/abseil-cpp/absl/algorithm/container.h +++ b/third_party/abseil-cpp/absl/algorithm/container.h
@@ -314,7 +314,7 @@ // c_mismatch() // -// Container-based version of the <algorithm> `std::mismatchf()` function to +// Container-based version of the <algorithm> `std::mismatch()` function to // return the first element where two ordered containers differ. template <typename C1, typename C2> container_algorithm_internal::ContainerIterPairType<C1, C2>
diff --git a/third_party/abseil-cpp/absl/base/BUILD.bazel b/third_party/abseil-cpp/absl/base/BUILD.bazel index 35414a2..06d092e 100644 --- a/third_party/abseil-cpp/absl/base/BUILD.bazel +++ b/third_party/abseil-cpp/absl/base/BUILD.bazel
@@ -362,6 +362,7 @@ copts = ABSL_TEST_COPTS, deps = [ ":base", + "//absl/strings", "@com_google_googletest//:gtest_main", ], )
diff --git a/third_party/abseil-cpp/absl/base/CMakeLists.txt b/third_party/abseil-cpp/absl/base/CMakeLists.txt index 303533e2..01d2af08 100644 --- a/third_party/abseil-cpp/absl/base/CMakeLists.txt +++ b/third_party/abseil-cpp/absl/base/CMakeLists.txt
@@ -310,7 +310,7 @@ # test raw_logging_test set(RAW_LOGGING_TEST_SRC "raw_logging_test.cc") -set(RAW_LOGGING_TEST_PUBLIC_LIBRARIES absl::base) +set(RAW_LOGGING_TEST_PUBLIC_LIBRARIES absl::base absl::strings) absl_test( TARGET
diff --git a/third_party/abseil-cpp/absl/base/config.h b/third_party/abseil-cpp/absl/base/config.h index 2f5f159..6890e31 100644 --- a/third_party/abseil-cpp/absl/base/config.h +++ b/third_party/abseil-cpp/absl/base/config.h
@@ -268,7 +268,7 @@ #error ABSL_HAVE_MMAP cannot be directly set #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \ - defined(__wasm__) || defined(__Fuchsia__) + defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) #define ABSL_HAVE_MMAP 1 #endif
diff --git a/third_party/abseil-cpp/absl/base/internal/endian_test.cc b/third_party/abseil-cpp/absl/base/internal/endian_test.cc index f3ff4b3..e276915 100644 --- a/third_party/abseil-cpp/absl/base/internal/endian_test.cc +++ b/third_party/abseil-cpp/absl/base/internal/endian_test.cc
@@ -33,32 +33,16 @@ const int kNumValuesToTest = 1000000; const int kRandomSeed = 12345; -#ifdef ABSL_IS_BIG_ENDIAN +#if defined(ABSL_IS_BIG_ENDIAN) const uint64_t kInitialInNetworkOrder{kInitialNumber}; const uint64_t k64ValueLE{0xefcdab8967452301}; const uint32_t k32ValueLE{0x67452301}; const uint16_t k16ValueLE{0x2301}; -const uint8_t k8ValueLE{k8Value}; -const uint64_t k64IValueLE{0xefcdab89674523a1}; -const uint32_t k32IValueLE{0x67452391}; -const uint16_t k16IValueLE{0x85ff}; -const uint8_t k8IValueLE{0xff}; -const uint64_t kDoubleValueLE{0x6e861bf0f9210940}; -const uint32_t kFloatValueLE{0xd00f4940}; -const uint8_t kBoolValueLE{0x1}; const uint64_t k64ValueBE{kInitialNumber}; const uint32_t k32ValueBE{k32Value}; const uint16_t k16ValueBE{k16Value}; -const uint8_t k8ValueBE{k8Value}; -const uint64_t k64IValueBE{0xa123456789abcdef}; -const uint32_t k32IValueBE{0x91234567}; -const uint16_t k16IValueBE{0xff85}; -const uint8_t k8IValueBE{0xff}; -const uint64_t kDoubleValueBE{0x400921f9f01b866e}; -const uint32_t kFloatValueBE{0x40490fd0}; -const uint8_t kBoolValueBE{0x1}; -#elif defined ABSL_IS_LITTLE_ENDIAN +#elif defined(ABSL_IS_LITTLE_ENDIAN) const uint64_t kInitialInNetworkOrder{0xefcdab8967452301}; const uint64_t k64ValueLE{kInitialNumber}; const uint32_t k32ValueLE{k32Value};
diff --git a/third_party/abseil-cpp/absl/base/internal/exception_testing.h b/third_party/abseil-cpp/absl/base/internal/exception_testing.h index fd89a3f..0cf7918e 100644 --- a/third_party/abseil-cpp/absl/base/internal/exception_testing.h +++ b/third_party/abseil-cpp/absl/base/internal/exception_testing.h
@@ -35,7 +35,7 @@ EXPECT_DEATH(expr, ".*") #else #define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \ - EXPECT_DEATH(expr, text) + EXPECT_DEATH_IF_SUPPORTED(expr, text) #endif
diff --git a/third_party/abseil-cpp/absl/base/internal/raw_logging.cc b/third_party/abseil-cpp/absl/base/internal/raw_logging.cc index 1ce1388..d9485a6 100644 --- a/third_party/abseil-cpp/absl/base/internal/raw_logging.cc +++ b/third_party/abseil-cpp/absl/base/internal/raw_logging.cc
@@ -139,7 +139,7 @@ #endif #ifdef ABSL_MIN_LOG_LEVEL - if (static_cast<int>(severity) < ABSL_MIN_LOG_LEVEL && + if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) && severity < absl::LogSeverity::kFatal) { enabled = false; } @@ -206,6 +206,15 @@ va_end(ap); } +// Non-formatting version of RawLog(). +// +// TODO(gfalcon): When string_view no longer depends on base, change this +// interface to take its message as a string_view instead. +static void DefaultInternalLog(absl::LogSeverity severity, const char* file, + int line, const std::string& message) { + RawLog(severity, file, line, "%s", message.c_str()); +} + bool RawLoggingFullySupported() { #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED return true; @@ -214,5 +223,12 @@ #endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED } +ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction> + internal_log_function(DefaultInternalLog); + +void RegisterInternalLogFunction(InternalLogFunction func) { + internal_log_function.Store(func); +} + } // namespace raw_logging_internal } // namespace absl
diff --git a/third_party/abseil-cpp/absl/base/internal/raw_logging.h b/third_party/abseil-cpp/absl/base/internal/raw_logging.h index a2b7207..67abfd3 100644 --- a/third_party/abseil-cpp/absl/base/internal/raw_logging.h +++ b/third_party/abseil-cpp/absl/base/internal/raw_logging.h
@@ -19,7 +19,10 @@ #ifndef ABSL_BASE_INTERNAL_RAW_LOGGING_H_ #define ABSL_BASE_INTERNAL_RAW_LOGGING_H_ +#include <string> + #include "absl/base/attributes.h" +#include "absl/base/internal/atomic_hook.h" #include "absl/base/log_severity.h" #include "absl/base/macros.h" #include "absl/base/port.h" @@ -57,6 +60,34 @@ } \ } while (0) +// ABSL_INTERNAL_LOG and ABSL_INTERNAL_CHECK work like the RAW variants above, +// except that if the richer log library is linked into the binary, we dispatch +// to that instead. This is potentially useful for internal logging and +// assertions, where we are using RAW_LOG neither for its async-signal-safety +// nor for its non-allocating nature, but rather because raw logging has very +// few other dependencies. +// +// The API is a subset of the above: each macro only takes two arguments. Use +// StrCat if you need to build a richer message. +#define ABSL_INTERNAL_LOG(severity, message) \ + do { \ + constexpr const char* absl_raw_logging_internal_basename = \ + ::absl::raw_logging_internal::Basename(__FILE__, \ + sizeof(__FILE__) - 1); \ + ::absl::raw_logging_internal::internal_log_function( \ + ABSL_RAW_LOGGING_INTERNAL_##severity, \ + absl_raw_logging_internal_basename, __LINE__, message); \ + } while (0) + +#define ABSL_INTERNAL_CHECK(condition, message) \ + do { \ + if (ABSL_PREDICT_FALSE(!(condition))) { \ + std::string death_message = "Check " #condition " failed: "; \ + death_message += std::string(message); \ + ABSL_INTERNAL_LOG(FATAL, death_message); \ + } \ + } while (0) + #define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo #define ABSL_RAW_LOGGING_INTERNAL_WARNING ::absl::LogSeverity::kWarning #define ABSL_RAW_LOGGING_INTERNAL_ERROR ::absl::LogSeverity::kError @@ -131,6 +162,18 @@ using AbortHook = void (*)(const char* file, int line, const char* buf_start, const char* prefix_end, const char* buf_end); +// Internal logging function for ABSL_INTERNAL_LOG to dispatch to. +// +// TODO(gfalcon): When string_view no longer depends on base, change this +// interface to take its message as a string_view instead. +using InternalLogFunction = void (*)(absl::LogSeverity severity, + const char* file, int line, + const std::string& message); + +extern base_internal::AtomicHook<InternalLogFunction> internal_log_function; + +void RegisterInternalLogFunction(InternalLogFunction func); + } // namespace raw_logging_internal } // namespace absl
diff --git a/third_party/abseil-cpp/absl/base/internal/unaligned_access.h b/third_party/abseil-cpp/absl/base/internal/unaligned_access.h index c572436..5c7517abd 100644 --- a/third_party/abseil-cpp/absl/base/internal/unaligned_access.h +++ b/third_party/abseil-cpp/absl/base/internal/unaligned_access.h
@@ -103,6 +103,47 @@ #define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \ (absl::UnalignedStore64(_p, _val)) +#elif defined(UNDEFINED_BEHAVIOR_SANITIZER) + +namespace absl { + +inline uint16_t UnalignedLoad16(const void *p) { + uint16_t t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint32_t UnalignedLoad32(const void *p) { + uint32_t t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint64_t UnalignedLoad64(const void *p) { + uint64_t t; + memcpy(&t, p, sizeof t); + return t; +} + +inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); } + +inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); } + +inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); } + +} // namespace absl + +#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) (absl::UnalignedLoad16(_p)) +#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) (absl::UnalignedLoad32(_p)) +#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) (absl::UnalignedLoad64(_p)) + +#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \ + (absl::UnalignedStore16(_p, _val)) +#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \ + (absl::UnalignedStore32(_p, _val)) +#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \ + (absl::UnalignedStore64(_p, _val)) + #elif defined(__x86_64__) || defined(_M_X64) || defined(__i386) || \ defined(_M_IX86) || defined(__ppc__) || defined(__PPC__) || \ defined(__ppc64__) || defined(__PPC64__)
diff --git a/third_party/abseil-cpp/absl/base/raw_logging_test.cc b/third_party/abseil-cpp/absl/base/raw_logging_test.cc index dae4b351..ebbc5db90 100644 --- a/third_party/abseil-cpp/absl/base/raw_logging_test.cc +++ b/third_party/abseil-cpp/absl/base/raw_logging_test.cc
@@ -18,12 +18,20 @@ #include "absl/base/internal/raw_logging.h" +#include <tuple> + #include "gtest/gtest.h" +#include "absl/strings/str_cat.h" namespace { TEST(RawLoggingCompilationTest, Log) { ABSL_RAW_LOG(INFO, "RAW INFO: %d", 1); + ABSL_RAW_LOG(INFO, "RAW INFO: %d %d", 1, 2); + ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d", 1, 2, 3); + ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d", 1, 2, 3, 4); + ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d %d", 1, 2, 3, 4, 5); + ABSL_RAW_LOG(WARNING, "RAW WARNING: %d", 1); ABSL_RAW_LOG(ERROR, "RAW ERROR: %d", 1); } @@ -47,4 +55,25 @@ kExpectedDeathOutput); } +TEST(InternalLog, CompilationTest) { + ABSL_INTERNAL_LOG(INFO, "Internal Log"); + std::string log_msg = "Internal Log"; + ABSL_INTERNAL_LOG(INFO, log_msg); + + ABSL_INTERNAL_LOG(INFO, log_msg + " 2"); + + float d = 1.1f; + ABSL_INTERNAL_LOG(INFO, absl::StrCat("Internal log ", 3, " + ", d)); +} + +TEST(InternalLogDeathTest, FailingCheck) { + EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_CHECK(1 == 0, "explanation"), + kExpectedDeathOutput); +} + +TEST(InternalLogDeathTest, LogFatal) { + EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_LOG(FATAL, "my dog has fleas"), + kExpectedDeathOutput); +} + } // namespace
diff --git a/third_party/abseil-cpp/absl/compiler_config_setting.bzl b/third_party/abseil-cpp/absl/compiler_config_setting.bzl new file mode 100644 index 0000000..b77c4f5 --- /dev/null +++ b/third_party/abseil-cpp/absl/compiler_config_setting.bzl
@@ -0,0 +1,39 @@ +# +# Copyright 2018 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +"""Creates config_setting that allows selecting based on 'compiler' value.""" + +def create_llvm_config(name, visibility): + # The "do_not_use_tools_cpp_compiler_present" attribute exists to + # distinguish between older versions of Bazel that do not support + # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do. + # In the future, the only way to select on the compiler will be through + # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can + # be removed. + if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"): + native.config_setting( + name = name, + flag_values = { + "@bazel_tools//tools/cpp:compiler": "llvm", + }, + visibility = visibility, + ) + else: + native.config_setting( + name = name, + values = {"compiler": "llvm"}, + visibility = visibility, + )
diff --git a/third_party/abseil-cpp/absl/container/BUILD.bazel b/third_party/abseil-cpp/absl/container/BUILD.bazel index 07df367..6d5c958 100644 --- a/third_party/abseil-cpp/absl/container/BUILD.bazel +++ b/third_party/abseil-cpp/absl/container/BUILD.bazel
@@ -26,10 +26,30 @@ licenses(["notice"]) # Apache 2.0 cc_library( + name = "compressed_tuple", + hdrs = ["internal/compressed_tuple.h"], + copts = ABSL_DEFAULT_COPTS, + deps = [ + "//absl/utility", + ], +) + +cc_test( + name = "compressed_tuple_test", + srcs = ["internal/compressed_tuple_test.cc"], + copts = ABSL_TEST_COPTS, + deps = [ + ":compressed_tuple", + "@com_google_googletest//:gtest_main", + ], +) + +cc_library( name = "fixed_array", hdrs = ["fixed_array.h"], copts = ABSL_DEFAULT_COPTS, deps = [ + ":compressed_tuple", "//absl/algorithm", "//absl/base:core_headers", "//absl/base:dynamic_annotations",
diff --git a/third_party/abseil-cpp/absl/container/BUILD.gn b/third_party/abseil-cpp/absl/container/BUILD.gn index a00eaf4b..001a2a3 100644 --- a/third_party/abseil-cpp/absl/container/BUILD.gn +++ b/third_party/abseil-cpp/absl/container/BUILD.gn
@@ -14,6 +14,21 @@ visibility = [ "*" ] } +source_set("compressed_tuple") { + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + "//build/config/compiler:no_chromium_code", + "//third_party/abseil-cpp:absl_default_cflags_cc", + ] + public_configs = [ "//third_party/abseil-cpp:absl_include_config" ] + public = [ + "internal/compressed_tuple.h", + ] + deps = [ + "../utility", + ] +} + source_set("fixed_array") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ @@ -25,6 +40,7 @@ "fixed_array.h", ] deps = [ + ":compressed_tuple", "../algorithm", "../base:core_headers", "../base:dynamic_annotations",
diff --git a/third_party/abseil-cpp/absl/container/CMakeLists.txt b/third_party/abseil-cpp/absl/container/CMakeLists.txt index d580b48..123e4c4 100644 --- a/third_party/abseil-cpp/absl/container/CMakeLists.txt +++ b/third_party/abseil-cpp/absl/container/CMakeLists.txt
@@ -52,7 +52,6 @@ ${TEST_INSTANCE_TRACKER_LIB_SRC} PUBLIC_LIBRARIES absl::container - DISABLE_INSTALL )
diff --git a/third_party/abseil-cpp/absl/container/fixed_array.h b/third_party/abseil-cpp/absl/container/fixed_array.h index 708c615..182258f 100644 --- a/third_party/abseil-cpp/absl/container/fixed_array.h +++ b/third_party/abseil-cpp/absl/container/fixed_array.h
@@ -47,6 +47,7 @@ #include "absl/base/macros.h" #include "absl/base/optimization.h" #include "absl/base/port.h" +#include "absl/container/internal/compressed_tuple.h" #include "absl/memory/memory.h" namespace absl { @@ -76,73 +77,99 @@ // heap allocation, it will do so with global `::operator new[]()` and // `::operator delete[]()`, even if T provides class-scope overrides for these // operators. -template <typename T, size_t inlined = kFixedArrayUseDefault> +template <typename T, size_t N = kFixedArrayUseDefault, + typename A = std::allocator<T>> class FixedArray { static_assert(!std::is_array<T>::value || std::extent<T>::value > 0, "Arrays with unknown bounds cannot be used with FixedArray."); + static constexpr size_t kInlineBytesDefault = 256; + using AllocatorTraits = std::allocator_traits<A>; // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17, // but this seems to be mostly pedantic. template <typename Iterator> using EnableIfForwardIterator = absl::enable_if_t<std::is_convertible< typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>::value>; + static constexpr bool NoexceptCopyable() { + return std::is_nothrow_copy_constructible<StorageElement>::value && + absl::allocator_is_nothrow<allocator_type>::value; + } + static constexpr bool NoexceptMovable() { + return std::is_nothrow_move_constructible<StorageElement>::value && + absl::allocator_is_nothrow<allocator_type>::value; + } + static constexpr bool DefaultConstructorIsNonTrivial() { + return !absl::is_trivially_default_constructible<StorageElement>::value; + } public: - using value_type = T; - using iterator = T*; - using const_iterator = const T*; + using allocator_type = typename AllocatorTraits::allocator_type; + using value_type = typename allocator_type::value_type; + using pointer = typename allocator_type::pointer; + using const_pointer = typename allocator_type::const_pointer; + using reference = typename allocator_type::reference; + using const_reference = typename allocator_type::const_reference; + using size_type = typename allocator_type::size_type; + using difference_type = typename allocator_type::difference_type; + using iterator = pointer; + using const_iterator = const_pointer; using reverse_iterator = std::reverse_iterator<iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>; - using reference = T&; - using const_reference = const T&; - using pointer = T*; - using const_pointer = const T*; - using difference_type = ptrdiff_t; - using size_type = size_t; static constexpr size_type inline_elements = - inlined == kFixedArrayUseDefault - ? kInlineBytesDefault / sizeof(value_type) - : inlined; + (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type) + : static_cast<size_type>(N)); - FixedArray(const FixedArray& other) - : FixedArray(other.begin(), other.end()) {} + FixedArray( + const FixedArray& other, + const allocator_type& a = allocator_type()) noexcept(NoexceptCopyable()) + : FixedArray(other.begin(), other.end(), a) {} - FixedArray(FixedArray&& other) noexcept( - absl::conjunction<absl::allocator_is_nothrow<std::allocator<value_type>>, - std::is_nothrow_move_constructible<value_type>>::value) + FixedArray( + FixedArray&& other, + const allocator_type& a = allocator_type()) noexcept(NoexceptMovable()) : FixedArray(std::make_move_iterator(other.begin()), - std::make_move_iterator(other.end())) {} + std::make_move_iterator(other.end()), a) {} // Creates an array object that can store `n` elements. // Note that trivially constructible elements will be uninitialized. - explicit FixedArray(size_type n) : storage_(n) { - absl::memory_internal::uninitialized_default_construct_n(storage_.begin(), - size()); + explicit FixedArray(size_type n, const allocator_type& a = allocator_type()) + : storage_(n, a) { + if (DefaultConstructorIsNonTrivial()) { + memory_internal::ConstructStorage(storage_.alloc(), storage_.begin(), + storage_.end()); + } } // Creates an array initialized with `n` copies of `val`. - FixedArray(size_type n, const value_type& val) : storage_(n) { - std::uninitialized_fill_n(data(), size(), val); + FixedArray(size_type n, const value_type& val, + const allocator_type& a = allocator_type()) + : storage_(n, a) { + memory_internal::ConstructStorage(storage_.alloc(), storage_.begin(), + storage_.end(), val); } + // Creates an array initialized with the size and contents of `init_list`. + FixedArray(std::initializer_list<value_type> init_list, + const allocator_type& a = allocator_type()) + : FixedArray(init_list.begin(), init_list.end(), a) {} + // Creates an array initialized with the elements from the input // range. The array's size will always be `std::distance(first, last)`. // REQUIRES: Iterator must be a forward_iterator or better. template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr> - FixedArray(Iterator first, Iterator last) - : storage_(std::distance(first, last)) { - std::uninitialized_copy(first, last, data()); + FixedArray(Iterator first, Iterator last, + const allocator_type& a = allocator_type()) + : storage_(std::distance(first, last), a) { + memory_internal::CopyToStorageFromRange(storage_.alloc(), storage_.begin(), + first, last); } - FixedArray(std::initializer_list<value_type> init_list) - : FixedArray(init_list.begin(), init_list.end()) {} - ~FixedArray() noexcept { - for (const StorageElement& cur : storage_) { - cur.~StorageElement(); + for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) { + AllocatorTraits::destroy(*storage_.alloc(), cur); } } @@ -332,7 +359,6 @@ friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) { return !(lhs < rhs); } - private: // StorageElement // @@ -364,6 +390,8 @@ using StorageElement = absl::conditional_t<std::is_array<value_type>::value, StorageElementWrapper<value_type>, value_type>; + using StorageElementBuffer = + absl::aligned_storage_t<sizeof(StorageElement), alignof(StorageElement)>; static pointer AsValueType(pointer ptr) { return ptr; } static pointer AsValueType(StorageElementWrapper<value_type>* ptr) { @@ -374,9 +402,6 @@ static_assert(alignof(StorageElement) == alignof(value_type), ""); struct NonEmptyInlinedStorage { - using StorageElementBuffer = - absl::aligned_storage_t<sizeof(StorageElement), - alignof(StorageElement)>; StorageElement* data() { return reinterpret_cast<StorageElement*>(inlined_storage_.data()); } @@ -386,8 +411,8 @@ void* RedzoneEnd() { return &redzone_end_ + 1; } #endif // ADDRESS_SANITIZER - void AnnotateConstruct(size_t); - void AnnotateDestruct(size_t); + void AnnotateConstruct(size_type); + void AnnotateDestruct(size_type); ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_); std::array<StorageElementBuffer, inline_elements> inlined_storage_; @@ -396,8 +421,8 @@ struct EmptyInlinedStorage { StorageElement* data() { return nullptr; } - void AnnotateConstruct(size_t) {} - void AnnotateDestruct(size_t) {} + void AnnotateConstruct(size_type) {} + void AnnotateDestruct(size_type) {} }; using InlinedStorage = @@ -414,48 +439,57 @@ // class Storage : public InlinedStorage { public: - explicit Storage(size_type n) : data_(CreateStorage(n)), size_(n) {} + Storage(size_type n, const allocator_type& a) + : size_alloc_(n, a), data_(InitializeData()) {} + ~Storage() noexcept { if (UsingInlinedStorage(size())) { - this->AnnotateDestruct(size()); + InlinedStorage::AnnotateDestruct(size()); } else { - std::allocator<StorageElement>().deallocate(begin(), size()); + AllocatorTraits::deallocate(*alloc(), AsValueType(begin()), size()); } } - size_type size() const { return size_; } + size_type size() const { return size_alloc_.template get<0>(); } StorageElement* begin() const { return data_; } StorageElement* end() const { return begin() + size(); } + allocator_type* alloc() { + return std::addressof(size_alloc_.template get<1>()); + } private: static bool UsingInlinedStorage(size_type n) { return n <= inline_elements; } - StorageElement* CreateStorage(size_type n) { - if (UsingInlinedStorage(n)) { - this->AnnotateConstruct(n); + StorageElement* InitializeData() { + if (UsingInlinedStorage(size())) { + InlinedStorage::AnnotateConstruct(size()); return InlinedStorage::data(); } else { - return std::allocator<StorageElement>().allocate(n); + return reinterpret_cast<StorageElement*>( + AllocatorTraits::allocate(*alloc(), size())); } } - StorageElement* const data_; - const size_type size_; + // `CompressedTuple` takes advantage of EBCO for stateless `allocator_type`s + container_internal::CompressedTuple<size_type, allocator_type> size_alloc_; + StorageElement* data_; }; - const Storage storage_; + Storage storage_; }; -template <typename T, size_t N> -constexpr size_t FixedArray<T, N>::inline_elements; +template <typename T, size_t N, typename A> +constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault; -template <typename T, size_t N> -constexpr size_t FixedArray<T, N>::kInlineBytesDefault; +template <typename T, size_t N, typename A> +constexpr typename FixedArray<T, N, A>::size_type + FixedArray<T, N, A>::inline_elements; -template <typename T, size_t N> -void FixedArray<T, N>::NonEmptyInlinedStorage::AnnotateConstruct(size_t n) { +template <typename T, size_t N, typename A> +void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct( + typename FixedArray<T, N, A>::size_type n) { #ifdef ADDRESS_SANITIZER if (!n) return; ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n); @@ -464,8 +498,9 @@ static_cast<void>(n); // Mark used when not in asan mode } -template <typename T, size_t N> -void FixedArray<T, N>::NonEmptyInlinedStorage::AnnotateDestruct(size_t n) { +template <typename T, size_t N, typename A> +void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct( + typename FixedArray<T, N, A>::size_type n) { #ifdef ADDRESS_SANITIZER if (!n) return; ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd()); @@ -473,6 +508,5 @@ #endif // ADDRESS_SANITIZER static_cast<void>(n); // Mark used when not in asan mode } - } // namespace absl #endif // ABSL_CONTAINER_FIXED_ARRAY_H_
diff --git a/third_party/abseil-cpp/absl/container/fixed_array_test.cc b/third_party/abseil-cpp/absl/container/fixed_array_test.cc index 2142132..b07ebcb 100644 --- a/third_party/abseil-cpp/absl/container/fixed_array_test.cc +++ b/third_party/abseil-cpp/absl/container/fixed_array_test.cc
@@ -15,9 +15,11 @@ #include "absl/container/fixed_array.h" #include <stdio.h> +#include <cstring> #include <list> #include <memory> #include <numeric> +#include <scoped_allocator> #include <stdexcept> #include <string> #include <vector> @@ -607,6 +609,216 @@ empty.fill(fill_val); } +// TODO(johnsoncj): Investigate InlinedStorage default initialization in GCC 4.x +#ifndef __GNUC__ +TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) { + using T = char; + constexpr auto capacity = 10; + using FixedArrType = absl::FixedArray<T, capacity>; + using FixedArrBuffType = + absl::aligned_storage_t<sizeof(FixedArrType), alignof(FixedArrType)>; + constexpr auto scrubbed_bits = 0x95; + constexpr auto length = capacity / 2; + + FixedArrBuffType buff; + std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrBuffType)); + + FixedArrType* arr = + ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length); + EXPECT_THAT(*arr, testing::Each(scrubbed_bits)); + arr->~FixedArrType(); +} +#endif // __GNUC__ + +// This is a stateful allocator, but the state lives outside of the +// allocator (in whatever test is using the allocator). This is odd +// but helps in tests where the allocator is propagated into nested +// containers - that chain of allocators uses the same state and is +// thus easier to query for aggregate allocation information. +template <typename T> +class CountingAllocator : public std::allocator<T> { + public: + using Alloc = std::allocator<T>; + using pointer = typename Alloc::pointer; + using size_type = typename Alloc::size_type; + + CountingAllocator() : bytes_used_(nullptr), instance_count_(nullptr) {} + explicit CountingAllocator(int64_t* b) + : bytes_used_(b), instance_count_(nullptr) {} + CountingAllocator(int64_t* b, int64_t* a) + : bytes_used_(b), instance_count_(a) {} + + template <typename U> + explicit CountingAllocator(const CountingAllocator<U>& x) + : Alloc(x), + bytes_used_(x.bytes_used_), + instance_count_(x.instance_count_) {} + + pointer allocate(size_type n, const void* const hint = nullptr) { + assert(bytes_used_ != nullptr); + *bytes_used_ += n * sizeof(T); + return Alloc::allocate(n, hint); + } + + void deallocate(pointer p, size_type n) { + Alloc::deallocate(p, n); + assert(bytes_used_ != nullptr); + *bytes_used_ -= n * sizeof(T); + } + + template <typename... Args> + void construct(pointer p, Args&&... args) { + Alloc::construct(p, absl::forward<Args>(args)...); + if (instance_count_) { + *instance_count_ += 1; + } + } + + void destroy(pointer p) { + Alloc::destroy(p); + if (instance_count_) { + *instance_count_ -= 1; + } + } + + template <typename U> + class rebind { + public: + using other = CountingAllocator<U>; + }; + + int64_t* bytes_used_; + int64_t* instance_count_; +}; + +TEST(AllocatorSupportTest, CountInlineAllocations) { + constexpr size_t inlined_size = 4; + using Alloc = CountingAllocator<int>; + using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; + + int64_t allocated = 0; + int64_t active_instances = 0; + + { + const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; + + Alloc alloc(&allocated, &active_instances); + + AllocFxdArr arr(ia, ia + inlined_size, alloc); + static_cast<void>(arr); + } + + EXPECT_EQ(allocated, 0); + EXPECT_EQ(active_instances, 0); +} + +TEST(AllocatorSupportTest, CountOutoflineAllocations) { + constexpr size_t inlined_size = 4; + using Alloc = CountingAllocator<int>; + using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; + + int64_t allocated = 0; + int64_t active_instances = 0; + + { + const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7}; + Alloc alloc(&allocated, &active_instances); + + AllocFxdArr arr(ia, ia + ABSL_ARRAYSIZE(ia), alloc); + + EXPECT_EQ(allocated, arr.size() * sizeof(int)); + static_cast<void>(arr); + } + + EXPECT_EQ(active_instances, 0); +} + +TEST(AllocatorSupportTest, CountCopyInlineAllocations) { + constexpr size_t inlined_size = 4; + using Alloc = CountingAllocator<int>; + using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; + + int64_t allocated1 = 0; + int64_t allocated2 = 0; + int64_t active_instances = 0; + Alloc alloc(&allocated1, &active_instances); + Alloc alloc2(&allocated2, &active_instances); + + { + int initial_value = 1; + + AllocFxdArr arr1(inlined_size / 2, initial_value, alloc); + + EXPECT_EQ(allocated1, 0); + + AllocFxdArr arr2(arr1, alloc2); + + EXPECT_EQ(allocated2, 0); + static_cast<void>(arr1); + static_cast<void>(arr2); + } + + EXPECT_EQ(active_instances, 0); +} + +TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) { + constexpr size_t inlined_size = 4; + using Alloc = CountingAllocator<int>; + using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; + + int64_t allocated1 = 0; + int64_t allocated2 = 0; + int64_t active_instances = 0; + Alloc alloc(&allocated1, &active_instances); + Alloc alloc2(&allocated2, &active_instances); + + { + int initial_value = 1; + + AllocFxdArr arr1(inlined_size * 2, initial_value, alloc); + + EXPECT_EQ(allocated1, arr1.size() * sizeof(int)); + + AllocFxdArr arr2(arr1, alloc2); + + EXPECT_EQ(allocated2, inlined_size * 2 * sizeof(int)); + static_cast<void>(arr1); + static_cast<void>(arr2); + } + + EXPECT_EQ(active_instances, 0); +} + +TEST(AllocatorSupportTest, SizeValAllocConstructor) { + using testing::AllOf; + using testing::Each; + using testing::SizeIs; + + constexpr size_t inlined_size = 4; + using Alloc = CountingAllocator<int>; + using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>; + + { + auto len = inlined_size / 2; + auto val = 0; + int64_t allocated = 0; + AllocFxdArr arr(len, val, Alloc(&allocated)); + + EXPECT_EQ(allocated, 0); + EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0))); + } + + { + auto len = inlined_size * 2; + auto val = 0; + int64_t allocated = 0; + AllocFxdArr arr(len, val, Alloc(&allocated)); + + EXPECT_EQ(allocated, len * sizeof(int)); + EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0))); + } +} + #ifdef ADDRESS_SANITIZER TEST(FixedArrayTest, AddressSanitizerAnnotations1) { absl::FixedArray<int, 32> a(10); @@ -655,5 +867,4 @@ EXPECT_DEATH(raw[21] = ThreeInts(), "container-overflow"); } #endif // ADDRESS_SANITIZER - } // namespace
diff --git a/third_party/abseil-cpp/absl/container/inlined_vector.h b/third_party/abseil-cpp/absl/container/inlined_vector.h index 03660f1..ca36fd3 100644 --- a/third_party/abseil-cpp/absl/container/inlined_vector.h +++ b/third_party/abseil-cpp/absl/container/inlined_vector.h
@@ -626,14 +626,18 @@ // It holds whether the vector is allocated or not in the lowest bit. // The size is held in the high bits: // size_ = (size << 1) | is_allocated; + // + // Maintainer's Note: size_type is user defined. The contract is limited to + // arithmetic operators to avoid depending on compliant overloaded bitwise + // operators. class Tag { public: Tag() : size_(0) {} - size_type size() const { return size_ >> 1; } - void add_size(size_type n) { size_ += n << 1; } - void set_inline_size(size_type n) { size_ = n << 1; } - void set_allocated_size(size_type n) { size_ = (n << 1) | 1; } - bool allocated() const { return size_ & 1; } + size_type size() const { return size_ / 2; } + void add_size(size_type n) { size_ += n * 2; } + void set_inline_size(size_type n) { size_ = n * 2; } + void set_allocated_size(size_type n) { size_ = (n * 2) + 1; } + bool allocated() const { return size_ % 2; } private: size_type size_; @@ -689,11 +693,14 @@ new (&rep_.allocation_storage.allocation) Allocation(allocation); } + // TODO(absl-team): investigate whether the reinterpret_cast is appropriate. value_type* inlined_space() { - return reinterpret_cast<value_type*>(&rep_.inlined_storage.inlined); + return reinterpret_cast<value_type*>( + std::addressof(rep_.inlined_storage.inlined[0])); } const value_type* inlined_space() const { - return reinterpret_cast<const value_type*>(&rep_.inlined_storage.inlined); + return reinterpret_cast<const value_type*>( + std::addressof(rep_.inlined_storage.inlined[0])); } value_type* allocated_space() { return allocation().buffer(); }
diff --git a/third_party/abseil-cpp/absl/container/inlined_vector_test.cc b/third_party/abseil-cpp/absl/container/inlined_vector_test.cc index f81fad5..196a1be 100644 --- a/third_party/abseil-cpp/absl/container/inlined_vector_test.cc +++ b/third_party/abseil-cpp/absl/container/inlined_vector_test.cc
@@ -1788,5 +1788,4 @@ EXPECT_THAT(v, AllOf(SizeIs(len), Each(0))); } } - } // anonymous namespace
diff --git a/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h b/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h new file mode 100644 index 0000000..cc52614f --- /dev/null +++ b/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h
@@ -0,0 +1,175 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Helper class to perform the Empty Base Optimization. +// Ts can contain classes and non-classes, empty or not. For the ones that +// are empty classes, we perform the optimization. If all types in Ts are empty +// classes, then CompressedTuple<Ts...> is itself an empty class. +// +// To access the members, use member get<N>() function. +// +// Eg: +// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2, +// t3); +// assert(value.get<0>() == 7); +// T1& t1 = value.get<1>(); +// const T2& t2 = value.get<2>(); +// ... +// +// http://en.cppreference.com/w/cpp/language/ebo + +#ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_ +#define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_ + +#include <tuple> +#include <type_traits> +#include <utility> + +#include "absl/utility/utility.h" + +#ifdef _MSC_VER +// We need to mark these classes with this declspec to ensure that +// CompressedTuple happens. +#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases) +#else // _MSC_VER +#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC +#endif // _MSC_VER + +namespace absl { +namespace container_internal { + +template <typename... Ts> +class CompressedTuple; + +namespace internal_compressed_tuple { + +template <typename D, size_t I> +struct Elem; +template <typename... B, size_t I> +struct Elem<CompressedTuple<B...>, I> + : std::tuple_element<I, std::tuple<B...>> {}; +template <typename D, size_t I> +using ElemT = typename Elem<D, I>::type; + +// Use the __is_final intrinsic if available. Where it's not available, classes +// declared with the 'final' specifier cannot be used as CompressedTuple +// elements. +// TODO(sbenza): Replace this with std::is_final in C++14. +template <typename T> +constexpr bool IsFinal() { +#if defined(__clang__) || defined(__GNUC__) + return __is_final(T); +#else + return false; +#endif +} + +template <typename T> +constexpr bool ShouldUseBase() { + return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>(); +} + +// The storage class provides two specializations: +// - For empty classes, it stores T as a base class. +// - For everything else, it stores T as a member. +template <typename D, size_t I, bool = ShouldUseBase<ElemT<D, I>>()> +struct Storage { + using T = ElemT<D, I>; + T value; + constexpr Storage() = default; + explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {} + constexpr const T& get() const { return value; } + T& get() { return value; } +}; + +template <typename D, size_t I> +struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<D, I, true> + : ElemT<D, I> { + using T = internal_compressed_tuple::ElemT<D, I>; + constexpr Storage() = default; + explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {} + constexpr const T& get() const { return *this; } + T& get() { return *this; } +}; + +template <typename D, typename I> +struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl; + +template <typename... Ts, size_t... I> +struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC + CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>> + // We use the dummy identity function through std::integral_constant to + // convince MSVC of accepting and expanding I in that context. Without it + // you would get: + // error C3548: 'I': parameter pack cannot be used in this context + : Storage<CompressedTuple<Ts...>, + std::integral_constant<size_t, I>::value>... { + constexpr CompressedTupleImpl() = default; + explicit constexpr CompressedTupleImpl(Ts&&... args) + : Storage<CompressedTuple<Ts...>, I>(absl::forward<Ts>(args))... {} +}; + +} // namespace internal_compressed_tuple + +// Helper class to perform the Empty Base Class Optimization. +// Ts can contain classes and non-classes, empty or not. For the ones that +// are empty classes, we perform the CompressedTuple. If all types in Ts are +// empty classes, then CompressedTuple<Ts...> is itself an empty class. +// +// To access the members, use member .get<N>() function. +// +// Eg: +// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2, +// t3); +// assert(value.get<0>() == 7); +// T1& t1 = value.get<1>(); +// const T2& t2 = value.get<2>(); +// ... +// +// http://en.cppreference.com/w/cpp/language/ebo +template <typename... Ts> +class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple + : private internal_compressed_tuple::CompressedTupleImpl< + CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>> { + private: + template <int I> + using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>; + + public: + constexpr CompressedTuple() = default; + explicit constexpr CompressedTuple(Ts... base) + : CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {} + + template <int I> + ElemT<I>& get() { + return internal_compressed_tuple::Storage<CompressedTuple, I>::get(); + } + + template <int I> + constexpr const ElemT<I>& get() const { + return internal_compressed_tuple::Storage<CompressedTuple, I>::get(); + } +}; + +// Explicit specialization for a zero-element tuple +// (needed to avoid ambiguous overloads for the default constructor). +template <> +class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {}; + +} // namespace container_internal +} // namespace absl + +#undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC + +#endif // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
diff --git a/third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc b/third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc new file mode 100644 index 0000000..45030c6 --- /dev/null +++ b/third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc
@@ -0,0 +1,166 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/container/internal/compressed_tuple.h" + +#include <string> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace absl { +namespace container_internal { +namespace { + +template <int> +struct Empty {}; + +template <typename T> +struct NotEmpty { + T value; +}; + +template <typename T, typename U> +struct TwoValues { + T value1; + U value2; +}; + +TEST(CompressedTupleTest, Sizeof) { + EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int>)); + EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>>)); + EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>, Empty<1>>)); + EXPECT_EQ(sizeof(int), + sizeof(CompressedTuple<int, Empty<0>, Empty<1>, Empty<2>>)); + + EXPECT_EQ(sizeof(TwoValues<int, double>), + sizeof(CompressedTuple<int, NotEmpty<double>>)); + EXPECT_EQ(sizeof(TwoValues<int, double>), + sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>>)); + EXPECT_EQ(sizeof(TwoValues<int, double>), + sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>, Empty<1>>)); +} + +TEST(CompressedTupleTest, Access) { + struct S { + std::string x; + }; + CompressedTuple<int, Empty<0>, S> x(7, {}, S{"ABC"}); + EXPECT_EQ(sizeof(x), sizeof(TwoValues<int, S>)); + EXPECT_EQ(7, x.get<0>()); + EXPECT_EQ("ABC", x.get<2>().x); +} + +TEST(CompressedTupleTest, NonClasses) { + CompressedTuple<int, const char*> x(7, "ABC"); + EXPECT_EQ(7, x.get<0>()); + EXPECT_STREQ("ABC", x.get<1>()); +} + +TEST(CompressedTupleTest, MixClassAndNonClass) { + CompressedTuple<int, const char*, Empty<0>, NotEmpty<double>> x(7, "ABC", {}, + {1.25}); + struct Mock { + int v; + const char* p; + double d; + }; + EXPECT_EQ(sizeof(x), sizeof(Mock)); + EXPECT_EQ(7, x.get<0>()); + EXPECT_STREQ("ABC", x.get<1>()); + EXPECT_EQ(1.25, x.get<3>().value); +} + +TEST(CompressedTupleTest, Nested) { + CompressedTuple<int, CompressedTuple<int>, + CompressedTuple<int, CompressedTuple<int>>> + x(1, CompressedTuple<int>(2), + CompressedTuple<int, CompressedTuple<int>>(3, CompressedTuple<int>(4))); + EXPECT_EQ(1, x.get<0>()); + EXPECT_EQ(2, x.get<1>().get<0>()); + EXPECT_EQ(3, x.get<2>().get<0>()); + EXPECT_EQ(4, x.get<2>().get<1>().get<0>()); + + CompressedTuple<Empty<0>, Empty<0>, + CompressedTuple<Empty<0>, CompressedTuple<Empty<0>>>> + y; + std::set<Empty<0>*> empties{&y.get<0>(), &y.get<1>(), &y.get<2>().get<0>(), + &y.get<2>().get<1>().get<0>()}; +#ifdef _MSC_VER + // MSVC has a bug where many instances of the same base class are layed out in + // the same address when using __declspec(empty_bases). + // This will be fixed in a future version of MSVC. + int expected = 1; +#else + int expected = 4; +#endif + EXPECT_EQ(expected, sizeof(y)); + EXPECT_EQ(expected, empties.size()); + EXPECT_EQ(sizeof(y), sizeof(Empty<0>) * empties.size()); + + EXPECT_EQ(4 * sizeof(char), + sizeof(CompressedTuple<CompressedTuple<char, char>, + CompressedTuple<char, char>>)); + EXPECT_TRUE( + (std::is_empty<CompressedTuple<CompressedTuple<Empty<0>>, + CompressedTuple<Empty<1>>>>::value)); +} + +TEST(CompressedTupleTest, Reference) { + int i = 7; + std::string s = "Very long std::string that goes in the heap"; + CompressedTuple<int, int&, std::string, std::string&> x(i, i, s, s); + + // Sanity check. We should have not moved from `s` + EXPECT_EQ(s, "Very long std::string that goes in the heap"); + + EXPECT_EQ(x.get<0>(), x.get<1>()); + EXPECT_NE(&x.get<0>(), &x.get<1>()); + EXPECT_EQ(&x.get<1>(), &i); + + EXPECT_EQ(x.get<2>(), x.get<3>()); + EXPECT_NE(&x.get<2>(), &x.get<3>()); + EXPECT_EQ(&x.get<3>(), &s); +} + +TEST(CompressedTupleTest, NoElements) { + CompressedTuple<> x; + static_cast<void>(x); // Silence -Wunused-variable. + EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value); +} + +TEST(CompressedTupleTest, Constexpr) { + constexpr CompressedTuple<int, double, CompressedTuple<int>> x( + 7, 1.25, CompressedTuple<int>(5)); + constexpr int x0 = x.get<0>(); + constexpr double x1 = x.get<1>(); + constexpr int x2 = x.get<2>().get<0>(); + EXPECT_EQ(x0, 7); + EXPECT_EQ(x1, 1.25); + EXPECT_EQ(x2, 5); +} + +#if defined(__clang__) || defined(__GNUC__) +TEST(CompressedTupleTest, EmptyFinalClass) { + struct S final { + int f() const { return 5; } + }; + CompressedTuple<S> x; + EXPECT_EQ(x.get<0>().f(), 5); +} +#endif + +} // namespace +} // namespace container_internal +} // namespace absl
diff --git a/third_party/abseil-cpp/absl/copts.bzl b/third_party/abseil-cpp/absl/copts.bzl index 20c9b61..0168ac5 100644 --- a/third_party/abseil-cpp/absl/copts.bzl +++ b/third_party/abseil-cpp/absl/copts.bzl
@@ -31,7 +31,6 @@ "-Wno-unused-private-field", ] - # Docs on single flags is preceded by a comment. # Docs on groups of flags is preceded by ###.
diff --git a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc index 4c131fe..d4b957b 100644 --- a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc +++ b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc
@@ -252,7 +252,7 @@ depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg); } -// Called by FailureSignalHandler() to write the failure info. It is +// Called by AbslFailureSignalHandler() to write the failure info. It is // called once with writerfn set to WriteToStderr() and then possibly // with writerfn set to the user provided function. static void WriteFailureInfo(int signo, void* ucontext, @@ -278,9 +278,9 @@ } #ifdef ABSL_HAVE_ALARM -// FailureSignalHandler() installs this as a signal handler for +// AbslFailureSignalHandler() installs this as a signal handler for // SIGALRM, then sets an alarm to be delivered to the program after a -// set amount of time. If FailureSignalHandler() hangs for more than +// set amount of time. If AbslFailureSignalHandler() hangs for more than // the alarm timeout, ImmediateAbortSignalHandler() will abort the // program. static void ImmediateAbortSignalHandler(int) { @@ -294,11 +294,10 @@ ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0); #ifndef ABSL_HAVE_SIGACTION -static void FailureSignalHandler(int signo) { +static void AbslFailureSignalHandler(int signo) { void* ucontext = nullptr; #else -static void FailureSignalHandler(int signo, siginfo_t*, - void* ucontext) { +static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) { #endif const GetTidType this_tid = absl::base_internal::GetTID(); @@ -308,10 +307,10 @@ std::memory_order_acq_rel, std::memory_order_relaxed)) { ABSL_RAW_LOG( ERROR, - "Signal %d raised at PC=%p while already in FailureSignalHandler()", + "Signal %d raised at PC=%p while already in AbslFailureSignalHandler()", signo, absl::debugging_internal::GetProgramCounter(ucontext)); if (this_tid != previous_failed_tid) { - // Another thread is already in FailureSignalHandler(), so wait + // Another thread is already in AbslFailureSignalHandler(), so wait // a bit for it to finish. If the other thread doesn't kill us, // we do so after sleeping. PortableSleepForSeconds(3); @@ -349,7 +348,7 @@ void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) { fsh_options = options; for (auto& it : failure_signal_data) { - InstallOneFailureHandler(&it, FailureSignalHandler); + InstallOneFailureHandler(&it, AbslFailureSignalHandler); } }
diff --git a/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc b/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc index 8434709f..faf8883 100644 --- a/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc +++ b/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc
@@ -52,6 +52,10 @@ return reinterpret_cast<void*>(context->uc_mcontext.gp_regs[32]); #elif defined(__powerpc__) return reinterpret_cast<void*>(context->uc_mcontext.regs->nip); +#elif defined(__s390__) && !defined(__s390x__) + return reinterpret_cast<void*>(context->uc_mcontext.psw.addr & 0x7fffffff); +#elif defined(__s390__) && defined(__s390x__) + return reinterpret_cast<void*>(context->uc_mcontext.psw.addr); #elif defined(__x86_64__) if (16 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs)) return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]);
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h index 48adfcc..dd713da 100644 --- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h +++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
@@ -21,26 +21,16 @@ #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_ #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_ -// First, test platforms which only support a stub. -#if ABSL_STACKTRACE_INL_HEADER +#if defined(ABSL_STACKTRACE_INL_HEADER) #error ABSL_STACKTRACE_INL_HEADER cannot be directly set -#elif defined(__native_client__) || defined(__APPLE__) || \ - defined(__FreeBSD__) || defined(__ANDROID__) || defined(__myriad2__) || \ - defined(__asmjs__) || defined(__wasm__) || defined(__Fuchsia__) -#define ABSL_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_unimplemented-inl.inc" -// Next, test for Mips and Windows. -// TODO(marmstrong): Mips case, remove the check for ABSL_STACKTRACE_INL_HEADER -#elif defined(__mips__) && !defined(ABSL_STACKTRACE_INL_HEADER) -#define ABSL_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_unimplemented-inl.inc" -#elif defined(_WIN32) // windows +#elif defined(_WIN32) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_win32-inl.inc" -// Finally, test NO_FRAME_POINTER. -#elif !defined(NO_FRAME_POINTER) +#elif defined(__linux__) && !defined(__ANDROID__) + +#if !defined(NO_FRAME_POINTER) # if defined(__i386__) || defined(__x86_64__) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_x86-inl.inc" @@ -53,22 +43,27 @@ # elif defined(__arm__) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_arm-inl.inc" +# else +#define ABSL_STACKTRACE_INL_HEADER \ + "absl/debugging/internal/stacktrace_unimplemented-inl.inc" # endif #else // defined(NO_FRAME_POINTER) # if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) #define ABSL_STACKTRACE_INL_HEADER \ - "absl/debugging/internal/stacktrace_unimplemented-inl.inc" + "absl/debugging/internal/stacktrace_generic-inl.inc" # elif defined(__ppc__) || defined(__PPC__) -// Use glibc's backtrace. #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_generic-inl.inc" -# elif defined(__arm__) -# error stacktrace without frame pointer is not supported on ARM +# else +#define ABSL_STACKTRACE_INL_HEADER \ + "absl/debugging/internal/stacktrace_unimplemented-inl.inc" # endif #endif // NO_FRAME_POINTER -#if !defined(ABSL_STACKTRACE_INL_HEADER) -#error Not supported yet +#else +#define ABSL_STACKTRACE_INL_HEADER \ + "absl/debugging/internal/stacktrace_unimplemented-inl.inc" + #endif #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc index 297bdad..860ac2b3 100644 --- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc +++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -31,6 +31,8 @@ #include <cstdint> #include <cstdio> +#include "absl/base/attributes.h" +#include "absl/base/optimization.h" #include "absl/base/port.h" #include "absl/debugging/stacktrace.h" #include "absl/debugging/internal/address_is_readable.h" @@ -150,8 +152,9 @@ } // This ensures that absl::GetStackTrace sets up the Link Register properly. -void StacktracePowerPCDummyFunction() __attribute__((noinline)); -void StacktracePowerPCDummyFunction() { __asm__ volatile(""); } +ABSL_ATTRIBUTE_NOINLINE static void AbslStacktracePowerPCDummyFunction() { + ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); +} template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack. @@ -176,7 +179,7 @@ // want here. While the compiler will always(?) set up LR for // subroutine calls, it may not for leaf functions (such as this one). // This routine forces the compiler (at least gcc) to push it anyway. - StacktracePowerPCDummyFunction(); + AbslStacktracePowerPCDummyFunction(); // The LR save area is used by the callee, so the top entry is bogus. skip_count++;
diff --git a/third_party/abseil-cpp/absl/memory/memory.h b/third_party/abseil-cpp/absl/memory/memory.h index c43e156..c7caf8b 100644 --- a/third_party/abseil-cpp/absl/memory/memory.h +++ b/third_party/abseil-cpp/absl/memory/memory.h
@@ -83,7 +83,11 @@ } // namespace memory_internal -#if __cplusplus >= 201402L || defined(_MSC_VER) +// gcc 4.8 has __cplusplus at 201301 but doesn't define make_unique. Other +// supported compilers either just define __cplusplus as 201103 but have +// make_unique (msvc), or have make_unique whenever __cplusplus > 201103 (clang) +#if (__cplusplus > 201103L || defined(_MSC_VER)) && \ + !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8) using std::make_unique; #else // ----------------------------------------------------------------------------- @@ -637,38 +641,56 @@ #endif namespace memory_internal { -// TODO(b110200014): Implement proper backports -template <typename ForwardIt> -void DefaultConstruct(ForwardIt it) { - using value_type = typename std::iterator_traits<ForwardIt>::value_type; - ::new (static_cast<void*>(std::addressof(*it))) value_type; -} // namespace memory_internal - #ifdef ABSL_HAVE_EXCEPTIONS -template <typename ForwardIt, typename Size> -void uninitialized_default_construct_n(ForwardIt first, Size size) { - for (ForwardIt cur = first; size > 0; static_cast<void>(++cur), --size) { +template <typename Allocator, typename StorageElement, typename... Args> +void ConstructStorage(Allocator* alloc, StorageElement* first, + StorageElement* last, const Args&... args) { + for (StorageElement* cur = first; cur != last; ++cur) { try { - absl::memory_internal::DefaultConstruct(cur); + std::allocator_traits<Allocator>::construct(*alloc, cur, args...); } catch (...) { - using value_type = typename std::iterator_traits<ForwardIt>::value_type; - for (; first != cur; ++first) { - first->~value_type(); + while (cur != first) { + --cur; + std::allocator_traits<Allocator>::destroy(*alloc, cur); + } + throw; + } + } +} +template <typename Allocator, typename StorageElement, typename Iterator> +void CopyToStorageFromRange(Allocator* alloc, StorageElement* destination, + Iterator first, Iterator last) { + for (StorageElement* cur = destination; first != last; + static_cast<void>(++cur), static_cast<void>(++first)) { + try { + std::allocator_traits<Allocator>::construct(*alloc, cur, *first); + } catch (...) { + while (cur != destination) { + --cur; + std::allocator_traits<Allocator>::destroy(*alloc, cur); } throw; } } } #else // ABSL_HAVE_EXCEPTIONS -template <typename ForwardIt, typename Size> -void uninitialized_default_construct_n(ForwardIt first, Size size) { - for (; size > 0; static_cast<void>(++first), --size) { - absl::memory_internal::DefaultConstruct(first); +template <typename Allocator, typename StorageElement, typename... Args> +void ConstructStorage(Allocator* alloc, StorageElement* first, + StorageElement* last, const Args&... args) { + for (; first != last; ++first) { + std::allocator_traits<Allocator>::construct(*alloc, first, args...); + } +} +template <typename Allocator, typename StorageElement, typename Iterator> +void CopyToStorageFromRange(Allocator* alloc, StorageElement* destination, + Iterator first, Iterator last) { + for (; first != last; + static_cast<void>(++destination), static_cast<void>(++first)) { + std::allocator_traits<Allocator>::construct(*alloc, destination, *first); } } #endif // ABSL_HAVE_EXCEPTIONS } // namespace memory_internal - } // namespace absl #endif // ABSL_MEMORY_MEMORY_H_
diff --git a/third_party/abseil-cpp/absl/memory/memory_exception_safety_test.cc b/third_party/abseil-cpp/absl/memory/memory_exception_safety_test.cc index fb8b561..d1f6e84 100644 --- a/third_party/abseil-cpp/absl/memory/memory_exception_safety_test.cc +++ b/third_party/abseil-cpp/absl/memory/memory_exception_safety_test.cc
@@ -48,16 +48,5 @@ })); } -TEST(MemoryInternal, UninitDefaultConstructNNonTrivial) { - EXPECT_TRUE(testing::MakeExceptionSafetyTester() - .WithInitialValue(ThrowerList{}) - .WithOperation([&](ThrowerList* list_ptr) { - absl::memory_internal::uninitialized_default_construct_n( - list_ptr->data(), kLength); - }) - .WithInvariants([&](...) { return true; }) - .Test()); -} - } // namespace } // namespace absl
diff --git a/third_party/abseil-cpp/absl/memory/memory_test.cc b/third_party/abseil-cpp/absl/memory/memory_test.cc index 8ff1945d..dee9b486 100644 --- a/third_party/abseil-cpp/absl/memory/memory_test.cc +++ b/third_party/abseil-cpp/absl/memory/memory_test.cc
@@ -611,47 +611,4 @@ EXPECT_FALSE(absl::allocator_is_nothrow<UnspecifiedAllocator>::value); } -TEST(MemoryInternal, UninitDefaultConstructNTrivial) { - constexpr int kInitialValue = 123; - constexpr int kExpectedValue = kInitialValue; // Expect no-op behavior - constexpr int len = 5; - - struct TestObj { - int val; - }; - static_assert(absl::is_trivially_default_constructible<TestObj>::value, ""); - static_assert(absl::is_trivially_destructible<TestObj>::value, ""); - - TestObj objs[len]; - for (auto& obj : objs) { - obj.val = kInitialValue; - } - - absl::memory_internal::uninitialized_default_construct_n(objs, len); - for (auto& obj : objs) { - EXPECT_EQ(obj.val, kExpectedValue); - } -} - -TEST(MemoryInternal, UninitDefaultConstructNNonTrivial) { - constexpr int kInitialValue = 123; - constexpr int kExpectedValue = 0; // Expect value-construction behavior - constexpr int len = 5; - - struct TestObj { - int val{kExpectedValue}; - }; - static_assert(absl::is_trivially_destructible<TestObj>::value, ""); - - TestObj objs[len]; - for (auto& obj : objs) { - obj.val = kInitialValue; - } - - absl::memory_internal::uninitialized_default_construct_n(objs, len); - for (auto& obj : objs) { - EXPECT_EQ(obj.val, kExpectedValue); - } -} - } // namespace
diff --git a/third_party/abseil-cpp/absl/meta/type_traits.h b/third_party/abseil-cpp/absl/meta/type_traits.h index c3e01fe..457b890 100644 --- a/third_party/abseil-cpp/absl/meta/type_traits.h +++ b/third_party/abseil-cpp/absl/meta/type_traits.h
@@ -44,6 +44,7 @@ namespace absl { namespace type_traits_internal { + template <typename... Ts> struct VoidTImpl { using type = void; @@ -61,6 +62,49 @@ static constexpr size_t value = Align; }; +//////////////////////////////// +// Library Fundamentals V2 TS // +//////////////////////////////// + +// NOTE: The `is_detected` family of templates here differ from the library +// fundamentals specification in that for library fundamentals, `Op<Args...>` is +// evaluated as soon as the type `is_detected<Op, Args...>` undergoes +// substitution, regardless of whether or not the `::value` is accessed. That +// is inconsistent with all other standard traits and prevents lazy evaluation +// in larger contexts (such as if the `is_detected` check is a trailing argument +// of a `conjunction`. This implementation opts to instead be lazy in the same +// way that the standard traits are (this "defect" of the detection idiom +// specifications has been reported). + +template <class Enabler, template <class...> class Op, class... Args> +struct is_detected_impl { + using type = std::false_type; +}; + +template <template <class...> class Op, class... Args> +struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> { + using type = std::true_type; +}; + +template <template <class...> class Op, class... Args> +struct is_detected : is_detected_impl<void, Op, Args...>::type {}; + +template <class Enabler, class To, template <class...> class Op, class... Args> +struct is_detected_convertible_impl { + using type = std::false_type; +}; + +template <class To, template <class...> class Op, class... Args> +struct is_detected_convertible_impl< + typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type, + To, Op, Args...> { + using type = std::true_type; +}; + +template <class To, template <class...> class Op, class... Args> +struct is_detected_convertible + : is_detected_convertible_impl<void, To, Op, Args...>::type {}; + } // namespace type_traits_internal // void_t() @@ -263,8 +307,9 @@ // `is_trivially_assignable<T&, const T&>`. template <typename T> struct is_trivially_copy_assignable - : std::integral_constant<bool, __has_trivial_assign(T) && - std::is_copy_assignable<T>::value> { + : std::integral_constant< + bool, __has_trivial_assign(typename std::remove_reference<T>::type) && + std::is_copy_assignable<T>::value> { #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE private: static constexpr bool compliant =
diff --git a/third_party/abseil-cpp/absl/meta/type_traits_test.cc b/third_party/abseil-cpp/absl/meta/type_traits_test.cc index c44d1c5..81b4bd3 100644 --- a/third_party/abseil-cpp/absl/meta/type_traits_test.cc +++ b/third_party/abseil-cpp/absl/meta/type_traits_test.cc
@@ -34,6 +34,83 @@ struct Dummy {}; +struct ReturnType {}; +struct ConvertibleToReturnType { + operator ReturnType() const; // NOLINT +}; + +// Unique types used as parameter types for testing the detection idiom. +struct StructA {}; +struct StructB {}; +struct StructC {}; + +struct TypeWithBarFunction { + template <class T, + absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0> + ReturnType bar(T&&, const StructB&, StructC&&) &&; // NOLINT +}; + +struct TypeWithBarFunctionAndConvertibleReturnType { + template <class T, + absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0> + ConvertibleToReturnType bar(T&&, const StructB&, StructC&&) &&; // NOLINT +}; + +template <class Class, class... Ts> +using BarIsCallableImpl = + decltype(std::declval<Class>().bar(std::declval<Ts>()...)); + +template <class Class, class... T> +using BarIsCallable = + absl::type_traits_internal::is_detected<BarIsCallableImpl, Class, T...>; + +template <class Class, class... T> +using BarIsCallableConv = absl::type_traits_internal::is_detected_convertible< + ReturnType, BarIsCallableImpl, Class, T...>; + +// NOTE: Test of detail type_traits_internal::is_detected. +TEST(IsDetectedTest, BasicUsage) { + EXPECT_TRUE((BarIsCallable<TypeWithBarFunction, StructA&, const StructB&, + StructC>::value)); + EXPECT_TRUE( + (BarIsCallable<TypeWithBarFunction, StructA&, StructB&, StructC>::value)); + EXPECT_TRUE( + (BarIsCallable<TypeWithBarFunction, StructA&, StructB, StructC>::value)); + + EXPECT_FALSE((BarIsCallable<int, StructA&, const StructB&, StructC>::value)); + EXPECT_FALSE((BarIsCallable<TypeWithBarFunction&, StructA&, const StructB&, + StructC>::value)); + EXPECT_FALSE((BarIsCallable<TypeWithBarFunction, StructA, const StructB&, + StructC>::value)); +} + +// NOTE: Test of detail type_traits_internal::is_detected_convertible. +TEST(IsDetectedConvertibleTest, BasicUsage) { + EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, const StructB&, + StructC>::value)); + EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB&, + StructC>::value)); + EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB, + StructC>::value)); + EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, + StructA&, const StructB&, StructC>::value)); + EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, + StructA&, StructB&, StructC>::value)); + EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, + StructA&, StructB, StructC>::value)); + + EXPECT_FALSE( + (BarIsCallableConv<int, StructA&, const StructB&, StructC>::value)); + EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction&, StructA&, + const StructB&, StructC>::value)); + EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction, StructA, const StructB&, + StructC>::value)); + EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType&, + StructA&, const StructB&, StructC>::value)); + EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType, + StructA, const StructB&, StructC>::value)); +} + TEST(VoidTTest, BasicUsage) { StaticAssertTypeEq<void, absl::void_t<Dummy>>(); StaticAssertTypeEq<void, absl::void_t<Dummy, Dummy, Dummy>>(); @@ -528,6 +605,10 @@ // Verify that arrays are not trivially copy assignable using int10 = int[10]; EXPECT_FALSE(absl::is_trivially_copy_assignable<int10>::value); + + // Verify that references are handled correctly + EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&&>::value); + EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&>::value); } #define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...) \ @@ -714,8 +795,8 @@ ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[][1]); ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int()); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(float)); - ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(char, ...)); + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(float)); // NOLINT + ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(char, ...)); // NOLINT } struct TypeA {};
diff --git a/third_party/abseil-cpp/absl/numeric/int128.h b/third_party/abseil-cpp/absl/numeric/int128.h index e4f39c3..2d131b8bd 100644 --- a/third_party/abseil-cpp/absl/numeric/int128.h +++ b/third_party/abseil-cpp/absl/numeric/int128.h
@@ -31,6 +31,7 @@ #include <cstring> #include <iosfwd> #include <limits> +#include <utility> #include "absl/base/config.h" #include "absl/base/macros.h"
diff --git a/third_party/abseil-cpp/absl/strings/BUILD.bazel b/third_party/abseil-cpp/absl/strings/BUILD.bazel index 3b1e067..3a5f133 100644 --- a/third_party/abseil-cpp/absl/strings/BUILD.bazel +++ b/third_party/abseil-cpp/absl/strings/BUILD.bazel
@@ -159,6 +159,18 @@ ) cc_test( + name = "ascii_benchmark", + srcs = ["ascii_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":strings", + "@com_github_google_benchmark//:benchmark_main", + ], +) + +cc_test( name = "memutil_benchmark", srcs = [ "internal/memutil.h",
diff --git a/third_party/abseil-cpp/absl/strings/ascii_benchmark.cc b/third_party/abseil-cpp/absl/strings/ascii_benchmark.cc new file mode 100644 index 0000000..8dea4b8 --- /dev/null +++ b/third_party/abseil-cpp/absl/strings/ascii_benchmark.cc
@@ -0,0 +1,120 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/strings/ascii.h" + +#include <cctype> +#include <string> +#include <array> +#include <random> + +#include "benchmark/benchmark.h" + +namespace { + +std::array<unsigned char, 256> MakeShuffledBytes() { + std::array<unsigned char, 256> bytes; + for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i); + std::random_device rd; + std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()}); + std::mt19937 g(seed); + std::shuffle(bytes.begin(), bytes.end(), g); + return bytes; +} + +template <typename Function> +void AsciiBenchmark(benchmark::State& state, Function f) { + std::array<unsigned char, 256> bytes = MakeShuffledBytes(); + size_t sum = 0; + for (auto _ : state) { + for (unsigned char b : bytes) sum += f(b) ? 1 : 0; + } + // Make a copy of `sum` before calling `DoNotOptimize` to make sure that `sum` + // can be put in a CPU register and not degrade performance in the loop above. + size_t sum2 = sum; + benchmark::DoNotOptimize(sum2); + state.SetBytesProcessed(state.iterations() * bytes.size()); +} + +using StdAsciiFunction = int (*)(int); +template <StdAsciiFunction f> +void BM_Ascii(benchmark::State& state) { + AsciiBenchmark(state, f); +} + +using AbslAsciiIsFunction = bool (*)(unsigned char); +template <AbslAsciiIsFunction f> +void BM_Ascii(benchmark::State& state) { + AsciiBenchmark(state, f); +} + +using AbslAsciiToFunction = char (*)(unsigned char); +template <AbslAsciiToFunction f> +void BM_Ascii(benchmark::State& state) { + AsciiBenchmark(state, f); +} + +inline char Noop(unsigned char b) { return static_cast<char>(b); } + +BENCHMARK_TEMPLATE(BM_Ascii, Noop); +BENCHMARK_TEMPLATE(BM_Ascii, std::isalpha); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalpha); +BENCHMARK_TEMPLATE(BM_Ascii, std::isdigit); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isdigit); +BENCHMARK_TEMPLATE(BM_Ascii, std::isalnum); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalnum); +BENCHMARK_TEMPLATE(BM_Ascii, std::isspace); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isspace); +BENCHMARK_TEMPLATE(BM_Ascii, std::ispunct); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_ispunct); +BENCHMARK_TEMPLATE(BM_Ascii, std::isblank); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isblank); +BENCHMARK_TEMPLATE(BM_Ascii, std::iscntrl); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_iscntrl); +BENCHMARK_TEMPLATE(BM_Ascii, std::isxdigit); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isxdigit); +BENCHMARK_TEMPLATE(BM_Ascii, std::isprint); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isprint); +BENCHMARK_TEMPLATE(BM_Ascii, std::isgraph); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isgraph); +BENCHMARK_TEMPLATE(BM_Ascii, std::isupper); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isupper); +BENCHMARK_TEMPLATE(BM_Ascii, std::islower); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_islower); +BENCHMARK_TEMPLATE(BM_Ascii, isascii); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isascii); +BENCHMARK_TEMPLATE(BM_Ascii, std::tolower); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_tolower); +BENCHMARK_TEMPLATE(BM_Ascii, std::toupper); +BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_toupper); + +static void BM_StrToLower(benchmark::State& state) { + const int size = state.range(0); + std::string s(size, 'X'); + for (auto _ : state) { + benchmark::DoNotOptimize(absl::AsciiStrToLower(s)); + } +} +BENCHMARK(BM_StrToLower)->Range(1, 1 << 20); + +static void BM_StrToUpper(benchmark::State& state) { + const int size = state.range(0); + std::string s(size, 'x'); + for (auto _ : state) { + benchmark::DoNotOptimize(absl::AsciiStrToUpper(s)); + } +} +BENCHMARK(BM_StrToUpper)->Range(1, 1 << 20); + +} // namespace
diff --git a/third_party/abseil-cpp/absl/strings/escaping.h b/third_party/abseil-cpp/absl/strings/escaping.h index 1af0afa..7f1ab96 100644 --- a/third_party/abseil-cpp/absl/strings/escaping.h +++ b/third_party/abseil-cpp/absl/strings/escaping.h
@@ -139,7 +139,7 @@ // WebSafeBase64Escape() // -// Encodes a `src` std::string into a `dest` buffer using uses '-' instead of '+' and +// Encodes a `src` std::string into a `dest` buffer using '-' instead of '+' and // '_' instead of '/', and without padding. This function conforms with RFC 4648 // section 5 (base64url). void WebSafeBase64Escape(absl::string_view src, std::string* dest);
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc index 37952b4..6176db9 100644 --- a/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc +++ b/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
@@ -153,7 +153,14 @@ template <typename Float, typename Int> constexpr bool CanFitMantissa() { - return std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits; + return +#if defined(__clang__) && !defined(__SSE3__) + // Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289 + // Casting from long double to uint64_t is miscompiled and drops bits. + (!std::is_same<Float, long double>::value || + !std::is_same<Int, uint64_t>::value) && +#endif + std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits; } template <typename Float>
diff --git a/third_party/abseil-cpp/absl/strings/numbers_test.cc b/third_party/abseil-cpp/absl/strings/numbers_test.cc index 24e7138c..27cc0479 100644 --- a/third_party/abseil-cpp/absl/strings/numbers_test.cc +++ b/third_party/abseil-cpp/absl/strings/numbers_test.cc
@@ -56,16 +56,11 @@ using testing::MatchesRegex; // Number of floats to test with. -// 10,000,000 is a reasonable default for a test that only takes a few seconds. +// 5,000,000 is a reasonable default for a test that only takes a few seconds. // 1,000,000,000+ triggers checking for all possible mantissa values for // double-precision tests. 2,000,000,000+ triggers checking for every possible // single-precision float. -#ifdef _MSC_VER -// Use a smaller number on MSVC to avoid test time out (1 min) const int kFloatNumCases = 5000000; -#else -const int kFloatNumCases = 10000000; -#endif // This is a slow, brute-force routine to compute the exact base-10 // representation of a double-precision floating-point number. It @@ -716,8 +711,9 @@ } } -// feenableexcept() and fedisableexcept() are missing on Mac OS X, MSVC. -#if defined(_MSC_VER) || defined(__APPLE__) +// feenableexcept() and fedisableexcept() are missing on Mac OS X, MSVC, +// and WebAssembly. +#if defined(_MSC_VER) || defined(__APPLE__) || defined(__EMSCRIPTEN__) #define ABSL_MISSING_FEENABLEEXCEPT 1 #define ABSL_MISSING_FEDISABLEEXCEPT 1 #endif
diff --git a/third_party/abseil-cpp/absl/strings/str_format_test.cc b/third_party/abseil-cpp/absl/strings/str_format_test.cc index fe742bf..fed75faf 100644 --- a/third_party/abseil-cpp/absl/strings/str_format_test.cc +++ b/third_party/abseil-cpp/absl/strings/str_format_test.cc
@@ -384,8 +384,8 @@ EXPECT_EQ(StrFormat("%G", 1e10), "1E+10"); // a/A - lower,upper case hex Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1" -// On NDK r16, there is a regression in hexfloat formatting. -#if !defined(__NDK_MAJOR__) || __NDK_MAJOR__ != 16 +// On Android platform <=21, there is a regression in hexfloat formatting. +#if !defined(__ANDROID_API__) || __ANDROID_API__ > 21 EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1"); // .1 to fix MSVC output EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1"); // .1 to fix MSVC output #endif
diff --git a/third_party/abseil-cpp/absl/strings/str_split.h b/third_party/abseil-cpp/absl/strings/str_split.h index 1f089b93..9a7be2b 100644 --- a/third_party/abseil-cpp/absl/strings/str_split.h +++ b/third_party/abseil-cpp/absl/strings/str_split.h
@@ -373,11 +373,11 @@ // StrSplit() // -// Splits a given `std::string` based on the provided `Delimiter` object, -// returning the elements within the type specified by the caller. Optionally, -// you may also pass a `Predicate` to `StrSplit()` indicating whether to include -// or exclude the resulting element within the final result set. (See the -// overviews for Delimiters and Predicates above.) +// Splits a given std::string based on the provided `Delimiter` object, returning the +// elements within the type specified by the caller. Optionally, you may pass a +// `Predicate` to `StrSplit()` indicating whether to include or exclude the +// resulting element within the final result set. (See the overviews for +// Delimiters and Predicates above.) // // Example: //
diff --git a/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt b/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt index c19f5725..de0d7b7 100644 --- a/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt +++ b/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt
@@ -34,7 +34,7 @@ # synchronization library -list(APPEND SYNCHRONIZATION_SRC +list(APPEND SYNCHRONIZATION_SRC "barrier.cc" "blocking_counter.cc" "internal/create_thread_identity.cc"
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h b/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h index 0d132d9..bb70800 100644 --- a/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h +++ b/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
@@ -25,9 +25,6 @@ #ifndef ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ #define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ -#ifdef _WIN32 -#include <intsafe.h> -#endif #include <time.h> #include <algorithm> #include <limits> @@ -117,9 +114,14 @@ // Windows. Callers should recognize that the return value is a // relative duration (it should be recomputed by calling this method // in the case of a spurious wakeup). - DWORD InMillisecondsFromNow() const { + // This header file may be included transitively by public header files, + // so we define our own DWORD and INFINITE instead of getting them from + // <intsafe.h> and <WinBase.h>. + typedef unsigned long DWord; // NOLINT + DWord InMillisecondsFromNow() const { + constexpr DWord kInfinite = std::numeric_limits<DWord>::max(); if (!has_timeout()) { - return INFINITE; + return kInfinite; } // The use of absl::Now() to convert from absolute time to // relative time means that absl::Now() cannot use anything that @@ -131,10 +133,10 @@ std::numeric_limits<int64_t>::max() - 999999u; uint64_t ms_from_now = (std::min<uint64_t>(max_nanos, ns_ - now) + 999999u) / 1000000u; - if (ms_from_now > std::numeric_limits<DWORD>::max()) { - return INFINITE; + if (ms_from_now > kInfinite) { + return kInfinite; } - return static_cast<DWORD>(ms_from_now); + return static_cast<DWord>(ms_from_now); } return 0; }
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.h b/third_party/abseil-cpp/absl/synchronization/mutex.h index 840b9d6..83c2148 100644 --- a/third_party/abseil-cpp/absl/synchronization/mutex.h +++ b/third_party/abseil-cpp/absl/synchronization/mutex.h
@@ -24,7 +24,7 @@ // Unlike a `std::mutex`, the Abseil `Mutex` provides the following additional // features: // * Conditional predicates intrinsic to the `Mutex` object -// * Reader/writer locks, in addition to standard exclusive/writer locks +// * Shared/reader locks, in addition to standard exclusive/writer locks // * Deadlock detection and debug support. // // The following helper classes are also defined within this file: @@ -290,7 +290,7 @@ // Mutex::ReaderLockWhen() // Mutex::WriterLockWhen() // - // Blocks until simultaneously both `cond` is `true` and this` Mutex` can + // Blocks until simultaneously both `cond` is `true` and this `Mutex` can // be acquired, then atomically acquires this `Mutex`. `LockWhen()` is // logically equivalent to `*Lock(); Await();` though they may have different // performance characteristics. @@ -558,7 +558,7 @@ // WriterMutexLock // // The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and -// releases a write (exclusive) lock on a `Mutex` va RAII. +// releases a write (exclusive) lock on a `Mutex` via RAII. class SCOPED_LOCKABLE WriterMutexLock { public: explicit WriterMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc b/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc index 30a5235..1e019e00 100644 --- a/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc +++ b/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc
@@ -74,11 +74,11 @@ mu.Unlock(); } -#ifdef THREAD_SANITIZER -// ThreadSanitizer can't handle 8192 threads. -constexpr int kMaxConditionWaiters = 2048; -#else +// Some configurations have higher thread limits than others. +#if defined(__linux__) && !defined(THREAD_SANITIZER) constexpr int kMaxConditionWaiters = 8192; +#else +constexpr int kMaxConditionWaiters = 1024; #endif BENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters);
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex_test.cc b/third_party/abseil-cpp/absl/synchronization/mutex_test.cc index 53b9378..b2820e2 100644 --- a/third_party/abseil-cpp/absl/synchronization/mutex_test.cc +++ b/third_party/abseil-cpp/absl/synchronization/mutex_test.cc
@@ -29,6 +29,7 @@ #include <vector> #include "gtest/gtest.h" +#include "absl/base/attributes.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/sysinfo.h" #include "absl/memory/memory.h" @@ -54,8 +55,8 @@ // Hack to schedule a function to run on a thread pool thread after a // duration has elapsed. static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp, - const std::function<void()> &func, - absl::Duration after) { + absl::Duration after, + const std::function<void()> &func) { tp->Schedule([func, after] { absl::SleepFor(after); func(); @@ -1150,249 +1151,369 @@ // and so never expires/passes, and one that will expire/pass in the near // future. -// Encapsulate a Mutex-protected bool with its associated Condition/CondVar. -class Cond { - public: - explicit Cond(bool use_deadline) : use_deadline_(use_deadline), c_(&b_) {} +static absl::Duration TimeoutTestAllowedSchedulingDelay() { + // Note: we use a function here because Microsoft Visual Studio fails to + // properly initialize constexpr static absl::Duration variables. + return absl::Milliseconds(150); +} - void Set(bool v) { - absl::MutexLock lock(&mu_); - b_ = v; +// Returns true if `actual_delay` is close enough to `expected_delay` to pass +// the timeouts/deadlines test. Otherwise, logs warnings and returns false. +ABSL_MUST_USE_RESULT +static bool DelayIsWithinBounds(absl::Duration expected_delay, + absl::Duration actual_delay) { + bool pass = true; + // Do not allow the observed delay to be less than expected. This may occur + // in practice due to clock skew or when the synchronization primitives use a + // different clock than absl::Now(), but these cases should be handled by the + // the retry mechanism in each TimeoutTest. + if (actual_delay < expected_delay) { + ABSL_RAW_LOG(WARNING, + "Actual delay %s was too short, expected %s (difference %s)", + absl::FormatDuration(actual_delay).c_str(), + absl::FormatDuration(expected_delay).c_str(), + absl::FormatDuration(actual_delay - expected_delay).c_str()); + pass = false; } - - bool AwaitWithTimeout(absl::Duration timeout) { - absl::MutexLock lock(&mu_); - return use_deadline_ ? mu_.AwaitWithDeadline(c_, absl::Now() + timeout) - : mu_.AwaitWithTimeout(c_, timeout); + // If the expected delay is <= zero then allow a small error tolerance, since + // we do not expect context switches to occur during test execution. + // Otherwise, thread scheduling delays may be substantial in rare cases, so + // tolerate up to kTimeoutTestAllowedSchedulingDelay of error. + absl::Duration tolerance = expected_delay <= absl::ZeroDuration() + ? absl::Milliseconds(10) + : TimeoutTestAllowedSchedulingDelay(); + if (actual_delay > expected_delay + tolerance) { + ABSL_RAW_LOG(WARNING, + "Actual delay %s was too long, expected %s (difference %s)", + absl::FormatDuration(actual_delay).c_str(), + absl::FormatDuration(expected_delay).c_str(), + absl::FormatDuration(actual_delay - expected_delay).c_str()); + pass = false; } + return pass; +} - bool LockWhenWithTimeout(absl::Duration timeout) { - bool b = use_deadline_ ? mu_.LockWhenWithDeadline(c_, absl::Now() + timeout) - : mu_.LockWhenWithTimeout(c_, timeout); - mu_.Unlock(); - return b; - } +// Parameters for TimeoutTest, below. +struct TimeoutTestParam { + // The file and line number (used for logging purposes only). + const char *from_file; + int from_line; - bool ReaderLockWhenWithTimeout(absl::Duration timeout) { - bool b = use_deadline_ - ? mu_.ReaderLockWhenWithDeadline(c_, absl::Now() + timeout) - : mu_.ReaderLockWhenWithTimeout(c_, timeout); - mu_.ReaderUnlock(); - return b; - } + // Should the absolute deadline API based on absl::Time be tested? If false, + // the relative deadline API based on absl::Duration is tested. + bool use_absolute_deadline; - void Await() { - absl::MutexLock lock(&mu_); - mu_.Await(c_); - } + // The deadline/timeout used when calling the API being tested + // (e.g. Mutex::LockWhenWithDeadline). + absl::Duration wait_timeout; - void Signal(bool v) { - absl::MutexLock lock(&mu_); - b_ = v; - cv_.Signal(); - } + // The delay before the condition will be set true by the test code. If zero + // or negative, the condition is set true immediately (before calling the API + // being tested). Otherwise, if infinite, the condition is never set true. + // Otherwise a closure is scheduled for the future that sets the condition + // true. + absl::Duration satisfy_condition_delay; - bool WaitWithTimeout(absl::Duration timeout) { - absl::MutexLock lock(&mu_); - absl::Time deadline = absl::Now() + timeout; - if (use_deadline_) { - while (!b_ && !cv_.WaitWithDeadline(&mu_, deadline)) { - } - } else { - while (!b_ && !cv_.WaitWithTimeout(&mu_, timeout)) { - timeout = deadline - absl::Now(); // recompute timeout - } - } - return b_; - } + // The expected result of the condition after the call to the API being + // tested. Generally `true` means the condition was true when the API returns, + // `false` indicates an expected timeout. + bool expected_result; - void Wait() { - absl::MutexLock lock(&mu_); - while (!b_) cv_.Wait(&mu_); - } - - private: - const bool use_deadline_; - - bool b_; - absl::Condition c_; - absl::CondVar cv_; - absl::Mutex mu_; + // The expected delay before the API under test returns. This is inherently + // flaky, so some slop is allowed (see `DelayIsWithinBounds` above), and the + // test keeps trying indefinitely until this constraint passes. + absl::Duration expected_delay; }; -class OperationTimer { - public: - OperationTimer() : start_(absl::Now()) {} - absl::Duration Get() const { return absl::Now() - start_; } +// Print a `TimeoutTestParam` to a debug log. +std::ostream &operator<<(std::ostream &os, const TimeoutTestParam ¶m) { + return os << "from: " << param.from_file << ":" << param.from_line + << " use_absolute_deadline: " + << (param.use_absolute_deadline ? "true" : "false") + << " wait_timeout: " << param.wait_timeout + << " satisfy_condition_delay: " << param.satisfy_condition_delay + << " expected_result: " + << (param.expected_result ? "true" : "false") + << " expected_delay: " << param.expected_delay; +} - private: - const absl::Time start_; -}; +std::string FormatString(const TimeoutTestParam ¶m) { + std::ostringstream os; + os << param; + return os.str(); +} -static void CheckResults(bool exp_result, bool act_result, - absl::Duration exp_duration, - absl::Duration act_duration) { - ABSL_RAW_CHECK(exp_result == act_result, "CheckResults failed"); - // Allow for some worse-case scheduling delay and clock skew. - if ((exp_duration - absl::Milliseconds(40) > act_duration) || - (exp_duration + absl::Milliseconds(150) < act_duration)) { - ABSL_RAW_LOG(FATAL, "CheckResults failed: operation took %s, expected %s", - absl::FormatDuration(act_duration).c_str(), - absl::FormatDuration(exp_duration).c_str()); +// Like `thread::Executor::ScheduleAt` except: +// a) Delays zero or negative are executed immediately in the current thread. +// b) Infinite delays are never scheduled. +// c) Calls this test's `ScheduleAt` helper instead of using `pool` directly. +static void RunAfterDelay(absl::Duration delay, + absl::synchronization_internal::ThreadPool *pool, + const std::function<void()> &callback) { + if (delay <= absl::ZeroDuration()) { + callback(); // immediate + } else if (delay != absl::InfiniteDuration()) { + ScheduleAfter(pool, delay, callback); } } -static void TestAwaitTimeout(Cond *cp, absl::Duration timeout, bool exp_result, - absl::Duration exp_duration) { - OperationTimer t; - bool act_result = cp->AwaitWithTimeout(timeout); - CheckResults(exp_result, act_result, exp_duration, t.Get()); -} +class TimeoutTest : public ::testing::Test, + public ::testing::WithParamInterface<TimeoutTestParam> {}; -static void TestLockWhenTimeout(Cond *cp, absl::Duration timeout, - bool exp_result, absl::Duration exp_duration) { - OperationTimer t; - bool act_result = cp->LockWhenWithTimeout(timeout); - CheckResults(exp_result, act_result, exp_duration, t.Get()); -} - -static void TestReaderLockWhenTimeout(Cond *cp, absl::Duration timeout, - bool exp_result, - absl::Duration exp_duration) { - OperationTimer t; - bool act_result = cp->ReaderLockWhenWithTimeout(timeout); - CheckResults(exp_result, act_result, exp_duration, t.Get()); -} - -static void TestWaitTimeout(Cond *cp, absl::Duration timeout, bool exp_result, - absl::Duration exp_duration) { - OperationTimer t; - bool act_result = cp->WaitWithTimeout(timeout); - CheckResults(exp_result, act_result, exp_duration, t.Get()); -} - -// Tests with a negative timeout (deadline in the past), which should -// immediately return the current state of the condition. -static void TestNegativeTimeouts(absl::synchronization_internal::ThreadPool *tp, - Cond *cp) { +std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() { + // The `finite` delay is a finite, relatively short, delay. We make it larger + // than our allowed scheduling delay (slop factor) to avoid confusion when + // diagnosing test failures. The other constants here have clear meanings. + const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay(); + const absl::Duration never = absl::InfiniteDuration(); const absl::Duration negative = -absl::InfiniteDuration(); const absl::Duration immediate = absl::ZeroDuration(); - // The condition is already true: - cp->Set(true); - TestAwaitTimeout(cp, negative, true, immediate); - TestLockWhenTimeout(cp, negative, true, immediate); - TestReaderLockWhenTimeout(cp, negative, true, immediate); - TestWaitTimeout(cp, negative, true, immediate); + // Every test case is run twice; once using the absolute deadline API and once + // using the relative timeout API. + std::vector<TimeoutTestParam> values; + for (bool use_absolute_deadline : {false, true}) { + // Tests with a negative timeout (deadline in the past), which should + // immediately return current state of the condition. - // The condition becomes true, but the timeout has already expired: - const absl::Duration delay = absl::Milliseconds(200); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), 3 * delay); - TestAwaitTimeout(cp, negative, false, immediate); - TestLockWhenTimeout(cp, negative, false, immediate); - TestReaderLockWhenTimeout(cp, negative, false, immediate); - cp->Await(); // wait for the scheduled Set() to complete - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay); - TestWaitTimeout(cp, negative, false, immediate); - cp->Wait(); // wait for the scheduled Signal() to complete + // The condition is already true: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + negative, // wait_timeout + immediate, // satisfy_condition_delay + true, // expected_result + immediate, // expected_delay + }); - // The condition never becomes true: - cp->Set(false); - TestAwaitTimeout(cp, negative, false, immediate); - TestLockWhenTimeout(cp, negative, false, immediate); - TestReaderLockWhenTimeout(cp, negative, false, immediate); - TestWaitTimeout(cp, negative, false, immediate); + // The condition becomes true, but the timeout has already expired: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + negative, // wait_timeout + finite, // satisfy_condition_delay + false, // expected_result + immediate // expected_delay + }); + + // The condition never becomes true: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + negative, // wait_timeout + never, // satisfy_condition_delay + false, // expected_result + immediate // expected_delay + }); + + // Tests with an infinite timeout (deadline in the infinite future), which + // should only return when the condition becomes true. + + // The condition is already true: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + never, // wait_timeout + immediate, // satisfy_condition_delay + true, // expected_result + immediate // expected_delay + }); + + // The condition becomes true before the (infinite) expiry: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + never, // wait_timeout + finite, // satisfy_condition_delay + true, // expected_result + finite, // expected_delay + }); + + // Tests with a (small) finite timeout (deadline soon), with the condition + // becoming true both before and after its expiry. + + // The condition is already true: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + never, // wait_timeout + immediate, // satisfy_condition_delay + true, // expected_result + immediate // expected_delay + }); + + // The condition becomes true before the expiry: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + finite * 2, // wait_timeout + finite, // satisfy_condition_delay + true, // expected_result + finite // expected_delay + }); + + // The condition becomes true, but the timeout has already expired: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + finite, // wait_timeout + finite * 2, // satisfy_condition_delay + false, // expected_result + finite // expected_delay + }); + + // The condition never becomes true: + values.push_back(TimeoutTestParam{ + __FILE__, __LINE__, use_absolute_deadline, + finite, // wait_timeout + never, // satisfy_condition_delay + false, // expected_result + finite // expected_delay + }); + } + return values; } -// Tests with an infinite timeout (deadline in the infinite future), which -// should only return when the condition becomes true. -static void TestInfiniteTimeouts(absl::synchronization_internal::ThreadPool *tp, - Cond *cp) { - const absl::Duration infinite = absl::InfiniteDuration(); - const absl::Duration immediate = absl::ZeroDuration(); +// Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`. +INSTANTIATE_TEST_CASE_P(All, TimeoutTest, + testing::ValuesIn(MakeTimeoutTestParamValues())); - // The condition is already true: - cp->Set(true); - TestAwaitTimeout(cp, infinite, true, immediate); - TestLockWhenTimeout(cp, infinite, true, immediate); - TestReaderLockWhenTimeout(cp, infinite, true, immediate); - TestWaitTimeout(cp, infinite, true, immediate); +TEST_P(TimeoutTest, Await) { + const TimeoutTestParam params = GetParam(); + ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); - // The condition becomes true before the (infinite) expiry: - const absl::Duration delay = absl::Milliseconds(200); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay); - TestAwaitTimeout(cp, infinite, true, delay); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay); - TestLockWhenTimeout(cp, infinite, true, delay); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay); - TestReaderLockWhenTimeout(cp, infinite, true, delay); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay); - TestWaitTimeout(cp, infinite, true, delay); + // Because this test asserts bounds on scheduling delays it is flaky. To + // compensate it loops forever until it passes. Failures express as test + // timeouts, in which case the test log can be used to diagnose the issue. + for (int attempt = 1;; ++attempt) { + ABSL_RAW_LOG(INFO, "Attempt %d", attempt); + + absl::Mutex mu; + bool value = false; // condition value (under mu) + + std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = + CreateDefaultPool(); + RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { + absl::MutexLock l(&mu); + value = true; + }); + + absl::MutexLock lock(&mu); + absl::Time start_time = absl::Now(); + absl::Condition cond(&value); + bool result = + params.use_absolute_deadline + ? mu.AwaitWithDeadline(cond, start_time + params.wait_timeout) + : mu.AwaitWithTimeout(cond, params.wait_timeout); + if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { + EXPECT_EQ(params.expected_result, result); + break; + } + } } -// Tests with a (small) finite timeout (deadline soon), with the condition -// becoming true both before and after its expiry. -static void TestFiniteTimeouts(absl::synchronization_internal::ThreadPool *tp, - Cond *cp) { - const absl::Duration finite = absl::Milliseconds(400); - const absl::Duration immediate = absl::ZeroDuration(); +TEST_P(TimeoutTest, LockWhen) { + const TimeoutTestParam params = GetParam(); + ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); - // The condition is already true: - cp->Set(true); - TestAwaitTimeout(cp, finite, true, immediate); - TestLockWhenTimeout(cp, finite, true, immediate); - TestReaderLockWhenTimeout(cp, finite, true, immediate); - TestWaitTimeout(cp, finite, true, immediate); + // Because this test asserts bounds on scheduling delays it is flaky. To + // compensate it loops forever until it passes. Failures express as test + // timeouts, in which case the test log can be used to diagnose the issue. + for (int attempt = 1;; ++attempt) { + ABSL_RAW_LOG(INFO, "Attempt %d", attempt); - // The condition becomes true before the expiry: - const absl::Duration delay1 = finite / 2; - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay1); - TestAwaitTimeout(cp, finite, true, delay1); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay1); - TestLockWhenTimeout(cp, finite, true, delay1); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay1); - TestReaderLockWhenTimeout(cp, finite, true, delay1); - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay1); - TestWaitTimeout(cp, finite, true, delay1); + absl::Mutex mu; + bool value = false; // condition value (under mu) - // The condition becomes true, but the timeout has already expired: - const absl::Duration delay2 = finite * 2; - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), 3 * delay2); - TestAwaitTimeout(cp, finite, false, finite); - TestLockWhenTimeout(cp, finite, false, finite); - TestReaderLockWhenTimeout(cp, finite, false, finite); - cp->Await(); // wait for the scheduled Set() to complete - cp->Set(false); - ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay2); - TestWaitTimeout(cp, finite, false, finite); - cp->Wait(); // wait for the scheduled Signal() to complete + std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = + CreateDefaultPool(); + RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { + absl::MutexLock l(&mu); + value = true; + }); - // The condition never becomes true: - cp->Set(false); - TestAwaitTimeout(cp, finite, false, finite); - TestLockWhenTimeout(cp, finite, false, finite); - TestReaderLockWhenTimeout(cp, finite, false, finite); - TestWaitTimeout(cp, finite, false, finite); + absl::Time start_time = absl::Now(); + absl::Condition cond(&value); + bool result = + params.use_absolute_deadline + ? mu.LockWhenWithDeadline(cond, start_time + params.wait_timeout) + : mu.LockWhenWithTimeout(cond, params.wait_timeout); + mu.Unlock(); + + if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { + EXPECT_EQ(params.expected_result, result); + break; + } + } } -TEST(Mutex, Timeouts) { - auto tp = CreateDefaultPool(); - for (bool use_deadline : {false, true}) { - Cond cond(use_deadline); - TestNegativeTimeouts(tp.get(), &cond); - TestInfiniteTimeouts(tp.get(), &cond); - TestFiniteTimeouts(tp.get(), &cond); +TEST_P(TimeoutTest, ReaderLockWhen) { + const TimeoutTestParam params = GetParam(); + ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); + + // Because this test asserts bounds on scheduling delays it is flaky. To + // compensate it loops forever until it passes. Failures express as test + // timeouts, in which case the test log can be used to diagnose the issue. + for (int attempt = 0;; ++attempt) { + ABSL_RAW_LOG(INFO, "Attempt %d", attempt); + + absl::Mutex mu; + bool value = false; // condition value (under mu) + + std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = + CreateDefaultPool(); + RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { + absl::MutexLock l(&mu); + value = true; + }); + + absl::Time start_time = absl::Now(); + bool result = + params.use_absolute_deadline + ? mu.ReaderLockWhenWithDeadline(absl::Condition(&value), + start_time + params.wait_timeout) + : mu.ReaderLockWhenWithTimeout(absl::Condition(&value), + params.wait_timeout); + mu.ReaderUnlock(); + + if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { + EXPECT_EQ(params.expected_result, result); + break; + } + } +} + +TEST_P(TimeoutTest, Wait) { + const TimeoutTestParam params = GetParam(); + ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str()); + + // Because this test asserts bounds on scheduling delays it is flaky. To + // compensate it loops forever until it passes. Failures express as test + // timeouts, in which case the test log can be used to diagnose the issue. + for (int attempt = 0;; ++attempt) { + ABSL_RAW_LOG(INFO, "Attempt %d", attempt); + + absl::Mutex mu; + bool value = false; // condition value (under mu) + absl::CondVar cv; // signals a change of `value` + + std::unique_ptr<absl::synchronization_internal::ThreadPool> pool = + CreateDefaultPool(); + RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] { + absl::MutexLock l(&mu); + value = true; + cv.Signal(); + }); + + absl::MutexLock lock(&mu); + absl::Time start_time = absl::Now(); + absl::Duration timeout = params.wait_timeout; + absl::Time deadline = start_time + timeout; + while (!value) { + if (params.use_absolute_deadline ? cv.WaitWithDeadline(&mu, deadline) + : cv.WaitWithTimeout(&mu, timeout)) { + break; // deadline/timeout exceeded + } + timeout = deadline - absl::Now(); // recompute + } + bool result = value; // note: `mu` is still held + + if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) { + EXPECT_EQ(params.expected_result, result); + break; + } } }
diff --git a/third_party/abseil-cpp/absl/time/BUILD.bazel b/third_party/abseil-cpp/absl/time/BUILD.bazel index e793da8..c7c16d4 100644 --- a/third_party/abseil-cpp/absl/time/BUILD.bazel +++ b/third_party/abseil-cpp/absl/time/BUILD.bazel
@@ -30,9 +30,8 @@ "clock.cc", "duration.cc", "format.cc", - "internal/get_current_time_ios.inc", + "internal/get_current_time_chrono.inc", "internal/get_current_time_posix.inc", - "internal/get_current_time_windows.inc", "time.cc", ], hdrs = [
diff --git a/third_party/abseil-cpp/absl/time/BUILD.gn b/third_party/abseil-cpp/absl/time/BUILD.gn index 24de31c..9927af8 100644 --- a/third_party/abseil-cpp/absl/time/BUILD.gn +++ b/third_party/abseil-cpp/absl/time/BUILD.gn
@@ -14,30 +14,19 @@ visibility = [ "*" ] } -config("suppress_unguarded_availability") { - # TODO(bugs.webrtc.org/9557): Remove -Wno-unguarded-availability when - # abseil will support Xcode 9.0+ (it currently supports Xcode 7.3.1+ - # which doesn't have -Wunguarded-availability and __builtin_available). - cflags = [ - "-Wno-unguarded-availability", - ] -} - source_set("time") { configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code", "//third_party/abseil-cpp:absl_default_cflags_cc", - ":suppress_unguarded_availability", ] public_configs = [ "//third_party/abseil-cpp:absl_include_config" ] sources = [ "clock.cc", "duration.cc", "format.cc", - "internal/get_current_time_ios.inc", + "internal/get_current_time_chrono.inc", "internal/get_current_time_posix.inc", - "internal/get_current_time_windows.inc", "time.cc", ] public = [
diff --git a/third_party/abseil-cpp/absl/time/clock.cc b/third_party/abseil-cpp/absl/time/clock.cc index 772f852..74ee140 100644 --- a/third_party/abseil-cpp/absl/time/clock.cc +++ b/third_party/abseil-cpp/absl/time/clock.cc
@@ -57,10 +57,8 @@ #endif #endif -#if defined(__APPLE__) -#include "absl/time/internal/get_current_time_ios.inc" -#elif defined(_WIN32) -#include "absl/time/internal/get_current_time_windows.inc" +#if defined(__APPLE__) || defined(_WIN32) +#include "absl/time/internal/get_current_time_chrono.inc" #else #include "absl/time/internal/get_current_time_posix.inc" #endif
diff --git a/third_party/abseil-cpp/absl/time/clock_test.cc b/third_party/abseil-cpp/absl/time/clock_test.cc index f143c036..707166d 100644 --- a/third_party/abseil-cpp/absl/time/clock_test.cc +++ b/third_party/abseil-cpp/absl/time/clock_test.cc
@@ -35,36 +35,84 @@ EXPECT_GE(after, now); } -TEST(SleepForTest, BasicSanity) { - absl::Duration sleep_time = absl::Milliseconds(2500); - absl::Time start = absl::Now(); - absl::SleepFor(sleep_time); - absl::Time end = absl::Now(); - EXPECT_LE(sleep_time - absl::Milliseconds(100), end - start); - EXPECT_GE(sleep_time + absl::Milliseconds(200), end - start); -} +enum class AlarmPolicy { kWithoutAlarm, kWithAlarm }; -#ifdef ABSL_HAVE_ALARM -// Helper for test SleepFor. +#if defined(ABSL_HAVE_ALARM) bool alarm_handler_invoked = false; + void AlarmHandler(int signo) { ASSERT_EQ(signo, SIGALRM); alarm_handler_invoked = true; } +#endif -TEST(SleepForTest, AlarmSupport) { - alarm_handler_invoked = false; - sig_t old_alarm = signal(SIGALRM, AlarmHandler); - alarm(2); - absl::Duration sleep_time = absl::Milliseconds(3500); - absl::Time start = absl::Now(); - absl::SleepFor(sleep_time); - absl::Time end = absl::Now(); - EXPECT_TRUE(alarm_handler_invoked); - EXPECT_LE(sleep_time - absl::Milliseconds(100), end - start); - EXPECT_GE(sleep_time + absl::Milliseconds(200), end - start); - signal(SIGALRM, old_alarm); +// Does SleepFor(d) take between lower_bound and upper_bound at least +// once between now and (now + timeout)? If requested (and supported), +// add an alarm for the middle of the sleep period and expect it to fire. +bool SleepForBounded(absl::Duration d, absl::Duration lower_bound, + absl::Duration upper_bound, absl::Duration timeout, + AlarmPolicy alarm_policy, int* attempts) { + const absl::Time deadline = absl::Now() + timeout; + while (absl::Now() < deadline) { +#if defined(ABSL_HAVE_ALARM) + sig_t old_alarm = SIG_DFL; + if (alarm_policy == AlarmPolicy::kWithAlarm) { + alarm_handler_invoked = false; + old_alarm = signal(SIGALRM, AlarmHandler); + alarm(absl::ToInt64Seconds(d / 2)); + } +#else + EXPECT_EQ(alarm_policy, AlarmPolicy::kWithoutAlarm); +#endif + ++*attempts; + absl::Time start = absl::Now(); + absl::SleepFor(d); + absl::Duration actual = absl::Now() - start; +#if defined(ABSL_HAVE_ALARM) + if (alarm_policy == AlarmPolicy::kWithAlarm) { + signal(SIGALRM, old_alarm); + if (!alarm_handler_invoked) continue; + } +#endif + if (lower_bound <= actual && actual <= upper_bound) { + return true; // yes, the SleepFor() was correctly bounded + } + } + return false; } -#endif // ABSL_HAVE_ALARM + +testing::AssertionResult AssertSleepForBounded(absl::Duration d, + absl::Duration early, + absl::Duration late, + absl::Duration timeout, + AlarmPolicy alarm_policy) { + const absl::Duration lower_bound = d - early; + const absl::Duration upper_bound = d + late; + int attempts = 0; + if (SleepForBounded(d, lower_bound, upper_bound, timeout, alarm_policy, + &attempts)) { + return testing::AssertionSuccess(); + } + return testing::AssertionFailure() + << "SleepFor(" << d << ") did not return within [" << lower_bound + << ":" << upper_bound << "] in " << attempts << " attempt" + << (attempts == 1 ? "" : "s") << " over " << timeout + << (alarm_policy == AlarmPolicy::kWithAlarm ? " with" : " without") + << " an alarm"; +} + +// Tests that SleepFor() returns neither too early nor too late. +TEST(SleepFor, Bounded) { + const absl::Duration d = absl::Milliseconds(2500); + const absl::Duration early = absl::Milliseconds(100); + const absl::Duration late = absl::Milliseconds(300); + const absl::Duration timeout = 48 * d; + EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout, + AlarmPolicy::kWithoutAlarm)); +#if defined(ABSL_HAVE_ALARM) + EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout, + AlarmPolicy::kWithAlarm)); +#endif +} } // namespace
diff --git a/third_party/abseil-cpp/absl/time/duration.cc b/third_party/abseil-cpp/absl/time/duration.cc index c13fa79..f402137b 100644 --- a/third_party/abseil-cpp/absl/time/duration.cc +++ b/third_party/abseil-cpp/absl/time/duration.cc
@@ -895,13 +895,10 @@ *d = dur; return true; } - bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { return ParseDuration(text, dst); } -std::string UnparseFlag(Duration d) { - return FormatDuration(d); -} +std::string UnparseFlag(Duration d) { return FormatDuration(d); } } // namespace absl
diff --git a/third_party/abseil-cpp/absl/time/duration_benchmark.cc b/third_party/abseil-cpp/absl/time/duration_benchmark.cc index 54f89a1..d5657bd 100644 --- a/third_party/abseil-cpp/absl/time/duration_benchmark.cc +++ b/third_party/abseil-cpp/absl/time/duration_benchmark.cc
@@ -27,47 +27,113 @@ // void BM_Duration_Factory_Nanoseconds(benchmark::State& state) { + int64_t i = 0; while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Nanoseconds(1)); + benchmark::DoNotOptimize(absl::Nanoseconds(i)); + i += 314159; } } BENCHMARK(BM_Duration_Factory_Nanoseconds); void BM_Duration_Factory_Microseconds(benchmark::State& state) { + int64_t i = 0; while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Microseconds(1)); + benchmark::DoNotOptimize(absl::Microseconds(i)); + i += 314; } } BENCHMARK(BM_Duration_Factory_Microseconds); void BM_Duration_Factory_Milliseconds(benchmark::State& state) { + int64_t i = 0; while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Milliseconds(1)); + benchmark::DoNotOptimize(absl::Milliseconds(i)); + i += 1; } } BENCHMARK(BM_Duration_Factory_Milliseconds); void BM_Duration_Factory_Seconds(benchmark::State& state) { + int64_t i = 0; while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Seconds(1)); + benchmark::DoNotOptimize(absl::Seconds(i)); + i += 1; } } BENCHMARK(BM_Duration_Factory_Seconds); void BM_Duration_Factory_Minutes(benchmark::State& state) { + int64_t i = 0; while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Minutes(1)); + benchmark::DoNotOptimize(absl::Minutes(i)); + i += 1; } } BENCHMARK(BM_Duration_Factory_Minutes); void BM_Duration_Factory_Hours(benchmark::State& state) { + int64_t i = 0; while (state.KeepRunning()) { - benchmark::DoNotOptimize(absl::Hours(1)); + benchmark::DoNotOptimize(absl::Hours(i)); + i += 1; } } BENCHMARK(BM_Duration_Factory_Hours); +void BM_Duration_Factory_DoubleNanoseconds(benchmark::State& state) { + double d = 1; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(absl::Nanoseconds(d)); + d = d * 1.00000001 + 1; + } +} +BENCHMARK(BM_Duration_Factory_DoubleNanoseconds); + +void BM_Duration_Factory_DoubleMicroseconds(benchmark::State& state) { + double d = 1e-3; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(absl::Microseconds(d)); + d = d * 1.00000001 + 1e-3; + } +} +BENCHMARK(BM_Duration_Factory_DoubleMicroseconds); + +void BM_Duration_Factory_DoubleMilliseconds(benchmark::State& state) { + double d = 1e-6; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(absl::Milliseconds(d)); + d = d * 1.00000001 + 1e-6; + } +} +BENCHMARK(BM_Duration_Factory_DoubleMilliseconds); + +void BM_Duration_Factory_DoubleSeconds(benchmark::State& state) { + double d = 1e-9; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(absl::Seconds(d)); + d = d * 1.00000001 + 1e-9; + } +} +BENCHMARK(BM_Duration_Factory_DoubleSeconds); + +void BM_Duration_Factory_DoubleMinutes(benchmark::State& state) { + double d = 1e-9; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(absl::Minutes(d)); + d = d * 1.00000001 + 1e-9; + } +} +BENCHMARK(BM_Duration_Factory_DoubleMinutes); + +void BM_Duration_Factory_DoubleHours(benchmark::State& state) { + double d = 1e-9; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(absl::Hours(d)); + d = d * 1.00000001 + 1e-9; + } +} +BENCHMARK(BM_Duration_Factory_DoubleHours); + // // Arithmetic //
diff --git a/third_party/abseil-cpp/absl/time/duration_test.cc b/third_party/abseil-cpp/absl/time/duration_test.cc index 704684e..7ae25dc6 100644 --- a/third_party/abseil-cpp/absl/time/duration_test.cc +++ b/third_party/abseil-cpp/absl/time/duration_test.cc
@@ -16,7 +16,9 @@ #include <cmath> #include <cstdint> #include <ctime> +#include <iomanip> #include <limits> +#include <random> #include <string> #include "gmock/gmock.h" @@ -105,22 +107,22 @@ } TEST(Duration, ToConversion) { -#define TEST_DURATION_CONVERSION(UNIT) \ - do { \ - const absl::Duration d = absl::UNIT(1.5); \ - const absl::Duration z = absl::ZeroDuration(); \ - const absl::Duration inf = absl::InfiniteDuration(); \ - const double dbl_inf = std::numeric_limits<double>::infinity(); \ - EXPECT_EQ(kint64min, absl::ToInt64##UNIT(-inf)); \ - EXPECT_EQ(-1, absl::ToInt64##UNIT(-d)); \ - EXPECT_EQ(0, absl::ToInt64##UNIT(z)); \ - EXPECT_EQ(1, absl::ToInt64##UNIT(d)); \ - EXPECT_EQ(kint64max, absl::ToInt64##UNIT(inf)); \ - EXPECT_EQ(-dbl_inf, absl::ToDouble##UNIT(-inf)); \ - EXPECT_EQ(-1.5, absl::ToDouble##UNIT(-d)); \ - EXPECT_EQ(0, absl::ToDouble##UNIT(z)); \ - EXPECT_EQ(1.5, absl::ToDouble##UNIT(d)); \ - EXPECT_EQ(dbl_inf, absl::ToDouble##UNIT(inf)); \ +#define TEST_DURATION_CONVERSION(UNIT) \ + do { \ + const absl::Duration d = absl::UNIT(1.5); \ + constexpr absl::Duration z = absl::ZeroDuration(); \ + constexpr absl::Duration inf = absl::InfiniteDuration(); \ + constexpr double dbl_inf = std::numeric_limits<double>::infinity(); \ + EXPECT_EQ(kint64min, absl::ToInt64##UNIT(-inf)); \ + EXPECT_EQ(-1, absl::ToInt64##UNIT(-d)); \ + EXPECT_EQ(0, absl::ToInt64##UNIT(z)); \ + EXPECT_EQ(1, absl::ToInt64##UNIT(d)); \ + EXPECT_EQ(kint64max, absl::ToInt64##UNIT(inf)); \ + EXPECT_EQ(-dbl_inf, absl::ToDouble##UNIT(-inf)); \ + EXPECT_EQ(-1.5, absl::ToDouble##UNIT(-d)); \ + EXPECT_EQ(0, absl::ToDouble##UNIT(z)); \ + EXPECT_EQ(1.5, absl::ToDouble##UNIT(d)); \ + EXPECT_EQ(dbl_inf, absl::ToDouble##UNIT(inf)); \ } while (0) TEST_DURATION_CONVERSION(Nanoseconds); @@ -1284,6 +1286,16 @@ EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(0.875e-9)); EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(1.000e-9)); + EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(-0.124999999e-9)); + EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.125e-9)); + EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.250e-9)); + EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.375e-9)); + EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.500e-9)); + EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.625e-9)); + EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.750e-9)); + EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-0.875e-9)); + EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-1.000e-9)); + timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0; @@ -1313,6 +1325,86 @@ EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv)); } +void VerifySameAsMul(double time_as_seconds, int* const misses) { + auto direct_seconds = absl::Seconds(time_as_seconds); + auto mul_by_one_second = time_as_seconds * absl::Seconds(1); + if (direct_seconds != mul_by_one_second) { + if (*misses > 10) return; + ASSERT_LE(++(*misses), 10) << "Too many errors, not reporting more."; + EXPECT_EQ(direct_seconds, mul_by_one_second) + << "given double time_as_seconds = " << std::setprecision(17) + << time_as_seconds; + } +} + +// For a variety of interesting durations, we find the exact point +// where one double converts to that duration, and the very next double +// converts to the next duration. For both of those points, verify that +// Seconds(point) returns the same duration as point * Seconds(1.0) +TEST(Duration, ToDoubleSecondsCheckEdgeCases) { + constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond; + constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u); + int misses = 0; + for (int64_t seconds = 0; seconds < 99; ++seconds) { + uint32_t tick_vals[] = {0, +999, +999999, +999999999, kTicksPerSecond - 1, + 0, 1000, 1000000, 1000000000, kTicksPerSecond, + 1, 1001, 1000001, 1000000001, kTicksPerSecond + 1, + 2, 1002, 1000002, 1000000002, kTicksPerSecond + 2, + 3, 1003, 1000003, 1000000003, kTicksPerSecond + 3, + 4, 1004, 1000004, 1000000004, kTicksPerSecond + 4, + 5, 6, 7, 8, 9}; + for (uint32_t ticks : tick_vals) { + absl::Duration s_plus_t = absl::Seconds(seconds) + ticks * duration_tick; + for (absl::Duration d : {s_plus_t, -s_plus_t}) { + absl::Duration after_d = d + duration_tick; + EXPECT_NE(d, after_d); + EXPECT_EQ(after_d - d, duration_tick); + + double low_edge = ToDoubleSeconds(d); + EXPECT_EQ(d, absl::Seconds(low_edge)); + + double high_edge = ToDoubleSeconds(after_d); + EXPECT_EQ(after_d, absl::Seconds(high_edge)); + + for (;;) { + double midpoint = low_edge + (high_edge - low_edge) / 2; + if (midpoint == low_edge || midpoint == high_edge) break; + absl::Duration mid_duration = absl::Seconds(midpoint); + if (mid_duration == d) { + low_edge = midpoint; + } else { + EXPECT_EQ(mid_duration, after_d); + high_edge = midpoint; + } + } + // Now low_edge is the highest double that converts to Duration d, + // and high_edge is the lowest double that converts to Duration after_d. + VerifySameAsMul(low_edge, &misses); + VerifySameAsMul(high_edge, &misses); + } + } + } +} + +TEST(Duration, ToDoubleSecondsCheckRandom) { + std::random_device rd; + std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()}); + std::mt19937_64 gen(seed); + // We want doubles distributed from 1/8ns up to 2^63, where + // as many values are tested from 1ns to 2ns as from 1sec to 2sec, + // so even distribute along a log-scale of those values, and + // exponentiate before using them. (9.223377e+18 is just slightly + // out of bounds for absl::Duration.) + std::uniform_real_distribution<double> uniform(std::log(0.125e-9), + std::log(9.223377e+18)); + int misses = 0; + for (int i = 0; i < 1000000; ++i) { + double d = std::exp(uniform(gen)); + VerifySameAsMul(d, &misses); + VerifySameAsMul(-d, &misses); + } +} + TEST(Duration, ConversionSaturation) { absl::Duration d;
diff --git a/third_party/abseil-cpp/absl/time/internal/get_current_time_chrono.inc b/third_party/abseil-cpp/absl/time/internal/get_current_time_chrono.inc new file mode 100644 index 0000000..cf884a1 --- /dev/null +++ b/third_party/abseil-cpp/absl/time/internal/get_current_time_chrono.inc
@@ -0,0 +1,29 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <chrono> +#include <cstdint> + +namespace absl { +namespace time_internal { + +static int64_t GetCurrentTimeNanosFromSystem() { + return std::chrono::duration_cast<std::chrono::nanoseconds>( + std::chrono::system_clock::now() - + std::chrono::system_clock::from_time_t(0)) + .count(); +} + +} // namespace time_internal +} // namespace absl
diff --git a/third_party/abseil-cpp/absl/time/internal/get_current_time_ios.inc b/third_party/abseil-cpp/absl/time/internal/get_current_time_ios.inc deleted file mode 100644 index f3db32b..0000000 --- a/third_party/abseil-cpp/absl/time/internal/get_current_time_ios.inc +++ /dev/null
@@ -1,80 +0,0 @@ -#include "absl/time/clock.h" - -#include <sys/time.h> -#include <ctime> -#include <cstdint> - -#include "absl/base/internal/raw_logging.h" - -// These are not defined in the Xcode 7.3.1 SDK Headers. -// Once we are no longer supporting Xcode 7.3.1 we can -// remove these. -#ifndef __WATCHOS_3_0 -#define __WATCHOS_3_0 30000 -#endif - -#ifndef __TVOS_10_0 -#define __TVOS_10_0 100000 -#endif - -#ifndef __IPHONE_10_0 -#define __IPHONE_10_0 100000 -#endif - -#ifndef __MAC_10_12 -#define __MAC_10_12 101200 -#endif - -namespace absl { -namespace time_internal { - -static int64_t GetCurrentTimeNanosFromSystem() { -#if (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12) || \ - (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0) || \ - (__WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0) || \ - (__TV_OS_VERSION_MAX_ALLOWED >= __TVOS_10_0) - // clock_gettime_nsec_np is not defined on SDKs before Xcode 8.0. - // This preprocessor logic is based upon __CLOCK_AVAILABILITY in - // usr/include/time.h. Once we are no longer supporting Xcode 7.3.1 we can - // remove this #if. - // We must continue to check if it is defined until we are sure that ALL the - // platforms we are shipping on support it. - // clock_gettime_nsec_np is preferred because it may give higher accuracy than - // gettimeofday in future Apple operating systems. - // Currently (macOS 10.12/iOS 10.2) clock_gettime_nsec_np accuracy is - // microsecond accuracy (i.e. equivalent to gettimeofday). - if (&clock_gettime_nsec_np != nullptr) { - return clock_gettime_nsec_np(CLOCK_REALTIME); - } -#endif -#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \ - (__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12)) || \ - (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \ - (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0)) || \ - (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && \ - (__WATCH_OS_VERSION_MIN_REQUIRED < __WATCHOS_3_0)) || \ - (defined(__TV_OS_VERSION_MIN_REQUIRED) && \ - (__TV_OS_VERSION_MIN_REQUIRED < __TVOS_10_0)) - // We need this block in 2 different cases: - // a) where we are compiling with Xcode 7 in which case the block above - // will not be compiled in, and this is the only block executed. - // b) where we are compiling with Xcode 8+ but supporting operating systems - // that do not define clock_gettime_nsec_np, so this is in effect - // an else block to the block above. - // This block will not be compiled if the min supported version is - // guaranteed to supply clock_gettime_nsec_np. - // - // Once we know that clock_gettime_nsec_np is in the SDK *AND* exists on - // all the platforms we support, we can remove both this block and alter the - // block above to just call clock_gettime_nsec_np directly. - const int64_t kNanosPerSecond = 1000 * 1000 * 1000; - const int64_t kNanosPerMicrosecond = 1000; - struct timeval tp; - ABSL_RAW_CHECK(gettimeofday(&tp, nullptr) == 0, "Failed gettimeofday"); - return (int64_t{tp.tv_sec} * kNanosPerSecond + - int64_t{tp.tv_usec} * kNanosPerMicrosecond); -#endif -} - -} // namespace time_internal -} // namespace absl
diff --git a/third_party/abseil-cpp/absl/time/internal/get_current_time_windows.inc b/third_party/abseil-cpp/absl/time/internal/get_current_time_windows.inc deleted file mode 100644 index b22a9c9..0000000 --- a/third_party/abseil-cpp/absl/time/internal/get_current_time_windows.inc +++ /dev/null
@@ -1,17 +0,0 @@ -#include "absl/time/clock.h" - -#include <chrono> -#include <cstdint> - -namespace absl { -namespace time_internal { - -static int64_t GetCurrentTimeNanosFromSystem() { - return std::chrono::duration_cast<std::chrono::nanoseconds>( - std::chrono::system_clock::now() - - std::chrono::system_clock::from_time_t(0)) - .count(); -} - -} // namespace time_internal -} // namespace absl
diff --git a/third_party/abseil-cpp/absl/time/time.h b/third_party/abseil-cpp/absl/time/time.h index ceec2de..c41cb89 100644 --- a/third_party/abseil-cpp/absl/time/time.h +++ b/third_party/abseil-cpp/absl/time/time.h
@@ -50,7 +50,7 @@ #ifndef ABSL_TIME_TIME_H_ #define ABSL_TIME_TIME_H_ -#if !defined(_WIN32) +#if !defined(_MSC_VER) #include <sys/time.h> #else #include <winsock2.h> @@ -81,6 +81,7 @@ constexpr uint32_t GetRepLo(Duration d); constexpr Duration MakeDuration(int64_t hi, uint32_t lo); constexpr Duration MakeDuration(int64_t hi, int64_t lo); +inline Duration MakePosDoubleDuration(double n); constexpr int64_t kTicksPerNanosecond = 4; constexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond; template <std::intmax_t N> @@ -295,6 +296,39 @@ // absl::Duration c = absl::Ceil(d, absl::Microseconds(1)); // 123457us Duration Ceil(Duration d, Duration unit); +// InfiniteDuration() +// +// Returns an infinite `Duration`. To get a `Duration` representing negative +// infinity, use `-InfiniteDuration()`. +// +// Duration arithmetic overflows to +/- infinity and saturates. In general, +// arithmetic with `Duration` infinities is similar to IEEE 754 infinities +// except where IEEE 754 NaN would be involved, in which case +/- +// `InfiniteDuration()` is used in place of a "nan" Duration. +// +// Examples: +// +// constexpr absl::Duration inf = absl::InfiniteDuration(); +// const absl::Duration d = ... any finite duration ... +// +// inf == inf + inf +// inf == inf + d +// inf == inf - inf +// -inf == d - inf +// +// inf == d * 1e100 +// inf == inf / 2 +// 0 == d / inf +// INT64_MAX == inf / d +// +// // Division by zero returns infinity, or INT64_MIN/MAX where appropriate. +// inf == d / 0 +// INT64_MAX == d / absl::ZeroDuration() +// +// The examples involving the `/` operator above also apply to `IDivDuration()` +// and `FDivDuration()`. +constexpr Duration InfiniteDuration(); + // Nanoseconds() // Microseconds() // Milliseconds() @@ -344,7 +378,13 @@ } template <typename T, time_internal::EnableIfFloat<T> = 0> Duration Seconds(T n) { - return n * Seconds(1); + if (n >= 0) { + if (n >= std::numeric_limits<int64_t>::max()) return InfiniteDuration(); + return time_internal::MakePosDoubleDuration(n); + } else { + if (n <= std::numeric_limits<int64_t>::min()) return -InfiniteDuration(); + return -time_internal::MakePosDoubleDuration(-n); + } } template <typename T, time_internal::EnableIfFloat<T> = 0> Duration Minutes(T n) { @@ -439,39 +479,6 @@ std::chrono::minutes ToChronoMinutes(Duration d); std::chrono::hours ToChronoHours(Duration d); -// InfiniteDuration() -// -// Returns an infinite `Duration`. To get a `Duration` representing negative -// infinity, use `-InfiniteDuration()`. -// -// Duration arithmetic overflows to +/- infinity and saturates. In general, -// arithmetic with `Duration` infinities is similar to IEEE 754 infinities -// except where IEEE 754 NaN would be involved, in which case +/- -// `InfiniteDuration()` is used in place of a "nan" Duration. -// -// Examples: -// -// constexpr absl::Duration inf = absl::InfiniteDuration(); -// const absl::Duration d = ... any finite duration ... -// -// inf == inf + inf -// inf == inf + d -// inf == inf - inf -// -inf == d - inf -// -// inf == d * 1e100 -// inf == inf / 2 -// 0 == d / inf -// INT64_MAX == inf / d -// -// // Division by zero returns infinity, or INT64_MIN/MAX where appropriate. -// inf == d / 0 -// INT64_MAX == d / absl::ZeroDuration() -// -// The examples involving the `/` operator above also apply to `IDivDuration()` -// and `FDivDuration()`. -constexpr Duration InfiniteDuration(); - // FormatDuration() // // Returns a std::string representing the duration in the form "72h3m0.5s". @@ -492,12 +499,9 @@ // `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`. bool ParseDuration(const std::string& dur_string, Duration* d); -// ParseFlag() -// +// Support for flag values of type Duration. Duration flags must be specified +// in a format that is valid input for absl::ParseDuration(). bool ParseFlag(const std::string& text, Duration* dst, std::string* error); - -// UnparseFlag() -// std::string UnparseFlag(Duration d); // Time @@ -991,9 +995,6 @@ bool ParseTime(const std::string& format, const std::string& input, TimeZone tz, Time* time, std::string* err); -// ParseFlag() -// UnparseFlag() -// // Support for flag values of type Time. Time flags must be specified in a // format that matches absl::RFC3339_full. For example: // @@ -1114,6 +1115,18 @@ return MakeDuration(hi, static_cast<uint32_t>(lo)); } +// Make a Duration value from a floating-point number, as long as that number +// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as +// it's positive and can be converted to int64_t without risk of UB. +inline Duration MakePosDoubleDuration(double n) { + const int64_t int_secs = static_cast<int64_t>(n); + const uint32_t ticks = + static_cast<uint32_t>((n - int_secs) * kTicksPerSecond + 0.5); + return ticks < kTicksPerSecond + ? MakeDuration(int_secs, ticks) + : MakeDuration(int_secs + 1, ticks - kTicksPerSecond); +} + // Creates a normalized Duration from an almost-normalized (sec,ticks) // pair. sec may be positive or negative. ticks must be in the range // -kTicksPerSecond < *ticks < kTicksPerSecond. If ticks is negative it
diff --git a/third_party/abseil-cpp/absl/types/internal/variant.h b/third_party/abseil-cpp/absl/types/internal/variant.h index 7db5e05..7708e67 100644 --- a/third_party/abseil-cpp/absl/types/internal/variant.h +++ b/third_party/abseil-cpp/absl/types/internal/variant.h
@@ -1062,32 +1062,6 @@ static void Overload(...); }; -//////////////////////////////// -// Library Fundamentals V2 TS // -//////////////////////////////// - -// TODO(calabrese): Consider moving this to absl/meta/type_traits.h - -// The following is a rough implementation of parts of the detection idiom. -// It is used for the comparison operator checks. - -template <class Enabler, class To, template <class...> class Op, class... Args> -struct is_detected_convertible_impl { - using type = std::false_type; -}; - -template <class To, template <class...> class Op, class... Args> -struct is_detected_convertible_impl< - absl::enable_if_t<std::is_convertible<Op<Args...>, To>::value>, To, Op, - Args...> { - using type = std::true_type; -}; - -// NOTE: This differs from library fundamentals by being lazy. -template <class To, template <class...> class Op, class... Args> -struct is_detected_convertible - : is_detected_convertible_impl<void, To, Op, Args...>::type {}; - template <class T> using LessThanResult = decltype(std::declval<T>() < std::declval<T>()); @@ -1107,6 +1081,8 @@ template <class T> using NotEqualResult = decltype(std::declval<T>() != std::declval<T>()); +using type_traits_internal::is_detected_convertible; + template <class... T> using RequireAllHaveEqualT = absl::enable_if_t< absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value,
diff --git a/third_party/abseil-cpp/absl/types/span_test.cc b/third_party/abseil-cpp/absl/types/span_test.cc index 5a4f0014..fbce7e87 100644 --- a/third_party/abseil-cpp/absl/types/span_test.cc +++ b/third_party/abseil-cpp/absl/types/span_test.cc
@@ -288,7 +288,7 @@ #ifdef ABSL_HAVE_EXCEPTIONS EXPECT_THROW(absl::MakeSpan(ramp).subspan(11, 5), std::out_of_range); #else - EXPECT_DEATH(absl::MakeSpan(ramp).subspan(11, 5), ""); + EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).subspan(11, 5), ""); #endif }
diff --git a/third_party/abseil-cpp/absl/types/variant.h b/third_party/abseil-cpp/absl/types/variant.h index fd1d49ac..17e0634 100644 --- a/third_party/abseil-cpp/absl/types/variant.h +++ b/third_party/abseil-cpp/absl/types/variant.h
@@ -248,7 +248,7 @@ // // Example: // -// absl::variant<int, std::string> bar = 42; +// absl::variant<int, std::string> foo = 42; // if (absl::holds_alternative<int>(foo)) { // std::cout << "The variant holds an integer"; // } @@ -449,14 +449,19 @@ //------------------------------------------------------------------------------ template <typename T0, typename... Tn> class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> { + static_assert(absl::conjunction<std::is_object<T0>, + std::is_object<Tn>...>::value, + "Attempted to instantiate a variant containing a non-object " + "type."); // Intentionally not qualifing `negation` with `absl::` to work around a bug // in MSVC 2015 with inline namespace and variadic template. - static_assert(absl::conjunction<std::is_object<T0>, std::is_object<Tn>..., - negation<std::is_array<T0> >, - negation<std::is_array<Tn> >..., - std::is_nothrow_destructible<T0>, + static_assert(absl::conjunction<negation<std::is_array<T0> >, + negation<std::is_array<Tn> >...>::value, + "Attempted to instantiate a variant containing an array type."); + static_assert(absl::conjunction<std::is_nothrow_destructible<T0>, std::is_nothrow_destructible<Tn>...>::value, - "Attempted to instantiate a variant with an unsupported type."); + "Attempted to instantiate a variant containing a non-nothrow " + "destructible type."); friend struct variant_internal::VariantCoreAccess;
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index b749189..21160770 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -1692,7 +1692,6 @@ kReplaceCharsetInXHR = 2230, kRespondToSameOriginRequestWithCrossOriginResponse = 2231, // Obsolete. kLinkRelModulePreload = 2232, - kHTMLFrameSetElementNonNullAnonymousNamedGetter = 2235, kCSPWithUnsafeEval = 2236, kWebAssemblyInstantiation = 2237, kV8IndexAccessor = 2238, @@ -1920,7 +1919,6 @@ kShapeOutsideContentBoxDifferentFromMarginBox = 2461, kShapeOutsidePaddingBoxDifferentFromMarginBox = 2462, kCSSContainLayoutPositionedDescendants = 2463, - kHTMLFrameSetElementAnonymousNamedGetter = 2464, kCanvasConvertToBlob = 2465, kPolymerV1Detected = 2466, kPolymerV2Detected = 2467,
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.h b/third_party/blink/renderer/bindings/core/v8/script_streamer.h index 80a39ce..7a4f0ee 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer.h +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.h
@@ -51,6 +51,7 @@ kStreamerNotReadyOnGetSource, kInlineScript, kDidntTryToStartStreaming, + kErrorOccurred, // Pseudo values that should never be seen in reported metrics kCount,
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 35b1b1e..e5aceae3 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1705,7 +1705,6 @@ "css/resolver/font_builder_test.cc", "css/resolver/font_style_resolver_test.cc", "css/resolver/match_result_test.cc", - "css/resolver/scoped_style_resolver_test.cc", "css/resolver/style_adjuster_test.cc", "css/rule_feature_set_test.cc", "css/rule_set_test.cc",
diff --git a/third_party/blink/renderer/core/css/ComputedStyleDiffFunctions.json5 b/third_party/blink/renderer/core/css/ComputedStyleDiffFunctions.json5 index c4866b3..4cae09bf 100644 --- a/third_party/blink/renderer/core/css/ComputedStyleDiffFunctions.json5 +++ b/third_party/blink/renderer/core/css/ComputedStyleDiffFunctions.json5
@@ -233,7 +233,6 @@ name: "DiffNeedsPaintInvalidationSubtree", fields_to_diff: ["mix-blend-mode", "isolation", "Mask", "MaskBoxImage"], }, - { name: "DiffNeedsPaintInvalidationObject", fields_to_diff: ["-webkit-user-modify", "user-select", "image-rendering", @@ -365,6 +364,10 @@ ] }, { + name: "UpdatePropertySpecificDifferencesMask", + fields_to_diff: ["Mask", "MaskBoxImage"], + }, + { name: "UpdatePropertySpecificDifferencesNeedsRecomputeOverflow", predicates_to_test: [ {
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc index f640c14..9b9a991 100644 --- a/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc +++ b/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
@@ -60,8 +60,7 @@ EXPECT_STREQ("rgb(0, 128, 0)", computed->GetPropertyValue(CSSPropertyColor).Utf8().data()); - EXPECT_EQ(RuntimeEnabledFeatures::SlotInFlatTreeEnabled(), - GetDocument().NeedsLayoutTreeUpdate()); + EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate()); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.cc b/third_party/blink/renderer/core/css/css_style_sheet.cc index d4dbe6ad..a8c013f 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet.cc +++ b/third_party/blink/renderer/core/css/css_style_sheet.cc
@@ -92,11 +92,6 @@ } CSSStyleSheet* CSSStyleSheet::Create(Document& document, - ExceptionState& exception_state) { - return CSSStyleSheet::Create(document, CSSStyleSheetInit(), exception_state); -} - -CSSStyleSheet* CSSStyleSheet::Create(Document& document, const CSSStyleSheetInit& options, ExceptionState& exception_state) { if (!RuntimeEnabledFeatures::ConstructableStylesheetsEnabled()) {
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.h b/third_party/blink/renderer/core/css/css_style_sheet.h index 2ee79dd..7dc0ace 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet.h +++ b/third_party/blink/renderer/core/css/css_style_sheet.h
@@ -53,7 +53,6 @@ public: static const Document* SingleOwnerDocument(const CSSStyleSheet*); - static CSSStyleSheet* Create(Document&, ExceptionState&); static CSSStyleSheet* Create(Document&, const CSSStyleSheetInit&, ExceptionState&); @@ -196,6 +195,11 @@ FRIEND_TEST_ALL_PREFIXES( CSSStyleSheetTest, CSSStyleSheetConstructionWithNonEmptyCSSStyleSheetInit); + FRIEND_TEST_ALL_PREFIXES(CSSStyleSheetTest, + CreateEmptyCSSStyleSheetWithEmptyCSSStyleSheetInit); + FRIEND_TEST_ALL_PREFIXES( + CSSStyleSheetTest, + CreateEmptyCSSStyleSheetWithNonEmptyCSSStyleSheetInit); FRIEND_TEST_ALL_PREFIXES( CSSStyleSheetTest, CreateCSSStyleSheetWithEmptyCSSStyleSheetInitAndText);
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.idl b/third_party/blink/renderer/core/css/css_style_sheet.idl index b70b9fe6..1251d19 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet.idl +++ b/third_party/blink/renderer/core/css/css_style_sheet.idl
@@ -21,9 +21,6 @@ // https://drafts.csswg.org/cssom/#the-cssstylesheet-interface [ - ConstructorCallWith=Document, - RaisesException=Constructor, - Constructor(optional CSSStyleSheetInit options), Exposed=Window ] interface CSSStyleSheet : StyleSheet { readonly attribute CSSRule? ownerRule;
diff --git a/third_party/blink/renderer/core/css/css_style_sheet_test.cc b/third_party/blink/renderer/core/css/css_style_sheet_test.cc index d4b1bf77..234c688 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet_test.cc +++ b/third_party/blink/renderer/core/css/css_style_sheet_test.cc
@@ -49,26 +49,12 @@ TEST_F(CSSStyleSheetTest, ConstructorWithoutRuntimeFlagThrowsException) { DummyExceptionStateForTesting exception_state; RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(false); - EXPECT_EQ(CSSStyleSheet::Create(GetDocument(), exception_state), nullptr); + EXPECT_EQ(CSSStyleSheet::Create(GetDocument(), CSSStyleSheetInit(), + exception_state), + nullptr); ASSERT_TRUE(exception_state.HadException()); } -TEST_F(CSSStyleSheetTest, CSSStyleSheetConstructionWithEmptyCSSStyleSheetInit) { - DummyExceptionStateForTesting exception_state; - CSSStyleSheet* sheet = CSSStyleSheet::Create(GetDocument(), exception_state); - ASSERT_FALSE(exception_state.HadException()); - EXPECT_TRUE(sheet->href().IsNull()); - EXPECT_EQ(sheet->parentStyleSheet(), nullptr); - EXPECT_EQ(sheet->ownerNode(), nullptr); - EXPECT_EQ(sheet->ownerRule(), nullptr); - EXPECT_EQ(sheet->media()->length(), 0U); - EXPECT_EQ(sheet->title(), StringImpl::empty_); - EXPECT_FALSE(sheet->AlternateFromConstructor()); - EXPECT_FALSE(sheet->disabled()); - EXPECT_EQ(sheet->cssRules(exception_state)->length(), 0U); - ASSERT_FALSE(exception_state.HadException()); -} - TEST_F(CSSStyleSheetTest, CSSStyleSheetConstructionWithNonEmptyCSSStyleSheetInit) { DummyExceptionStateForTesting exception_state; @@ -93,6 +79,48 @@ ASSERT_FALSE(exception_state.HadException()); } +TEST_F(CSSStyleSheetTest, CreateEmptyCSSStyleSheetWithEmptyCSSStyleSheetInit) { + V8TestingScope scope; + DummyExceptionStateForTesting exception_state; + CSSStyleSheet* sheet = GetDocument().createEmptyCSSStyleSheet( + scope.GetScriptState(), CSSStyleSheetInit(), exception_state); + ASSERT_FALSE(exception_state.HadException()); + EXPECT_TRUE(sheet->href().IsNull()); + EXPECT_EQ(sheet->parentStyleSheet(), nullptr); + EXPECT_EQ(sheet->ownerNode(), nullptr); + EXPECT_EQ(sheet->ownerRule(), nullptr); + EXPECT_EQ(sheet->media()->length(), 0U); + EXPECT_EQ(sheet->title(), StringImpl::empty_); + EXPECT_FALSE(sheet->AlternateFromConstructor()); + EXPECT_FALSE(sheet->disabled()); + EXPECT_EQ(sheet->cssRules(exception_state)->length(), 0U); + ASSERT_FALSE(exception_state.HadException()); +} + +TEST_F(CSSStyleSheetTest, + CreateEmptyCSSStyleSheetWithNonEmptyCSSStyleSheetInit) { + CSSStyleSheetInit init; + init.setMedia(MediaListOrString::FromString("screen, print")); + init.setTitle("test"); + init.setAlternate(true); + init.setDisabled(true); + V8TestingScope scope; + DummyExceptionStateForTesting exception_state; + CSSStyleSheet* sheet = GetDocument().createEmptyCSSStyleSheet( + scope.GetScriptState(), init, exception_state); + ASSERT_FALSE(exception_state.HadException()); + EXPECT_TRUE(sheet->href().IsNull()); + EXPECT_EQ(sheet->parentStyleSheet(), nullptr); + EXPECT_EQ(sheet->ownerNode(), nullptr); + EXPECT_EQ(sheet->ownerRule(), nullptr); + EXPECT_EQ(sheet->media()->length(), 2U); + EXPECT_EQ(sheet->media()->mediaText(), init.media().GetAsString()); + EXPECT_EQ(sheet->title(), init.title()); + EXPECT_TRUE(sheet->AlternateFromConstructor()); + EXPECT_TRUE(sheet->disabled()); + ASSERT_FALSE(exception_state.HadException()); +} + TEST_F(CSSStyleSheetTest, CreateCSSStyleSheetWithEmptyCSSStyleSheetInitAndText) { V8TestingScope scope;
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc index 288b55a4..de1df7a 100644 --- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
@@ -385,28 +385,6 @@ RuleSubSet::Create(parent_style_sheet, sheet_index, slotted_rule_set)); } -bool ScopedStyleResolver::HaveSameStyles(const ScopedStyleResolver* first, - const ScopedStyleResolver* second) { - // This method will return true if the two resolvers are either both empty, or - // if they contain the same active stylesheets by sharing the same - // StyleSheetContents. It is used to check if we can share ComputedStyle - // between two shadow hosts. This typically works when we have multiple - // instantiations of the same web component where the style elements are in - // the same order and contain the exact same source string in which case we - // will get a cache hit for sharing StyleSheetContents. - - size_t first_count = first ? first->author_style_sheets_.size() : 0; - size_t second_count = second ? second->author_style_sheets_.size() : 0; - if (first_count != second_count) - return false; - while (first_count--) { - if (first->author_style_sheets_[first_count]->Contents() != - second->author_style_sheets_[first_count]->Contents()) - return false; - } - return true; -} - void ScopedStyleResolver::RuleSubSet::Trace(blink::Visitor* visitor) { visitor->Trace(parent_style_sheet_); visitor->Trace(rule_set_);
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h index b426d49..81c2a47 100644 --- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
@@ -87,8 +87,6 @@ void SetNeedsAppendAllSheets() { needs_append_all_sheets_ = true; } static void KeyframesRulesAdded(const TreeScope&); static ContainerNode& InvalidationRootForTreeScope(const TreeScope&); - CORE_EXPORT static bool HaveSameStyles(const ScopedStyleResolver*, - const ScopedStyleResolver*); void V0ShadowAddedOnV1Document(); void Trace(blink::Visitor*);
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver_test.cc deleted file mode 100644 index c98d5ef..0000000 --- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver_test.cc +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" -#include "third_party/blink/renderer/core/dom/shadow_root.h" -#include "third_party/blink/renderer/core/dom/shadow_root_init.h" -#include "third_party/blink/renderer/core/frame/local_frame_view.h" -#include "third_party/blink/renderer/core/html/html_element.h" -#include "third_party/blink/renderer/core/testing/page_test_base.h" - -namespace blink { - -class ScopedStyleResolverTest : public PageTestBase { - protected: - StyleEngine& GetStyleEngine() { return GetDocument().GetStyleEngine(); } -}; - -TEST_F(ScopedStyleResolverTest, HasSameStylesNullNull) { - EXPECT_TRUE(ScopedStyleResolver::HaveSameStyles(nullptr, nullptr)); -} - -TEST_F(ScopedStyleResolverTest, HasSameStylesNullEmpty) { - ScopedStyleResolver& resolver = GetDocument().EnsureScopedStyleResolver(); - EXPECT_TRUE(ScopedStyleResolver::HaveSameStyles(nullptr, &resolver)); - EXPECT_TRUE(ScopedStyleResolver::HaveSameStyles(&resolver, nullptr)); -} - -TEST_F(ScopedStyleResolverTest, HasSameStylesEmptyEmpty) { - ScopedStyleResolver& resolver = GetDocument().EnsureScopedStyleResolver(); - EXPECT_TRUE(ScopedStyleResolver::HaveSameStyles(&resolver, &resolver)); -} - -TEST_F(ScopedStyleResolverTest, HasSameStylesNonEmpty) { - GetDocument().body()->SetInnerHTMLFromString( - "<div id=host1></div><div id=host2></div>"); - Element* host1 = GetDocument().getElementById("host1"); - Element* host2 = GetDocument().getElementById("host2"); - ASSERT_TRUE(host1); - ASSERT_TRUE(host2); - ShadowRoot& root1 = host1->AttachShadowRootInternal(ShadowRootType::kOpen); - ShadowRoot& root2 = host2->AttachShadowRootInternal(ShadowRootType::kOpen); - root1.SetInnerHTMLFromString("<style>::slotted(#dummy){color:pink}</style>"); - root2.SetInnerHTMLFromString("<style>::slotted(#dummy){color:pink}</style>"); - GetDocument().View()->UpdateAllLifecyclePhases(); - EXPECT_TRUE(ScopedStyleResolver::HaveSameStyles( - &root1.EnsureScopedStyleResolver(), &root2.EnsureScopedStyleResolver())); -} - -TEST_F(ScopedStyleResolverTest, HasSameStylesDifferentSheetCount) { - GetDocument().body()->SetInnerHTMLFromString( - "<div id=host1></div><div id=host2></div>"); - Element* host1 = GetDocument().getElementById("host1"); - Element* host2 = GetDocument().getElementById("host2"); - ASSERT_TRUE(host1); - ASSERT_TRUE(host2); - ShadowRoot& root1 = host1->AttachShadowRootInternal(ShadowRootType::kOpen); - ShadowRoot& root2 = host2->AttachShadowRootInternal(ShadowRootType::kOpen); - root1.SetInnerHTMLFromString( - "<style>::slotted(#dummy){color:pink}</style><style>div{}</style>"); - root2.SetInnerHTMLFromString("<style>::slotted(#dummy){color:pink}</style>"); - GetDocument().View()->UpdateAllLifecyclePhases(); - EXPECT_FALSE(ScopedStyleResolver::HaveSameStyles( - &root1.EnsureScopedStyleResolver(), &root2.EnsureScopedStyleResolver())); -} - -TEST_F(ScopedStyleResolverTest, HasSameStylesCacheMiss) { - GetDocument().body()->SetInnerHTMLFromString( - "<div id=host1></div><div id=host2></div>"); - Element* host1 = GetDocument().getElementById("host1"); - Element* host2 = GetDocument().getElementById("host2"); - ASSERT_TRUE(host1); - ASSERT_TRUE(host2); - ShadowRoot& root1 = host1->AttachShadowRootInternal(ShadowRootType::kOpen); - ShadowRoot& root2 = host2->AttachShadowRootInternal(ShadowRootType::kOpen); - // Style equality is detected when StyleSheetContents is shared. That is only - // the case when the source text is the same. The comparison will fail when - // adding an extra space to one of the sheets. - root1.SetInnerHTMLFromString("<style>::slotted(#dummy){color:pink}</style>"); - root2.SetInnerHTMLFromString("<style>::slotted(#dummy){ color:pink}</style>"); - GetDocument().View()->UpdateAllLifecyclePhases(); - EXPECT_FALSE(ScopedStyleResolver::HaveSameStyles( - &root1.EnsureScopedStyleResolver(), &root2.EnsureScopedStyleResolver())); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index a9ff7be8..fa2f454 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2189,6 +2189,7 @@ DetachPseudoElement(kPseudoIdAfter, context); DetachPseudoElement(kPseudoIdBackdrop, context); + DetachPseudoElement(kPseudoIdFirstLetter, context); if (!context.performing_reattach && IsUserActionElement()) { if (IsHovered())
diff --git a/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc b/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc index dbb09dae..8c310ff 100644 --- a/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc +++ b/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc
@@ -27,12 +27,9 @@ namespace flat_tree_traversal_test { class FlatTreeTraversalTest : public PageTestBase, - private ScopedSlotInFlatTreeForTest, ScopedIncrementalShadowDOMForTest { public: - FlatTreeTraversalTest() - : ScopedSlotInFlatTreeForTest(true), - ScopedIncrementalShadowDOMForTest(true) {} + FlatTreeTraversalTest() : ScopedIncrementalShadowDOMForTest(true) {} protected: // Sets |mainHTML| to BODY element with |innerHTML| property and attaches
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index a9d1b695..f8d37659 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -876,10 +876,7 @@ if (node.IsPseudoElement()) return node.ParentOrShadowHostNode(); if (node.IsChildOfV1ShadowHost()) { - HTMLSlotElement* slot = RuntimeEnabledFeatures::SlotInFlatTreeEnabled() - ? node.AssignedSlot() - : node.FinalDestinationSlot(); - if (slot) + if (HTMLSlotElement* slot = node.AssignedSlot()) return slot; } if (node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost()) { @@ -1181,10 +1178,7 @@ bool Node::CanParticipateInFlatTree() const { // TODO(hayato): Return false for pseudo elements. - if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled()) { return !IsShadowRoot() && !IsActiveV0InsertionPoint(*this); - } - return !IsShadowRoot() && !IsActiveSlotOrActiveV0InsertionPoint(); } bool Node::IsActiveSlotOrActiveV0InsertionPoint() const {
diff --git a/third_party/blink/renderer/core/editing/layout_selection.cc b/third_party/blink/renderer/core/editing/layout_selection.cc index 3c4637f..1b478f2 100644 --- a/third_party/blink/renderer/core/editing/layout_selection.cc +++ b/third_party/blink/renderer/core/editing/layout_selection.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/core/editing/layout_selection.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/editing/ephemeral_range.h" #include "third_party/blink/renderer/core/editing/frame_selection.h" @@ -293,19 +294,30 @@ return nullptr; } +static bool IsDisplayContentElement(const Node& node) { + if (!node.IsElementNode()) + return false; + const ComputedStyle* const style = node.GetComputedStyle(); + return style && style->Display() == EDisplay::kContents; +} + template <typename Visitor> static void VisitSelectedInclusiveDescendantsOfInternal(const Node& node, Visitor* visitor) { - LayoutObject* layout_object = node.GetLayoutObject(); - if (!layout_object) - return; - if (LayoutTextFragment* first_letter = FirstLetterPartFor(layout_object)) { - if (first_letter->GetSelectionState() != SelectionState::kNone) - visitor->Visit(first_letter); + // Display:content element appears in a flat tree even it doesn't have + // a LayoutObject but we need to visit its children. + if (!IsDisplayContentElement(node)) { + LayoutObject* layout_object = node.GetLayoutObject(); + if (!layout_object) + return; + if (LayoutTextFragment* first_letter = FirstLetterPartFor(layout_object)) { + if (first_letter->GetSelectionState() != SelectionState::kNone) + visitor->Visit(first_letter); + } + if (layout_object->GetSelectionState() == SelectionState::kNone) + return; + visitor->Visit(layout_object); } - if (layout_object->GetSelectionState() == SelectionState::kNone) - return; - visitor->Visit(layout_object); for (Node& child : FlatTreeTraversal::ChildrenOf(node)) VisitSelectedInclusiveDescendantsOfInternal(child, visitor);
diff --git a/third_party/blink/renderer/core/editing/layout_selection_test.cc b/third_party/blink/renderer/core/editing/layout_selection_test.cc index f6582f5..9c8dcc3e 100644 --- a/third_party/blink/renderer/core/editing/layout_selection_test.cc +++ b/third_party/blink/renderer/core/editing/layout_selection_test.cc
@@ -850,6 +850,35 @@ DumpSelectionInfo()); } +// http://crbug.com/870734 +TEST_F(LayoutSelectionTest, InvalidateSlot) { + Selection().SetSelectionAndEndTyping( + SetSelectionTextToBody("^<div>" + "<template data-mode=open>" + "<slot></slot>" + "</template>" + "foo" + "</div>|")); + UpdateAllLifecyclePhases(); + EXPECT_EQ( + "BODY, Contain, NotInvalidate \n" + " DIV, Contain, NotInvalidate \n" + " #shadow-root \n" + " SLOT, <null LayoutObject> \n" + " 'foo', StartAndEnd, NotInvalidate ", + DumpSelectionInfo()); + + Selection().Clear(); + Selection().CommitAppearanceIfNeeded(); + EXPECT_EQ( + "BODY, None, NotInvalidate \n" + " DIV, None, NotInvalidate \n" + " #shadow-root \n" + " SLOT, <null LayoutObject> \n" + " 'foo', None, ShouldInvalidate ", + DumpSelectionInfo()); +} + static const NGPaintFragment* FindNGPaintFragmentInternal( const NGPaintFragment* paint, const LayoutObject* layout_object) {
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc index d5c2fa7..7e425b0 100644 --- a/third_party/blink/renderer/core/frame/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -540,11 +540,6 @@ "self.origin (window.origin)", kM70, "5701042356355072")}; - case WebFeature::kHTMLFrameSetElementAnonymousNamedGetter: - return {"HTMLFrameSetElementAnonymousNamedGetter", kM70, - WillBeRemoved("Anonymous named getter of HTMLFrameSetElement", - kM70, "5235521668251648")}; - case WebFeature::kMediaElementSourceOnOfflineContext: return {"MediaElementAudioSourceNode", kM70, WillBeRemoved("Creating a MediaElementAudioSourceNode on an "
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index e681cb8..69c10f7 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -848,11 +848,11 @@ if (flags & kLayerTreeIncludesPaintInvalidations) { std::unique_ptr<JSONArray> object_paint_invalidations = view_->TrackedObjectPaintInvalidationsAsJSON(); - if (object_paint_invalidations && object_paint_invalidations->size()) { if (!layers) layers = JSONObject::Create(); - layers->SetArray("objectPaintInvalidations", - std::move(object_paint_invalidations)); + if (object_paint_invalidations && object_paint_invalidations->size()) { + layers->SetArray("objectPaintInvalidations", + std::move(object_paint_invalidations)); } }
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc b/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc index b3654203..bd294a4 100644 --- a/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc +++ b/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc
@@ -435,9 +435,11 @@ TEST_F(CustomElementRegistryTest, defineCustomElementWithStyle) { RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(true); + V8TestingScope scope; NonThrowableExceptionState should_not_throw; ElementDefinitionOptions options; - CSSStyleSheet* sheet = CSSStyleSheet::Create(GetDocument(), should_not_throw); + CSSStyleSheet* sheet = GetDocument().createEmptyCSSStyleSheet( + scope.GetScriptState(), CSSStyleSheetInit(), should_not_throw); options.setStyle(sheet); TestCustomElementDefinitionBuilder builder(sheet); CustomElementDefinition* definition_a =
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.cc b/third_party/blink/renderer/core/html/html_frame_set_element.cc index b1a5c9e..5b97378f 100644 --- a/third_party/blink/renderer/core/html/html_frame_set_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_set_element.cc
@@ -29,7 +29,6 @@ #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/events/mouse_event.h" -#include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/use_counter.h" @@ -292,23 +291,4 @@ } } -LocalDOMWindow* HTMLFrameSetElement::AnonymousNamedGetter( - const AtomicString& name) { - Element* frame_element = Children()->namedItem(name); - if (!IsHTMLFrameElement(frame_element)) - return nullptr; - Document* document = ToHTMLFrameElement(frame_element)->contentDocument(); - if (!document || !document->GetFrame()) - return nullptr; - - LocalDOMWindow* window = document->domWindow(); - if (window) { - UseCounter::Count( - *document, WebFeature::kHTMLFrameSetElementNonNullAnonymousNamedGetter); - } - Deprecation::CountDeprecation( - *document, WebFeature::kHTMLFrameSetElementAnonymousNamedGetter); - return window; -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.h b/third_party/blink/renderer/core/html/html_frame_set_element.h index 98e44dea..b526b381 100644 --- a/third_party/blink/renderer/core/html/html_frame_set_element.h +++ b/third_party/blink/renderer/core/html/html_frame_set_element.h
@@ -51,8 +51,6 @@ bool HasNonInBodyInsertionMode() const override { return true; } - LocalDOMWindow* AnonymousNamedGetter(const AtomicString&); - DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(blur); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(error); DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(focus);
diff --git a/third_party/blink/renderer/core/html/html_frame_set_element.idl b/third_party/blink/renderer/core/html/html_frame_set_element.idl index 372df54..c341896 100644 --- a/third_party/blink/renderer/core/html/html_frame_set_element.idl +++ b/third_party/blink/renderer/core/html/html_frame_set_element.idl
@@ -39,7 +39,6 @@ attribute EventHandler onscroll; // Non-standard APIs - [NotEnumerable] getter Window (DOMString name); [RuntimeEnabled=OrientationEvent] attribute EventHandler onorientationchange; };
diff --git a/third_party/blink/renderer/core/html/html_slot_element.cc b/third_party/blink/renderer/core/html/html_slot_element.cc index ee8af18..5927c57a 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.cc +++ b/third_party/blink/renderer/core/html/html_slot_element.cc
@@ -231,7 +231,6 @@ for (const auto& node : other.distributed_nodes_) distributed_indices_.Set(node.Get(), index++); } - void HTMLSlotElement::ClearAssignedNodes() { DCHECK(RuntimeEnabledFeatures::IncrementalShadowDOMEnabled()); assigned_nodes_.clear(); @@ -357,17 +356,12 @@ // of IncementalShadowDOM. const HeapVector<Member<Node>>& HTMLSlotElement::ChildrenInFlatTreeIfAssignmentIsSupported() { - if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled()) - return AssignedNodes(); - DCHECK(!NeedsDistributionRecalc()); - return distributed_nodes_; + return AssignedNodes(); } void HTMLSlotElement::DetachLayoutTree(const AttachContext& context) { if (SupportsAssignment()) { - const HeapVector<Member<Node>>& flat_tree_children = - RuntimeEnabledFeatures::SlotInFlatTreeEnabled() ? assigned_nodes_ - : distributed_nodes_; + const HeapVector<Member<Node>>& flat_tree_children = assigned_nodes_; for (auto& node : flat_tree_children) node->LazyReattachIfAttached(); } @@ -490,24 +484,8 @@ HTMLElement::RemovedFrom(insertion_point); } -void HTMLSlotElement::WillRecalcStyle(StyleRecalcChange change) { - if (RuntimeEnabledFeatures::SlotInFlatTreeEnabled()) - return; - if (change < kIndependentInherit && - GetStyleChangeType() < kSubtreeStyleChange) { - return; - } - for (auto& node : distributed_nodes_) { - node->SetNeedsStyleRecalc( - kLocalStyleChange, - StyleChangeReasonForTracing::Create( - StyleChangeReason::kPropagateInheritChangeToDistributedNodes)); - } -} void HTMLSlotElement::DidRecalcStyle(StyleRecalcChange change) { - if (!RuntimeEnabledFeatures::SlotInFlatTreeEnabled()) - return; if (change < kIndependentInherit) return; for (auto& node : assigned_nodes_) {
diff --git a/third_party/blink/renderer/core/html/html_slot_element.h b/third_party/blink/renderer/core/html/html_slot_element.h index e9a7f68..ffcb1a5 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.h +++ b/third_party/blink/renderer/core/html/html_slot_element.h
@@ -136,7 +136,6 @@ InsertionNotificationRequest InsertedInto(ContainerNode*) final; void RemovedFrom(ContainerNode*) final; - void WillRecalcStyle(StyleRecalcChange) final; void DidRecalcStyle(StyleRecalcChange) final; void EnqueueSlotChangeEvent();
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc index 245172b..946d717 100644 --- a/third_party/blink/renderer/core/input/event_handler.cc +++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -287,12 +287,12 @@ HitTestLocation adjusted_location( (LayoutRect(main_content_point, location.BoundingBox().Size()))); return main_frame.GetEventHandler().HitTestResultAtLocation( - adjusted_location, hit_type, stop_node); + adjusted_location, hit_type, stop_node, no_lifecycle_update); } else { HitTestLocation adjusted_location(main_view->ConvertFromRootFrame( frame_view->ConvertToRootFrame(location.Point()))); return main_frame.GetEventHandler().HitTestResultAtLocation( - adjusted_location, hit_type, stop_node); + adjusted_location, hit_type, stop_node, no_lifecycle_update); } } }
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 444a6d4..e547e3f 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -384,6 +384,8 @@ return "inline script"; case ScriptStreamer::kDidntTryToStartStreaming: return "start streaming not called"; + case ScriptStreamer::kErrorOccurred: + return "an error occurred"; case ScriptStreamer::kAlreadyLoaded: case ScriptStreamer::kCount: case ScriptStreamer::kInvalid:
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc index 05f71c3..4d4bda02 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -16,6 +16,10 @@ namespace { bool IsOccluded(const Element& element, const IntersectionGeometry& geometry) { + // TODO(layout-dev): This should hit-test the intersection rect, not the + // target rect; it's not helpful to know that the portion of the target that + // is clipped is also occluded. To do that, the intersection rect must be + // mapped down to the local space of the target element. HitTestResult result( element.GetLayoutObject()->HitTestForOcclusion(geometry.TargetRect())); return result.InnerNode() && result.InnerNode() != &element; @@ -80,7 +84,8 @@ Observer()->FirstThresholdGreaterThan(new_visible_ratio); if (RuntimeEnabledFeatures::IntersectionObserverV2Enabled() && Observer()->trackVisibility()) { - is_visible = !Target()->GetLayoutObject()->HasDistortingVisualEffects() && + is_visible = new_threshold_index > 0 && + !Target()->GetLayoutObject()->HasDistortingVisualEffects() && !IsOccluded(*Target(), geometry); } } else { @@ -99,7 +104,7 @@ IntersectionObserverEntry* new_entry = new IntersectionObserverEntry( timestamp, new_visible_ratio, FloatRect(geometry.TargetRect()), root_bounds_pointer, FloatRect(geometry.IntersectionRect()), - geometry.DoesIntersect(), is_visible, Target()); + new_threshold_index > 0, is_visible, Target()); Observer()->EnqueueIntersectionObserverEntry(*new_entry); SetLastThresholdIndex(new_threshold_index); SetWasVisible(is_visible);
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 28ed3f3..313f270 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -2679,7 +2679,7 @@ if (RuntimeEnabledFeatures::LayoutNGEnabled()) { if (const NGPaintFragment* paint_fragment = PaintFragment()) { NGBoxFragment box_fragment( - StyleRef().GetWritingMode(), + StyleRef().GetWritingMode(), StyleRef().Direction(), ToNGPhysicalBoxFragment(paint_fragment->PhysicalFragment())); NGLineHeightMetrics metrics = box_fragment.BaselineMetricsWithoutSynthesize(
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_content.cc b/third_party/blink/renderer/core/layout/layout_embedded_content.cc index 9e41eb9..d9de52d 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_content.cc +++ b/third_party/blink/renderer/core/layout/layout_embedded_content.cc
@@ -198,8 +198,10 @@ LayoutPoint(BorderLeft() + PaddingLeft(), BorderTop() + PaddingTop()); HitTestLocation new_hit_test_location( location_in_container, -adjusted_location - content_offset); - HitTestRequest new_hit_test_request(result.GetHitTestRequest().GetType() | - HitTestRequest::kChildFrameHitTest); + HitTestRequest new_hit_test_request( + result.GetHitTestRequest().GetType() | + HitTestRequest::kChildFrameHitTest, + result.GetHitTestRequest().GetStopNode()); HitTestResult child_frame_result(new_hit_test_request, new_hit_test_location);
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 0c3d6ac..76c542e 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -2082,7 +2082,7 @@ if (!IsText() && (diff.TransformChanged() || diff.OpacityChanged() || diff.ZIndexChanged() || diff.FilterChanged() || diff.BackdropFilterChanged() || diff.CssClipChanged() || - diff.BlendModeChanged())) { + diff.BlendModeChanged() || diff.MaskChanged())) { SetNeedsPaintPropertyUpdate(); if (HasLayer() && IsBoxModelObject()) { ToLayoutBoxModelObject(this)->Layer()->SetNeedsCompositingInputsUpdate();
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc index c611605c..9f6b920 100644 --- a/third_party/blink/renderer/core/layout/layout_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -847,4 +847,34 @@ EXPECT_FALSE(DocumentHasTouchActionRegion(registry)); } +TEST_F(LayoutObjectSimTest, HitTestForOcclusionInIframe) { + SimRequest main_resource("https://example.com/test.html", "text/html"); + SimRequest frame_resource("https://example.com/frame.html", "text/html"); + + LoadURL("https://example.com/test.html"); + main_resource.Complete(R"HTML( + <iframe style='width:300px;height:150px;' src=frame.html></iframe> + <div id='occluder' style='will-change:transform;width:100px;height:100px;'> + </div> + )HTML"); + frame_resource.Complete(R"HTML( + <div id='target'>target</div> + )HTML"); + + GetDocument().View()->UpdateAllLifecyclePhases(); + Element* iframe_element = GetDocument().QuerySelector("iframe"); + HTMLFrameOwnerElement* frame_owner_element = + ToHTMLFrameOwnerElement(iframe_element); + Document* iframe_doc = frame_owner_element->contentDocument(); + Element* target = iframe_doc->getElementById("target"); + HitTestResult result = target->GetLayoutObject()->HitTestForOcclusion(); + EXPECT_TRUE(result.InnerNode() == target); + + Element* occluder = GetDocument().getElementById("occluder"); + occluder->SetInlineStyleProperty(CSSPropertyMarginTop, "-150px"); + GetDocument().View()->UpdateAllLifecyclePhases(); + result = target->GetLayoutObject()->HitTestForOcclusion(); + EXPECT_TRUE(result.InnerNode() == occluder); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc index 24658d7..089fb15 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -424,7 +424,7 @@ const NGInlineItem& item = *item_result->item; DCHECK(item.Style()); NGBoxFragment fragment( - ConstraintSpace().GetWritingMode(), + ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(), ToNGPhysicalBoxFragment(*item_result->layout_result->PhysicalFragment())); NGLineHeightMetrics metrics = fragment.BaselineMetrics( {NGBaselineAlgorithmType::kAtomicInline, baseline_type_},
diff --git a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc index e41932c..92a8543b 100644 --- a/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc +++ b/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
@@ -75,7 +75,7 @@ content_metrics = line_box.Metrics(); } else { - NGBoxFragment content_fragment(space.GetWritingMode(), + NGBoxFragment content_fragment(space.GetWritingMode(), space.Direction(), ToNGPhysicalBoxFragment(content)); content_metrics = content_fragment.BaselineMetricsWithoutSynthesize( {NGBaselineAlgorithmType::kFirstLine, baseline_type}); @@ -95,7 +95,7 @@ ToNGPhysicalBoxFragment(*marker_layout_result->PhysicalFragment()); // Compute the inline offset of the marker. - NGBoxFragment marker_fragment(space.GetWritingMode(), + NGBoxFragment marker_fragment(space.GetWritingMode(), space.Direction(), marker_physical_fragment); NGLogicalOffset marker_offset( InlineOffset(marker_fragment.Size().inline_size),
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 125b8f7..a4d6837f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -305,6 +305,7 @@ DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess); NGBoxFragment fragment( container_writing_mode, + TextDirection::kLtr, // irrelevant here ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment())); sizes.min_size = sizes.max_size = fragment.Size().inline_size; return sizes; @@ -326,6 +327,7 @@ scoped_refptr<NGLayoutResult> layout_result = Layout(*zero_constraint_space); NGBoxFragment min_fragment( container_writing_mode, + TextDirection::kLtr, // irrelevant here ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment())); sizes.min_size = min_fragment.Size().inline_size; @@ -339,6 +341,7 @@ layout_result = Layout(*infinite_constraint_space); NGBoxFragment max_fragment( container_writing_mode, + TextDirection::kLtr, // irrelevant here ToNGPhysicalBoxFragment(*layout_result->PhysicalFragment())); sizes.max_size = max_fragment.Size().inline_size; return sizes; @@ -421,7 +424,8 @@ const NGPhysicalBoxFragment& physical_fragment = ToNGPhysicalBoxFragment(*layout_result.PhysicalFragment()); - NGBoxFragment fragment(constraint_space.GetWritingMode(), physical_fragment); + NGBoxFragment fragment(constraint_space.GetWritingMode(), + constraint_space.Direction(), physical_fragment); NGLogicalSize fragment_logical_size = fragment.Size(); // For each fragment we process, we'll accumulate the logical height and // logical intrinsic content box height. We reset it at the first fragment, @@ -444,7 +448,7 @@ NGBoxStrut borders = ComputeBorders(constraint_space, Style()); NGBoxStrut scrollbars = GetScrollbarSizes(); - NGBoxStrut padding = ComputePadding(constraint_space, Style()); + NGBoxStrut padding = fragment.Padding(); NGBoxStrut border_scrollbar_padding = borders + scrollbars + padding; if (IsLastFragment(physical_fragment))
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc index b5a5bf1..7dcf098 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
@@ -83,4 +83,10 @@ return NGLineHeightMetrics(block_size - block_size / 2, block_size / 2); } +NGBoxStrut NGBoxFragment::Padding() const { + const auto& physical_fragment = ToNGPhysicalBoxFragment(physical_fragment_); + return physical_fragment.Padding().ConvertToLogical(GetWritingMode(), + direction_); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h index 93c08fc..09ebade 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/layout/ng/ng_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" +#include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/text/writing_mode.h" namespace blink { @@ -18,8 +19,9 @@ class CORE_EXPORT NGBoxFragment final : public NGFragment { public: NGBoxFragment(WritingMode writing_mode, + TextDirection direction, const NGPhysicalBoxFragment& physical_fragment) - : NGFragment(writing_mode, physical_fragment) {} + : NGFragment(writing_mode, physical_fragment), direction_(direction) {} // Compute baseline metrics (ascent/descent) for this box. // @@ -33,6 +35,11 @@ const NGBaselineRequest&) const; NGLineHeightMetrics BaselineMetrics(const NGBaselineRequest&, const NGConstraintSpace&) const; + + NGBoxStrut Padding() const; + + private: + TextDirection direction_; }; DEFINE_TYPE_CASTS(NGBoxFragment,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc index 209816b..6ae4c0f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -131,7 +131,9 @@ separate_leading_margins = false; } - LayoutUnit block_size = NGBoxFragment(writing_mode, *column).BlockSize(); + LayoutUnit block_size = + NGBoxFragment(writing_mode, ConstraintSpace().Direction(), *column) + .BlockSize(); intrinsic_block_size = std::max(intrinsic_block_size, column_block_offset + block_size);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc index 3b6b61d..80e0055 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
@@ -308,8 +308,7 @@ scoped_refptr<NGPhysicalBoxFragment> fragment = base::AdoptRef(new NGPhysicalBoxFragment( layout_object_, Style(), style_variant_, physical_size, children_, - padding_.ConvertToPhysical(GetWritingMode(), Direction()) - .SnapToDevicePixels(), + padding_.ConvertToPhysical(GetWritingMode(), Direction()), contents_ink_overflow, baselines_, BoxType(), is_old_layout_root_, border_edges_.ToPhysical(GetWritingMode()), std::move(break_token)));
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc index 96198041..f6b0998 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -21,6 +21,7 @@ if (!break_token) return LayoutUnit(); NGBoxFragment logical_fragment(constraint_space.GetWritingMode(), + constraint_space.Direction(), ToNGPhysicalBoxFragment(fragment)); return break_token->UsedBlockSize() - logical_fragment.BlockSize(); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc index bc3ab40e..9620257 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
@@ -56,7 +56,8 @@ container_builder_.AddChild(result, page_offset); - NGBoxFragment logical_fragment(writing_mode, *page); + NGBoxFragment logical_fragment(writing_mode, ConstraintSpace().Direction(), + *page); intrinsic_block_size = std::max(intrinsic_block_size, page_offset.block_offset + logical_fragment.BlockSize());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index fdb249e..aff29b78 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -22,7 +22,7 @@ NGStyleVariant style_variant, NGPhysicalSize size, Vector<scoped_refptr<NGPhysicalFragment>>& children, - const NGPixelSnappedPhysicalBoxStrut& padding, + const NGPhysicalBoxStrut& padding, const NGPhysicalOffsetRect& contents_ink_overflow, Vector<NGBaseline>& baselines, NGBoxType box_type,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h index a0c47ef..3e7f084 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -22,7 +22,7 @@ NGStyleVariant style_variant, NGPhysicalSize size, Vector<scoped_refptr<NGPhysicalFragment>>& children, - const NGPixelSnappedPhysicalBoxStrut& padding, + const NGPhysicalBoxStrut& padding, const NGPhysicalOffsetRect& contents_ink_overflow, Vector<NGBaseline>& baselines, NGBoxType box_type, @@ -32,7 +32,10 @@ const NGBaseline* Baseline(const NGBaselineRequest&) const; - const NGPixelSnappedPhysicalBoxStrut& Padding() const { return padding_; } + const NGPhysicalBoxStrut& Padding() const { return padding_; } + NGPixelSnappedPhysicalBoxStrut PixelSnappedPadding() const { + return padding_.SnapToDevicePixels(); + } bool HasSelfPaintingLayer() const; bool ChildrenInline() const; @@ -69,7 +72,7 @@ private: Vector<NGBaseline> baselines_; - NGPixelSnappedPhysicalBoxStrut padding_; + NGPhysicalBoxStrut padding_; NGPhysicalOffsetRect descendant_outlines_; };
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 e50a69a..ffa3a8f 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
@@ -464,16 +464,6 @@ CompositingLayerAssigner layer_assigner(this); layer_assigner.Assign(update_root, layers_needing_paint_invalidation); - { - TRACE_EVENT0("blink", - "PaintLayerCompositor::updateAfterCompositingChange"); - if (const LocalFrameView::ScrollableAreaSet* scrollable_areas = - layout_view_.GetFrameView()->ScrollableAreas()) { - for (PaintLayerScrollableArea* scrollable_area : *scrollable_areas) - scrollable_area->UpdateAfterCompositingChange(); - } - } - if (layer_assigner.LayersChanged()) { update_type = std::max(update_type, kCompositingUpdateRebuildTree); if (ScrollingCoordinator* scrolling_coordinator =
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index 5d925da..bdaa022 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -796,7 +796,8 @@ LayoutRectOutsets NGBoxFragmentPainter::ComputePadding() const { return BoxStrutToLayoutRectOutsets( - ToNGPhysicalBoxFragment(box_fragment_.PhysicalFragment()).Padding()); + ToNGPhysicalBoxFragment(box_fragment_.PhysicalFragment()) + .PixelSnappedPadding()); } BoxPainterBase::FillLayerInfo NGBoxFragmentPainter::GetFillLayerInfo(
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 687d40b..13e0c5d5 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -151,7 +151,6 @@ needs_ancestor_dependent_compositing_inputs_update_(true), child_needs_compositing_inputs_update_(true), has_compositing_descendant_(false), - is_all_scrolling_content_composited_(false), should_isolate_composited_descendants_(false), lost_grouped_mapping_(false), needs_repaint_(false), @@ -704,34 +703,6 @@ } } -// FIXME: this is quite brute-force. We could be more efficient if we were to -// track state and update it as appropriate as changes are made in the layout -// tree. -void PaintLayer::UpdateScrollingStateAfterCompositingChange() { - TRACE_EVENT0("blink", - "PaintLayer::updateScrollingStateAfterCompositingChange"); - is_all_scrolling_content_composited_ = true; - for (LayoutObject* r = GetLayoutObject().SlowFirstChild(); r; - r = r->NextSibling()) { - if (!r->HasLayer()) { - is_all_scrolling_content_composited_ = false; - return; - } - } - - for (PaintLayer* child = FirstChild(); child; child = child->NextSibling()) { - if (child->GetCompositingState() == kNotComposited) { - is_all_scrolling_content_composited_ = false; - return; - } else if (!child->GetLayoutObject().StyleRef().IsStackingContext()) { - // If the child is composited, but not a stacking context, it may paint - // negative z-index descendants into an ancestor's GraphicsLayer. - is_all_scrolling_content_composited_ = false; - return; - } - } -} - void PaintLayer::UpdateDescendantDependentFlags() { if (needs_descendant_dependent_flags_update_) { bool old_has_non_isolated_descendant_with_blend_mode =
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 2b67369..b3c274b1 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -353,12 +353,6 @@ // True if this layer container layoutObjects that paint. bool HasNonEmptyChildLayoutObjects() const; - // Will ensure that isAllScrollingContentComposited() is up to date. - void UpdateScrollingStateAfterCompositingChange(); - bool IsAllScrollingContentComposited() const { - return is_all_scrolling_content_composited_; - } - // Gets the ancestor layer that serves as the containing block (in the sense // of LayoutObject::container() instead of LayoutObject::containingBlock()) // of this layer. Normally the parent layer is the containing layer, except @@ -1275,11 +1269,6 @@ // the tree of z-order lists. unsigned has_compositing_descendant_ : 1; - // True iff we have scrollable overflow and all children of layout_object_ are - // known to paint exclusively into their own composited layers. Set by - // updateScrollingStateAfterCompositingChange(). - unsigned is_all_scrolling_content_composited_ : 1; - // Should be for stacking contexts having unisolated blending descendants. unsigned should_isolate_composited_descendants_ : 1;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 2c9bbb7f..766fd23 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -509,18 +509,25 @@ void PaintLayerScrollableArea::InvalidatePaintForScrollOffsetChange( bool offset_was_zero) { - if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { - // "background-attachment: local" causes the background of this element to - // change position due to scroll so a paint invalidation is needed. - // TODO(pdr): This invalidation can be removed if the local background - // attachment is painted into the scrolling contents. - if (ScrollsOverflow() && - GetLayoutBox()->Style()->BackgroundLayers().Attachment() == - EFillAttachment::kLocal) { + bool requires_paint_invalidation = false; + + // "background-attachment: local" causes the background of this element to + // change position due to scroll so a paint invalidation is needed. + // TODO(pdr): This invalidation can be removed if the local background + // attachment is painted into the scrolling contents. + if (ScrollsOverflow() && + GetLayoutBox()->Style()->BackgroundLayers().Attachment() == + EFillAttachment::kLocal) { + if (!UsesCompositedScrolling()) + requires_paint_invalidation = true; + + if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { GetLayoutBox()->SetShouldDoFullPaintInvalidation(); return; } + } + if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { // TODO(pdr): If this is the root frame, descendants with fixed background // attachments need to be invalidated. @@ -537,32 +544,17 @@ // PaintLayer to just check for interest rect changes instead of doing a // full repaint. bool needs_repaint_for_interest_rect = true; - if (needs_repaint_for_overflow_hidden || needs_repaint_for_interest_rect) { + if (needs_repaint_for_overflow_hidden || needs_repaint_for_interest_rect) Layer()->SetNeedsRepaint(); - return; - } return; } - bool requires_paint_invalidation = true; - LocalFrameView* frame_view = GetLayoutBox()->GetFrameView(); bool is_root_layer = Layer()->IsRootLayer(); - if (GetLayoutBox()->View()->Compositor()->InCompositingMode()) { - bool only_scrolled_composited_layers = - ScrollsOverflow() && Layer()->IsAllScrollingContentComposited() && - GetLayoutBox()->Style()->BackgroundLayers().Attachment() != - EFillAttachment::kLocal; + frame_view->InvalidateBackgroundAttachmentFixedDescendants(*GetLayoutBox()); - if (UsesCompositedScrolling() || only_scrolled_composited_layers) - requires_paint_invalidation = false; - } - - if (requires_paint_invalidation || is_root_layer) - frame_view->InvalidateBackgroundAttachmentFixedDescendants(*GetLayoutBox()); - - if (!requires_paint_invalidation && is_root_layer) { + if (is_root_layer) { // Some special invalidations for the root layer. if (frame_view->HasViewportConstrainedObjects()) { if (!frame_view->InvalidateViewportConstrainedObjects()) @@ -574,6 +566,13 @@ if (requires_paint_invalidation) { GetLayoutBox()->SetShouldDoFullPaintInvalidation(); GetLayoutBox()->SetMayNeedPaintInvalidationSubtree(); + } else if (!UsesCompositedScrolling()) { + // If any scrolling content might have ben clipped by a cull rect, then + // that cull rect could be affected by scroll offset. For composited + // scrollers, this will be taken care of by the interest rect computation + // in CompositedLayerMapping. + // TODO(chrishtr): replace this shortcut with interest rects. + Layer()->SetNeedsRepaint(); } } @@ -1222,10 +1221,6 @@ UpdateResizerStyle(old_style); } -void PaintLayerScrollableArea::UpdateAfterCompositingChange() { - Layer()->UpdateScrollingStateAfterCompositingChange(); -} - void PaintLayerScrollableArea::UpdateAfterOverflowRecalc() { UpdateScrollDimensions(); UpdateScrollbarProportions();
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h index 11fbcd3..b11c19df 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -378,8 +378,6 @@ void UpdateAfterStyleChange(const ComputedStyle*); void UpdateAfterOverflowRecalc(); - void UpdateAfterCompositingChange(); - bool HasScrollbar() const { return HasHorizontalScrollbar() || HasVerticalScrollbar(); }
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.cc b/third_party/blink/renderer/core/script/classic_pending_script.cc index a08c15b..b34d5f65 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.cc +++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -380,11 +380,13 @@ DCHECK_EQ(not_streamed_reason, ScriptStreamer::kInvalid); if (streamer_->StreamingSuppressed()) { not_streamed_reason = streamer_->StreamingSuppressedReason(); - } else if (ready_state_ != kReady) { - DCHECK_EQ(ready_state_, kReadyStreaming); + } else if (ready_state_ == kErrorOccurred) { + not_streamed_reason = ScriptStreamer::kErrorOccurred; + } else if (ready_state_ == kReadyStreaming) { not_streamed_reason = ScriptStreamer::kStreamerNotReadyOnGetSource; } else { // Streamer can be used to compile script. + DCHECK_EQ(ready_state_, kReady); streamer_ready = true; } }
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index c6aa9af24..c20bd46 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -814,6 +814,9 @@ diff.SetTextDecorationOrColorChanged(); } + if (ComputedStyleBase::UpdatePropertySpecificDifferencesMask(*this, other)) + diff.SetMaskChanged(); + bool has_clip = HasOutOfFlowPosition() && !HasAutoClip(); bool other_has_clip = other.HasOutOfFlowPosition() && !other.HasAutoClip(); if (has_clip != other_has_clip ||
diff --git a/third_party/blink/renderer/core/style/style_difference.h b/third_party/blink/renderer/core/style/style_difference.h index 356d6810..2d9e013 100644 --- a/third_party/blink/renderer/core/style/style_difference.h +++ b/third_party/blink/renderer/core/style/style_difference.h
@@ -27,6 +27,7 @@ // decorations or properties dependent on color (e.g., border or outline). kTextDecorationOrColorChanged = 1 << 6, kBlendModeChanged = 1 << 7, + kMaskChanged = 1 << 8, // If you add a value here, be sure to update kPropertyDifferenceCount. }; @@ -146,6 +147,11 @@ property_specific_differences_ |= kTextDecorationOrColorChanged; } + bool MaskChanged() const { + return property_specific_differences_ & kMaskChanged; + } + void SetMaskChanged() { property_specific_differences_ |= kMaskChanged; } + bool ScrollAnchorDisablingPropertyChanged() const { return scroll_anchor_disabling_property_changed_; } @@ -156,7 +162,7 @@ void SetCompositingReasonsChanged() { composited_reasons_changed_ = true; } private: - static constexpr int kPropertyDifferenceCount = 8; + static constexpr int kPropertyDifferenceCount = 9; friend CORE_EXPORT std::ostream& operator<<(std::ostream&, const StyleDifference&);
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js index 5fe611e..44b1ee9 100644 --- a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js +++ b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js
@@ -71,7 +71,8 @@ const titleElement = popoverContentElement.createChild('div', 'monospace object-popover-title'); titleElement.createChild('span').textContent = description; linkifier = new Components.Linkifier(); - const section = new ObjectUI.ObjectPropertiesSection(result, '', linkifier); + const section = new ObjectUI.ObjectPropertiesSection( + result, '', linkifier, undefined, undefined, undefined, true /* showOverflow */); section.element.classList.add('object-popover-tree'); section.titleLessMode(); popoverContentElement.appendChild(section.element);
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css b/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css index fe10ae09..2ce0756a 100644 --- a/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css +++ b/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css
@@ -54,6 +54,7 @@ .name-and-value { overflow-x: hidden; text-overflow: ellipsis; + line-height: normal; } .editing-sub-part .name-and-value {
diff --git a/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js b/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js index 7cf6d2f..376b50d 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js +++ b/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js
@@ -56,6 +56,20 @@ /** * @param {!Element} element */ +UI.ARIAUtils.markAsMenu = function(element) { + element.setAttribute('role', 'menu'); +}; + +/** + * @param {!Element} element + */ +UI.ARIAUtils.markAsMenuItem = function(element) { + element.setAttribute('role', 'menuitem'); +}; + +/** + * @param {!Element} element + */ UI.ARIAUtils.markAsHidden = function(element) { element.setAttribute('aria-hidden', 'true'); };
diff --git a/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js b/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js index 65da0ee..759b485 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js +++ b/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js
@@ -434,8 +434,7 @@ _innerShow() { const menuObject = this._buildMenuDescriptors(); - if (this._useSoftMenu || UI.ContextMenu._useSoftMenu || InspectorFrontendHost.isHostedMode() || - (UI.themeSupport.hasTheme() && menuObject.length)) { + if (this._useSoftMenu || UI.ContextMenu._useSoftMenu || InspectorFrontendHost.isHostedMode()) { this._softMenu = new UI.SoftContextMenu(menuObject, this._itemSelected.bind(this)); this._softMenu.show(this._event.target.ownerDocument, new AnchorBox(this._x, this._y, 0, 0)); } else {
diff --git a/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js b/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js index 1f2a605..aff0106c 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js +++ b/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js
@@ -36,6 +36,8 @@ this._items = items; this._itemSelectedCallback = itemSelectedCallback; this._parentMenu = parentMenu; + /** @type {?Element} */ + this._highlightedMenuItemElement = null; } /** @@ -60,7 +62,8 @@ this._parentMenu ? UI.GlassPane.AnchorBehavior.PreferRight : UI.GlassPane.AnchorBehavior.PreferBottom); this._contextMenuElement = this._glassPane.contentElement.createChild('div', 'soft-context-menu'); - this._contextMenuElement.tabIndex = 0; + this._contextMenuElement.tabIndex = -1; + UI.ARIAUtils.markAsMenu(this._contextMenuElement); this._contextMenuElement.addEventListener('mouseup', e => e.consume(), false); this._contextMenuElement.addEventListener('keydown', this._menuKeyDown.bind(this), false); @@ -106,6 +109,8 @@ return this._createSubMenu(item); const menuItemElement = createElementWithClass('div', 'soft-context-menu-item'); + menuItemElement.tabIndex = -1; + UI.ARIAUtils.markAsMenuItem(menuItemElement); const checkMarkElement = UI.Icon.create('smallicon-checkmark', 'checkmark'); menuItemElement.appendChild(checkMarkElement); if (!item.checked) @@ -131,12 +136,22 @@ menuItemElement.addEventListener('mouseleave', this._menuItemMouseLeave.bind(this), false); menuItemElement._actionId = item.id; + + let accessibleName = item.label; + if (item.checked) + accessibleName += ', checked'; + if (item.shortcut) + accessibleName += ', ' + item.shortcut; + UI.ARIAUtils.setAccessibleName(menuItemElement, accessibleName); + return menuItemElement; } _createSubMenu(item) { const menuItemElement = createElementWithClass('div', 'soft-context-menu-item'); menuItemElement._subItems = item.subItems; + menuItemElement.tabIndex = -1; + UI.ARIAUtils.markAsMenuItem(menuItemElement); // Occupy the same space on the left in all items. const checkMarkElement = UI.Icon.create('smallicon-checkmark', 'soft-context-menu-item-checkmark'); @@ -262,7 +277,7 @@ if (UI.themeSupport.hasTheme() || Host.isMac()) this._highlightedMenuItemElement.classList.add('force-white-icons'); this._highlightedMenuItemElement.classList.add('soft-context-menu-item-mouse-over'); - this._contextMenuElement.focus(); + this._highlightedMenuItemElement.focus(); if (scheduleSubMenu && this._highlightedMenuItemElement._subItems && !this._highlightedMenuItemElement._subMenuTimer) { this._highlightedMenuItemElement._subMenuTimer = @@ -274,7 +289,9 @@ _highlightPrevious() { let menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.previousSibling : this._contextMenuElement.lastChild; - while (menuItemElement && (menuItemElement._isSeparator || menuItemElement._isCustom)) + while (menuItemElement && + (menuItemElement._isSeparator || menuItemElement._isCustom || + menuItemElement.classList.contains('soft-context-menu-disabled'))) menuItemElement = menuItemElement.previousSibling; if (menuItemElement) this._highlightMenuItem(menuItemElement, false); @@ -283,7 +300,9 @@ _highlightNext() { let menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.nextSibling : this._contextMenuElement.firstChild; - while (menuItemElement && (menuItemElement._isSeparator || menuItemElement._isCustom)) + while (menuItemElement && + (menuItemElement._isSeparator || menuItemElement._isCustom || + menuItemElement.classList.contains('soft-context-menu-disabled'))) menuItemElement = menuItemElement.nextSibling; if (menuItemElement) this._highlightMenuItem(menuItemElement, false);
diff --git a/third_party/blink/renderer/modules/budget/budget_service.idl b/third_party/blink/renderer/modules/budget/budget_service.idl index 9f3e6c76..22cdb21 100644 --- a/third_party/blink/renderer/modules/budget/budget_service.idl +++ b/third_party/blink/renderer/modules/budget/budget_service.idl
@@ -9,7 +9,6 @@ }; [ - RuntimeEnabled=Budget, SecureContext, Exposed=(Window,Worker) ] interface BudgetService {
diff --git a/third_party/blink/renderer/modules/budget/navigator_budget.idl b/third_party/blink/renderer/modules/budget/navigator_budget.idl index 525dc1de..b94d0d96 100644 --- a/third_party/blink/renderer/modules/budget/navigator_budget.idl +++ b/third_party/blink/renderer/modules/budget/navigator_budget.idl
@@ -5,8 +5,7 @@ // https://wicg.github.io/budget-api/#navigator-workernavigator-extensions [ - ImplementedAs=NavigatorBudget, - RuntimeEnabled=Budget + ImplementedAs=NavigatorBudget ] partial interface Navigator { [SameObject, CallWith=ExecutionContext] readonly attribute BudgetService budget; };
diff --git a/third_party/blink/renderer/modules/budget/worker_navigator_budget.idl b/third_party/blink/renderer/modules/budget/worker_navigator_budget.idl index 8f4f2b51..86677a2 100644 --- a/third_party/blink/renderer/modules/budget/worker_navigator_budget.idl +++ b/third_party/blink/renderer/modules/budget/worker_navigator_budget.idl
@@ -5,8 +5,7 @@ // https://wicg.github.io/budget-api/#navigator-workernavigator-extensions [ - ImplementedAs=WorkerNavigatorBudget, - RuntimeEnabled=Budget + ImplementedAs=WorkerNavigatorBudget ] partial interface WorkerNavigator { [SameObject, CallWith=ExecutionContext] readonly attribute BudgetService budget; };
diff --git a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css index 0d07598..247682f6 100644 --- a/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css +++ b/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
@@ -383,6 +383,15 @@ transition: opacity 0.25s cubic-bezier(0.25, 0.1, 0.25, 1); } +/** + * The overlay-play-button is disabled if the video element is loaded via + * MHTML, and a ruleset for input[type=button]:disabled in themeWin.css has + * higher priority than the above ruleset. + */ +video::-webkit-media-controls-overlay-play-button:disabled { + background: transparent; +} + video::-webkit-media-controls-overlay-play-button.hidden { opacity: 0; transition: opacity 0.75s cubic-bezier(0.25, 0.1, 0.25, 1);
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index 0eae7b43..46150507 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -219,6 +219,7 @@ "peerconnection/rtc_data_channel.idl", "peerconnection/rtc_data_channel_event.idl", "peerconnection/rtc_ice_candidate.idl", + "peerconnection/rtc_ice_transport.idl", "peerconnection/rtc_legacy_stats_report.idl", "peerconnection/rtc_peer_connection.idl", "peerconnection/rtc_peer_connection_ice_event.idl", @@ -591,6 +592,8 @@ "peerconnection/rtc_dtmf_tone_change_event_init.idl", "peerconnection/rtc_data_channel_init.idl", "peerconnection/rtc_ice_candidate_init.idl", + "peerconnection/rtc_ice_candidate_pair.idl", + "peerconnection/rtc_ice_parameters.idl", "peerconnection/rtc_ice_server.idl", "peerconnection/rtc_offer_answer_options.idl", "peerconnection/rtc_offer_options.idl",
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc index 487384a..d057a3a5 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.cc +++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -52,7 +52,6 @@ #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/feature_policy/feature_policy.h" #include "third_party/blink/renderer/platform/mojo/mojo_helper.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/uuid.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" @@ -518,8 +517,7 @@ if (exception_state.HadException()) exception_state.ClearException(); } - if (RuntimeEnabledFeatures::PaymentRequestBasicCardEnabled() && - supported_method == "basic-card") { + if (supported_method == "basic-card") { SetBasicCardMethodData(input, output, exception_state); if (exception_state.HadException()) exception_state.ClearException();
diff --git a/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/third_party/blink/renderer/modules/peerconnection/BUILD.gn index 924ebf1e..5413f86 100644 --- a/third_party/blink/renderer/modules/peerconnection/BUILD.gn +++ b/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -20,6 +20,8 @@ "rtc_error_util.h", "rtc_ice_candidate.cc", "rtc_ice_candidate.h", + "rtc_ice_transport.cc", + "rtc_ice_transport.h", "rtc_legacy_stats_report.cc", "rtc_legacy_stats_report.h", "rtc_peer_connection.cc",
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate_pair.idl b/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate_pair.idl new file mode 100644 index 0000000..56681878 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate_pair.idl
@@ -0,0 +1,9 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://w3c.github.io/webrtc-pc/#dom-rtcicecandidatepair +dictionary RTCIceCandidatePair { + RTCIceCandidate local; + RTCIceCandidate remote; +};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_parameters.idl b/third_party/blink/renderer/modules/peerconnection/rtc_ice_parameters.idl new file mode 100644 index 0000000..4598ce85 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_parameters.idl
@@ -0,0 +1,9 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://w3c.github.io/webrtc-pc/#dom-rtciceparameters +dictionary RTCIceParameters { + DOMString usernameFragment; + DOMString password; +};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc new file mode 100644 index 0000000..aef2f13 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
@@ -0,0 +1,63 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h" + +#include "third_party/blink/renderer/core/dom/events/event.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_parameters.h" + +namespace blink { + +RTCIceTransport* RTCIceTransport::Create() { + return new RTCIceTransport(); +} + +RTCIceTransport::RTCIceTransport() = default; + +String RTCIceTransport::role() const { + return String(); +} + +String RTCIceTransport::state() const { + return "new"; +} + +String RTCIceTransport::gatheringState() const { + return "new"; +} + +const HeapVector<Member<RTCIceCandidate>>& RTCIceTransport::getLocalCandidates() + const { + return local_candidates_; +} + +const HeapVector<Member<RTCIceCandidate>>& +RTCIceTransport::getRemoteCandidates() const { + return remote_candidates_; +} + +void RTCIceTransport::getSelectedCandidatePair( + base::Optional<RTCIceCandidatePair>& result) const { + result = selected_candidate_pair_; +} + +void RTCIceTransport::getLocalParameters( + base::Optional<RTCIceParameters>& result) const { + result = base::nullopt; +} + +void RTCIceTransport::getRemoteParameters( + base::Optional<RTCIceParameters>& result) const { + result = base::nullopt; +} + +void RTCIceTransport::Trace(blink::Visitor* visitor) { + visitor->Trace(local_candidates_); + visitor->Trace(remote_candidates_); + visitor->Trace(selected_candidate_pair_); + ScriptWrappable::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h new file mode 100644 index 0000000..d6a3983 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h
@@ -0,0 +1,47 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ICE_TRANSPORT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ICE_TRANSPORT_H_ + +#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_candidate_pair.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate_pair.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_parameters.h" + +namespace blink { + +class RTCIceCandidate; + +// Blink bindings for the RTCIceTransport JavaScript object. +class MODULES_EXPORT RTCIceTransport final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static RTCIceTransport* Create(); + + // rtc_ice_transport.idl + String role() const; + String state() const; + String gatheringState() const; + const HeapVector<Member<RTCIceCandidate>>& getLocalCandidates() const; + const HeapVector<Member<RTCIceCandidate>>& getRemoteCandidates() const; + void getSelectedCandidatePair( + base::Optional<RTCIceCandidatePair>& result) const; + void getLocalParameters(base::Optional<RTCIceParameters>& result) const; + void getRemoteParameters(base::Optional<RTCIceParameters>& result) const; + + // For garbage collection. + void Trace(blink::Visitor* visitor) override; + + private: + RTCIceTransport(); + + HeapVector<Member<RTCIceCandidate>> local_candidates_; + HeapVector<Member<RTCIceCandidate>> remote_candidates_; + base::Optional<RTCIceCandidatePair> selected_candidate_pair_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ICE_TRANSPORT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.idl b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.idl new file mode 100644 index 0000000..e87051e --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.idl
@@ -0,0 +1,48 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://w3c.github.io/webrtc-pc/#dom-rtcicerole +enum RTCIceRole { + "controlling", + "controlled", +}; + +// https://w3c.github.io/webrtc-pc/#dom-rtcicetransportstate +enum RTCIceTransportState { + "new", + "checking", + "connected", + "completed", + "disconnected", + "failed", + "closed", +}; + +// https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate +enum RTCIceGatheringState { + "new", + "gathering", + "complete" +}; + +// https://w3c.github.io/webrtc-pc/#rtcicetransport +[ + // Constructor from https://w3c.github.io/webrtc-ice/#rtcicetransport* + Constructor(), + Exposed=Window, + RuntimeEnabled=RTCIceTransportExtension +] interface RTCIceTransport { + // TODO(github.com/w3c/webrtc-ice/issues/4): role is non-null in the + // WebRTC-PC specification. + readonly attribute RTCIceRole? role; + readonly attribute RTCIceTransportState state; + readonly attribute RTCIceGatheringState gatheringState; + sequence<RTCIceCandidate> getLocalCandidates(); + sequence<RTCIceCandidate> getRemoteCandidates(); + RTCIceCandidatePair? getSelectedCandidatePair(); + RTCIceParameters? getLocalParameters(); + RTCIceParameters? getRemoteParameters(); + + // TODO(crbug.com/864871): Add events and extension methods. +};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl index 35913ca..dc3060f 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
@@ -39,12 +39,6 @@ "closed" }; -enum RTCIceGatheringState { - "new", - "gathering", - "complete" -}; - enum RTCIceConnectionState { "new", "checking",
diff --git a/third_party/blink/renderer/modules/vr/vr_display.cc b/third_party/blink/renderer/modules/vr/vr_display.cc index d6513fa..771340b 100644 --- a/third_party/blink/renderer/modules/vr/vr_display.cc +++ b/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -129,7 +129,6 @@ } void VRDisplay::Update(const device::mojom::blink::VRDisplayInfoPtr& display) { - display_id_ = display->index; display_name_ = display->displayName; is_connected_ = true;
diff --git a/third_party/blink/renderer/modules/vr/vr_display.h b/third_party/blink/renderer/modules/vr/vr_display.h index 462d066..5cd4aee 100644 --- a/third_party/blink/renderer/modules/vr/vr_display.h +++ b/third_party/blink/renderer/modules/vr/vr_display.h
@@ -163,7 +163,6 @@ std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback); Member<NavigatorVR> navigator_vr_; - unsigned display_id_ = 0; String display_name_; bool is_connected_ = false; bool is_presenting_ = false;
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc index 4bddb688..b470acd 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -4216,7 +4216,7 @@ } GLboolean WebGL2RenderingContextBase::isSync(WebGLSync* sync) { - if (isContextLost() || !sync) + if (isContextLost() || !sync || !sync->Validate(ContextGroup(), this)) return 0; return sync->Object() != 0;
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.cc b/third_party/blink/renderer/platform/heap/heap_allocator.cc index 7791505..411f19a 100644 --- a/third_party/blink/renderer/platform/heap/heap_allocator.cc +++ b/third_party/blink/renderer/platform/heap/heap_allocator.cc
@@ -40,8 +40,10 @@ BackingFree(address); } -void HeapAllocator::FreeHashTableBacking(void* address, bool is_weak_table) { - if (!ThreadState::Current()->IsMarkingInProgress() || !is_weak_table) +void HeapAllocator::FreeHashTableBacking(void* address) { + // When incremental marking is enabled weak callbacks may have been + // registered. + if (!ThreadState::Current()->IsMarkingInProgress()) BackingFree(address); }
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.h b/third_party/blink/renderer/platform/heap/heap_allocator.h index 8e72066..116a9e0 100644 --- a/third_party/blink/renderer/platform/heap/heap_allocator.h +++ b/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -125,7 +125,7 @@ static T* AllocateZeroedHashTableBacking(size_t size) { return AllocateHashTableBacking<T, HashTable>(size); } - static void FreeHashTableBacking(void* address, bool is_weak_table); + static void FreeHashTableBacking(void* address); static bool ExpandHashTableBacking(void*, size_t); static void TraceMarkedBackingStore(void* address) {
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc index 3b0f678..4bc04a8 100644 --- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc +++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -1695,6 +1695,28 @@ CHECK_EQ(1u, count); } +TEST(IncrementalMarkingTest, NoBackingFreeDuringIncrementalMarking) { + // Regression test: https://crbug.com/870306 + // Only reproduces in ASAN configurations. + using WeakStore = HeapHashCountedSet<std::pair<WeakMember<Object>, size_t>>; + + Persistent<WeakStore> persistent(new WeakStore); + // Prefill the collection to grow backing store. A new backing store allocaton + // would trigger the write barrier, mitigating the bug where a backing store + // is promptly freed. + for (size_t i = 0; i < 8; i++) { + persistent->insert({Object::Create(), i}); + } + IncrementalMarkingTestDriver driver(ThreadState::Current()); + driver.Start(); + persistent->insert({Object::Create(), 8}); + // Is not allowed to free the backing store as the previous insert may have + // registered a slot. + persistent->clear(); + driver.FinishSteps(); + driver.FinishGC(); +} + } // namespace incremental_marking_test } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc index 551c0a7..bd30c224 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -823,6 +823,7 @@ void ResourceLoader::Dispose() { loader_ = nullptr; + progress_binding_.Close(); // Release() should be called to release |scheduler_client_id_| beforehand in // DidFinishLoading() or DidFail(), but when a timer to call Cancel() is
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index e25326b..fcddb4c3 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -147,10 +147,6 @@ status: "stable" }, { - name: "Budget", - status: "stable", - }, - { name: "BudgetQuery", origin_trial_feature_name: "BudgetQuery", status: "experimental", @@ -935,10 +931,6 @@ status: "experimental", }, { - name: "PaymentRequestBasicCard", - status: "stable", - }, - { name: "PaymentRetry", status: "experimental", }, @@ -1061,6 +1053,11 @@ name: "RestrictCanRequestURLCharacterSet", status: "stable", }, + // Enables the use of the RTCIceTransport with extensions. + { + name: "RTCIceTransportExtension", + status: "test", + }, { name: "RtcPeerConnectionId", origin_trial_feature_name: "RtcPeerConnectionId", @@ -1165,10 +1162,6 @@ name: "SlimmingPaintV2", }, { - name: "SlotInFlatTree", - status: "stable", - }, - { name: "SMIL", status: "stable", },
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc index 8d56b92..ae458f1 100644 --- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc +++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
@@ -147,6 +147,10 @@ return base::TimeTicks::Now(); } +void SchedulerHelper::SetTimerSlack(base::TimerSlack timer_slack) { + sequence_manager_->SetTimerSlack(timer_slack); +} + double SchedulerHelper::GetSamplingRateForRecordingCPUTime() const { if (sequence_manager_) { return sequence_manager_->GetMetricRecordingSettings()
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h index 2cb6a3e..577f1ed 100644 --- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h +++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
@@ -33,6 +33,7 @@ const base::TickClock* GetClock() const; base::TimeTicks NowTicks() const; + void SetTimerSlack(base::TimerSlack timer_slack); // Returns the default task queue. virtual scoped_refptr<base::sequence_manager::TaskQueue>
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index eb714f7..bc28d0a 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -958,6 +958,13 @@ void MainThreadSchedulerImpl::SetRendererBackgrounded(bool backgrounded) { helper_.CheckOnValidThread(); + + // Increasing timer slack helps the OS to coalesce timers efficiently. + base::TimerSlack timer_slack = base::TIMER_SLACK_NONE; + if (backgrounded) + timer_slack = base::TIMER_SLACK_MAXIMUM; + helper_.SetTimerSlack(timer_slack); + if (helper_.IsShutdown() || main_thread_only().renderer_backgrounded == backgrounded) return;
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator.cc b/third_party/blink/renderer/platform/text/text_break_iterator.cc index 28fb948..c9920471 100644 --- a/third_party/blink/renderer/platform/text/text_break_iterator.cc +++ b/third_party/blink/renderer/platform/text/text_break_iterator.cc
@@ -59,8 +59,7 @@ if (!length) return; - String string = text.ToString(); - NonSharedCharacterBreakIterator it(string); + NonSharedCharacterBreakIterator it(text); int cursor_pos = it.Next(); unsigned count = 0; unsigned pos = 0;
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator.h b/third_party/blink/renderer/platform/text/text_break_iterator.h index 3fa2f390..dee25350 100644 --- a/third_party/blink/renderer/platform/text/text_break_iterator.h +++ b/third_party/blink/renderer/platform/text/text_break_iterator.h
@@ -315,7 +315,7 @@ STACK_ALLOCATED(); public: - explicit NonSharedCharacterBreakIterator(const String&); + explicit NonSharedCharacterBreakIterator(const StringView&); NonSharedCharacterBreakIterator(const UChar*, unsigned length); ~NonSharedCharacterBreakIterator();
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc b/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc index 327c6f9..1a5c8e0b 100644 --- a/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc +++ b/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc
@@ -751,7 +751,7 @@ } NonSharedCharacterBreakIterator::NonSharedCharacterBreakIterator( - const String& string) + const StringView& string) : is8_bit_(true), charaters8_(nullptr), offset_(0),
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.cc b/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.cc index bb4fd19f..30686ea6 100644 --- a/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.cc +++ b/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.cc
@@ -17,8 +17,7 @@ Partitions::BufferFree(address); } -void PartitionAllocator::FreeHashTableBacking(void* address, - bool is_weak_table) { +void PartitionAllocator::FreeHashTableBacking(void* address) { Partitions::BufferFree(address); }
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h b/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h index cbd0f90..bcfff867 100644 --- a/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h +++ b/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
@@ -82,7 +82,7 @@ memset(result, 0, size); return reinterpret_cast<T*>(result); } - static void FreeHashTableBacking(void* address, bool is_weak_table); + static void FreeHashTableBacking(void* address); template <typename Return, typename Metadata> static Return Malloc(size_t size, const char* type_name) {
diff --git a/third_party/blink/renderer/platform/wtf/hash_table.h b/third_party/blink/renderer/platform/wtf/hash_table.h index 26173045..119f4ebb 100644 --- a/third_party/blink/renderer/platform/wtf/hash_table.h +++ b/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -1667,10 +1667,7 @@ } } } - // Notify if this is a weak table since immediately freeing a weak hash table - // backing may cause a use-after-free when the weak callback is called. - Allocator::FreeHashTableBacking(table, - Traits::kWeakHandlingFlag == kWeakHandling); + Allocator::FreeHashTableBacking(table); } template <typename Key,
diff --git a/third_party/fuchsia-sdk/BUILD.gn b/third_party/fuchsia-sdk/BUILD.gn index 0cf8012..a355f4a5 100644 --- a/third_party/fuchsia-sdk/BUILD.gn +++ b/third_party/fuchsia-sdk/BUILD.gn
@@ -209,7 +209,7 @@ namespace = "fuchsia" namespace_path = "fuchsia" sources = [ - "geometry.fidl", + "math.fidl", ] }
diff --git a/third_party/nvml/LICENSE b/third_party/nvml/LICENSE new file mode 100644 index 0000000..030bfc1 --- /dev/null +++ b/third_party/nvml/LICENSE
@@ -0,0 +1,33 @@ + +Copyright 1993-2017 NVIDIA Corporation. All rights reserved. + +NOTICE TO USER: + +This source code is subject to NVIDIA ownership rights under U.S. and +international Copyright laws. Users and possessors of this source code +are hereby granted a nonexclusive, royalty-free license to use this code +in individual and commercial software. + +NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE +CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR +IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, +OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOURCE CODE. + +U.S. Government End Users. This source code is a "commercial item" as +that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of +"commercial computer software" and "commercial computer software +documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) +and is provided to the U.S. Government only as a commercial end item. +Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through +227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the +source code with only those rights set forth herein. + +Any use of this source code in individual and commercial software must +include, in the user documentation and internal comments to the code, +the above Disclaimer and U.S. Government End Users Notice.
diff --git a/third_party/nvml/OWNERS b/third_party/nvml/OWNERS new file mode 100644 index 0000000..84f8217 --- /dev/null +++ b/third_party/nvml/OWNERS
@@ -0,0 +1,2 @@ +kbr@chromium.org +zmo@chromium.org
diff --git a/third_party/nvml/README.chromium b/third_party/nvml/README.chromium new file mode 100644 index 0000000..5d62575 --- /dev/null +++ b/third_party/nvml/README.chromium
@@ -0,0 +1,20 @@ +Name: NVIDIA Management Library +Short Name: nvml +URL: https://developer.nvidia.com/nvidia-management-library-nvml +Version: 9.1.85 +License: NVML license +License File: LICENSE +Security Critical: yes + +Description: +This is a header file for interfacing with the NVML library that ships as a part +of NVIDIA proprietary drivers on Windows. The library can be used to query GPU +hardware and GPU driver information. Chromium loads the NVML library dynamically +and uses it for whitelisting and blacklisting purposes on Windows. + +Points of contact at NVIDIA: +oetuaho@nvidia.com +amalp@nvidia.com + +Local Modifications: +Trailing whitespace has been trimmed from the header file.
diff --git a/third_party/nvml/nvml.h b/third_party/nvml/nvml.h new file mode 100644 index 0000000..8e960db --- /dev/null +++ b/third_party/nvml/nvml.h
@@ -0,0 +1,5684 @@ +/* + * Copyright 1993-2017 NVIDIA Corporation. All rights reserved. + * + * NOTICE TO USER: + * + * This source code is subject to NVIDIA ownership rights under U.S. and + * international Copyright laws. Users and possessors of this source code + * are hereby granted a nonexclusive, royalty-free license to use this code + * in individual and commercial software. + * + * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE + * CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR + * IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE. + * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOURCE CODE. + * + * U.S. Government End Users. This source code is a "commercial item" as + * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting of + * "commercial computer software" and "commercial computer software + * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) + * and is provided to the U.S. Government only as a commercial end item. + * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through + * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the + * source code with only those rights set forth herein. + * + * Any use of this source code in individual and commercial software must + * include, in the user documentation and internal comments to the code, + * the above Disclaimer and U.S. Government End Users Notice. + */ + +/* +NVML API Reference + +The NVIDIA Management Library (NVML) is a C-based programmatic interface for monitoring and +managing various states within NVIDIA Tesla &tm; GPUs. It is intended to be a platform for building +3rd party applications, and is also the underlying library for the NVIDIA-supported nvidia-smi +tool. NVML is thread-safe so it is safe to make simultaneous NVML calls from multiple threads. + +API Documentation + +Supported platforms: +- Windows: Windows Server 2008 R2 64bit, Windows Server 2012 R2 64bit, Windows 7 64bit, Windows 8 64bit, Windows 10 64bit +- Linux: 32-bit and 64-bit +- Hypervisors: Windows Server 2008R2/2012 Hyper-V 64bit, Citrix XenServer 6.2 SP1+, VMware ESX 5.1/5.5 + +Supported products: +- Full Support + - All Tesla products, starting with the Fermi architecture + - All Quadro products, starting with the Fermi architecture + - All GRID products, starting with the Kepler architecture + - Selected GeForce Titan products +- Limited Support + - All Geforce products, starting with the Fermi architecture + +The NVML library can be found at \%ProgramW6432\%\\"NVIDIA Corporation"\\NVSMI\\ on Windows. It is +not be added to the system path by default. To dynamically link to NVML, add this path to the PATH +environmental variable. To dynamically load NVML, call LoadLibrary with this path. + +On Linux the NVML library will be found on the standard library path. For 64 bit Linux, both the 32 bit +and 64 bit NVML libraries will be installed. + +Online documentation for this library is available at http://docs.nvidia.com/deploy/nvml-api/index.html +*/ + +#ifndef __nvml_nvml_h__ +#define __nvml_nvml_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * On Windows, set up methods for DLL export + * define NVML_STATIC_IMPORT when using nvml_loader library + */ +#if defined _WINDOWS + #if !defined NVML_STATIC_IMPORT + #if defined NVML_LIB_EXPORT + #define DECLDIR __declspec(dllexport) + #else + #define DECLDIR __declspec(dllimport) + #endif + #else + #define DECLDIR + #endif +#else + #define DECLDIR +#endif + +/** + * NVML API versioning support + */ +#define NVML_API_VERSION 9 +#define NVML_API_VERSION_STR "9" +#define nvmlInit nvmlInit_v2 +#define nvmlDeviceGetPciInfo nvmlDeviceGetPciInfo_v3 +#define nvmlDeviceGetCount nvmlDeviceGetCount_v2 +#define nvmlDeviceGetHandleByIndex nvmlDeviceGetHandleByIndex_v2 +#define nvmlDeviceGetHandleByPciBusId nvmlDeviceGetHandleByPciBusId_v2 +#define nvmlDeviceGetNvLinkRemotePciInfo nvmlDeviceGetNvLinkRemotePciInfo_v2 + +/***************************************************************************************************/ +/** @defgroup nvmlDeviceStructs Device Structs + * @{ + */ +/***************************************************************************************************/ + +/** + * Special constant that some fields take when they are not available. + * Used when only part of the struct is not available. + * + * Each structure explicitly states when to check for this value. + */ +#define NVML_VALUE_NOT_AVAILABLE (-1) + +typedef struct nvmlDevice_st* nvmlDevice_t; + +/** + * Buffer size guaranteed to be large enough for pci bus id + */ +#define NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE 32 + +/** + * Buffer size guaranteed to be large enough for pci bus id for ::busIdLegacy + */ +#define NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE 16 + +/** + * PCI information about a GPU device. + */ +typedef struct nvmlPciInfo_st +{ + char busIdLegacy[NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE]; //!< The legacy tuple domain:bus:device.function PCI identifier (& NULL terminator) + unsigned int domain; //!< The PCI domain on which the device's bus resides, 0 to 0xffffffff + unsigned int bus; //!< The bus on which the device resides, 0 to 0xff + unsigned int device; //!< The device's id on the bus, 0 to 31 + unsigned int pciDeviceId; //!< The combined 16-bit device id and 16-bit vendor id + + // Added in NVML 2.285 API + unsigned int pciSubSystemId; //!< The 32-bit Sub System Device ID + + char busId[NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE]; //!< The tuple domain:bus:device.function PCI identifier (& NULL terminator) +} nvmlPciInfo_t; + +/** + * Detailed ECC error counts for a device. + * + * @deprecated Different GPU families can have different memory error counters + * See \ref nvmlDeviceGetMemoryErrorCounter + */ +typedef struct nvmlEccErrorCounts_st +{ + unsigned long long l1Cache; //!< L1 cache errors + unsigned long long l2Cache; //!< L2 cache errors + unsigned long long deviceMemory; //!< Device memory errors + unsigned long long registerFile; //!< Register file errors +} nvmlEccErrorCounts_t; + +/** + * Utilization information for a device. + * Each sample period may be between 1 second and 1/6 second, depending on the product being queried. + */ +typedef struct nvmlUtilization_st +{ + unsigned int gpu; //!< Percent of time over the past sample period during which one or more kernels was executing on the GPU + unsigned int memory; //!< Percent of time over the past sample period during which global (device) memory was being read or written +} nvmlUtilization_t; + +/** + * Memory allocation information for a device. + */ +typedef struct nvmlMemory_st +{ + unsigned long long total; //!< Total installed FB memory (in bytes) + unsigned long long free; //!< Unallocated FB memory (in bytes) + unsigned long long used; //!< Allocated FB memory (in bytes). Note that the driver/GPU always sets aside a small amount of memory for bookkeeping +} nvmlMemory_t; + +/** + * BAR1 Memory allocation Information for a device + */ +typedef struct nvmlBAR1Memory_st +{ + unsigned long long bar1Total; //!< Total BAR1 Memory (in bytes) + unsigned long long bar1Free; //!< Unallocated BAR1 Memory (in bytes) + unsigned long long bar1Used; //!< Allocated Used Memory (in bytes) +}nvmlBAR1Memory_t; + +/** + * Information about running compute processes on the GPU + */ +typedef struct nvmlProcessInfo_st +{ + unsigned int pid; //!< Process ID + unsigned long long usedGpuMemory; //!< Amount of used GPU memory in bytes. + //! Under WDDM, \ref NVML_VALUE_NOT_AVAILABLE is always reported + //! because Windows KMD manages all the memory and not the NVIDIA driver +} nvmlProcessInfo_t; + +/** + * Enum to represent type of bridge chip + */ +typedef enum nvmlBridgeChipType_enum +{ + NVML_BRIDGE_CHIP_PLX = 0, + NVML_BRIDGE_CHIP_BRO4 = 1 +}nvmlBridgeChipType_t; + +/** + * Maximum number of NvLink links supported + */ +#define NVML_NVLINK_MAX_LINKS 6 + +/** + * Enum to represent the NvLink utilization counter packet units + */ +typedef enum nvmlNvLinkUtilizationCountUnits_enum +{ + NVML_NVLINK_COUNTER_UNIT_CYCLES = 0, // count by cycles + NVML_NVLINK_COUNTER_UNIT_PACKETS = 1, // count by packets + NVML_NVLINK_COUNTER_UNIT_BYTES = 2, // count by bytes + + // this must be last + NVML_NVLINK_COUNTER_UNIT_COUNT +} nvmlNvLinkUtilizationCountUnits_t; + +/** + * Enum to represent the NvLink utilization counter packet types to count + * ** this is ONLY applicable with the units as packets or bytes + * ** as specified in \a nvmlNvLinkUtilizationCountUnits_t + * ** all packet filter descriptions are target GPU centric + * ** these can be "OR'd" together + */ +typedef enum nvmlNvLinkUtilizationCountPktTypes_enum +{ + NVML_NVLINK_COUNTER_PKTFILTER_NOP = 0x1, // no operation packets + NVML_NVLINK_COUNTER_PKTFILTER_READ = 0x2, // read packets + NVML_NVLINK_COUNTER_PKTFILTER_WRITE = 0x4, // write packets + NVML_NVLINK_COUNTER_PKTFILTER_RATOM = 0x8, // reduction atomic requests + NVML_NVLINK_COUNTER_PKTFILTER_NRATOM = 0x10, // non-reduction atomic requests + NVML_NVLINK_COUNTER_PKTFILTER_FLUSH = 0x20, // flush requests + NVML_NVLINK_COUNTER_PKTFILTER_RESPDATA = 0x40, // responses with data + NVML_NVLINK_COUNTER_PKTFILTER_RESPNODATA = 0x80, // responses without data + NVML_NVLINK_COUNTER_PKTFILTER_ALL = 0xFF // all packets +} nvmlNvLinkUtilizationCountPktTypes_t; + +/** + * Struct to define the NVLINK counter controls + */ +typedef struct nvmlNvLinkUtilizationControl_st +{ + nvmlNvLinkUtilizationCountUnits_t units; + nvmlNvLinkUtilizationCountPktTypes_t pktfilter; +} nvmlNvLinkUtilizationControl_t; + +/** + * Enum to represent NvLink queryable capabilities + */ +typedef enum nvmlNvLinkCapability_enum +{ + NVML_NVLINK_CAP_P2P_SUPPORTED = 0, // P2P over NVLink is supported + NVML_NVLINK_CAP_SYSMEM_ACCESS = 1, // Access to system memory is supported + NVML_NVLINK_CAP_P2P_ATOMICS = 2, // P2P atomics are supported + NVML_NVLINK_CAP_SYSMEM_ATOMICS= 3, // System memory atomics are supported + NVML_NVLINK_CAP_SLI_BRIDGE = 4, // SLI is supported over this link + NVML_NVLINK_CAP_VALID = 5, // Link is supported on this device + // should be last + NVML_NVLINK_CAP_COUNT +} nvmlNvLinkCapability_t; + +/** + * Enum to represent NvLink queryable error counters + */ +typedef enum nvmlNvLinkErrorCounter_enum +{ + NVML_NVLINK_ERROR_DL_REPLAY = 0, // Data link transmit replay error counter + NVML_NVLINK_ERROR_DL_RECOVERY = 1, // Data link transmit recovery error counter + NVML_NVLINK_ERROR_DL_CRC_FLIT = 2, // Data link receive flow control digit CRC error counter + NVML_NVLINK_ERROR_DL_CRC_DATA = 3, // Data link receive data CRC error counter + + // this must be last + NVML_NVLINK_ERROR_COUNT +} nvmlNvLinkErrorCounter_t; + +/** + * Represents level relationships within a system between two GPUs + * The enums are spaced to allow for future relationships + */ +typedef enum nvmlGpuLevel_enum +{ + NVML_TOPOLOGY_INTERNAL = 0, // e.g. Tesla K80 + NVML_TOPOLOGY_SINGLE = 10, // all devices that only need traverse a single PCIe switch + NVML_TOPOLOGY_MULTIPLE = 20, // all devices that need not traverse a host bridge + NVML_TOPOLOGY_HOSTBRIDGE = 30, // all devices that are connected to the same host bridge + NVML_TOPOLOGY_NODE = 40, // all devices that are connected to the same NUMA node but possibly multiple host bridges + NVML_TOPOLOGY_SYSTEM = 50, // all devices in the system + + // there is purposefully no COUNT here because of the need for spacing above +} nvmlGpuTopologyLevel_t; + +/* Compatibility for CPU->NODE renaming */ +#define NVML_TOPOLOGY_CPU NVML_TOPOLOGY_NODE + +/* P2P Capability Index Status*/ +typedef enum nvmlGpuP2PStatus_enum +{ + NVML_P2P_STATUS_OK = 0, + NVML_P2P_STATUS_CHIPSET_NOT_SUPPORED, + NVML_P2P_STATUS_GPU_NOT_SUPPORTED, + NVML_P2P_STATUS_IOH_TOPOLOGY_NOT_SUPPORTED, + NVML_P2P_STATUS_DISABLED_BY_REGKEY, + NVML_P2P_STATUS_NOT_SUPPORTED, + NVML_P2P_STATUS_UNKNOWN + +} nvmlGpuP2PStatus_t; + +/* P2P Capability Index*/ +typedef enum nvmlGpuP2PCapsIndex_enum +{ + NVML_P2P_CAPS_INDEX_READ = 0, + NVML_P2P_CAPS_INDEX_WRITE, + NVML_P2P_CAPS_INDEX_NVLINK, + NVML_P2P_CAPS_INDEX_ATOMICS, + NVML_P2P_CAPS_INDEX_PROP, + NVML_P2P_CAPS_INDEX_UNKNOWN +}nvmlGpuP2PCapsIndex_t; + +/** + * Maximum limit on Physical Bridges per Board + */ +#define NVML_MAX_PHYSICAL_BRIDGE (128) + +/** + * Information about the Bridge Chip Firmware + */ +typedef struct nvmlBridgeChipInfo_st +{ + nvmlBridgeChipType_t type; //!< Type of Bridge Chip + unsigned int fwVersion; //!< Firmware Version. 0=Version is unavailable +}nvmlBridgeChipInfo_t; + +/** + * This structure stores the complete Hierarchy of the Bridge Chip within the board. The immediate + * bridge is stored at index 0 of bridgeInfoList, parent to immediate bridge is at index 1 and so forth. + */ +typedef struct nvmlBridgeChipHierarchy_st +{ + unsigned char bridgeCount; //!< Number of Bridge Chips on the Board + nvmlBridgeChipInfo_t bridgeChipInfo[NVML_MAX_PHYSICAL_BRIDGE]; //!< Hierarchy of Bridge Chips on the board +}nvmlBridgeChipHierarchy_t; + +/** + * Represents Type of Sampling Event + */ +typedef enum nvmlSamplingType_enum +{ + NVML_TOTAL_POWER_SAMPLES = 0, //!< To represent total power drawn by GPU + NVML_GPU_UTILIZATION_SAMPLES = 1, //!< To represent percent of time during which one or more kernels was executing on the GPU + NVML_MEMORY_UTILIZATION_SAMPLES = 2, //!< To represent percent of time during which global (device) memory was being read or written + NVML_ENC_UTILIZATION_SAMPLES = 3, //!< To represent percent of time during which NVENC remains busy + NVML_DEC_UTILIZATION_SAMPLES = 4, //!< To represent percent of time during which NVDEC remains busy + NVML_PROCESSOR_CLK_SAMPLES = 5, //!< To represent processor clock samples + NVML_MEMORY_CLK_SAMPLES = 6, //!< To represent memory clock samples + + // Keep this last + NVML_SAMPLINGTYPE_COUNT +}nvmlSamplingType_t; + +/** + * Represents the queryable PCIe utilization counters + */ +typedef enum nvmlPcieUtilCounter_enum +{ + NVML_PCIE_UTIL_TX_BYTES = 0, // 1KB granularity + NVML_PCIE_UTIL_RX_BYTES = 1, // 1KB granularity + + // Keep this last + NVML_PCIE_UTIL_COUNT +} nvmlPcieUtilCounter_t; + +/** + * Represents the type for sample value returned + */ +typedef enum nvmlValueType_enum +{ + NVML_VALUE_TYPE_DOUBLE = 0, + NVML_VALUE_TYPE_UNSIGNED_INT = 1, + NVML_VALUE_TYPE_UNSIGNED_LONG = 2, + NVML_VALUE_TYPE_UNSIGNED_LONG_LONG = 3, + NVML_VALUE_TYPE_SIGNED_LONG_LONG = 4, + + // Keep this last + NVML_VALUE_TYPE_COUNT +}nvmlValueType_t; + + +/** + * Union to represent different types of Value + */ +typedef union nvmlValue_st +{ + double dVal; //!< If the value is double + unsigned int uiVal; //!< If the value is unsigned int + unsigned long ulVal; //!< If the value is unsigned long + unsigned long long ullVal; //!< If the value is unsigned long long + signed long long sllVal; //!< If the value is signed long long +}nvmlValue_t; + +/** + * Information for Sample + */ +typedef struct nvmlSample_st +{ + unsigned long long timeStamp; //!< CPU Timestamp in microseconds + nvmlValue_t sampleValue; //!< Sample Value +}nvmlSample_t; + +/** + * Represents type of perf policy for which violation times can be queried + */ +typedef enum nvmlPerfPolicyType_enum +{ + NVML_PERF_POLICY_POWER = 0, //!< How long did power violations cause the GPU to be below application clocks + NVML_PERF_POLICY_THERMAL = 1, //!< How long did thermal violations cause the GPU to be below application clocks + NVML_PERF_POLICY_SYNC_BOOST = 2, //!< How long did sync boost cause the GPU to be below application clocks + NVML_PERF_POLICY_BOARD_LIMIT = 3, //!< How long did the board limit cause the GPU to be below application clocks + NVML_PERF_POLICY_LOW_UTILIZATION = 4, //!< How long did low utilization cause the GPU to be below application clocks + NVML_PERF_POLICY_RELIABILITY = 5, //!< How long did the board reliability limit cause the GPU to be below application clocks + + NVML_PERF_POLICY_TOTAL_APP_CLOCKS = 10, //!< Total time the GPU was held below application clocks by any limiter (0 - 5 above) + NVML_PERF_POLICY_TOTAL_BASE_CLOCKS = 11, //!< Total time the GPU was held below base clocks + + // Keep this last + NVML_PERF_POLICY_COUNT +}nvmlPerfPolicyType_t; + +/** + * Struct to hold perf policy violation status data + */ +typedef struct nvmlViolationTime_st +{ + unsigned long long referenceTime; //!< referenceTime represents CPU timestamp in microseconds + unsigned long long violationTime; //!< violationTime in Nanoseconds +}nvmlViolationTime_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlDeviceEnumvs Device Enums + * @{ + */ +/***************************************************************************************************/ + +/** + * Generic enable/disable enum. + */ +typedef enum nvmlEnableState_enum +{ + NVML_FEATURE_DISABLED = 0, //!< Feature disabled + NVML_FEATURE_ENABLED = 1 //!< Feature enabled +} nvmlEnableState_t; + +//! Generic flag used to specify the default behavior of some functions. See description of particular functions for details. +#define nvmlFlagDefault 0x00 +//! Generic flag used to force some behavior. See description of particular functions for details. +#define nvmlFlagForce 0x01 + +/** + * * The Brand of the GPU + * */ +typedef enum nvmlBrandType_enum +{ + NVML_BRAND_UNKNOWN = 0, + NVML_BRAND_QUADRO = 1, + NVML_BRAND_TESLA = 2, + NVML_BRAND_NVS = 3, + NVML_BRAND_GRID = 4, + NVML_BRAND_GEFORCE = 5, + + // Keep this last + NVML_BRAND_COUNT +} nvmlBrandType_t; + +/** + * Temperature thresholds. + */ +typedef enum nvmlTemperatureThresholds_enum +{ + NVML_TEMPERATURE_THRESHOLD_SHUTDOWN = 0, // Temperature at which the GPU will shut down + // for HW protection + NVML_TEMPERATURE_THRESHOLD_SLOWDOWN = 1, // Temperature at which the GPU will begin HW slowdown + NVML_TEMPERATURE_THRESHOLD_MEM_MAX = 2, // Memory Temperature at which the GPU will begin SW slowdown + NVML_TEMPERATURE_THRESHOLD_GPU_MAX = 3, // GPU Temperature at which the GPU can be throttled below base clock + // Keep this last + NVML_TEMPERATURE_THRESHOLD_COUNT +} nvmlTemperatureThresholds_t; + +/** + * Temperature sensors. + */ +typedef enum nvmlTemperatureSensors_enum +{ + NVML_TEMPERATURE_GPU = 0, //!< Temperature sensor for the GPU die + + // Keep this last + NVML_TEMPERATURE_COUNT +} nvmlTemperatureSensors_t; + +/** + * Compute mode. + * + * NVML_COMPUTEMODE_EXCLUSIVE_PROCESS was added in CUDA 4.0. + * Earlier CUDA versions supported a single exclusive mode, + * which is equivalent to NVML_COMPUTEMODE_EXCLUSIVE_THREAD in CUDA 4.0 and beyond. + */ +typedef enum nvmlComputeMode_enum +{ + NVML_COMPUTEMODE_DEFAULT = 0, //!< Default compute mode -- multiple contexts per device + NVML_COMPUTEMODE_EXCLUSIVE_THREAD = 1, //!< Support Removed + NVML_COMPUTEMODE_PROHIBITED = 2, //!< Compute-prohibited mode -- no contexts per device + NVML_COMPUTEMODE_EXCLUSIVE_PROCESS = 3, //!< Compute-exclusive-process mode -- only one context per device, usable from multiple threads at a time + + // Keep this last + NVML_COMPUTEMODE_COUNT +} nvmlComputeMode_t; + +/** + * ECC bit types. + * + * @deprecated See \ref nvmlMemoryErrorType_t for a more flexible type + */ +#define nvmlEccBitType_t nvmlMemoryErrorType_t + +/** + * Single bit ECC errors + * + * @deprecated Mapped to \ref NVML_MEMORY_ERROR_TYPE_CORRECTED + */ +#define NVML_SINGLE_BIT_ECC NVML_MEMORY_ERROR_TYPE_CORRECTED + +/** + * Double bit ECC errors + * + * @deprecated Mapped to \ref NVML_MEMORY_ERROR_TYPE_UNCORRECTED + */ +#define NVML_DOUBLE_BIT_ECC NVML_MEMORY_ERROR_TYPE_UNCORRECTED + +/** + * Memory error types + */ +typedef enum nvmlMemoryErrorType_enum +{ + /** + * A memory error that was corrected + * + * For ECC errors, these are single bit errors + * For Texture memory, these are errors fixed by resend + */ + NVML_MEMORY_ERROR_TYPE_CORRECTED = 0, + /** + * A memory error that was not corrected + * + * For ECC errors, these are double bit errors + * For Texture memory, these are errors where the resend fails + */ + NVML_MEMORY_ERROR_TYPE_UNCORRECTED = 1, + + + // Keep this last + NVML_MEMORY_ERROR_TYPE_COUNT //!< Count of memory error types + +} nvmlMemoryErrorType_t; + +/** + * ECC counter types. + * + * Note: Volatile counts are reset each time the driver loads. On Windows this is once per boot. On Linux this can be more frequent. + * On Linux the driver unloads when no active clients exist. If persistence mode is enabled or there is always a driver + * client active (e.g. X11), then Linux also sees per-boot behavior. If not, volatile counts are reset each time a compute app + * is run. + */ +typedef enum nvmlEccCounterType_enum +{ + NVML_VOLATILE_ECC = 0, //!< Volatile counts are reset each time the driver loads. + NVML_AGGREGATE_ECC = 1, //!< Aggregate counts persist across reboots (i.e. for the lifetime of the device) + + // Keep this last + NVML_ECC_COUNTER_TYPE_COUNT //!< Count of memory counter types +} nvmlEccCounterType_t; + +/** + * Clock types. + * + * All speeds are in Mhz. + */ +typedef enum nvmlClockType_enum +{ + NVML_CLOCK_GRAPHICS = 0, //!< Graphics clock domain + NVML_CLOCK_SM = 1, //!< SM clock domain + NVML_CLOCK_MEM = 2, //!< Memory clock domain + NVML_CLOCK_VIDEO = 3, //!< Video encoder/decoder clock domain + + // Keep this last + NVML_CLOCK_COUNT //<! Count of clock types +} nvmlClockType_t; + +/** + * Clock Ids. These are used in combination with nvmlClockType_t + * to specify a single clock value. + */ +typedef enum nvmlClockId_enum +{ + NVML_CLOCK_ID_CURRENT = 0, //!< Current actual clock value + NVML_CLOCK_ID_APP_CLOCK_TARGET = 1, //!< Target application clock + NVML_CLOCK_ID_APP_CLOCK_DEFAULT = 2, //!< Default application clock target + NVML_CLOCK_ID_CUSTOMER_BOOST_MAX = 3, //!< OEM-defined maximum clock rate + + //Keep this last + NVML_CLOCK_ID_COUNT //<! Count of Clock Ids. +} nvmlClockId_t; + +/** + * Driver models. + * + * Windows only. + */ +typedef enum nvmlDriverModel_enum +{ + NVML_DRIVER_WDDM = 0, //!< WDDM driver model -- GPU treated as a display device + NVML_DRIVER_WDM = 1 //!< WDM (TCC) model (recommended) -- GPU treated as a generic device +} nvmlDriverModel_t; + +/** + * Allowed PStates. + */ +typedef enum nvmlPStates_enum +{ + NVML_PSTATE_0 = 0, //!< Performance state 0 -- Maximum Performance + NVML_PSTATE_1 = 1, //!< Performance state 1 + NVML_PSTATE_2 = 2, //!< Performance state 2 + NVML_PSTATE_3 = 3, //!< Performance state 3 + NVML_PSTATE_4 = 4, //!< Performance state 4 + NVML_PSTATE_5 = 5, //!< Performance state 5 + NVML_PSTATE_6 = 6, //!< Performance state 6 + NVML_PSTATE_7 = 7, //!< Performance state 7 + NVML_PSTATE_8 = 8, //!< Performance state 8 + NVML_PSTATE_9 = 9, //!< Performance state 9 + NVML_PSTATE_10 = 10, //!< Performance state 10 + NVML_PSTATE_11 = 11, //!< Performance state 11 + NVML_PSTATE_12 = 12, //!< Performance state 12 + NVML_PSTATE_13 = 13, //!< Performance state 13 + NVML_PSTATE_14 = 14, //!< Performance state 14 + NVML_PSTATE_15 = 15, //!< Performance state 15 -- Minimum Performance + NVML_PSTATE_UNKNOWN = 32 //!< Unknown performance state +} nvmlPstates_t; + +/** + * GPU Operation Mode + * + * GOM allows to reduce power usage and optimize GPU throughput by disabling GPU features. + * + * Each GOM is designed to meet specific user needs. + */ +typedef enum nvmlGom_enum +{ + NVML_GOM_ALL_ON = 0, //!< Everything is enabled and running at full speed + + NVML_GOM_COMPUTE = 1, //!< Designed for running only compute tasks. Graphics operations + //!< are not allowed + + NVML_GOM_LOW_DP = 2 //!< Designed for running graphics applications that don't require + //!< high bandwidth double precision +} nvmlGpuOperationMode_t; + +/** + * Available infoROM objects. + */ +typedef enum nvmlInforomObject_enum +{ + NVML_INFOROM_OEM = 0, //!< An object defined by OEM + NVML_INFOROM_ECC = 1, //!< The ECC object determining the level of ECC support + NVML_INFOROM_POWER = 2, //!< The power management object + + // Keep this last + NVML_INFOROM_COUNT //!< This counts the number of infoROM objects the driver knows about +} nvmlInforomObject_t; + +/** + * Return values for NVML API calls. + */ +typedef enum nvmlReturn_enum +{ + NVML_SUCCESS = 0, //!< The operation was successful + NVML_ERROR_UNINITIALIZED = 1, //!< NVML was not first initialized with nvmlInit() + NVML_ERROR_INVALID_ARGUMENT = 2, //!< A supplied argument is invalid + NVML_ERROR_NOT_SUPPORTED = 3, //!< The requested operation is not available on target device + NVML_ERROR_NO_PERMISSION = 4, //!< The current user does not have permission for operation + NVML_ERROR_ALREADY_INITIALIZED = 5, //!< Deprecated: Multiple initializations are now allowed through ref counting + NVML_ERROR_NOT_FOUND = 6, //!< A query to find an object was unsuccessful + NVML_ERROR_INSUFFICIENT_SIZE = 7, //!< An input argument is not large enough + NVML_ERROR_INSUFFICIENT_POWER = 8, //!< A device's external power cables are not properly attached + NVML_ERROR_DRIVER_NOT_LOADED = 9, //!< NVIDIA driver is not loaded + NVML_ERROR_TIMEOUT = 10, //!< User provided timeout passed + NVML_ERROR_IRQ_ISSUE = 11, //!< NVIDIA Kernel detected an interrupt issue with a GPU + NVML_ERROR_LIBRARY_NOT_FOUND = 12, //!< NVML Shared Library couldn't be found or loaded + NVML_ERROR_FUNCTION_NOT_FOUND = 13, //!< Local version of NVML doesn't implement this function + NVML_ERROR_CORRUPTED_INFOROM = 14, //!< infoROM is corrupted + NVML_ERROR_GPU_IS_LOST = 15, //!< The GPU has fallen off the bus or has otherwise become inaccessible + NVML_ERROR_RESET_REQUIRED = 16, //!< The GPU requires a reset before it can be used again + NVML_ERROR_OPERATING_SYSTEM = 17, //!< The GPU control device has been blocked by the operating system/cgroups + NVML_ERROR_LIB_RM_VERSION_MISMATCH = 18, //!< RM detects a driver/library version mismatch + NVML_ERROR_IN_USE = 19, //!< An operation cannot be performed because the GPU is currently in use + NVML_ERROR_MEMORY = 20, //!< Insufficient memory + NVML_ERROR_NO_DATA = 21, //!<No data + NVML_ERROR_VGPU_ECC_NOT_SUPPORTED = 22, //!< The requested vgpu operation is not available on target device, becasue ECC is enabled + NVML_ERROR_UNKNOWN = 999 //!< An internal driver error occurred +} nvmlReturn_t; + +/** + * Memory locations + * + * See \ref nvmlDeviceGetMemoryErrorCounter + */ +typedef enum nvmlMemoryLocation_enum +{ + NVML_MEMORY_LOCATION_L1_CACHE = 0, //!< GPU L1 Cache + NVML_MEMORY_LOCATION_L2_CACHE = 1, //!< GPU L2 Cache + NVML_MEMORY_LOCATION_DEVICE_MEMORY = 2, //!< GPU Device Memory + NVML_MEMORY_LOCATION_REGISTER_FILE = 3, //!< GPU Register File + NVML_MEMORY_LOCATION_TEXTURE_MEMORY = 4, //!< GPU Texture Memory + NVML_MEMORY_LOCATION_TEXTURE_SHM = 5, //!< Shared memory + NVML_MEMORY_LOCATION_CBU = 6, //!< CBU + + // Keep this last + NVML_MEMORY_LOCATION_COUNT //!< This counts the number of memory locations the driver knows about +} nvmlMemoryLocation_t; + +/** + * Causes for page retirement + */ +typedef enum nvmlPageRetirementCause_enum +{ + NVML_PAGE_RETIREMENT_CAUSE_MULTIPLE_SINGLE_BIT_ECC_ERRORS = 0, //!< Page was retired due to multiple single bit ECC error + NVML_PAGE_RETIREMENT_CAUSE_DOUBLE_BIT_ECC_ERROR = 1, //!< Page was retired due to double bit ECC error + + // Keep this last + NVML_PAGE_RETIREMENT_CAUSE_COUNT +} nvmlPageRetirementCause_t; + +/** + * API types that allow changes to default permission restrictions + */ +typedef enum nvmlRestrictedAPI_enum +{ + NVML_RESTRICTED_API_SET_APPLICATION_CLOCKS = 0, //!< APIs that change application clocks, see nvmlDeviceSetApplicationsClocks + //!< and see nvmlDeviceResetApplicationsClocks + NVML_RESTRICTED_API_SET_AUTO_BOOSTED_CLOCKS = 1, //!< APIs that enable/disable Auto Boosted clocks + //!< see nvmlDeviceSetAutoBoostedClocksEnabled + // Keep this last + NVML_RESTRICTED_API_COUNT +} nvmlRestrictedAPI_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlGridEnums GRID Enums + * @{ + */ +/***************************************************************************************************/ + +/*! + * GPU virtualization mode types. + */ +typedef enum nvmlGpuVirtualizationMode { + NVML_GPU_VIRTUALIZATION_MODE_NONE = 0, //!< Represents Bare Metal GPU + NVML_GPU_VIRTUALIZATION_MODE_PASSTHROUGH = 1, //!< Device is associated with GPU-Passthorugh + NVML_GPU_VIRTUALIZATION_MODE_VGPU = 2, //!< Device is associated with vGPU inside virtual machine. + NVML_GPU_VIRTUALIZATION_MODE_HOST_VGPU = 3, //!< Device is associated with VGX hypervisor in vGPU mode + NVML_GPU_VIRTUALIZATION_MODE_HOST_VSGA = 4, //!< Device is associated with VGX hypervisor in vSGA mode +} nvmlGpuVirtualizationMode_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlFieldValueEnums Field Value Enums + * @{ + */ +/***************************************************************************************************/ + +/** + * Field Identifiers. + * + * All Identifiers pertain to a device. Each ID is only used once and is guaranteed never to change. + */ +#define NVML_FI_DEV_ECC_CURRENT 1 //!< Current ECC mode. 1=Active. 0=Inactive +#define NVML_FI_DEV_ECC_PENDING 2 //!< Pending ECC mode. 1=Active. 0=Inactive +/* ECC Count Totals */ +#define NVML_FI_DEV_ECC_SBE_VOL_TOTAL 3 //!< Total single bit volatile ECC errors +#define NVML_FI_DEV_ECC_DBE_VOL_TOTAL 4 //!< Total double bit volatile ECC errors +#define NVML_FI_DEV_ECC_SBE_AGG_TOTAL 5 //!< Total single bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_DBE_AGG_TOTAL 6 //!< Total double bit aggregate (persistent) ECC errors +/* Individual ECC locations */ +#define NVML_FI_DEV_ECC_SBE_VOL_L1 7 //!< L1 cache single bit volatile ECC errors +#define NVML_FI_DEV_ECC_DBE_VOL_L1 8 //!< L1 cache double bit volatile ECC errors +#define NVML_FI_DEV_ECC_SBE_VOL_L2 9 //!< L2 cache single bit volatile ECC errors +#define NVML_FI_DEV_ECC_DBE_VOL_L2 10 //!< L2 cache double bit volatile ECC errors +#define NVML_FI_DEV_ECC_SBE_VOL_DEV 11 //!< Device memory single bit volatile ECC errors +#define NVML_FI_DEV_ECC_DBE_VOL_DEV 12 //!< Device memory double bit volatile ECC errors +#define NVML_FI_DEV_ECC_SBE_VOL_REG 13 //!< Register file single bit volatile ECC errors +#define NVML_FI_DEV_ECC_DBE_VOL_REG 14 //!< Register file double bit volatile ECC errors +#define NVML_FI_DEV_ECC_SBE_VOL_TEX 15 //!< Texture memory single bit volatile ECC errors +#define NVML_FI_DEV_ECC_DBE_VOL_TEX 16 //!< Texture memory double bit volatile ECC errors +#define NVML_FI_DEV_ECC_DBE_VOL_CBU 17 //!< CBU double bit volatile ECC errors +#define NVML_FI_DEV_ECC_SBE_AGG_L1 18 //!< L1 cache single bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_DBE_AGG_L1 19 //!< L1 cache double bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_SBE_AGG_L2 20 //!< L2 cache single bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_DBE_AGG_L2 21 //!< L2 cache double bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_SBE_AGG_DEV 22 //!< Device memory single bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_DBE_AGG_DEV 23 //!< Device memory double bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_SBE_AGG_REG 24 //!< Register File single bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_DBE_AGG_REG 25 //!< Register File double bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_SBE_AGG_TEX 26 //!< Texture memory single bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_DBE_AGG_TEX 27 //!< Texture memory double bit aggregate (persistent) ECC errors +#define NVML_FI_DEV_ECC_DBE_AGG_CBU 28 //!< CBU double bit aggregate ECC errors + +/* Page Retirement */ +#define NVML_FI_DEV_RETIRED_SBE 29 //!< Number of retired pages because of single bit errors +#define NVML_FI_DEV_RETIRED_DBE 30 //!< Number of retired pages because of double bit errors +#define NVML_FI_DEV_RETIRED_PENDING 31 //!< If any pages are pending retirement. 1=yes. 0=no. + +/* NvLink Flit Error Counters */ +#define NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L0 32 //!< NVLink flow control CRC Error Counter for Lane 0 +#define NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L1 33 //!< NVLink flow control CRC Error Counter for Lane 1 +#define NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L2 34 //!< NVLink flow control CRC Error Counter for Lane 2 +#define NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L3 35 //!< NVLink flow control CRC Error Counter for Lane 3 +#define NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L4 36 //!< NVLink flow control CRC Error Counter for Lane 4 +#define NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_L5 37 //!< NVLink flow control CRC Error Counter for Lane 5 +#define NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT_TOTAL 38 //!< NVLink flow control CRC Error Counter total for all Lanes + +/* NvLink CRC Data Error Counters */ +#define NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L0 39 //!< NVLink data CRC Error Counter for Lane 0 +#define NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L1 40 //!< NVLink data CRC Error Counter for Lane 1 +#define NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L2 41 //!< NVLink data CRC Error Counter for Lane 2 +#define NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L3 42 //!< NVLink data CRC Error Counter for Lane 3 +#define NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L4 43 //!< NVLink data CRC Error Counter for Lane 4 +#define NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_L5 44 //!< NVLink data CRC Error Counter for Lane 5 +#define NVML_FI_DEV_NVLINK_CRC_DATA_ERROR_COUNT_TOTAL 45 //!< NvLink data CRC Error Counter total for all Lanes + +/* NvLink Replay Error Counters */ +#define NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L0 46 //!< NVLink Replay Error Counter for Lane 0 +#define NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L1 47 //!< NVLink Replay Error Counter for Lane 1 +#define NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L2 48 //!< NVLink Replay Error Counter for Lane 2 +#define NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L3 49 //!< NVLink Replay Error Counter for Lane 3 +#define NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L4 50 //!< NVLink Replay Error Counter for Lane 4 +#define NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L5 51 //!< NVLink Replay Error Counter for Lane 5 +#define NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_TOTAL 52 //!< NVLink Replay Error Counter total for all Lanes + +/* NvLink Recovery Error Counters */ +#define NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L0 53 //!< NVLink Recovery Error Counter for Lane 0 +#define NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L1 54 //!< NVLink Recovery Error Counter for Lane 1 +#define NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L2 55 //!< NVLink Recovery Error Counter for Lane 2 +#define NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L3 56 //!< NVLink Recovery Error Counter for Lane 3 +#define NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L4 57 //!< NVLink Recovery Error Counter for Lane 4 +#define NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_L5 58 //!< NVLink Recovery Error Counter for Lane 5 +#define NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_TOTAL 59 //!< NVLink Recovery Error Counter total for all Lanes + +/* NvLink Bandwidth Counters */ +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L0 60 //!< NVLink Bandwidth Counter for Counter Set 0, Lane 0 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L1 61 //!< NVLink Bandwidth Counter for Counter Set 0, Lane 1 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L2 62 //!< NVLink Bandwidth Counter for Counter Set 0, Lane 2 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L3 63 //!< NVLink Bandwidth Counter for Counter Set 0, Lane 3 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L4 64 //!< NVLink Bandwidth Counter for Counter Set 0, Lane 4 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C0_L5 65 //!< NVLink Bandwidth Counter for Counter Set 0, Lane 5 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C0_TOTAL 66 //!< NVLink Bandwidth Counter Total for Counter Set 0, All Lanes + +/* NvLink Bandwidth Counters */ +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L0 67 //!< NVLink Bandwidth Counter for Counter Set 1, Lane 0 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L1 68 //!< NVLink Bandwidth Counter for Counter Set 1, Lane 1 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L2 69 //!< NVLink Bandwidth Counter for Counter Set 1, Lane 2 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L3 70 //!< NVLink Bandwidth Counter for Counter Set 1, Lane 3 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L4 71 //!< NVLink Bandwidth Counter for Counter Set 1, Lane 4 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C1_L5 72 //!< NVLink Bandwidth Counter for Counter Set 1, Lane 5 +#define NVML_FI_DEV_NVLINK_BANDWIDTH_C1_TOTAL 73 //!< NVLink Bandwidth Counter Total for Counter Set 1, All Lanes + +/* NVML Perf Policy Counters */ +#define NVML_FI_DEV_PERF_POLICY_POWER 74 //!< Perf Policy Counter for Power Policy +#define NVML_FI_DEV_PERF_POLICY_THERMAL 75 //!< Perf Policy Counter for Thermal Policy +#define NVML_FI_DEV_PERF_POLICY_SYNC_BOOST 76 //!< Perf Policy Counter for Sync boost Policy +#define NVML_FI_DEV_PERF_POLICY_BOARD_LIMIT 77 //!< Perf Policy Counter for Board Limit +#define NVML_FI_DEV_PERF_POLICY_LOW_UTILIZATION 78 //!< Perf Policy Counter for Low GPU Utilization Policy +#define NVML_FI_DEV_PERF_POLICY_RELIABILITY 79 //!< Perf Policy Counter for Reliability Policy +#define NVML_FI_DEV_PERF_POLICY_TOTAL_APP_CLOCKS 80 //!< Perf Policy Counter for Total App Clock Policy +#define NVML_FI_DEV_PERF_POLICY_TOTAL_BASE_CLOCKS 81 //!< Perf Policy Counter for Total Base Clocks Policy + +/* Memory temperatures */ +#define NVML_FI_DEV_MEMORY_TEMP 82 //!< Memory temperature for the device + +/* Energy Counter */ +#define NVML_FI_DEV_TOTAL_ENERGY_CONSUMPTION 83 //!< Total energy consumption for the GPU in mJ since the driver was last reloaded + +/* NVLink Speed */ +#define NVML_FI_DEV_NVLINK_SPEED_MBPS_L0 84 //!< NVLink Speed in MBps for Link 0 +#define NVML_FI_DEV_NVLINK_SPEED_MBPS_L1 85 //!< NVLink Speed in MBps for Link 1 +#define NVML_FI_DEV_NVLINK_SPEED_MBPS_L2 86 //!< NVLink Speed in MBps for Link 2 +#define NVML_FI_DEV_NVLINK_SPEED_MBPS_L3 87 //!< NVLink Speed in MBps for Link 3 +#define NVML_FI_DEV_NVLINK_SPEED_MBPS_L4 88 //!< NVLink Speed in MBps for Link 4 +#define NVML_FI_DEV_NVLINK_SPEED_MBPS_L5 89 //!< NVLink Speed in MBps for Link 5 +#define NVML_FI_DEV_NVLINK_SPEED_MBPS_COMMON 90 //!< Common NVLink Speed in MBps for active links + +#define NVML_FI_DEV_NVLINK_LINK_COUNT 91 //!< Number of NVLinks present on the device + +#define NVML_FI_MAX 92 //!< One greater than the largest field ID defined above + +/** + * Information for a Field Value Sample + */ +typedef struct nvmlFieldValue_st +{ + unsigned int fieldId; //!< ID of the NVML field to retrieve. This must be set before any call that uses this struct. See the constants starting with NVML_FI_ above. + unsigned int unused; //!< Currently unused. This should be initialized to 0 by the caller before any API call + long long timestamp; //!< CPU Timestamp of this value in microseconds since 1970 + long long latencyUsec; //!< How long this field value took to update (in usec) within NVML. This may be averaged across several fields that are serviced by the same driver call. + nvmlValueType_t valueType; //!< Type of the value stored in value + nvmlReturn_t nvmlReturn; //!< Return code for retrieving this value. This must be checked before looking at value, as value is undefined if nvmlReturn != NVML_SUCCESS + nvmlValue_t value; //!< Value for this field. This is only valid if nvmlReturn == NVML_SUCCESS +} nvmlFieldValue_t; + + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlUnitStructs Unit Structs + * @{ + */ +/***************************************************************************************************/ + +typedef struct nvmlUnit_st* nvmlUnit_t; + +/** + * Description of HWBC entry + */ +typedef struct nvmlHwbcEntry_st +{ + unsigned int hwbcId; + char firmwareVersion[32]; +} nvmlHwbcEntry_t; + +/** + * Fan state enum. + */ +typedef enum nvmlFanState_enum +{ + NVML_FAN_NORMAL = 0, //!< Fan is working properly + NVML_FAN_FAILED = 1 //!< Fan has failed +} nvmlFanState_t; + +/** + * Led color enum. + */ +typedef enum nvmlLedColor_enum +{ + NVML_LED_COLOR_GREEN = 0, //!< GREEN, indicates good health + NVML_LED_COLOR_AMBER = 1 //!< AMBER, indicates problem +} nvmlLedColor_t; + + +/** + * LED states for an S-class unit. + */ +typedef struct nvmlLedState_st +{ + char cause[256]; //!< If amber, a text description of the cause + nvmlLedColor_t color; //!< GREEN or AMBER +} nvmlLedState_t; + +/** + * Static S-class unit info. + */ +typedef struct nvmlUnitInfo_st +{ + char name[96]; //!< Product name + char id[96]; //!< Product identifier + char serial[96]; //!< Product serial number + char firmwareVersion[96]; //!< Firmware version +} nvmlUnitInfo_t; + +/** + * Power usage information for an S-class unit. + * The power supply state is a human readable string that equals "Normal" or contains + * a combination of "Abnormal" plus one or more of the following: + * + * - High voltage + * - Fan failure + * - Heatsink temperature + * - Current limit + * - Voltage below UV alarm threshold + * - Low-voltage + * - SI2C remote off command + * - MOD_DISABLE input + * - Short pin transition +*/ +typedef struct nvmlPSUInfo_st +{ + char state[256]; //!< The power supply state + unsigned int current; //!< PSU current (A) + unsigned int voltage; //!< PSU voltage (V) + unsigned int power; //!< PSU power draw (W) +} nvmlPSUInfo_t; + +/** + * Fan speed reading for a single fan in an S-class unit. + */ +typedef struct nvmlUnitFanInfo_st +{ + unsigned int speed; //!< Fan speed (RPM) + nvmlFanState_t state; //!< Flag that indicates whether fan is working properly +} nvmlUnitFanInfo_t; + +/** + * Fan speed readings for an entire S-class unit. + */ +typedef struct nvmlUnitFanSpeeds_st +{ + nvmlUnitFanInfo_t fans[24]; //!< Fan speed data for each fan + unsigned int count; //!< Number of fans in unit +} nvmlUnitFanSpeeds_t; + +/** @} */ + +/***************************************************************************************************/ +/** @addtogroup nvmlEvents + * @{ + */ +/***************************************************************************************************/ + +/** + * Handle to an event set + */ +typedef struct nvmlEventSet_st* nvmlEventSet_t; + +/** @defgroup nvmlEventType Event Types + * @{ + * Event Types which user can be notified about. + * See description of particular functions for details. + * + * See \ref nvmlDeviceRegisterEvents and \ref nvmlDeviceGetSupportedEventTypes to check which devices + * support each event. + * + * Types can be combined with bitwise or operator '|' when passed to \ref nvmlDeviceRegisterEvents + */ +//! Event about single bit ECC errors +/** + * \note A corrected texture memory error is not an ECC error, so it does not generate a single bit event + */ +#define nvmlEventTypeSingleBitEccError 0x0000000000000001LL + +//! Event about double bit ECC errors +/** + * \note An uncorrected texture memory error is not an ECC error, so it does not generate a double bit event + */ +#define nvmlEventTypeDoubleBitEccError 0x0000000000000002LL + +//! Event about PState changes +/** + * \note On Fermi architecture PState changes are also an indicator that GPU is throttling down due to + * no work being executed on the GPU, power capping or thermal capping. In a typical situation, + * Fermi-based GPU should stay in P0 for the duration of the execution of the compute process. + */ +#define nvmlEventTypePState 0x0000000000000004LL + +//! Event that Xid critical error occurred +#define nvmlEventTypeXidCriticalError 0x0000000000000008LL + +//! Event about clock changes +/** + * Kepler only + */ +#define nvmlEventTypeClock 0x0000000000000010LL + +//! Mask with no events +#define nvmlEventTypeNone 0x0000000000000000LL +//! Mask of all events +#define nvmlEventTypeAll (nvmlEventTypeNone \ + | nvmlEventTypeSingleBitEccError \ + | nvmlEventTypeDoubleBitEccError \ + | nvmlEventTypePState \ + | nvmlEventTypeClock \ + | nvmlEventTypeXidCriticalError \ + ) +/** @} */ + +/** + * Information about occurred event + */ +typedef struct nvmlEventData_st +{ + nvmlDevice_t device; //!< Specific device where the event occurred + unsigned long long eventType; //!< Information about what specific event occurred + unsigned long long eventData; //!< Stores last XID error for the device in the event of nvmlEventTypeXidCriticalError, + // eventData is 0 for any other event. eventData is set as 999 for unknown xid error. +} nvmlEventData_t; + +/** @} */ + +/***************************************************************************************************/ +/** @addtogroup nvmlClocksThrottleReasons + * @{ + */ +/***************************************************************************************************/ + +/** Nothing is running on the GPU and the clocks are dropping to Idle state + * \note This limiter may be removed in a later release + */ +#define nvmlClocksThrottleReasonGpuIdle 0x0000000000000001LL + +/** GPU clocks are limited by current setting of applications clocks + * + * @see nvmlDeviceSetApplicationsClocks + * @see nvmlDeviceGetApplicationsClock + */ +#define nvmlClocksThrottleReasonApplicationsClocksSetting 0x0000000000000002LL + +/** + * @deprecated Renamed to \ref nvmlClocksThrottleReasonApplicationsClocksSetting + * as the name describes the situation more accurately. + */ +#define nvmlClocksThrottleReasonUserDefinedClocks nvmlClocksThrottleReasonApplicationsClocksSetting + +/** SW Power Scaling algorithm is reducing the clocks below requested clocks + * + * @see nvmlDeviceGetPowerUsage + * @see nvmlDeviceSetPowerManagementLimit + * @see nvmlDeviceGetPowerManagementLimit + */ +#define nvmlClocksThrottleReasonSwPowerCap 0x0000000000000004LL + +/** HW Slowdown (reducing the core clocks by a factor of 2 or more) is engaged + * + * This is an indicator of: + * - temperature being too high + * - External Power Brake Assertion is triggered (e.g. by the system power supply) + * - Power draw is too high and Fast Trigger protection is reducing the clocks + * - May be also reported during PState or clock change + * - This behavior may be removed in a later release. + * + * @see nvmlDeviceGetTemperature + * @see nvmlDeviceGetTemperatureThreshold + * @see nvmlDeviceGetPowerUsage + */ +#define nvmlClocksThrottleReasonHwSlowdown 0x0000000000000008LL + +/** Sync Boost + * + * This GPU has been added to a Sync boost group with nvidia-smi or DCGM in + * order to maximize performance per watt. All GPUs in the sync boost group + * will boost to the minimum possible clocks across the entire group. Look at + * the throttle reasons for other GPUs in the system to see why those GPUs are + * holding this one at lower clocks. + * + */ +#define nvmlClocksThrottleReasonSyncBoost 0x0000000000000010LL + +/** SW Thermal Slowdown + * + * This is an indicator of one or more of the following: + * - Current GPU temperature above the GPU Max Operating Temperature + * - Current memory temperature above the Memory Max Operating Temperature + * + */ +#define nvmlClocksThrottleReasonSwThermalSlowdown 0x0000000000000020LL + +/** HW Thermal Slowdown (reducing the core clocks by a factor of 2 or more) is engaged + * + * This is an indicator of: + * - temperature being too high + * + * @see nvmlDeviceGetTemperature + * @see nvmlDeviceGetTemperatureThreshold + * @see nvmlDeviceGetPowerUsage + */ +#define nvmlClocksThrottleReasonHwThermalSlowdown 0x0000000000000040LL + +/** HW Power Brake Slowdown (reducing the core clocks by a factor of 2 or more) is engaged + * + * This is an indicator of: + * - External Power Brake Assertion being triggered (e.g. by the system power supply) + * + * @see nvmlDeviceGetTemperature + * @see nvmlDeviceGetTemperatureThreshold + * @see nvmlDeviceGetPowerUsage + */ +#define nvmlClocksThrottleReasonHwPowerBrakeSlowdown 0x0000000000000080LL + +/** Bit mask representing no clocks throttling + * + * Clocks are as high as possible. + * */ +#define nvmlClocksThrottleReasonNone 0x0000000000000000LL + +/** Bit mask representing all supported clocks throttling reasons + * New reasons might be added to this list in the future + */ +#define nvmlClocksThrottleReasonAll (nvmlClocksThrottleReasonNone \ + | nvmlClocksThrottleReasonGpuIdle \ + | nvmlClocksThrottleReasonApplicationsClocksSetting \ + | nvmlClocksThrottleReasonSwPowerCap \ + | nvmlClocksThrottleReasonHwSlowdown \ + | nvmlClocksThrottleReasonSyncBoost \ + | nvmlClocksThrottleReasonSwThermalSlowdown \ + | nvmlClocksThrottleReasonHwThermalSlowdown \ + | nvmlClocksThrottleReasonHwPowerBrakeSlowdown \ +) +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlAccountingStats Accounting Statistics + * @{ + * + * Set of APIs designed to provide per process information about usage of GPU. + * + * @note All accounting statistics and accounting mode live in nvidia driver and reset + * to default (Disabled) when driver unloads. + * It is advised to run with persistence mode enabled. + * + * @note Enabling accounting mode has no negative impact on the GPU performance. + */ +/***************************************************************************************************/ + +/** + * Describes accounting statistics of a process. + */ +typedef struct nvmlAccountingStats_st { + unsigned int gpuUtilization; //!< Percent of time over the process's lifetime during which one or more kernels was executing on the GPU. + //! Utilization stats just like returned by \ref nvmlDeviceGetUtilizationRates but for the life time of a + //! process (not just the last sample period). + //! Set to NVML_VALUE_NOT_AVAILABLE if nvmlDeviceGetUtilizationRates is not supported + + unsigned int memoryUtilization; //!< Percent of time over the process's lifetime during which global (device) memory was being read or written. + //! Set to NVML_VALUE_NOT_AVAILABLE if nvmlDeviceGetUtilizationRates is not supported + + unsigned long long maxMemoryUsage; //!< Maximum total memory in bytes that was ever allocated by the process. + //! Set to NVML_VALUE_NOT_AVAILABLE if nvmlProcessInfo_t->usedGpuMemory is not supported + + + unsigned long long time; //!< Amount of time in ms during which the compute context was active. The time is reported as 0 if + //!< the process is not terminated + + unsigned long long startTime; //!< CPU Timestamp in usec representing start time for the process + + unsigned int isRunning; //!< Flag to represent if the process is running (1 for running, 0 for terminated) + + unsigned int reserved[5]; //!< Reserved for future use +} nvmlAccountingStats_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlVgpuConstants Vgpu Constants + * @{ + */ +/***************************************************************************************************/ + +/** + * Buffer size guaranteed to be large enough for \ref nvmlVgpuTypeGetLicense + */ +#define NVML_GRID_LICENSE_BUFFER_SIZE 128 + +#define NVML_VGPU_NAME_BUFFER_SIZE 64 + +#define NVML_MAX_VGPU_TYPES_PER_PGPU 17 + +#define NVML_MAX_VGPU_INSTANCES_PER_PGPU 24 + +#define NVML_GRID_LICENSE_FEATURE_MAX_COUNT 3 + +#define NVML_GRID_LICENSE_INFO_MAX_LENGTH 128 + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlVgpuEnum Vgpu Enum + * @{ + */ +/***************************************************************************************************/ + +/*! + * Types of VM identifiers + */ +typedef enum nvmlVgpuVmIdType { + NVML_VGPU_VM_ID_DOMAIN_ID = 0, //!< VM ID represents DOMAIN ID + NVML_VGPU_VM_ID_UUID = 1, //!< VM ID represents UUID +} nvmlVgpuVmIdType_t; + +// vGPU GUEST info state. +typedef enum nvmlVgpuGuestInfoState_enum +{ + NVML_VGPU_INSTANCE_GUEST_INFO_STATE_UNINITIALIZED = 0, //<! Guest-dependent fields uninitialized + NVML_VGPU_INSTANCE_GUEST_INFO_STATE_INITIALIZED = 1, //<! Guest-dependent fields initialized +} nvmlVgpuGuestInfoState_t; + +// GRID license feature code +typedef enum { + NVML_GRID_LICENSE_FEATURE_CODE_VGPU = 1, // Virtual GPU + NVML_GRID_LICENSE_FEATURE_CODE_VWORKSTATION = 2 // Virtual Workstation +} nvmlGridLicenseFeatureCode_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlVgpuStructs Vgpu Structs + * @{ + */ +/***************************************************************************************************/ + +typedef unsigned int nvmlVgpuTypeId_t; + +typedef unsigned int nvmlVgpuInstance_t; + +/** + * Structure to store Utilization Value and vgpuInstance + */ +typedef struct nvmlVgpuInstanceUtilizationSample_st +{ + nvmlVgpuInstance_t vgpuInstance; //!< vGPU Instance + unsigned long long timeStamp; //!< CPU Timestamp in microseconds + nvmlValue_t smUtil; //!< SM (3D/Compute) Util Value + nvmlValue_t memUtil; //!< Frame Buffer Memory Util Value + nvmlValue_t encUtil; //!< Encoder Util Value + nvmlValue_t decUtil; //!< Decoder Util Value +} nvmlVgpuInstanceUtilizationSample_t; + +/** + * Structure to store Utilization Value, vgpuInstance and subprocess information + */ +typedef struct nvmlVgpuProcessUtilizationSample_st +{ + nvmlVgpuInstance_t vgpuInstance; //!< vGPU Instance + unsigned int pid; //!< PID of process running within the vGPU VM + char processName[NVML_VGPU_NAME_BUFFER_SIZE]; //!< Name of process running within the vGPU VM + unsigned long long timeStamp; //!< CPU Timestamp in microseconds + unsigned int smUtil; //!< SM (3D/Compute) Util Value + unsigned int memUtil; //!< Frame Buffer Memory Util Value + unsigned int encUtil; //!< Encoder Util Value + unsigned int decUtil; //!< Decoder Util Value +} nvmlVgpuProcessUtilizationSample_t; + +/** + * Structure to store utilization value and process Id + */ +typedef struct nvmlProcessUtilizationSample_st +{ + unsigned int pid; //!< PID of process + unsigned long long timeStamp; //!< CPU Timestamp in microseconds + unsigned int smUtil; //!< SM (3D/Compute) Util Value + unsigned int memUtil; //!< Frame Buffer Memory Util Value + unsigned int encUtil; //!< Encoder Util Value + unsigned int decUtil; //!< Decoder Util Value +} nvmlProcessUtilizationSample_t; + +/** + * Structure to store GRID licensable features + */ +typedef struct nvmlGridLicensableFeature_st +{ + nvmlGridLicenseFeatureCode_t featureCode; //<! Licensed feature code + unsigned int featureState; //<! Non-zero if feature is currently licensed, otherwise zero + char licenseInfo[NVML_GRID_LICENSE_INFO_MAX_LENGTH]; +} nvmlGridLicensableFeature_t; + +typedef struct nvmlGridLicensableFeatures_st +{ + int isGridLicenseSupported; //<! Non-zero if GRID Software Licensing is supported on the system, otherwise zero + unsigned int licensableFeaturesCount; //<! Entries returned in \a gridLicensableFeatures array + nvmlGridLicensableFeature_t gridLicensableFeatures[NVML_GRID_LICENSE_FEATURE_MAX_COUNT]; +} nvmlGridLicensableFeatures_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlEncoderStructs Encoder Structs + * @{ + */ +/***************************************************************************************************/ + +/* + * Represents type of encoder for capacity can be queried + */ +typedef enum nvmlEncoderQueryType_enum +{ + NVML_ENCODER_QUERY_H264 = 0, + NVML_ENCODER_QUERY_HEVC = 1, +}nvmlEncoderType_t; + +/* + * Struct to hold encoder session data + */ +typedef struct nvmlEncoderSessionInfo_st +{ + unsigned int sessionId; //!< Unique session ID + unsigned int pid; //!< Owning process ID + nvmlVgpuInstance_t vgpuInstance; //!< Owning vGPU instance ID (only valid on vGPU hosts, otherwise zero) + nvmlEncoderType_t codecType; //!< Video encoder type + unsigned int hResolution; //!< Current encode horizontal resolution + unsigned int vResolution; //!< Current encode vertical resolution + unsigned int averageFps; //!< Moving average encode frames per second + unsigned int averageLatency; //!< Moving average encode latency in microseconds +}nvmlEncoderSessionInfo_t; + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlInitializationAndCleanup Initialization and Cleanup + * This chapter describes the methods that handle NVML initialization and cleanup. + * It is the user's responsibility to call \ref nvmlInit() before calling any other methods, and + * nvmlShutdown() once NVML is no longer being used. + * @{ + */ +/***************************************************************************************************/ + +#define NVML_INIT_FLAG_NO_GPUS 1 //!< Don't fail nvmlInit() when no GPUs are found + +/** + * Initialize NVML, but don't initialize any GPUs yet. + * + * \note nvmlInit_v3 introduces a "flags" argument, that allows passing boolean values + * modifying the behaviour of nvmlInit(). + * \note In NVML 5.319 new nvmlInit_v2 has replaced nvmlInit"_v1" (default in NVML 4.304 and older) that + * did initialize all GPU devices in the system. + * + * This allows NVML to communicate with a GPU + * when other GPUs in the system are unstable or in a bad state. When using this API, GPUs are + * discovered and initialized in nvmlDeviceGetHandleBy* functions instead. + * + * \note To contrast nvmlInit_v2 with nvmlInit"_v1", NVML 4.304 nvmlInit"_v1" will fail when any detected GPU is in + * a bad or unstable state. + * + * For all products. + * + * @param flags behaviour modifier flags + * + * This method, should be called once before invoking any other methods in the library. + * A reference count of the number of initializations is maintained. Shutdown only occurs + * when the reference count reaches zero. + * + * @return + * - \ref NVML_SUCCESS if NVML has been properly initialized + * - \ref NVML_ERROR_DRIVER_NOT_LOADED if NVIDIA driver is not running + * - \ref NVML_ERROR_NO_PERMISSION if NVML does not have permission to talk to the driver + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlInit(void); + +/** + * nvmlInitWithFlags is a variant of nvmlInit(), that allows passing a set of boolean values + * modifying the behaviour of nvmlInit(). + * Other than the "flags" parameter it is completely similar to \ref nvmlInit. + * + * For all products. + * + * @param flags behaviour modifier flags + * + * @return + * - \ref NVML_SUCCESS if NVML has been properly initialized + * - \ref NVML_ERROR_DRIVER_NOT_LOADED if NVIDIA driver is not running + * - \ref NVML_ERROR_NO_PERMISSION if NVML does not have permission to talk to the driver + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlInitWithFlags(unsigned int flags); + +/** + * Shut down NVML by releasing all GPU resources previously allocated with \ref nvmlInit(). + * + * For all products. + * + * This method should be called after NVML work is done, once for each call to \ref nvmlInit() + * A reference count of the number of initializations is maintained. Shutdown only occurs + * when the reference count reaches zero. For backwards compatibility, no error is reported if + * nvmlShutdown() is called more times than nvmlInit(). + * + * @return + * - \ref NVML_SUCCESS if NVML has been properly shut down + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlShutdown(void); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlErrorReporting Error reporting + * This chapter describes helper functions for error reporting routines. + * @{ + */ +/***************************************************************************************************/ + +/** + * Helper method for converting NVML error codes into readable strings. + * + * For all products. + * + * @param result NVML error code to convert + * + * @return String representation of the error. + * + */ +const DECLDIR char* nvmlErrorString(nvmlReturn_t result); +/** @} */ + + +/***************************************************************************************************/ +/** @defgroup nvmlConstants Constants + * @{ + */ +/***************************************************************************************************/ + +/** + * Buffer size guaranteed to be large enough for \ref nvmlDeviceGetInforomVersion and \ref nvmlDeviceGetInforomImageVersion + */ +#define NVML_DEVICE_INFOROM_VERSION_BUFFER_SIZE 16 + +/** + * Buffer size guaranteed to be large enough for \ref nvmlDeviceGetUUID + */ +#define NVML_DEVICE_UUID_BUFFER_SIZE 80 + +/** + * Buffer size guaranteed to be large enough for \ref nvmlDeviceGetBoardPartNumber + */ +#define NVML_DEVICE_PART_NUMBER_BUFFER_SIZE 80 + +/** + * Buffer size guaranteed to be large enough for \ref nvmlSystemGetDriverVersion + */ +#define NVML_SYSTEM_DRIVER_VERSION_BUFFER_SIZE 80 + +/** + * Buffer size guaranteed to be large enough for \ref nvmlSystemGetNVMLVersion + */ +#define NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE 80 + +/** + * Buffer size guaranteed to be large enough for \ref nvmlDeviceGetName + */ +#define NVML_DEVICE_NAME_BUFFER_SIZE 64 + +/** + * Buffer size guaranteed to be large enough for \ref nvmlDeviceGetSerial + */ +#define NVML_DEVICE_SERIAL_BUFFER_SIZE 30 + +/** + * Buffer size guaranteed to be large enough for \ref nvmlDeviceGetVbiosVersion + */ +#define NVML_DEVICE_VBIOS_VERSION_BUFFER_SIZE 32 + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlSystemQueries System Queries + * This chapter describes the queries that NVML can perform against the local system. These queries + * are not device-specific. + * @{ + */ +/***************************************************************************************************/ + +/** + * Retrieves the version of the system's graphics driver. + * + * For all products. + * + * The version identifier is an alphanumeric string. It will not exceed 80 characters in length + * (including the NULL terminator). See \ref nvmlConstants::NVML_SYSTEM_DRIVER_VERSION_BUFFER_SIZE. + * + * @param version Reference in which to return the version identifier + * @param length The maximum allowed length of the string returned in \a version + * + * @return + * - \ref NVML_SUCCESS if \a version has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a version is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + */ +nvmlReturn_t DECLDIR nvmlSystemGetDriverVersion(char *version, unsigned int length); + +/** + * Retrieves the version of the NVML library. + * + * For all products. + * + * The version identifier is an alphanumeric string. It will not exceed 80 characters in length + * (including the NULL terminator). See \ref nvmlConstants::NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE. + * + * @param version Reference in which to return the version identifier + * @param length The maximum allowed length of the string returned in \a version + * + * @return + * - \ref NVML_SUCCESS if \a version has been set + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a version is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + */ +nvmlReturn_t DECLDIR nvmlSystemGetNVMLVersion(char *version, unsigned int length); + +/** + * Retrieves the version of the CUDA driver. + * + * For all products. + * + * The returned CUDA driver version is the same as the CUDA API + * cuDriverGetVersion() would return on the system. + * + * @param cudaDriverVersion Reference in which to return the version identifier + * + * @return + * - \ref NVML_SUCCESS if \a cudaDriverVersion has been set + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a cudaDriverVersion is NULL + */ +nvmlReturn_t DECLDIR nvmlSystemGetCudaDriverVersion(int *cudaDriverVersion); + +/** + * Gets name of the process with provided process id + * + * For all products. + * + * Returned process name is cropped to provided length. + * name string is encoded in ANSI. + * + * @param pid The identifier of the process + * @param name Reference in which to return the process name + * @param length The maximum allowed length of the string returned in \a name + * + * @return + * - \ref NVML_SUCCESS if \a name has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a name is NULL or \a length is 0. + * - \ref NVML_ERROR_NOT_FOUND if process doesn't exists + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlSystemGetProcessName(unsigned int pid, char *name, unsigned int length); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlUnitQueries Unit Queries + * This chapter describes that queries that NVML can perform against each unit. For S-class systems only. + * In each case the device is identified with an nvmlUnit_t handle. This handle is obtained by + * calling \ref nvmlUnitGetHandleByIndex(). + * @{ + */ +/***************************************************************************************************/ + + /** + * Retrieves the number of units in the system. + * + * For S-class products. + * + * @param unitCount Reference in which to return the number of units + * + * @return + * - \ref NVML_SUCCESS if \a unitCount has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unitCount is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlUnitGetCount(unsigned int *unitCount); + +/** + * Acquire the handle for a particular unit, based on its index. + * + * For S-class products. + * + * Valid indices are derived from the \a unitCount returned by \ref nvmlUnitGetCount(). + * For example, if \a unitCount is 2 the valid indices are 0 and 1, corresponding to UNIT 0 and UNIT 1. + * + * The order in which NVML enumerates units has no guarantees of consistency between reboots. + * + * @param index The index of the target unit, >= 0 and < \a unitCount + * @param unit Reference in which to return the unit handle + * + * @return + * - \ref NVML_SUCCESS if \a unit has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a index is invalid or \a unit is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlUnitGetHandleByIndex(unsigned int index, nvmlUnit_t *unit); + +/** + * Retrieves the static information associated with a unit. + * + * For S-class products. + * + * See \ref nvmlUnitInfo_t for details on available unit info. + * + * @param unit The identifier of the target unit + * @param info Reference in which to return the unit information + * + * @return + * - \ref NVML_SUCCESS if \a info has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unit is invalid or \a info is NULL + */ +nvmlReturn_t DECLDIR nvmlUnitGetUnitInfo(nvmlUnit_t unit, nvmlUnitInfo_t *info); + +/** + * Retrieves the LED state associated with this unit. + * + * For S-class products. + * + * See \ref nvmlLedState_t for details on allowed states. + * + * @param unit The identifier of the target unit + * @param state Reference in which to return the current LED state + * + * @return + * - \ref NVML_SUCCESS if \a state has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unit is invalid or \a state is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this is not an S-class product + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlUnitSetLedState() + */ +nvmlReturn_t DECLDIR nvmlUnitGetLedState(nvmlUnit_t unit, nvmlLedState_t *state); + +/** + * Retrieves the PSU stats for the unit. + * + * For S-class products. + * + * See \ref nvmlPSUInfo_t for details on available PSU info. + * + * @param unit The identifier of the target unit + * @param psu Reference in which to return the PSU information + * + * @return + * - \ref NVML_SUCCESS if \a psu has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unit is invalid or \a psu is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this is not an S-class product + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlUnitGetPsuInfo(nvmlUnit_t unit, nvmlPSUInfo_t *psu); + +/** + * Retrieves the temperature readings for the unit, in degrees C. + * + * For S-class products. + * + * Depending on the product, readings may be available for intake (type=0), + * exhaust (type=1) and board (type=2). + * + * @param unit The identifier of the target unit + * @param type The type of reading to take + * @param temp Reference in which to return the intake temperature + * + * @return + * - \ref NVML_SUCCESS if \a temp has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unit or \a type is invalid or \a temp is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this is not an S-class product + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlUnitGetTemperature(nvmlUnit_t unit, unsigned int type, unsigned int *temp); + +/** + * Retrieves the fan speed readings for the unit. + * + * For S-class products. + * + * See \ref nvmlUnitFanSpeeds_t for details on available fan speed info. + * + * @param unit The identifier of the target unit + * @param fanSpeeds Reference in which to return the fan speed information + * + * @return + * - \ref NVML_SUCCESS if \a fanSpeeds has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unit is invalid or \a fanSpeeds is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this is not an S-class product + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlUnitGetFanSpeedInfo(nvmlUnit_t unit, nvmlUnitFanSpeeds_t *fanSpeeds); + +/** + * Retrieves the set of GPU devices that are attached to the specified unit. + * + * For S-class products. + * + * The \a deviceCount argument is expected to be set to the size of the input \a devices array. + * + * @param unit The identifier of the target unit + * @param deviceCount Reference in which to provide the \a devices array size, and + * to return the number of attached GPU devices + * @param devices Reference in which to return the references to the attached GPU devices + * + * @return + * - \ref NVML_SUCCESS if \a deviceCount and \a devices have been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a deviceCount indicates that the \a devices array is too small + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unit is invalid, either of \a deviceCount or \a devices is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlUnitGetDevices(nvmlUnit_t unit, unsigned int *deviceCount, nvmlDevice_t *devices); + +/** + * Retrieves the IDs and firmware versions for any Host Interface Cards (HICs) in the system. + * + * For S-class products. + * + * The \a hwbcCount argument is expected to be set to the size of the input \a hwbcEntries array. + * The HIC must be connected to an S-class system for it to be reported by this function. + * + * @param hwbcCount Size of hwbcEntries array + * @param hwbcEntries Array holding information about hwbc + * + * @return + * - \ref NVML_SUCCESS if \a hwbcCount and \a hwbcEntries have been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if either \a hwbcCount or \a hwbcEntries is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a hwbcCount indicates that the \a hwbcEntries array is too small + */ +nvmlReturn_t DECLDIR nvmlSystemGetHicVersion(unsigned int *hwbcCount, nvmlHwbcEntry_t *hwbcEntries); +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlDeviceQueries Device Queries + * This chapter describes that queries that NVML can perform against each device. + * In each case the device is identified with an nvmlDevice_t handle. This handle is obtained by + * calling one of \ref nvmlDeviceGetHandleByIndex(), \ref nvmlDeviceGetHandleBySerial(), + * \ref nvmlDeviceGetHandleByPciBusId(). or \ref nvmlDeviceGetHandleByUUID(). + * @{ + */ +/***************************************************************************************************/ + + /** + * Retrieves the number of compute devices in the system. A compute device is a single GPU. + * + * For all products. + * + * Note: New nvmlDeviceGetCount_v2 (default in NVML 5.319) returns count of all devices in the system + * even if nvmlDeviceGetHandleByIndex_v2 returns NVML_ERROR_NO_PERMISSION for such device. + * Update your code to handle this error, or use NVML 4.304 or older nvml header file. + * For backward binary compatibility reasons _v1 version of the API is still present in the shared + * library. + * Old _v1 version of nvmlDeviceGetCount doesn't count devices that NVML has no permission to talk to. + * + * @param deviceCount Reference in which to return the number of accessible devices + * + * @return + * - \ref NVML_SUCCESS if \a deviceCount has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a deviceCount is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetCount(unsigned int *deviceCount); + +/** + * Acquire the handle for a particular device, based on its index. + * + * For all products. + * + * Valid indices are derived from the \a accessibleDevices count returned by + * \ref nvmlDeviceGetCount(). For example, if \a accessibleDevices is 2 the valid indices + * are 0 and 1, corresponding to GPU 0 and GPU 1. + * + * The order in which NVML enumerates devices has no guarantees of consistency between reboots. For that reason it + * is recommended that devices be looked up by their PCI ids or UUID. See + * \ref nvmlDeviceGetHandleByUUID() and \ref nvmlDeviceGetHandleByPciBusId(). + * + * Note: The NVML index may not correlate with other APIs, such as the CUDA device index. + * + * Starting from NVML 5, this API causes NVML to initialize the target GPU + * NVML may initialize additional GPUs if: + * - The target GPU is an SLI slave + * + * Note: New nvmlDeviceGetCount_v2 (default in NVML 5.319) returns count of all devices in the system + * even if nvmlDeviceGetHandleByIndex_v2 returns NVML_ERROR_NO_PERMISSION for such device. + * Update your code to handle this error, or use NVML 4.304 or older nvml header file. + * For backward binary compatibility reasons _v1 version of the API is still present in the shared + * library. + * Old _v1 version of nvmlDeviceGetCount doesn't count devices that NVML has no permission to talk to. + * + * This means that nvmlDeviceGetHandleByIndex_v2 and _v1 can return different devices for the same index. + * If you don't touch macros that map old (_v1) versions to _v2 versions at the top of the file you don't + * need to worry about that. + * + * @param index The index of the target GPU, >= 0 and < \a accessibleDevices + * @param device Reference in which to return the device handle + * + * @return + * - \ref NVML_SUCCESS if \a device has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a index is invalid or \a device is NULL + * - \ref NVML_ERROR_INSUFFICIENT_POWER if any attached devices have improperly attached external power cables + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to talk to this device + * - \ref NVML_ERROR_IRQ_ISSUE if NVIDIA kernel detected an interrupt issue with the attached GPUs + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetIndex + * @see nvmlDeviceGetCount + */ +nvmlReturn_t DECLDIR nvmlDeviceGetHandleByIndex(unsigned int index, nvmlDevice_t *device); + +/** + * Acquire the handle for a particular device, based on its board serial number. + * + * For Fermi &tm; or newer fully supported devices. + * + * This number corresponds to the value printed directly on the board, and to the value returned by + * \ref nvmlDeviceGetSerial(). + * + * @deprecated Since more than one GPU can exist on a single board this function is deprecated in favor + * of \ref nvmlDeviceGetHandleByUUID. + * For dual GPU boards this function will return NVML_ERROR_INVALID_ARGUMENT. + * + * Starting from NVML 5, this API causes NVML to initialize the target GPU + * NVML may initialize additional GPUs as it searches for the target GPU + * + * @param serial The board serial number of the target GPU + * @param device Reference in which to return the device handle + * + * @return + * - \ref NVML_SUCCESS if \a device has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a serial is invalid, \a device is NULL or more than one + * device has the same serial (dual GPU boards) + * - \ref NVML_ERROR_NOT_FOUND if \a serial does not match a valid device on the system + * - \ref NVML_ERROR_INSUFFICIENT_POWER if any attached devices have improperly attached external power cables + * - \ref NVML_ERROR_IRQ_ISSUE if NVIDIA kernel detected an interrupt issue with the attached GPUs + * - \ref NVML_ERROR_GPU_IS_LOST if any GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetSerial + * @see nvmlDeviceGetHandleByUUID + */ +nvmlReturn_t DECLDIR nvmlDeviceGetHandleBySerial(const char *serial, nvmlDevice_t *device); + +/** + * Acquire the handle for a particular device, based on its globally unique immutable UUID associated with each device. + * + * For all products. + * + * @param uuid The UUID of the target GPU + * @param device Reference in which to return the device handle + * + * Starting from NVML 5, this API causes NVML to initialize the target GPU + * NVML may initialize additional GPUs as it searches for the target GPU + * + * @return + * - \ref NVML_SUCCESS if \a device has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a uuid is invalid or \a device is null + * - \ref NVML_ERROR_NOT_FOUND if \a uuid does not match a valid device on the system + * - \ref NVML_ERROR_INSUFFICIENT_POWER if any attached devices have improperly attached external power cables + * - \ref NVML_ERROR_IRQ_ISSUE if NVIDIA kernel detected an interrupt issue with the attached GPUs + * - \ref NVML_ERROR_GPU_IS_LOST if any GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetUUID + */ +nvmlReturn_t DECLDIR nvmlDeviceGetHandleByUUID(const char *uuid, nvmlDevice_t *device); + +/** + * Acquire the handle for a particular device, based on its PCI bus id. + * + * For all products. + * + * This value corresponds to the nvmlPciInfo_t::busId returned by \ref nvmlDeviceGetPciInfo(). + * + * Starting from NVML 5, this API causes NVML to initialize the target GPU + * NVML may initialize additional GPUs if: + * - The target GPU is an SLI slave + * + * \note NVML 4.304 and older version of nvmlDeviceGetHandleByPciBusId"_v1" returns NVML_ERROR_NOT_FOUND + * instead of NVML_ERROR_NO_PERMISSION. + * + * @param pciBusId The PCI bus id of the target GPU + * @param device Reference in which to return the device handle + * + * @return + * - \ref NVML_SUCCESS if \a device has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a pciBusId is invalid or \a device is NULL + * - \ref NVML_ERROR_NOT_FOUND if \a pciBusId does not match a valid device on the system + * - \ref NVML_ERROR_INSUFFICIENT_POWER if the attached device has improperly attached external power cables + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to talk to this device + * - \ref NVML_ERROR_IRQ_ISSUE if NVIDIA kernel detected an interrupt issue with the attached GPUs + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetHandleByPciBusId(const char *pciBusId, nvmlDevice_t *device); + +/** + * Retrieves the name of this device. + * + * For all products. + * + * The name is an alphanumeric string that denotes a particular product, e.g. Tesla &tm; C2070. It will not + * exceed 64 characters in length (including the NULL terminator). See \ref + * nvmlConstants::NVML_DEVICE_NAME_BUFFER_SIZE. + * + * @param device The identifier of the target device + * @param name Reference in which to return the product name + * @param length The maximum allowed length of the string returned in \a name + * + * @return + * - \ref NVML_SUCCESS if \a name has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a name is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetName(nvmlDevice_t device, char *name, unsigned int length); + +/** + * Retrieves the brand of this device. + * + * For all products. + * + * The type is a member of \ref nvmlBrandType_t defined above. + * + * @param device The identifier of the target device + * @param type Reference in which to return the product brand type + * + * @return + * - \ref NVML_SUCCESS if \a name has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a type is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t *type); + +/** + * Retrieves the NVML index of this device. + * + * For all products. + * + * Valid indices are derived from the \a accessibleDevices count returned by + * \ref nvmlDeviceGetCount(). For example, if \a accessibleDevices is 2 the valid indices + * are 0 and 1, corresponding to GPU 0 and GPU 1. + * + * The order in which NVML enumerates devices has no guarantees of consistency between reboots. For that reason it + * is recommended that devices be looked up by their PCI ids or GPU UUID. See + * \ref nvmlDeviceGetHandleByPciBusId() and \ref nvmlDeviceGetHandleByUUID(). + * + * Note: The NVML index may not correlate with other APIs, such as the CUDA device index. + * + * @param device The identifier of the target device + * @param index Reference in which to return the NVML index of the device + * + * @return + * - \ref NVML_SUCCESS if \a index has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a index is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetHandleByIndex() + * @see nvmlDeviceGetCount() + */ +nvmlReturn_t DECLDIR nvmlDeviceGetIndex(nvmlDevice_t device, unsigned int *index); + +/** + * Retrieves the globally unique board serial number associated with this device's board. + * + * For all products with an inforom. + * + * The serial number is an alphanumeric string that will not exceed 30 characters (including the NULL terminator). + * This number matches the serial number tag that is physically attached to the board. See \ref + * nvmlConstants::NVML_DEVICE_SERIAL_BUFFER_SIZE. + * + * @param device The identifier of the target device + * @param serial Reference in which to return the board/module serial number + * @param length The maximum allowed length of the string returned in \a serial + * + * @return + * - \ref NVML_SUCCESS if \a serial has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a serial is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetSerial(nvmlDevice_t device, char *serial, unsigned int length); + +/** + * Retrieves an array of unsigned ints (sized to cpuSetSize) of bitmasks with the ideal CPU affinity for the device + * For example, if processors 0, 1, 32, and 33 are ideal for the device and cpuSetSize == 2, + * result[0] = 0x3, result[1] = 0x3 + * + * For Kepler &tm; or newer fully supported devices. + * Supported on Linux only. + * + * @param device The identifier of the target device + * @param cpuSetSize The size of the cpuSet array that is safe to access + * @param cpuSet Array reference in which to return a bitmask of CPUs, 64 CPUs per + * unsigned long on 64-bit machines, 32 on 32-bit machines + * + * @return + * - \ref NVML_SUCCESS if \a cpuAffinity has been filled + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, cpuSetSize == 0, or cpuSet is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetCpuAffinity(nvmlDevice_t device, unsigned int cpuSetSize, unsigned long *cpuSet); + +/** + * Sets the ideal affinity for the calling thread and device using the guidelines + * given in nvmlDeviceGetCpuAffinity(). Note, this is a change as of version 8.0. + * Older versions set the affinity for a calling process and all children. + * Currently supports up to 64 processors. + * + * For Kepler &tm; or newer fully supported devices. + * Supported on Linux only. + * + * @param device The identifier of the target device + * + * @return + * - \ref NVML_SUCCESS if the calling process has been successfully bound + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceSetCpuAffinity(nvmlDevice_t device); + +/** + * Clear all affinity bindings for the calling thread. Note, this is a change as of version + * 8.0 as older versions cleared the affinity for a calling process and all children. + * + * For Kepler &tm; or newer fully supported devices. + * Supported on Linux only. + * + * @param device The identifier of the target device + * + * @return + * - \ref NVML_SUCCESS if the calling process has been successfully unbound + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceClearCpuAffinity(nvmlDevice_t device); + +/** + * Retrieve the common ancestor for two devices + * For all products. + * Supported on Linux only. + * + * @param device1 The identifier of the first device + * @param device2 The identifier of the second device + * @param pathInfo A \ref nvmlGpuTopologyLevel_t that gives the path type + * + * @return + * - \ref NVML_SUCCESS if \a pathInfo has been set + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device1, or \a device2 is invalid, or \a pathInfo is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device or OS does not support this feature + * - \ref NVML_ERROR_UNKNOWN an error has occurred in underlying topology discovery + */ +nvmlReturn_t DECLDIR nvmlDeviceGetTopologyCommonAncestor(nvmlDevice_t device1, nvmlDevice_t device2, nvmlGpuTopologyLevel_t *pathInfo); + +/** + * Retrieve the set of GPUs that are nearest to a given device at a specific interconnectivity level + * For all products. + * Supported on Linux only. + * + * @param device The identifier of the first device + * @param level The \ref nvmlGpuTopologyLevel_t level to search for other GPUs + * @param count When zero, is set to the number of matching GPUs such that \a deviceArray + * can be malloc'd. When non-zero, \a deviceArray will be filled with \a count + * number of device handles. + * @param deviceArray An array of device handles for GPUs found at \a level + * + * @return + * - \ref NVML_SUCCESS if \a deviceArray or \a count (if initially zero) has been set + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a level, or \a count is invalid, or \a deviceArray is NULL with a non-zero \a count + * - \ref NVML_ERROR_NOT_SUPPORTED if the device or OS does not support this feature + * - \ref NVML_ERROR_UNKNOWN an error has occurred in underlying topology discovery + */ +nvmlReturn_t DECLDIR nvmlDeviceGetTopologyNearestGpus(nvmlDevice_t device, nvmlGpuTopologyLevel_t level, unsigned int *count, nvmlDevice_t *deviceArray); + +/** + * Retrieve the set of GPUs that have a CPU affinity with the given CPU number + * For all products. + * Supported on Linux only. + * + * @param cpuNumber The CPU number + * @param count When zero, is set to the number of matching GPUs such that \a deviceArray + * can be malloc'd. When non-zero, \a deviceArray will be filled with \a count + * number of device handles. + * @param deviceArray An array of device handles for GPUs found with affinity to \a cpuNumber + * + * @return + * - \ref NVML_SUCCESS if \a deviceArray or \a count (if initially zero) has been set + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a cpuNumber, or \a count is invalid, or \a deviceArray is NULL with a non-zero \a count + * - \ref NVML_ERROR_NOT_SUPPORTED if the device or OS does not support this feature + * - \ref NVML_ERROR_UNKNOWN an error has occurred in underlying topology discovery + */ +nvmlReturn_t DECLDIR nvmlSystemGetTopologyGpuSet(unsigned int cpuNumber, unsigned int *count, nvmlDevice_t *deviceArray); + +/** + * Retrieve the status for a given p2p capability index between a given pair of GPU + * + * @param device1 The first device + * @param device2 The second device + * @param p2pIndex p2p Capability Index being looked for between \a device1 and \a device2 + * @param p2pStatus Reference in which to return the status of the \a p2pIndex + * between \a device1 and \a device2 + * @return + * - \ref NVML_SUCCESS if \a p2pStatus has been populated + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device1 or \a device2 or \a p2pIndex is invalid or \a p2pStatus is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetP2PStatus(nvmlDevice_t device1, nvmlDevice_t device2, nvmlGpuP2PCapsIndex_t p2pIndex,nvmlGpuP2PStatus_t *p2pStatus); + +/** + * Retrieves the globally unique immutable UUID associated with this device, as a 5 part hexadecimal string, + * that augments the immutable, board serial identifier. + * + * For all products. + * + * The UUID is a globally unique identifier. It is the only available identifier for pre-Fermi-architecture products. + * It does NOT correspond to any identifier printed on the board. It will not exceed 80 characters in length + * (including the NULL terminator). See \ref nvmlConstants::NVML_DEVICE_UUID_BUFFER_SIZE. + * + * @param device The identifier of the target device + * @param uuid Reference in which to return the GPU UUID + * @param length The maximum allowed length of the string returned in \a uuid + * + * @return + * - \ref NVML_SUCCESS if \a uuid has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a uuid is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetUUID(nvmlDevice_t device, char *uuid, unsigned int length); + +/** + * Retrieves minor number for the device. The minor number for the device is such that the Nvidia device node file for + * each GPU will have the form /dev/nvidia[minor number]. + * + * For all products. + * Supported only for Linux + * + * @param device The identifier of the target device + * @param minorNumber Reference in which to return the minor number for the device + * @return + * - \ref NVML_SUCCESS if the minor number is successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a minorNumber is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMinorNumber(nvmlDevice_t device, unsigned int *minorNumber); + +/** + * Retrieves the the device board part number which is programmed into the board's InfoROM + * + * For all products. + * + * @param device Identifier of the target device + * @param partNumber Reference to the buffer to return + * @param length Length of the buffer reference + * + * @return + * - \ref NVML_SUCCESS if \a partNumber has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_NOT_SUPPORTED if the needed VBIOS fields have not been filled + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a serial is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetBoardPartNumber(nvmlDevice_t device, char* partNumber, unsigned int length); + +/** + * Retrieves the version information for the device's infoROM object. + * + * For all products with an inforom. + * + * Fermi and higher parts have non-volatile on-board memory for persisting device info, such as aggregate + * ECC counts. The version of the data structures in this memory may change from time to time. It will not + * exceed 16 characters in length (including the NULL terminator). + * See \ref nvmlConstants::NVML_DEVICE_INFOROM_VERSION_BUFFER_SIZE. + * + * See \ref nvmlInforomObject_t for details on the available infoROM objects. + * + * @param device The identifier of the target device + * @param object The target infoROM object + * @param version Reference in which to return the infoROM version + * @param length The maximum allowed length of the string returned in \a version + * + * @return + * - \ref NVML_SUCCESS if \a version has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a version is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not have an infoROM + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetInforomImageVersion + */ +nvmlReturn_t DECLDIR nvmlDeviceGetInforomVersion(nvmlDevice_t device, nvmlInforomObject_t object, char *version, unsigned int length); + +/** + * Retrieves the global infoROM image version + * + * For all products with an inforom. + * + * Image version just like VBIOS version uniquely describes the exact version of the infoROM flashed on the board + * in contrast to infoROM object version which is only an indicator of supported features. + * Version string will not exceed 16 characters in length (including the NULL terminator). + * See \ref nvmlConstants::NVML_DEVICE_INFOROM_VERSION_BUFFER_SIZE. + * + * @param device The identifier of the target device + * @param version Reference in which to return the infoROM image version + * @param length The maximum allowed length of the string returned in \a version + * + * @return + * - \ref NVML_SUCCESS if \a version has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a version is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not have an infoROM + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetInforomVersion + */ +nvmlReturn_t DECLDIR nvmlDeviceGetInforomImageVersion(nvmlDevice_t device, char *version, unsigned int length); + +/** + * Retrieves the checksum of the configuration stored in the device's infoROM. + * + * For all products with an inforom. + * + * Can be used to make sure that two GPUs have the exact same configuration. + * Current checksum takes into account configuration stored in PWR and ECC infoROM objects. + * Checksum can change between driver releases or when user changes configuration (e.g. disable/enable ECC) + * + * @param device The identifier of the target device + * @param checksum Reference in which to return the infoROM configuration checksum + * + * @return + * - \ref NVML_SUCCESS if \a checksum has been set + * - \ref NVML_ERROR_CORRUPTED_INFOROM if the device's checksum couldn't be retrieved due to infoROM corruption + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a checksum is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetInforomConfigurationChecksum(nvmlDevice_t device, unsigned int *checksum); + +/** + * Reads the infoROM from the flash and verifies the checksums. + * + * For all products with an inforom. + * + * @param device The identifier of the target device + * + * @return + * - \ref NVML_SUCCESS if infoROM is not corrupted + * - \ref NVML_ERROR_CORRUPTED_INFOROM if the device's infoROM is corrupted + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceValidateInforom(nvmlDevice_t device); + +/** + * Retrieves the display mode for the device. + * + * For all products. + * + * This method indicates whether a physical display (e.g. monitor) is currently connected to + * any of the device's connectors. + * + * See \ref nvmlEnableState_t for details on allowed modes. + * + * @param device The identifier of the target device + * @param display Reference in which to return the display mode + * + * @return + * - \ref NVML_SUCCESS if \a display has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a display is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetDisplayMode(nvmlDevice_t device, nvmlEnableState_t *display); + +/** + * Retrieves the display active state for the device. + * + * For all products. + * + * This method indicates whether a display is initialized on the device. + * For example whether X Server is attached to this device and has allocated memory for the screen. + * + * Display can be active even when no monitor is physically attached. + * + * See \ref nvmlEnableState_t for details on allowed modes. + * + * @param device The identifier of the target device + * @param isActive Reference in which to return the display active state + * + * @return + * - \ref NVML_SUCCESS if \a isActive has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a isActive is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetDisplayActive(nvmlDevice_t device, nvmlEnableState_t *isActive); + +/** + * Retrieves the persistence mode associated with this device. + * + * For all products. + * For Linux only. + * + * When driver persistence mode is enabled the driver software state is not torn down when the last + * client disconnects. By default this feature is disabled. + * + * See \ref nvmlEnableState_t for details on allowed modes. + * + * @param device The identifier of the target device + * @param mode Reference in which to return the current driver persistence mode + * + * @return + * - \ref NVML_SUCCESS if \a mode has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a mode is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceSetPersistenceMode() + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPersistenceMode(nvmlDevice_t device, nvmlEnableState_t *mode); + +/** + * Retrieves the PCI attributes of this device. + * + * For all products. + * + * See \ref nvmlPciInfo_t for details on the available PCI info. + * + * @param device The identifier of the target device + * @param pci Reference in which to return the PCI info + * + * @return + * - \ref NVML_SUCCESS if \a pci has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a pci is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPciInfo(nvmlDevice_t device, nvmlPciInfo_t *pci); + +/** + * Retrieves the maximum PCIe link generation possible with this device and system + * + * I.E. for a generation 2 PCIe device attached to a generation 1 PCIe bus the max link generation this function will + * report is generation 1. + * + * For Fermi &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param maxLinkGen Reference in which to return the max PCIe link generation + * + * @return + * - \ref NVML_SUCCESS if \a maxLinkGen has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a maxLinkGen is null + * - \ref NVML_ERROR_NOT_SUPPORTED if PCIe link information is not available + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMaxPcieLinkGeneration(nvmlDevice_t device, unsigned int *maxLinkGen); + +/** + * Retrieves the maximum PCIe link width possible with this device and system + * + * I.E. for a device with a 16x PCIe bus width attached to a 8x PCIe system bus this function will report + * a max link width of 8. + * + * For Fermi &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param maxLinkWidth Reference in which to return the max PCIe link generation + * + * @return + * - \ref NVML_SUCCESS if \a maxLinkWidth has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a maxLinkWidth is null + * - \ref NVML_ERROR_NOT_SUPPORTED if PCIe link information is not available + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMaxPcieLinkWidth(nvmlDevice_t device, unsigned int *maxLinkWidth); + +/** + * Retrieves the current PCIe link generation + * + * For Fermi &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param currLinkGen Reference in which to return the current PCIe link generation + * + * @return + * - \ref NVML_SUCCESS if \a currLinkGen has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a currLinkGen is null + * - \ref NVML_ERROR_NOT_SUPPORTED if PCIe link information is not available + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetCurrPcieLinkGeneration(nvmlDevice_t device, unsigned int *currLinkGen); + +/** + * Retrieves the current PCIe link width + * + * For Fermi &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param currLinkWidth Reference in which to return the current PCIe link generation + * + * @return + * - \ref NVML_SUCCESS if \a currLinkWidth has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a currLinkWidth is null + * - \ref NVML_ERROR_NOT_SUPPORTED if PCIe link information is not available + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetCurrPcieLinkWidth(nvmlDevice_t device, unsigned int *currLinkWidth); + +/** + * Retrieve PCIe utilization information. + * This function is querying a byte counter over a 20ms interval and thus is the + * PCIe throughput over that interval. + * + * For Maxwell &tm; or newer fully supported devices. + * + * This method is not supported in virtual machines running virtual GPU (vGPU). + * + * @param device The identifier of the target device + * @param counter The specific counter that should be queried \ref nvmlPcieUtilCounter_t + * @param value Reference in which to return throughput in KB/s + * + * @return + * - \ref NVML_SUCCESS if \a value has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device or \a counter is invalid, or \a value is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPcieThroughput(nvmlDevice_t device, nvmlPcieUtilCounter_t counter, unsigned int *value); + +/** + * Retrieve the PCIe replay counter. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param value Reference in which to return the counter's value + * + * @return + * - \ref NVML_SUCCESS if \a value and \a rollover have been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a value or \a rollover are NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPcieReplayCounter(nvmlDevice_t device, unsigned int *value); + +/** + * Retrieves the current clock speeds for the device. + * + * For Fermi &tm; or newer fully supported devices. + * + * See \ref nvmlClockType_t for details on available clock information. + * + * @param device The identifier of the target device + * @param type Identify which clock domain to query + * @param clock Reference in which to return the clock speed in MHz + * + * @return + * - \ref NVML_SUCCESS if \a clock has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clock is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device cannot report the specified clock + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int *clock); + +/** + * Retrieves the maximum clock speeds for the device. + * + * For Fermi &tm; or newer fully supported devices. + * + * See \ref nvmlClockType_t for details on available clock information. + * + * \note On GPUs from Fermi family current P0 clocks (reported by \ref nvmlDeviceGetClockInfo) can differ from max clocks + * by few MHz. + * + * @param device The identifier of the target device + * @param type Identify which clock domain to query + * @param clock Reference in which to return the clock speed in MHz + * + * @return + * - \ref NVML_SUCCESS if \a clock has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clock is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device cannot report the specified clock + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int *clock); + +/** + * Retrieves the current setting of a clock that applications will use unless an overspec situation occurs. + * Can be changed using \ref nvmlDeviceSetApplicationsClocks. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param clockType Identify which clock domain to query + * @param clockMHz Reference in which to return the clock in MHz + * + * @return + * - \ref NVML_SUCCESS if \a clockMHz has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clockMHz is NULL or \a clockType is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetApplicationsClock(nvmlDevice_t device, nvmlClockType_t clockType, unsigned int *clockMHz); + +/** + * Retrieves the default applications clock that GPU boots with or + * defaults to after \ref nvmlDeviceResetApplicationsClocks call. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param clockType Identify which clock domain to query + * @param clockMHz Reference in which to return the default clock in MHz + * + * @return + * - \ref NVML_SUCCESS if \a clockMHz has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clockMHz is NULL or \a clockType is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * \see nvmlDeviceGetApplicationsClock + */ +nvmlReturn_t DECLDIR nvmlDeviceGetDefaultApplicationsClock(nvmlDevice_t device, nvmlClockType_t clockType, unsigned int *clockMHz); + +/** + * Resets the application clock to the default value + * + * This is the applications clock that will be used after system reboot or driver reload. + * Default value is constant, but the current value an be changed using \ref nvmlDeviceSetApplicationsClocks. + * + * On Pascal and newer hardware, if clocks were previously locked with \ref nvmlDeviceSetApplicationsClocks, + * this call will unlock clocks. This returns clocks their default behavior ofautomatically boosting above + * base clocks as thermal limits allow. + * + * @see nvmlDeviceGetApplicationsClock + * @see nvmlDeviceSetApplicationsClocks + * + * For Fermi &tm; or newer non-GeForce fully supported devices and Maxwell or newer GeForce devices. + * + * @param device The identifier of the target device + * + * @return + * - \ref NVML_SUCCESS if new settings were successfully set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceResetApplicationsClocks(nvmlDevice_t device); + +/** + * Retrieves the clock speed for the clock specified by the clock type and clock ID. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param clockType Identify which clock domain to query + * @param clockId Identify which clock in the domain to query + * @param clockMHz Reference in which to return the clock in MHz + * + * @return + * - \ref NVML_SUCCESS if \a clockMHz has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clockMHz is NULL or \a clockType is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetClock(nvmlDevice_t device, nvmlClockType_t clockType, nvmlClockId_t clockId, unsigned int *clockMHz); + +/** + * Retrieves the customer defined maximum boost clock speed specified by the given clock type. + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param clockType Identify which clock domain to query + * @param clockMHz Reference in which to return the clock in MHz + * + * @return + * - \ref NVML_SUCCESS if \a clockMHz has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clockMHz is NULL or \a clockType is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device or the \a clockType on this device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMaxCustomerBoostClock(nvmlDevice_t device, nvmlClockType_t clockType, unsigned int *clockMHz); + +/** + * Retrieves the list of possible memory clocks that can be used as an argument for \ref nvmlDeviceSetApplicationsClocks. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param count Reference in which to provide the \a clocksMHz array size, and + * to return the number of elements + * @param clocksMHz Reference in which to return the clock in MHz + * + * @return + * - \ref NVML_SUCCESS if \a count and \a clocksMHz have been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a count is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a count is too small (\a count is set to the number of + * required elements) + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceSetApplicationsClocks + * @see nvmlDeviceGetSupportedGraphicsClocks + */ +nvmlReturn_t DECLDIR nvmlDeviceGetSupportedMemoryClocks(nvmlDevice_t device, unsigned int *count, unsigned int *clocksMHz); + +/** + * Retrieves the list of possible graphics clocks that can be used as an argument for \ref nvmlDeviceSetApplicationsClocks. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param memoryClockMHz Memory clock for which to return possible graphics clocks + * @param count Reference in which to provide the \a clocksMHz array size, and + * to return the number of elements + * @param clocksMHz Reference in which to return the clocks in MHz + * + * @return + * - \ref NVML_SUCCESS if \a count and \a clocksMHz have been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_NOT_FOUND if the specified \a memoryClockMHz is not a supported frequency + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clock is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a count is too small + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceSetApplicationsClocks + * @see nvmlDeviceGetSupportedMemoryClocks + */ +nvmlReturn_t DECLDIR nvmlDeviceGetSupportedGraphicsClocks(nvmlDevice_t device, unsigned int memoryClockMHz, unsigned int *count, unsigned int *clocksMHz); + +/** + * Retrieve the current state of Auto Boosted clocks on a device and store it in \a isEnabled + * + * For Kepler &tm; or newer fully supported devices. + * + * Auto Boosted clocks are enabled by default on some hardware, allowing the GPU to run at higher clock rates + * to maximize performance as thermal limits allow. + * + * On Pascal and newer hardware, Auto Aoosted clocks are controlled through application clocks. + * Use \ref nvmlDeviceSetApplicationsClocks and \ref nvmlDeviceResetApplicationsClocks to control Auto Boost + * behavior. + * + * @param device The identifier of the target device + * @param isEnabled Where to store the current state of Auto Boosted clocks of the target device + * @param defaultIsEnabled Where to store the default Auto Boosted clocks behavior of the target device that the device will + * revert to when no applications are using the GPU + * + * @return + * - \ref NVML_SUCCESS If \a isEnabled has been been set with the Auto Boosted clocks state of \a device + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a isEnabled is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support Auto Boosted clocks + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetAutoBoostedClocksEnabled(nvmlDevice_t device, nvmlEnableState_t *isEnabled, nvmlEnableState_t *defaultIsEnabled); + +/** + * Try to set the current state of Auto Boosted clocks on a device. + * + * For Kepler &tm; or newer fully supported devices. + * + * Auto Boosted clocks are enabled by default on some hardware, allowing the GPU to run at higher clock rates + * to maximize performance as thermal limits allow. Auto Boosted clocks should be disabled if fixed clock + * rates are desired. + * + * Non-root users may use this API by default but can be restricted by root from using this API by calling + * \ref nvmlDeviceSetAPIRestriction with apiType=NVML_RESTRICTED_API_SET_AUTO_BOOSTED_CLOCKS. + * Note: Persistence Mode is required to modify current Auto Boost settings, therefore, it must be enabled. + * + * On Pascal and newer hardware, Auto Boosted clocks are controlled through application clocks. + * Use \ref nvmlDeviceSetApplicationsClocks and \ref nvmlDeviceResetApplicationsClocks to control Auto Boost + * behavior. + * + * @param device The identifier of the target device + * @param enabled What state to try to set Auto Boosted clocks of the target device to + * + * @return + * - \ref NVML_SUCCESS If the Auto Boosted clocks were successfully set to the state specified by \a enabled + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support Auto Boosted clocks + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + */ +nvmlReturn_t DECLDIR nvmlDeviceSetAutoBoostedClocksEnabled(nvmlDevice_t device, nvmlEnableState_t enabled); + +/** + * Try to set the default state of Auto Boosted clocks on a device. This is the default state that Auto Boosted clocks will + * return to when no compute running processes (e.g. CUDA application which have an active context) are running + * + * For Kepler &tm; or newer non-GeForce fully supported devices and Maxwell or newer GeForce devices. + * Requires root/admin permissions. + * + * Auto Boosted clocks are enabled by default on some hardware, allowing the GPU to run at higher clock rates + * to maximize performance as thermal limits allow. Auto Boosted clocks should be disabled if fixed clock + * rates are desired. + * + * On Pascal and newer hardware, Auto Boosted clocks are controlled through application clocks. + * Use \ref nvmlDeviceSetApplicationsClocks and \ref nvmlDeviceResetApplicationsClocks to control Auto Boost + * behavior. + * + * @param device The identifier of the target device + * @param enabled What state to try to set default Auto Boosted clocks of the target device to + * @param flags Flags that change the default behavior. Currently Unused. + * + * @return + * - \ref NVML_SUCCESS If the Auto Boosted clock's default state was successfully set to the state specified by \a enabled + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_NO_PERMISSION If the calling user does not have permission to change Auto Boosted clock's default state. + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support Auto Boosted clocks + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + */ +nvmlReturn_t DECLDIR nvmlDeviceSetDefaultAutoBoostedClocksEnabled(nvmlDevice_t device, nvmlEnableState_t enabled, unsigned int flags); + + +/** + * Retrieves the intended operating speed of the device's fan. + * + * Note: The reported speed is the intended fan speed. If the fan is physically blocked and unable to spin, the + * output will not match the actual fan speed. + * + * For all discrete products with dedicated fans. + * + * The fan speed is expressed as a percent of the maximum, i.e. full speed is 100%. + * + * @param device The identifier of the target device + * @param speed Reference in which to return the fan speed percentage + * + * @return + * - \ref NVML_SUCCESS if \a speed has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a speed is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not have a fan + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetFanSpeed(nvmlDevice_t device, unsigned int *speed); + +/** + * Retrieves the current temperature readings for the device, in degrees C. + * + * For all products. + * + * See \ref nvmlTemperatureSensors_t for details on available temperature sensors. + * + * @param device The identifier of the target device + * @param sensorType Flag that indicates which sensor reading to retrieve + * @param temp Reference in which to return the temperature reading + * + * @return + * - \ref NVML_SUCCESS if \a temp has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a sensorType is invalid or \a temp is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not have the specified sensor + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int *temp); + +/** + * Retrieves the temperature threshold for the GPU with the specified threshold type in degrees C. + * + * For Kepler &tm; or newer fully supported devices. + * + * See \ref nvmlTemperatureThresholds_t for details on available temperature thresholds. + * + * @param device The identifier of the target device + * @param thresholdType The type of threshold value queried + * @param temp Reference in which to return the temperature reading + * @return + * - \ref NVML_SUCCESS if \a temp has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a thresholdType is invalid or \a temp is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not have a temperature sensor or is unsupported + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetTemperatureThreshold(nvmlDevice_t device, nvmlTemperatureThresholds_t thresholdType, unsigned int *temp); + +/** + * Retrieves the current performance state for the device. + * + * For Fermi &tm; or newer fully supported devices. + * + * See \ref nvmlPstates_t for details on allowed performance states. + * + * @param device The identifier of the target device + * @param pState Reference in which to return the performance state reading + * + * @return + * - \ref NVML_SUCCESS if \a pState has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a pState is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPerformanceState(nvmlDevice_t device, nvmlPstates_t *pState); + +/** + * Retrieves current clocks throttling reasons. + * + * For all fully supported products. + * + * \note More than one bit can be enabled at the same time. Multiple reasons can be affecting clocks at once. + * + * @param device The identifier of the target device + * @param clocksThrottleReasons Reference in which to return bitmask of active clocks throttle + * reasons + * + * @return + * - \ref NVML_SUCCESS if \a clocksThrottleReasons has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a clocksThrottleReasons is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlClocksThrottleReasons + * @see nvmlDeviceGetSupportedClocksThrottleReasons + */ +nvmlReturn_t DECLDIR nvmlDeviceGetCurrentClocksThrottleReasons(nvmlDevice_t device, unsigned long long *clocksThrottleReasons); + +/** + * Retrieves bitmask of supported clocks throttle reasons that can be returned by + * \ref nvmlDeviceGetCurrentClocksThrottleReasons + * + * For all fully supported products. + * + * This method is not supported in virtual machines running virtual GPU (vGPU). + * + * @param device The identifier of the target device + * @param supportedClocksThrottleReasons Reference in which to return bitmask of supported + * clocks throttle reasons + * + * @return + * - \ref NVML_SUCCESS if \a supportedClocksThrottleReasons has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a supportedClocksThrottleReasons is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlClocksThrottleReasons + * @see nvmlDeviceGetCurrentClocksThrottleReasons + */ +nvmlReturn_t DECLDIR nvmlDeviceGetSupportedClocksThrottleReasons(nvmlDevice_t device, unsigned long long *supportedClocksThrottleReasons); + +/** + * Deprecated: Use \ref nvmlDeviceGetPerformanceState. This function exposes an incorrect generalization. + * + * Retrieve the current performance state for the device. + * + * For Fermi &tm; or newer fully supported devices. + * + * See \ref nvmlPstates_t for details on allowed performance states. + * + * @param device The identifier of the target device + * @param pState Reference in which to return the performance state reading + * + * @return + * - \ref NVML_SUCCESS if \a pState has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a pState is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPowerState(nvmlDevice_t device, nvmlPstates_t *pState); + +/** + * This API has been deprecated. + * + * Retrieves the power management mode associated with this device. + * + * For products from the Fermi family. + * - Requires \a NVML_INFOROM_POWER version 3.0 or higher. + * + * For from the Kepler or newer families. + * - Does not require \a NVML_INFOROM_POWER object. + * + * This flag indicates whether any power management algorithm is currently active on the device. An + * enabled state does not necessarily mean the device is being actively throttled -- only that + * that the driver will do so if the appropriate conditions are met. + * + * See \ref nvmlEnableState_t for details on allowed modes. + * + * @param device The identifier of the target device + * @param mode Reference in which to return the current power management mode + * + * @return + * - \ref NVML_SUCCESS if \a mode has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a mode is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPowerManagementMode(nvmlDevice_t device, nvmlEnableState_t *mode); + +/** + * Retrieves the power management limit associated with this device. + * + * For Fermi &tm; or newer fully supported devices. + * + * The power limit defines the upper boundary for the card's power draw. If + * the card's total power draw reaches this limit the power management algorithm kicks in. + * + * This reading is only available if power management mode is supported. + * See \ref nvmlDeviceGetPowerManagementMode. + * + * @param device The identifier of the target device + * @param limit Reference in which to return the power management limit in milliwatts + * + * @return + * - \ref NVML_SUCCESS if \a limit has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a limit is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPowerManagementLimit(nvmlDevice_t device, unsigned int *limit); + +/** + * Retrieves information about possible values of power management limits on this device. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param minLimit Reference in which to return the minimum power management limit in milliwatts + * @param maxLimit Reference in which to return the maximum power management limit in milliwatts + * + * @return + * - \ref NVML_SUCCESS if \a minLimit and \a maxLimit have been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a minLimit or \a maxLimit is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceSetPowerManagementLimit + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPowerManagementLimitConstraints(nvmlDevice_t device, unsigned int *minLimit, unsigned int *maxLimit); + +/** + * Retrieves default power management limit on this device, in milliwatts. + * Default power management limit is a power management limit that the device boots with. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param defaultLimit Reference in which to return the default power management limit in milliwatts + * + * @return + * - \ref NVML_SUCCESS if \a defaultLimit has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a defaultLimit is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPowerManagementDefaultLimit(nvmlDevice_t device, unsigned int *defaultLimit); + +/** + * Retrieves power usage for this GPU in milliwatts and its associated circuitry (e.g. memory) + * + * For Fermi &tm; or newer fully supported devices. + * + * On Fermi and Kepler GPUs the reading is accurate to within +/- 5% of current power draw. + * + * It is only available if power management mode is supported. See \ref nvmlDeviceGetPowerManagementMode. + * + * @param device The identifier of the target device + * @param power Reference in which to return the power usage information + * + * @return + * - \ref NVML_SUCCESS if \a power has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a power is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support power readings + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetPowerUsage(nvmlDevice_t device, unsigned int *power); + +/** + * Retrieves total energy consumption for this GPU in millijoules (mJ) since the driver was last reloaded + * + * For newer than Pascal &tm; fully supported devices. + * + * @param device The identifier of the target device + * @param energy Reference in which to return the energy consumption information + * + * @return + * - \ref NVML_SUCCESS if \a energy has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a energy is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support energy readings + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetTotalEnergyConsumption(nvmlDevice_t device, unsigned long long *energy); + +/** + * Get the effective power limit that the driver enforces after taking into account all limiters + * + * Note: This can be different from the \ref nvmlDeviceGetPowerManagementLimit if other limits are set elsewhere + * This includes the out of band power limit interface + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The device to communicate with + * @param limit Reference in which to return the power management limit in milliwatts + * + * @return + * - \ref NVML_SUCCESS if \a limit has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a limit is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetEnforcedPowerLimit(nvmlDevice_t device, unsigned int *limit); + +/** + * Retrieves the current GOM and pending GOM (the one that GPU will switch to after reboot). + * + * For GK110 M-class and X-class Tesla &tm; products from the Kepler family. + * Modes \ref NVML_GOM_LOW_DP and \ref NVML_GOM_ALL_ON are supported on fully supported GeForce products. + * Not supported on Quadro ® and Tesla &tm; C-class products. + * + * @param device The identifier of the target device + * @param current Reference in which to return the current GOM + * @param pending Reference in which to return the pending GOM + * + * @return + * - \ref NVML_SUCCESS if \a mode has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a current or \a pending is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlGpuOperationMode_t + * @see nvmlDeviceSetGpuOperationMode + */ +nvmlReturn_t DECLDIR nvmlDeviceGetGpuOperationMode(nvmlDevice_t device, nvmlGpuOperationMode_t *current, nvmlGpuOperationMode_t *pending); + +/** + * Retrieves the amount of used, free and total memory available on the device, in bytes. + * + * For all products. + * + * Enabling ECC reduces the amount of total available memory, due to the extra required parity bits. + * Under WDDM most device memory is allocated and managed on startup by Windows. + * + * Under Linux and Windows TCC, the reported amount of used memory is equal to the sum of memory allocated + * by all active channels on the device. + * + * See \ref nvmlMemory_t for details on available memory info. + * + * @param device The identifier of the target device + * @param memory Reference in which to return the memory information + * + * @return + * - \ref NVML_SUCCESS if \a memory has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a memory is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t *memory); + +/** + * Retrieves the current compute mode for the device. + * + * For all products. + * + * See \ref nvmlComputeMode_t for details on allowed compute modes. + * + * @param device The identifier of the target device + * @param mode Reference in which to return the current compute mode + * + * @return + * - \ref NVML_SUCCESS if \a mode has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a mode is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceSetComputeMode() + */ +nvmlReturn_t DECLDIR nvmlDeviceGetComputeMode(nvmlDevice_t device, nvmlComputeMode_t *mode); + +/** + * Retrieves the CUDA compute capability of the device. + * + * For all products. + * + * Returns the major and minor compute capability version numbers of the + * device. The major and minor versions are equivalent to the + * CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR and + * CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR attributes that would be + * returned by CUDA's cuDeviceGetAttribute(). + * + * @param device The identifier of the target device + * @param major Reference in which to return the major CUDA compute capability + * @param minor Reference in which to return the minor CUDA compute capability + * + * @return + * - \ref NVML_SUCCESS if \a major and \a minor have been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a major or \a minor are NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetCudaComputeCapability(nvmlDevice_t device, int *major, int *minor); + +/** + * Retrieves the current and pending ECC modes for the device. + * + * For Fermi &tm; or newer fully supported devices. + * Only applicable to devices with ECC. + * Requires \a NVML_INFOROM_ECC version 1.0 or higher. + * + * Changing ECC modes requires a reboot. The "pending" ECC mode refers to the target mode following + * the next reboot. + * + * See \ref nvmlEnableState_t for details on allowed modes. + * + * @param device The identifier of the target device + * @param current Reference in which to return the current ECC mode + * @param pending Reference in which to return the pending ECC mode + * + * @return + * - \ref NVML_SUCCESS if \a current and \a pending have been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or either \a current or \a pending is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceSetEccMode() + */ +nvmlReturn_t DECLDIR nvmlDeviceGetEccMode(nvmlDevice_t device, nvmlEnableState_t *current, nvmlEnableState_t *pending); + +/** + * Retrieves the device boardId from 0-N. + * Devices with the same boardId indicate GPUs connected to the same PLX. Use in conjunction with + * \ref nvmlDeviceGetMultiGpuBoard() to decide if they are on the same board as well. + * The boardId returned is a unique ID for the current configuration. Uniqueness and ordering across + * reboots and system configurations is not guaranteed (i.e. if a Tesla K40c returns 0x100 and + * the two GPUs on a Tesla K10 in the same system returns 0x200 it is not guaranteed they will + * always return those values but they will always be different from each other). + * + * + * For Fermi &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param boardId Reference in which to return the device's board ID + * + * @return + * - \ref NVML_SUCCESS if \a boardId has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a boardId is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetBoardId(nvmlDevice_t device, unsigned int *boardId); + +/** + * Retrieves whether the device is on a Multi-GPU Board + * Devices that are on multi-GPU boards will set \a multiGpuBool to a non-zero value. + * + * For Fermi &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param multiGpuBool Reference in which to return a zero or non-zero value + * to indicate whether the device is on a multi GPU board + * + * @return + * - \ref NVML_SUCCESS if \a multiGpuBool has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a multiGpuBool is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMultiGpuBoard(nvmlDevice_t device, unsigned int *multiGpuBool); + +/** + * Retrieves the total ECC error counts for the device. + * + * For Fermi &tm; or newer fully supported devices. + * Only applicable to devices with ECC. + * Requires \a NVML_INFOROM_ECC version 1.0 or higher. + * Requires ECC Mode to be enabled. + * + * The total error count is the sum of errors across each of the separate memory systems, i.e. the total set of + * errors across the entire device. + * + * See \ref nvmlMemoryErrorType_t for a description of available error types.\n + * See \ref nvmlEccCounterType_t for a description of available counter types. + * + * @param device The identifier of the target device + * @param errorType Flag that specifies the type of the errors. + * @param counterType Flag that specifies the counter-type of the errors. + * @param eccCounts Reference in which to return the specified ECC errors + * + * @return + * - \ref NVML_SUCCESS if \a eccCounts has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a errorType or \a counterType is invalid, or \a eccCounts is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceClearEccErrorCounts() + */ +nvmlReturn_t DECLDIR nvmlDeviceGetTotalEccErrors(nvmlDevice_t device, nvmlMemoryErrorType_t errorType, nvmlEccCounterType_t counterType, unsigned long long *eccCounts); + +/** + * Retrieves the detailed ECC error counts for the device. + * + * @deprecated This API supports only a fixed set of ECC error locations + * On different GPU architectures different locations are supported + * See \ref nvmlDeviceGetMemoryErrorCounter + * + * For Fermi &tm; or newer fully supported devices. + * Only applicable to devices with ECC. + * Requires \a NVML_INFOROM_ECC version 2.0 or higher to report aggregate location-based ECC counts. + * Requires \a NVML_INFOROM_ECC version 1.0 or higher to report all other ECC counts. + * Requires ECC Mode to be enabled. + * + * Detailed errors provide separate ECC counts for specific parts of the memory system. + * + * Reports zero for unsupported ECC error counters when a subset of ECC error counters are supported. + * + * See \ref nvmlMemoryErrorType_t for a description of available bit types.\n + * See \ref nvmlEccCounterType_t for a description of available counter types.\n + * See \ref nvmlEccErrorCounts_t for a description of provided detailed ECC counts. + * + * @param device The identifier of the target device + * @param errorType Flag that specifies the type of the errors. + * @param counterType Flag that specifies the counter-type of the errors. + * @param eccCounts Reference in which to return the specified ECC errors + * + * @return + * - \ref NVML_SUCCESS if \a eccCounts has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a errorType or \a counterType is invalid, or \a eccCounts is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceClearEccErrorCounts() + */ +nvmlReturn_t DECLDIR nvmlDeviceGetDetailedEccErrors(nvmlDevice_t device, nvmlMemoryErrorType_t errorType, nvmlEccCounterType_t counterType, nvmlEccErrorCounts_t *eccCounts); + +/** + * Retrieves the requested memory error counter for the device. + * + * For Fermi &tm; or newer fully supported devices. + * Requires \a NVML_INFOROM_ECC version 2.0 or higher to report aggregate location-based memory error counts. + * Requires \a NVML_INFOROM_ECC version 1.0 or higher to report all other memory error counts. + * + * Only applicable to devices with ECC. + * + * Requires ECC Mode to be enabled. + * + * See \ref nvmlMemoryErrorType_t for a description of available memory error types.\n + * See \ref nvmlEccCounterType_t for a description of available counter types.\n + * See \ref nvmlMemoryLocation_t for a description of available counter locations.\n + * + * @param device The identifier of the target device + * @param errorType Flag that specifies the type of error. + * @param counterType Flag that specifies the counter-type of the errors. + * @param locationType Specifies the location of the counter. + * @param count Reference in which to return the ECC counter + * + * @return + * - \ref NVML_SUCCESS if \a count has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a bitTyp,e \a counterType or \a locationType is + * invalid, or \a count is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support ECC error reporting in the specified memory + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetMemoryErrorCounter(nvmlDevice_t device, nvmlMemoryErrorType_t errorType, + nvmlEccCounterType_t counterType, + nvmlMemoryLocation_t locationType, unsigned long long *count); + +/** + * Retrieves the current utilization rates for the device's major subsystems. + * + * For Fermi &tm; or newer fully supported devices. + * + * See \ref nvmlUtilization_t for details on available utilization rates. + * + * \note During driver initialization when ECC is enabled one can see high GPU and Memory Utilization readings. + * This is caused by ECC Memory Scrubbing mechanism that is performed during driver initialization. + * + * @param device The identifier of the target device + * @param utilization Reference in which to return the utilization information + * + * @return + * - \ref NVML_SUCCESS if \a utilization has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a utilization is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization); + +/** + * Retrieves the current utilization and sampling size in microseconds for the Encoder + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param utilization Reference to an unsigned int for encoder utilization info + * @param samplingPeriodUs Reference to an unsigned int for the sampling period in US + * + * @return + * - \ref NVML_SUCCESS if \a utilization has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a utilization is NULL, or \a samplingPeriodUs is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetEncoderUtilization(nvmlDevice_t device, unsigned int *utilization, unsigned int *samplingPeriodUs); + +/** + * Retrieves the current capacity of the device's encoder, in macroblocks per second. + * + * For Maxwell &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param encoderQueryType Type of encoder to query + * @param encoderCapacity Reference to an unsigned int for the encoder capacity + * + * @return + * - \ref NVML_SUCCESS if \a encoderCapacity is fetched + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a encoderCapacity is NULL, or \a device or \a encoderQueryType + * are invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if device does not support the encoder specified in \a encodeQueryType + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetEncoderCapacity (nvmlDevice_t device, nvmlEncoderType_t encoderQueryType, unsigned int *encoderCapacity); + +/** + * Retrieves the current encoder statistics for a given device. + * + * For Maxwell &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param sessionCount Reference to an unsigned int for count of active encoder sessions + * @param averageFps Reference to an unsigned int for trailing average FPS of all active sessions + * @param averageLatency Reference to an unsigned int for encode latency in microseconds + * + * @return + * - \ref NVML_SUCCESS if \a sessionCount, \a averageFps and \a averageLatency is fetched + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a sessionCount, or \a device or \a averageFps, + * or \a averageLatency is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetEncoderStats (nvmlDevice_t device, unsigned int *sessionCount, + unsigned int *averageFps, unsigned int *averageLatency); + +/** + * Retrieves information about active encoder sessions on a target device. + * + * An array of active encoder sessions is returned in the caller-supplied buffer pointed at by \a sessionInfos. The + * array elememt count is passed in \a sessionCount, and \a sessionCount is used to return the number of sessions + * written to the buffer. + * + * If the supplied buffer is not large enough to accomodate the active session array, the function returns + * NVML_ERROR_INSUFFICIENT_SIZE, with the element count of nvmlEncoderSessionInfo_t array required in \a sessionCount. + * To query the number of active encoder sessions, call this function with *sessionCount = 0. The code will return + * NVML_SUCCESS with number of active encoder sessions updated in *sessionCount. + * + * For Maxwell &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param sessionCount Reference to caller supplied array size, and returns the number of sessions. + * @param sessionInfos Reference in which to return the session information + * + * @return + * - \ref NVML_SUCCESS if \a sessionInfos is fetched + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a sessionCount is too small, array element count is returned in \a sessionCount + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a sessionCount is NULL. + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetEncoderSessions(nvmlDevice_t device, unsigned int *sessionCount, nvmlEncoderSessionInfo_t *sessionInfos); + +/** + * Retrieves the current utilization and sampling size in microseconds for the Decoder + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param utilization Reference to an unsigned int for decoder utilization info + * @param samplingPeriodUs Reference to an unsigned int for the sampling period in US + * + * @return + * - \ref NVML_SUCCESS if \a utilization has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a utilization is NULL, or \a samplingPeriodUs is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetDecoderUtilization(nvmlDevice_t device, unsigned int *utilization, unsigned int *samplingPeriodUs); + +/** + * Retrieves the current and pending driver model for the device. + * + * For Fermi &tm; or newer fully supported devices. + * For windows only. + * + * On Windows platforms the device driver can run in either WDDM or WDM (TCC) mode. If a display is attached + * to the device it must run in WDDM mode. TCC mode is preferred if a display is not attached. + * + * See \ref nvmlDriverModel_t for details on available driver models. + * + * @param device The identifier of the target device + * @param current Reference in which to return the current driver model + * @param pending Reference in which to return the pending driver model + * + * @return + * - \ref NVML_SUCCESS if either \a current and/or \a pending have been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or both \a current and \a pending are NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the platform is not windows + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceSetDriverModel() + */ +nvmlReturn_t DECLDIR nvmlDeviceGetDriverModel(nvmlDevice_t device, nvmlDriverModel_t *current, nvmlDriverModel_t *pending); + +/** + * Get VBIOS version of the device. + * + * For all products. + * + * The VBIOS version may change from time to time. It will not exceed 32 characters in length + * (including the NULL terminator). See \ref nvmlConstants::NVML_DEVICE_VBIOS_VERSION_BUFFER_SIZE. + * + * @param device The identifier of the target device + * @param version Reference to which to return the VBIOS version + * @param length The maximum allowed length of the string returned in \a version + * + * @return + * - \ref NVML_SUCCESS if \a version has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a version is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetVbiosVersion(nvmlDevice_t device, char *version, unsigned int length); + +/** + * Get Bridge Chip Information for all the bridge chips on the board. + * + * For all fully supported products. + * Only applicable to multi-GPU products. + * + * @param device The identifier of the target device + * @param bridgeHierarchy Reference to the returned bridge chip Hierarchy + * + * @return + * - \ref NVML_SUCCESS if bridge chip exists + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a bridgeInfo is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if bridge chip not supported on the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetBridgeChipInfo(nvmlDevice_t device, nvmlBridgeChipHierarchy_t *bridgeHierarchy); + +/** + * Get information about processes with a compute context on a device + * + * For Fermi &tm; or newer fully supported devices. + * + * This function returns information only about compute running processes (e.g. CUDA application which have + * active context). Any graphics applications (e.g. using OpenGL, DirectX) won't be listed by this function. + * + * To query the current number of running compute processes, call this function with *infoCount = 0. The + * return code will be NVML_ERROR_INSUFFICIENT_SIZE, or NVML_SUCCESS if none are running. For this call + * \a infos is allowed to be NULL. + * + * The usedGpuMemory field returned is all of the memory used by the application. + * + * Keep in mind that information returned by this call is dynamic and the number of elements might change in + * time. Allocate more space for \a infos table in case new compute processes are spawned. + * + * @param device The identifier of the target device + * @param infoCount Reference in which to provide the \a infos array size, and + * to return the number of returned elements + * @param infos Reference in which to return the process information + * + * @return + * - \ref NVML_SUCCESS if \a infoCount and \a infos have been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a infoCount indicates that the \a infos array is too small + * \a infoCount will contain minimal amount of space necessary for + * the call to complete + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, either of \a infoCount or \a infos is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see \ref nvmlSystemGetProcessName + */ +nvmlReturn_t DECLDIR nvmlDeviceGetComputeRunningProcesses(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); + +/** + * Get information about processes with a graphics context on a device + * + * For Kepler &tm; or newer fully supported devices. + * + * This function returns information only about graphics based processes + * (eg. applications using OpenGL, DirectX) + * + * To query the current number of running graphics processes, call this function with *infoCount = 0. The + * return code will be NVML_ERROR_INSUFFICIENT_SIZE, or NVML_SUCCESS if none are running. For this call + * \a infos is allowed to be NULL. + * + * The usedGpuMemory field returned is all of the memory used by the application. + * + * Keep in mind that information returned by this call is dynamic and the number of elements might change in + * time. Allocate more space for \a infos table in case new graphics processes are spawned. + * + * @param device The identifier of the target device + * @param infoCount Reference in which to provide the \a infos array size, and + * to return the number of returned elements + * @param infos Reference in which to return the process information + * + * @return + * - \ref NVML_SUCCESS if \a infoCount and \a infos have been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a infoCount indicates that the \a infos array is too small + * \a infoCount will contain minimal amount of space necessary for + * the call to complete + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, either of \a infoCount or \a infos is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see \ref nvmlSystemGetProcessName + */ +nvmlReturn_t DECLDIR nvmlDeviceGetGraphicsRunningProcesses(nvmlDevice_t device, unsigned int *infoCount, nvmlProcessInfo_t *infos); + +/** + * Check if the GPU devices are on the same physical board. + * + * For all fully supported products. + * + * @param device1 The first GPU device + * @param device2 The second GPU device + * @param onSameBoard Reference in which to return the status. + * Non-zero indicates that the GPUs are on the same board. + * + * @return + * - \ref NVML_SUCCESS if \a onSameBoard has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a dev1 or \a dev2 are invalid or \a onSameBoard is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this check is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the either GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceOnSameBoard(nvmlDevice_t device1, nvmlDevice_t device2, int *onSameBoard); + +/** + * Retrieves the root/admin permissions on the target API. See \a nvmlRestrictedAPI_t for the list of supported APIs. + * If an API is restricted only root users can call that API. See \a nvmlDeviceSetAPIRestriction to change current permissions. + * + * For all fully supported products. + * + * @param device The identifier of the target device + * @param apiType Target API type for this operation + * @param isRestricted Reference in which to return the current restriction + * NVML_FEATURE_ENABLED indicates that the API is root-only + * NVML_FEATURE_DISABLED indicates that the API is accessible to all users + * + * @return + * - \ref NVML_SUCCESS if \a isRestricted has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a apiType incorrect or \a isRestricted is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device or the device does not support + * the feature that is being queried (E.G. Enabling/disabling Auto Boosted clocks is + * not supported by the device) + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlRestrictedAPI_t + */ +nvmlReturn_t DECLDIR nvmlDeviceGetAPIRestriction(nvmlDevice_t device, nvmlRestrictedAPI_t apiType, nvmlEnableState_t *isRestricted); + +/** + * Gets recent samples for the GPU. + * + * For Kepler &tm; or newer fully supported devices. + * + * Based on type, this method can be used to fetch the power, utilization or clock samples maintained in the buffer by + * the driver. + * + * Power, Utilization and Clock samples are returned as type "unsigned int" for the union nvmlValue_t. + * + * To get the size of samples that user needs to allocate, the method is invoked with samples set to NULL. + * The returned samplesCount will provide the number of samples that can be queried. The user needs to + * allocate the buffer with size as samplesCount * sizeof(nvmlSample_t). + * + * lastSeenTimeStamp represents CPU timestamp in microseconds. Set it to 0 to fetch all the samples maintained by the + * underlying buffer. Set lastSeenTimeStamp to one of the timeStamps retrieved from the date of the previous query + * to get more recent samples. + * + * This method fetches the number of entries which can be accommodated in the provided samples array, and the + * reference samplesCount is updated to indicate how many samples were actually retrieved. The advantage of using this + * method for samples in contrast to polling via existing methods is to get get higher frequency data at lower polling cost. + * + * @param device The identifier for the target device + * @param type Type of sampling event + * @param lastSeenTimeStamp Return only samples with timestamp greater than lastSeenTimeStamp. + * @param sampleValType Output parameter to represent the type of sample value as described in nvmlSampleVal_t + * @param sampleCount Reference to provide the number of elements which can be queried in samples array + * @param samples Reference in which samples are returned + + * @return + * - \ref NVML_SUCCESS if samples are successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a samplesCount is NULL or + * reference to \a sampleCount is 0 for non null \a samples + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_NOT_FOUND if sample entries are not found + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetSamples(nvmlDevice_t device, nvmlSamplingType_t type, unsigned long long lastSeenTimeStamp, + nvmlValueType_t *sampleValType, unsigned int *sampleCount, nvmlSample_t *samples); + +/** + * Gets Total, Available and Used size of BAR1 memory. + * + * BAR1 is used to map the FB (device memory) so that it can be directly accessed by the CPU or by 3rd party + * devices (peer-to-peer on the PCIE bus). + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param bar1Memory Reference in which BAR1 memory + * information is returned. + * + * @return + * - \ref NVML_SUCCESS if BAR1 memory is successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a bar1Memory is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetBAR1MemoryInfo(nvmlDevice_t device, nvmlBAR1Memory_t *bar1Memory); + + +/** + * Gets the duration of time during which the device was throttled (lower than requested clocks) due to power + * or thermal constraints. + * + * The method is important to users who are tying to understand if their GPUs throttle at any point during their applications. The + * difference in violation times at two different reference times gives the indication of GPU throttling event. + * + * Violation for thermal capping is not supported at this time. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param perfPolicyType Represents Performance policy which can trigger GPU throttling + * @param violTime Reference to which violation time related information is returned + * + * + * @return + * - \ref NVML_SUCCESS if violation time is successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a perfPolicyType is invalid, or \a violTime is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if this query is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * + */ +nvmlReturn_t DECLDIR nvmlDeviceGetViolationStatus(nvmlDevice_t device, nvmlPerfPolicyType_t perfPolicyType, nvmlViolationTime_t *violTime); + +/** + * @} + */ + +/** @addtogroup nvmlAccountingStats + * @{ + */ + +/** + * Queries the state of per process accounting mode. + * + * For Kepler &tm; or newer fully supported devices. + * + * See \ref nvmlDeviceGetAccountingStats for more details. + * See \ref nvmlDeviceSetAccountingMode + * + * @param device The identifier of the target device + * @param mode Reference in which to return the current accounting mode + * + * @return + * - \ref NVML_SUCCESS if the mode has been successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a mode are NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetAccountingMode(nvmlDevice_t device, nvmlEnableState_t *mode); + +/** + * Queries process's accounting stats. + * + * For Kepler &tm; or newer fully supported devices. + * + * Accounting stats capture GPU utilization and other statistics across the lifetime of a process. + * Accounting stats can be queried during life time of the process and after its termination. + * The time field in \ref nvmlAccountingStats_t is reported as 0 during the lifetime of the process and + * updated to actual running time after its termination. + * Accounting stats are kept in a circular buffer, newly created processes overwrite information about old + * processes. + * + * See \ref nvmlAccountingStats_t for description of each returned metric. + * List of processes that can be queried can be retrieved from \ref nvmlDeviceGetAccountingPids. + * + * @note Accounting Mode needs to be on. See \ref nvmlDeviceGetAccountingMode. + * @note Only compute and graphics applications stats can be queried. Monitoring applications stats can't be + * queried since they don't contribute to GPU utilization. + * @note In case of pid collision stats of only the latest process (that terminated last) will be reported + * + * @warning On Kepler devices per process statistics are accurate only if there's one process running on a GPU. + * + * @param device The identifier of the target device + * @param pid Process Id of the target process to query stats for + * @param stats Reference in which to return the process's accounting stats + * + * @return + * - \ref NVML_SUCCESS if stats have been successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a stats are NULL + * - \ref NVML_ERROR_NOT_FOUND if process stats were not found + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature or accounting mode is disabled + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetAccountingBufferSize + */ +nvmlReturn_t DECLDIR nvmlDeviceGetAccountingStats(nvmlDevice_t device, unsigned int pid, nvmlAccountingStats_t *stats); + +/** + * Queries list of processes that can be queried for accounting stats. The list of processes returned + * can be in running or terminated state. + * + * For Kepler &tm; or newer fully supported devices. + * + * To just query the number of processes ready to be queried, call this function with *count = 0 and + * pids=NULL. The return code will be NVML_ERROR_INSUFFICIENT_SIZE, or NVML_SUCCESS if list is empty. + * + * For more details see \ref nvmlDeviceGetAccountingStats. + * + * @note In case of PID collision some processes might not be accessible before the circular buffer is full. + * + * @param device The identifier of the target device + * @param count Reference in which to provide the \a pids array size, and + * to return the number of elements ready to be queried + * @param pids Reference in which to return list of process ids + * + * @return + * - \ref NVML_SUCCESS if pids were successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a count is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature or accounting mode is disabled + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a count is too small (\a count is set to + * expected value) + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetAccountingBufferSize + */ +nvmlReturn_t DECLDIR nvmlDeviceGetAccountingPids(nvmlDevice_t device, unsigned int *count, unsigned int *pids); + +/** + * Returns the number of processes that the circular buffer with accounting pids can hold. + * + * For Kepler &tm; or newer fully supported devices. + * + * This is the maximum number of processes that accounting information will be stored for before information + * about oldest processes will get overwritten by information about new processes. + * + * @param device The identifier of the target device + * @param bufferSize Reference in which to provide the size (in number of elements) + * of the circular buffer for accounting stats. + * + * @return + * - \ref NVML_SUCCESS if buffer size was successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a bufferSize is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature or accounting mode is disabled + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetAccountingStats + * @see nvmlDeviceGetAccountingPids + */ +nvmlReturn_t DECLDIR nvmlDeviceGetAccountingBufferSize(nvmlDevice_t device, unsigned int *bufferSize); + +/** @} */ + +/** @addtogroup nvmlDeviceQueries + * @{ + */ + +/** + * Returns the list of retired pages by source, including pages that are pending retirement + * The address information provided from this API is the hardware address of the page that was retired. Note + * that this does not match the virtual address used in CUDA, but will match the address information in XID 63 + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param cause Filter page addresses by cause of retirement + * @param pageCount Reference in which to provide the \a addresses buffer size, and + * to return the number of retired pages that match \a cause + * Set to 0 to query the size without allocating an \a addresses buffer + * @param addresses Buffer to write the page addresses into + * + * @return + * - \ref NVML_SUCCESS if \a pageCount was populated and \a addresses was filled + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a pageCount indicates the buffer is not large enough to store all the + * matching page addresses. \a pageCount is set to the needed size. + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a pageCount is NULL, \a cause is invalid, or + * \a addresses is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetRetiredPages(nvmlDevice_t device, nvmlPageRetirementCause_t cause, + unsigned int *pageCount, unsigned long long *addresses); + +/** + * Check if any pages are pending retirement and need a reboot to fully retire. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param isPending Reference in which to return the pending status + * + * @return + * - \ref NVML_SUCCESS if \a isPending was populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a isPending is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetRetiredPagesPendingStatus(nvmlDevice_t device, nvmlEnableState_t *isPending); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlUnitCommands Unit Commands + * This chapter describes NVML operations that change the state of the unit. For S-class products. + * Each of these requires root/admin access. Non-admin users will see an NVML_ERROR_NO_PERMISSION + * error code when invoking any of these methods. + * @{ + */ +/***************************************************************************************************/ + +/** + * Set the LED state for the unit. The LED can be either green (0) or amber (1). + * + * For S-class products. + * Requires root/admin permissions. + * + * This operation takes effect immediately. + * + * + * <b>Current S-Class products don't provide unique LEDs for each unit. As such, both front + * and back LEDs will be toggled in unison regardless of which unit is specified with this command.</b> + * + * See \ref nvmlLedColor_t for available colors. + * + * @param unit The identifier of the target unit + * @param color The target LED color + * + * @return + * - \ref NVML_SUCCESS if the LED color has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a unit or \a color is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if this is not an S-class product + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlUnitGetLedState() + */ +nvmlReturn_t DECLDIR nvmlUnitSetLedState(nvmlUnit_t unit, nvmlLedColor_t color); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlDeviceCommands Device Commands + * This chapter describes NVML operations that change the state of the device. + * Each of these requires root/admin access. Non-admin users will see an NVML_ERROR_NO_PERMISSION + * error code when invoking any of these methods. + * @{ + */ +/***************************************************************************************************/ + +/** + * Set the persistence mode for the device. + * + * For all products. + * For Linux only. + * Requires root/admin permissions. + * + * The persistence mode determines whether the GPU driver software is torn down after the last client + * exits. + * + * This operation takes effect immediately. It is not persistent across reboots. After each reboot the + * persistence mode is reset to "Disabled". + * + * See \ref nvmlEnableState_t for available modes. + * + * @param device The identifier of the target device + * @param mode The target persistence mode + * + * @return + * - \ref NVML_SUCCESS if the persistence mode was set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a mode is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetPersistenceMode() + */ +nvmlReturn_t DECLDIR nvmlDeviceSetPersistenceMode(nvmlDevice_t device, nvmlEnableState_t mode); + +/** + * Set the compute mode for the device. + * + * For all products. + * Requires root/admin permissions. + * + * The compute mode determines whether a GPU can be used for compute operations and whether it can + * be shared across contexts. + * + * This operation takes effect immediately. Under Linux it is not persistent across reboots and + * always resets to "Default". Under windows it is persistent. + * + * Under windows compute mode may only be set to DEFAULT when running in WDDM + * + * See \ref nvmlComputeMode_t for details on available compute modes. + * + * @param device The identifier of the target device + * @param mode The target compute mode + * + * @return + * - \ref NVML_SUCCESS if the compute mode was set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a mode is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetComputeMode() + */ +nvmlReturn_t DECLDIR nvmlDeviceSetComputeMode(nvmlDevice_t device, nvmlComputeMode_t mode); + +/** + * Set the ECC mode for the device. + * + * For Kepler &tm; or newer fully supported devices. + * Only applicable to devices with ECC. + * Requires \a NVML_INFOROM_ECC version 1.0 or higher. + * Requires root/admin permissions. + * + * The ECC mode determines whether the GPU enables its ECC support. + * + * This operation takes effect after the next reboot. + * + * See \ref nvmlEnableState_t for details on available modes. + * + * @param device The identifier of the target device + * @param ecc The target ECC mode + * + * @return + * - \ref NVML_SUCCESS if the ECC mode was set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a ecc is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetEccMode() + */ +nvmlReturn_t DECLDIR nvmlDeviceSetEccMode(nvmlDevice_t device, nvmlEnableState_t ecc); + +/** + * Clear the ECC error and other memory error counts for the device. + * + * For Kepler &tm; or newer fully supported devices. + * Only applicable to devices with ECC. + * Requires \a NVML_INFOROM_ECC version 2.0 or higher to clear aggregate location-based ECC counts. + * Requires \a NVML_INFOROM_ECC version 1.0 or higher to clear all other ECC counts. + * Requires root/admin permissions. + * Requires ECC Mode to be enabled. + * + * Sets all of the specified ECC counters to 0, including both detailed and total counts. + * + * This operation takes effect immediately. + * + * See \ref nvmlMemoryErrorType_t for details on available counter types. + * + * @param device The identifier of the target device + * @param counterType Flag that indicates which type of errors should be cleared. + * + * @return + * - \ref NVML_SUCCESS if the error counts were cleared + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a counterType is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see + * - nvmlDeviceGetDetailedEccErrors() + * - nvmlDeviceGetTotalEccErrors() + */ +nvmlReturn_t DECLDIR nvmlDeviceClearEccErrorCounts(nvmlDevice_t device, nvmlEccCounterType_t counterType); + +/** + * Set the driver model for the device. + * + * For Fermi &tm; or newer fully supported devices. + * For windows only. + * Requires root/admin permissions. + * + * On Windows platforms the device driver can run in either WDDM or WDM (TCC) mode. If a display is attached + * to the device it must run in WDDM mode. + * + * It is possible to force the change to WDM (TCC) while the display is still attached with a force flag (nvmlFlagForce). + * This should only be done if the host is subsequently powered down and the display is detached from the device + * before the next reboot. + * + * This operation takes effect after the next reboot. + * + * Windows driver model may only be set to WDDM when running in DEFAULT compute mode. + * + * Change driver model to WDDM is not supported when GPU doesn't support graphics acceleration or + * will not support it after reboot. See \ref nvmlDeviceSetGpuOperationMode. + * + * See \ref nvmlDriverModel_t for details on available driver models. + * See \ref nvmlFlagDefault and \ref nvmlFlagForce + * + * @param device The identifier of the target device + * @param driverModel The target driver model + * @param flags Flags that change the default behavior + * + * @return + * - \ref NVML_SUCCESS if the driver model has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a driverModel is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the platform is not windows or the device does not support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetDriverModel() + */ +nvmlReturn_t DECLDIR nvmlDeviceSetDriverModel(nvmlDevice_t device, nvmlDriverModel_t driverModel, unsigned int flags); + +/** + * Set clocks that applications will lock to. + * + * Sets the clocks that compute and graphics applications will be running at. + * e.g. CUDA driver requests these clocks during context creation which means this property + * defines clocks at which CUDA applications will be running unless some overspec event + * occurs (e.g. over power, over thermal or external HW brake). + * + * Can be used as a setting to request constant performance. + * + * On Pascal and newer hardware, this will automatically disable automatic boosting of clocks. + * + * On K80 and newer Kepler and Maxwell GPUs, users desiring fixed performance should also call + * \ref nvmlDeviceSetAutoBoostedClocksEnabled to prevent clocks from automatically boosting + * above the clock value being set. + * + * For Kepler &tm; or newer non-GeForce fully supported devices and Maxwell or newer GeForce devices. + * Requires root/admin permissions. + * + * See \ref nvmlDeviceGetSupportedMemoryClocks and \ref nvmlDeviceGetSupportedGraphicsClocks + * for details on how to list available clocks combinations. + * + * After system reboot or driver reload applications clocks go back to their default value. + * See \ref nvmlDeviceResetApplicationsClocks. + * + * @param device The identifier of the target device + * @param memClockMHz Requested memory clock in MHz + * @param graphicsClockMHz Requested graphics clock in MHz + * + * @return + * - \ref NVML_SUCCESS if new settings were successfully set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a memClockMHz and \a graphicsClockMHz + * is not a valid clock combination + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceSetApplicationsClocks(nvmlDevice_t device, unsigned int memClockMHz, unsigned int graphicsClockMHz); + +/** + * Set new power limit of this device. + * + * For Kepler &tm; or newer fully supported devices. + * Requires root/admin permissions. + * + * See \ref nvmlDeviceGetPowerManagementLimitConstraints to check the allowed ranges of values. + * + * \note Limit is not persistent across reboots or driver unloads. + * Enable persistent mode to prevent driver from unloading when no application is using the device. + * + * @param device The identifier of the target device + * @param limit Power management limit in milliwatts to set + * + * @return + * - \ref NVML_SUCCESS if \a limit has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a defaultLimit is out of range + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceGetPowerManagementLimitConstraints + * @see nvmlDeviceGetPowerManagementDefaultLimit + */ +nvmlReturn_t DECLDIR nvmlDeviceSetPowerManagementLimit(nvmlDevice_t device, unsigned int limit); + +/** + * Sets new GOM. See \a nvmlGpuOperationMode_t for details. + * + * For GK110 M-class and X-class Tesla &tm; products from the Kepler family. + * Modes \ref NVML_GOM_LOW_DP and \ref NVML_GOM_ALL_ON are supported on fully supported GeForce products. + * Not supported on Quadro ® and Tesla &tm; C-class products. + * Requires root/admin permissions. + * + * Changing GOMs requires a reboot. + * The reboot requirement might be removed in the future. + * + * Compute only GOMs don't support graphics acceleration. Under windows switching to these GOMs when + * pending driver model is WDDM is not supported. See \ref nvmlDeviceSetDriverModel. + * + * @param device The identifier of the target device + * @param mode Target GOM + * + * @return + * - \ref NVML_SUCCESS if \a mode has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a mode incorrect + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support GOM or specific mode + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlGpuOperationMode_t + * @see nvmlDeviceGetGpuOperationMode + */ +nvmlReturn_t DECLDIR nvmlDeviceSetGpuOperationMode(nvmlDevice_t device, nvmlGpuOperationMode_t mode); + +/** + * Changes the root/admin restructions on certain APIs. See \a nvmlRestrictedAPI_t for the list of supported APIs. + * This method can be used by a root/admin user to give non-root/admin access to certain otherwise-restricted APIs. + * The new setting lasts for the lifetime of the NVIDIA driver; it is not persistent. See \a nvmlDeviceGetAPIRestriction + * to query the current restriction settings. + * + * For Kepler &tm; or newer fully supported devices. + * Requires root/admin permissions. + * + * @param device The identifier of the target device + * @param apiType Target API type for this operation + * @param isRestricted The target restriction + * + * @return + * - \ref NVML_SUCCESS if \a isRestricted has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a apiType incorrect + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support changing API restrictions or the device does not support + * the feature that api restrictions are being set for (E.G. Enabling/disabling auto + * boosted clocks is not supported by the device) + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlRestrictedAPI_t + */ +nvmlReturn_t DECLDIR nvmlDeviceSetAPIRestriction(nvmlDevice_t device, nvmlRestrictedAPI_t apiType, nvmlEnableState_t isRestricted); + +/** + * @} + */ + +/** @addtogroup nvmlAccountingStats + * @{ + */ + +/** + * Enables or disables per process accounting. + * + * For Kepler &tm; or newer fully supported devices. + * Requires root/admin permissions. + * + * @note This setting is not persistent and will default to disabled after driver unloads. + * Enable persistence mode to be sure the setting doesn't switch off to disabled. + * + * @note Enabling accounting mode has no negative impact on the GPU performance. + * + * @note Disabling accounting clears all accounting pids information. + * + * See \ref nvmlDeviceGetAccountingMode + * See \ref nvmlDeviceGetAccountingStats + * See \ref nvmlDeviceClearAccountingPids + * + * @param device The identifier of the target device + * @param mode The target accounting mode + * + * @return + * - \ref NVML_SUCCESS if the new mode has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device or \a mode are invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceSetAccountingMode(nvmlDevice_t device, nvmlEnableState_t mode); + +/** + * Clears accounting information about all processes that have already terminated. + * + * For Kepler &tm; or newer fully supported devices. + * Requires root/admin permissions. + * + * See \ref nvmlDeviceGetAccountingMode + * See \ref nvmlDeviceGetAccountingStats + * See \ref nvmlDeviceSetAccountingMode + * + * @param device The identifier of the target device + * + * @return + * - \ref NVML_SUCCESS if accounting information has been cleared + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device are invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the user doesn't have permission to perform this operation + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceClearAccountingPids(nvmlDevice_t device); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup NvLink NvLink Methods + * This chapter describes methods that NVML can perform on NVLINK enabled devices. + * @{ + */ +/***************************************************************************************************/ + +/** + * Retrieves the state of the device's NvLink for the link specified + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * @param isActive \a nvmlEnableState_t where NVML_FEATURE_ENABLED indicates that + * the link is active and NVML_FEATURE_DISABLED indicates it + * is inactive + * + * @return + * - \ref NVML_SUCCESS if \a isActive has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device or \a link is invalid or \a isActive is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNvLinkState(nvmlDevice_t device, unsigned int link, nvmlEnableState_t *isActive); + +/** + * Retrieves the version of the device's NvLink for the link specified + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * @param version Requested NvLink version + * + * @return + * - \ref NVML_SUCCESS if \a version has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device or \a link is invalid or \a version is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNvLinkVersion(nvmlDevice_t device, unsigned int link, unsigned int *version); + +/** + * Retrieves the requested capability from the device's NvLink for the link specified + * Please refer to the \a nvmlNvLinkCapability_t structure for the specific caps that can be queried + * The return value should be treated as a boolean. + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * @param capability Specifies the \a nvmlNvLinkCapability_t to be queried + * @param capResult A boolean for the queried capability indicating that feature is available + * + * @return + * - \ref NVML_SUCCESS if \a capResult has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a link, or \a capability is invalid or \a capResult is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNvLinkCapability(nvmlDevice_t device, unsigned int link, + nvmlNvLinkCapability_t capability, unsigned int *capResult); + +/** + * Retrieves the PCI information for the remote node on a NvLink link + * Note: pciSubSystemId is not filled in this function and is indeterminate + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * @param pci \a nvmlPciInfo_t of the remote node for the specified link + * + * @return + * - \ref NVML_SUCCESS if \a pci has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device or \a link is invalid or \a pci is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNvLinkRemotePciInfo(nvmlDevice_t device, unsigned int link, nvmlPciInfo_t *pci); + +/** + * Retrieves the specified error counter value + * Please refer to \a nvmlNvLinkErrorCounter_t for error counters that are available + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * @param counter Specifies the NvLink counter to be queried + * @param counterValue Returned counter value + * + * @return + * - \ref NVML_SUCCESS if \a counter has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a link, or \a counter is invalid or \a counterValue is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNvLinkErrorCounter(nvmlDevice_t device, unsigned int link, + nvmlNvLinkErrorCounter_t counter, unsigned long long *counterValue); + +/** + * Resets all error counters to zero + * Please refer to \a nvmlNvLinkErrorCounter_t for the list of error counters that are reset + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * + * @return + * - \ref NVML_SUCCESS if the reset is successful + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device or \a link is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceResetNvLinkErrorCounters(nvmlDevice_t device, unsigned int link); + +/** + * Set the NVLINK utilization counter control information for the specified counter, 0 or 1. + * Please refer to \a nvmlNvLinkUtilizationControl_t for the structure definition. Performs a reset + * of the counters if the reset parameter is non-zero. + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param counter Specifies the counter that should be set (0 or 1). + * @param link Specifies the NvLink link to be queried + * @param control A reference to the \a nvmlNvLinkUtilizationControl_t to set + * @param reset Resets the counters on set if non-zero + * + * @return + * - \ref NVML_SUCCESS if the control has been set successfully + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a counter, \a link, or \a control is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceSetNvLinkUtilizationControl(nvmlDevice_t device, unsigned int link, unsigned int counter, + nvmlNvLinkUtilizationControl_t *control, unsigned int reset); + +/** + * Get the NVLINK utilization counter control information for the specified counter, 0 or 1. + * Please refer to \a nvmlNvLinkUtilizationControl_t for the structure definition + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param counter Specifies the counter that should be set (0 or 1). + * @param link Specifies the NvLink link to be queried + * @param control A reference to the \a nvmlNvLinkUtilizationControl_t to place information + * + * @return + * - \ref NVML_SUCCESS if the control has been set successfully + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a counter, \a link, or \a control is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNvLinkUtilizationControl(nvmlDevice_t device, unsigned int link, unsigned int counter, + nvmlNvLinkUtilizationControl_t *control); + + +/** + * Retrieve the NVLINK utilization counter based on the current control for a specified counter. + * In general it is good practice to use \a nvmlDeviceSetNvLinkUtilizationControl + * before reading the utilization counters as they have no default state + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * @param counter Specifies the counter that should be read (0 or 1). + * @param rxcounter Receive counter return value + * @param txcounter Transmit counter return value + * + * @return + * - \ref NVML_SUCCESS if \a rxcounter and \a txcounter have been successfully set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a counter, or \a link is invalid or \a rxcounter or \a txcounter are NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetNvLinkUtilizationCounter(nvmlDevice_t device, unsigned int link, unsigned int counter, + unsigned long long *rxcounter, unsigned long long *txcounter); + +/** + * Freeze the NVLINK utilization counters + * Both the receive and transmit counters are operated on by this function + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be queried + * @param counter Specifies the counter that should be frozen (0 or 1). + * @param freeze NVML_FEATURE_ENABLED = freeze the receive and transmit counters + * NVML_FEATURE_DISABLED = unfreeze the receive and transmit counters + * + * @return + * - \ref NVML_SUCCESS if counters were successfully frozen or unfrozen + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a link, \a counter, or \a freeze is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceFreezeNvLinkUtilizationCounter (nvmlDevice_t device, unsigned int link, + unsigned int counter, nvmlEnableState_t freeze); + +/** + * Reset the NVLINK utilization counters + * Both the receive and transmit counters are operated on by this function + * + * For Pascal &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param link Specifies the NvLink link to be reset + * @param counter Specifies the counter that should be reset (0 or 1) + * + * @return + * - \ref NVML_SUCCESS if counters were successfully reset + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device, \a link, or \a counter is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceResetNvLinkUtilizationCounter (nvmlDevice_t device, unsigned int link, unsigned int counter); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlEvents Event Handling Methods + * This chapter describes methods that NVML can perform against each device to register and wait for + * some event to occur. + * @{ + */ +/***************************************************************************************************/ + +/** + * Create an empty set of events. + * Event set should be freed by \ref nvmlEventSetFree + * + * For Fermi &tm; or newer fully supported devices. + * @param set Reference in which to return the event handle + * + * @return + * - \ref NVML_SUCCESS if the event has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a set is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlEventSetFree + */ +nvmlReturn_t DECLDIR nvmlEventSetCreate(nvmlEventSet_t *set); + +/** + * Starts recording of events on a specified devices and add the events to specified \ref nvmlEventSet_t + * + * For Fermi &tm; or newer fully supported devices. + * Ecc events are available only on ECC enabled devices (see \ref nvmlDeviceGetTotalEccErrors) + * Power capping events are available only on Power Management enabled devices (see \ref nvmlDeviceGetPowerManagementMode) + * + * For Linux only. + * + * \b IMPORTANT: Operations on \a set are not thread safe + * + * This call starts recording of events on specific device. + * All events that occurred before this call are not recorded. + * Checking if some event occurred can be done with \ref nvmlEventSetWait + * + * If function reports NVML_ERROR_UNKNOWN, event set is in undefined state and should be freed. + * If function reports NVML_ERROR_NOT_SUPPORTED, event set can still be used. None of the requested eventTypes + * are registered in that case. + * + * @param device The identifier of the target device + * @param eventTypes Bitmask of \ref nvmlEventType to record + * @param set Set to which add new event types + * + * @return + * - \ref NVML_SUCCESS if the event has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a eventTypes is invalid or \a set is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the platform does not support this feature or some of requested event types + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlEventType + * @see nvmlDeviceGetSupportedEventTypes + * @see nvmlEventSetWait + * @see nvmlEventSetFree + */ +nvmlReturn_t DECLDIR nvmlDeviceRegisterEvents(nvmlDevice_t device, unsigned long long eventTypes, nvmlEventSet_t set); + +/** + * Returns information about events supported on device + * + * For Fermi &tm; or newer fully supported devices. + * + * Events are not supported on Windows. So this function returns an empty mask in \a eventTypes on Windows. + * + * @param device The identifier of the target device + * @param eventTypes Reference in which to return bitmask of supported events + * + * @return + * - \ref NVML_SUCCESS if the eventTypes has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a eventType is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlEventType + * @see nvmlDeviceRegisterEvents + */ +nvmlReturn_t DECLDIR nvmlDeviceGetSupportedEventTypes(nvmlDevice_t device, unsigned long long *eventTypes); + +/** + * Waits on events and delivers events + * + * For Fermi &tm; or newer fully supported devices. + * + * If some events are ready to be delivered at the time of the call, function returns immediately. + * If there are no events ready to be delivered, function sleeps till event arrives + * but not longer than specified timeout. This function in certain conditions can return before + * specified timeout passes (e.g. when interrupt arrives) + * + * In case of xid error, the function returns the most recent xid error type seen by the system. If there are multiple + * xid errors generated before nvmlEventSetWait is invoked then the last seen xid error type is returned for all + * xid error events. + * + * @param set Reference to set of events to wait on + * @param data Reference in which to return event data + * @param timeoutms Maximum amount of wait time in milliseconds for registered event + * + * @return + * - \ref NVML_SUCCESS if the data has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a data is NULL + * - \ref NVML_ERROR_TIMEOUT if no event arrived in specified timeout or interrupt arrived + * - \ref NVML_ERROR_GPU_IS_LOST if a GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlEventType + * @see nvmlDeviceRegisterEvents + */ +nvmlReturn_t DECLDIR nvmlEventSetWait(nvmlEventSet_t set, nvmlEventData_t * data, unsigned int timeoutms); + +/** + * Releases events in the set + * + * For Fermi &tm; or newer fully supported devices. + * + * @param set Reference to events to be released + * + * @return + * - \ref NVML_SUCCESS if the event has been successfully released + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + * + * @see nvmlDeviceRegisterEvents + */ +nvmlReturn_t DECLDIR nvmlEventSetFree(nvmlEventSet_t set); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlZPI Drain states + * This chapter describes methods that NVML can perform against each device to control their drain state + * and recognition by NVML and NVIDIA kernel driver. These methods can be used with out-of-band tools to + * power on/off GPUs, enable robust reset scenarios, etc. + * @{ + */ +/***************************************************************************************************/ + +/** + * Modify the drain state of a GPU. This method forces a GPU to no longer accept new incoming requests. + * Any new NVML process will no longer see this GPU. Persistence mode for this GPU must be turned off before + * this call is made. + * Must be called as administrator. + * For Linux only. + * + * For Pascal &tm; or newer fully supported devices. + * Some Kepler devices supported. + * + * @param pciInfo The PCI address of the GPU drain state to be modified + * @param newState The drain state that should be entered, see \ref nvmlEnableState_t + * + * @return + * - \ref NVML_SUCCESS if counters were successfully reset + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a nvmlIndex or \a newState is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_NO_PERMISSION if the calling process has insufficient permissions to perform operation + * - \ref NVML_ERROR_IN_USE if the device has persistence mode turned on + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceModifyDrainState (nvmlPciInfo_t *pciInfo, nvmlEnableState_t newState); + +/** + * Query the drain state of a GPU. This method is used to check if a GPU is in a currently draining + * state. + * For Linux only. + * + * For Pascal &tm; or newer fully supported devices. + * Some Kepler devices supported. + * + * @param pciInfo The PCI address of the GPU drain state to be queried + * @param currentState The current drain state for this GPU, see \ref nvmlEnableState_t + * + * @return + * - \ref NVML_SUCCESS if counters were successfully reset + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a nvmlIndex or \a currentState is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceQueryDrainState (nvmlPciInfo_t *pciInfo, nvmlEnableState_t *currentState); + +/** + * This method will remove the specified GPU from the view of both NVML and the NVIDIA kernel driver + * as long as no other processes are attached. If other processes are attached, this call will return + * NVML_ERROR_IN_USE and the GPU will be returned to its original "draining" state. Note: the + * only situation where a process can still be attached after nvmlDeviceModifyDrainState() is called + * to initiate the draining state is if that process was using, and is still using, a GPU before the + * call was made. Also note, persistence mode counts as an attachment to the GPU thus it must be disabled + * prior to this call. + * + * For long-running NVML processes please note that this will change the enumeration of current GPUs. + * For example, if there are four GPUs present and GPU1 is removed, the new enumeration will be 0-2. + * Also, device handles after the removed GPU will not be valid and must be re-established. + * Must be run as administrator. + * For Linux only. + * + * For Pascal &tm; or newer fully supported devices. + * Some Kepler devices supported. + * + * @param pciInfo The PCI address of the GPU to be removed + * + * @return + * - \ref NVML_SUCCESS if counters were successfully reset + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a nvmlIndex is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the device doesn't support this feature + * - \ref NVML_ERROR_IN_USE if the device is still in use and cannot be removed + */ +nvmlReturn_t DECLDIR nvmlDeviceRemoveGpu (nvmlPciInfo_t *pciInfo); + +/** + * Request the OS and the NVIDIA kernel driver to rediscover a portion of the PCI subsystem looking for GPUs that + * were previously removed. The portion of the PCI tree can be narrowed by specifying a domain, bus, and device. + * If all are zeroes then the entire PCI tree will be searched. Please note that for long-running NVML processes + * the enumeration will change based on how many GPUs are discovered and where they are inserted in bus order. + * + * In addition, all newly discovered GPUs will be initialized and their ECC scrubbed which may take several seconds + * per GPU. Also, all device handles are no longer guaranteed to be valid post discovery. + * + * Must be run as administrator. + * For Linux only. + * + * For Pascal &tm; or newer fully supported devices. + * Some Kepler devices supported. + * + * @param pciInfo The PCI tree to be searched. Only the domain, bus, and device + * fields are used in this call. + * + * @return + * - \ref NVML_SUCCESS if counters were successfully reset + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a pciInfo is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if the operating system does not support this feature + * - \ref NVML_ERROR_OPERATING_SYSTEM if the operating system is denying this feature + * - \ref NVML_ERROR_NO_PERMISSION if the calling process has insufficient permissions to perform operation + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceDiscoverGpus (nvmlPciInfo_t *pciInfo); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlFieldValueQueries Field Value Queries + * This chapter describes NVML operations that are associated with retrieving Field Values from NVML + * @{ + */ +/***************************************************************************************************/ + +/** + * Request values for a list of fields for a device. This API allows multiple fields to be queried at once. + * If any of the underlying fieldIds are populated by the same driver call, the results for those field IDs + * will be populated from a single call rather than making a driver call for each fieldId. + * + * @param device The device handle of the GPU to request field values for + * @param valuesCount Number of entries in values that should be retrieved + * @param values Array of \a valuesCount structures to hold field values. + * Each value's fieldId must be populated prior to this call + * + * @return + * - \ref NVML_SUCCESS if any values in \a values were populated. Note that you must + * check the nvmlReturn field of each value for each individual + * status + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a values is NULL + */ +nvmlReturn_t DECLDIR nvmlDeviceGetFieldValues(nvmlDevice_t device, int valuesCount, nvmlFieldValue_t *values); + + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlGridQueries Grid Queries + * This chapter describes NVML operations that are associated with NVIDIA GRID products. + * @{ + */ +/***************************************************************************************************/ + +/** + * This method is used to get the virtualization mode corresponding to the GPU. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device Identifier of the target device + * @param pVirtualMode Reference to virtualization mode. One of NVML_GPU_VIRTUALIZATION_? + * + * @return + * - \ref NVML_SUCCESS if \a pVirtualMode is fetched + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a pVirtualMode is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetVirtualizationMode(nvmlDevice_t device, nvmlGpuVirtualizationMode_t *pVirtualMode); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlGridCommands Grid Commands + * This chapter describes NVML operations that are associated with NVIDIA GRID products. + * @{ + */ +/***************************************************************************************************/ + +/** + * This method is used to set the virtualization mode corresponding to the GPU. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device Identifier of the target device + * @param virtualMode virtualization mode. One of NVML_GPU_VIRTUALIZATION_? + * + * @return + * - \ref NVML_SUCCESS if \a pVirtualMode is set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid or \a pVirtualMode is NULL + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_NOT_SUPPORTED if setting of virtualization mode is not supported. + * - \ref NVML_ERROR_NO_PERMISSION if setting of virtualization mode is not allowed for this client. + */ +nvmlReturn_t DECLDIR nvmlDeviceSetVirtualizationMode(nvmlDevice_t device, nvmlGpuVirtualizationMode_t virtualMode); + +/** @} */ + +/***************************************************************************************************/ +/** @defgroup nvmlVgpu vGPU Management + * @{ + * + * Set of APIs supporting GRID vGPU + */ +/***************************************************************************************************/ + +/** + * Retrieve the supported vGPU types on a physical GPU (device). + * + * An array of supported vGPU types for the physical GPU indicated by \a device is returned in the caller-supplied buffer + * pointed at by \a vgpuTypeIds. The element count of nvmlVgpuTypeId_t array is passed in \a vgpuCount, and \a vgpuCount + * is used to return the number of vGPU types written to the buffer. + * + * If the supplied buffer is not large enough to accomodate the vGPU type array, the function returns + * NVML_ERROR_INSUFFICIENT_SIZE, with the element count of nvmlVgpuTypeId_t array required in \a vgpuCount. + * To query the number of vGPU types supported for the GPU, call this function with *vgpuCount = 0. + * The code will return NVML_ERROR_INSUFFICIENT_SIZE, or NVML_SUCCESS if no vGPU types are supported. + * + * @param device The identifier of the target device + * @param vgpuCount Pointer to caller-supplied array size, and returns number of vGPU types + * @param vgpuTypeIds Pointer to caller-supplied array in which to return list of vGPU types + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_INSUFFICIENT_SIZE \a vgpuTypeIds buffer is too small, array element count is returned in \a vgpuCount + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuCount is NULL or \a device is invalid + * - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the device + * - \ref NVML_ERROR_VGPU_ECC_NOT_SUPPORTED if ECC is enabled on the device + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetSupportedVgpus(nvmlDevice_t device, unsigned int *vgpuCount, nvmlVgpuTypeId_t *vgpuTypeIds); + +/** + * Retrieve the currently creatable vGPU types on a physical GPU (device). + * + * An array of creatable vGPU types for the physical GPU indicated by \a device is returned in the caller-supplied buffer + * pointed at by \a vgpuTypeIds. The element count of nvmlVgpuTypeId_t array is passed in \a vgpuCount, and \a vgpuCount + * is used to return the number of vGPU types written to the buffer. + * + * The creatable vGPU types for a device may differ over time, as there may be restrictions on what type of vGPU types + * can concurrently run on a device. For example, if only one vGPU type is allowed at a time on a device, then the creatable + * list will be restricted to whatever vGPU type is already running on the device. + * + * If the supplied buffer is not large enough to accomodate the vGPU type array, the function returns + * NVML_ERROR_INSUFFICIENT_SIZE, with the element count of nvmlVgpuTypeId_t array required in \a vgpuCount. + * To query the number of vGPU types createable for the GPU, call this function with *vgpuCount = 0. + * The code will return NVML_ERROR_INSUFFICIENT_SIZE, or NVML_SUCCESS if no vGPU types are creatable. + * + * @param device The identifier of the target device + * @param vgpuCount Pointer to caller-supplied array size, and returns number of vGPU types + * @param vgpuTypeIds Pointer to caller-supplied array in which to return list of vGPU types + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_INSUFFICIENT_SIZE \a vgpuTypeIds buffer is too small, array element count is returned in \a vgpuCount + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuCount is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the device + * - \ref NVML_ERROR_VGPU_ECC_NOT_SUPPORTED if ECC is enabled on the device + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetCreatableVgpus(nvmlDevice_t device, unsigned int *vgpuCount, nvmlVgpuTypeId_t *vgpuTypeIds); + +/** + * Retrieve the class of a vGPU type. It will not exceed 64 characters in length (including the NUL terminator). + * See \ref nvmlConstants::NVML_DEVICE_NAME_BUFFER_SIZE. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param vgpuTypeClass Pointer to string array to return class in + * @param size Size of string + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid, or \a vgpuTypeClass is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a size is too small + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetClass(nvmlVgpuTypeId_t vgpuTypeId, char *vgpuTypeClass, unsigned int *size); + +/** + * Retrieve the vGPU type name. + * + * The name is an alphanumeric string that denotes a particular vGPU, e.g. GRID M60-2Q. It will not + * exceed 64 characters in length (including the NUL terminator). See \ref + * nvmlConstants::NVML_DEVICE_NAME_BUFFER_SIZE. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param vgpuTypeName Pointer to buffer to return name + * @param size Size of buffer + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid, or \a name is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a size is too small + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetName(nvmlVgpuTypeId_t vgpuTypeId, char *vgpuTypeName, unsigned int *size); + +/** + * Retrieve the device ID of a vGPU type. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param deviceID Device ID and vendor ID of the device contained in single 32 bit value + * @param subsystemID Subsytem ID and subsytem vendor ID of the device contained in single 32 bit value + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid, or \a deviceId or \a subsystemID are NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetDeviceID(nvmlVgpuTypeId_t vgpuTypeId, unsigned long long *deviceID, unsigned long long *subsystemID); + +/** + * Retrieve the vGPU framebuffer size in bytes. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param fbSize Pointer to framebuffer size in bytes + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid, or \a fbSize is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetFramebufferSize(nvmlVgpuTypeId_t vgpuTypeId, unsigned long long *fbSize); + +/** + * Retrieve count of vGPU's supported display heads. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param numDisplayHeads Pointer to number of display heads + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid, or \a numDisplayHeads is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetNumDisplayHeads(nvmlVgpuTypeId_t vgpuTypeId, unsigned int *numDisplayHeads); + +/** + * Retrieve vGPU display head's maximum supported resolution. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param displayIndex Zero-based index of display head + * @param xdim Pointer to maximum number of pixels in X dimension + * @param ydim Pointer to maximum number of pixels in Y dimension + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid, or \a xdim or \a ydim are NULL, or \a displayIndex + * is out of range. + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetResolution(nvmlVgpuTypeId_t vgpuTypeId, unsigned int displayIndex, unsigned int *xdim, unsigned int *ydim); + +/** + * Retrieve license requirements for a vGPU type + * + * The license type and version required to run the specified vGPU type is returned as an alphanumeric string, in the form + * "<license name>,<version>", for example "GRID-Virtual-PC,2.0". If a vGPU is runnable with* more than one type of license, + * the licenses are delimited by a semicolon, for example "GRID-Virtual-PC,2.0;GRID-Virtual-WS,2.0;GRID-Virtual-WS-Ext,2.0". + * + * The total length of the returned string will not exceed 128 characters, including the NUL terminator. + * See \ref nvmlVgpuConstants::NVML_GRID_LICENSE_BUFFER_SIZE. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param vgpuTypeLicenseString Pointer to buffer to return license info + * @param size Size of \a vgpuTypeLicenseString buffer + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid, or \a vgpuTypeLicenseString is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a size is too small + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetLicense(nvmlVgpuTypeId_t vgpuTypeId, char *vgpuTypeLicenseString, unsigned int size); + +/** + * Retrieve the static frame rate limit value of the vGPU type + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuTypeId Handle to vGPU type + * @param frameRateLimit Reference to return the frame rate limit value + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_NOT_SUPPORTED if frame rate limiter is turned off for the vGPU type + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a frameRateLimit is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetFrameRateLimit(nvmlVgpuTypeId_t vgpuTypeId, unsigned int *frameRateLimit); + +/** + * Retrieve the maximum number of vGPU instances creatable on a device for given vGPU type + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param vgpuTypeId Handle to vGPU type + * @param vgpuInstanceCount Pointer to get the max number of vGPU instances + * that can be created on a deicve for given vgpuTypeId + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuTypeId is invalid or is not supported on target device, + * or \a vgpuInstanceCount is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuTypeGetMaxInstances(nvmlDevice_t device, nvmlVgpuTypeId_t vgpuTypeId, unsigned int *vgpuInstanceCount); + +/** + * Retrieve the active vGPU instances on a device. + * + * An array of active vGPU instances is returned in the caller-supplied buffer pointed at by \a vgpuInstances. The + * array elememt count is passed in \a vgpuCount, and \a vgpuCount is used to return the number of vGPU instances + * written to the buffer. + * + * If the supplied buffer is not large enough to accomodate the vGPU instance array, the function returns + * NVML_ERROR_INSUFFICIENT_SIZE, with the element count of nvmlVgpuInstance_t array required in \a vgpuCount. + * To query the number of active vGPU instances, call this function with *vgpuCount = 0. The code will return + * NVML_ERROR_INSUFFICIENT_SIZE, or NVML_SUCCESS if no vGPU Types are supported. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param device The identifier of the target device + * @param vgpuCount Pointer which passes in the array size as well as get + * back the number of types + * @param vgpuInstances Pointer to array in which to return list of vGPU instances + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, or \a vgpuCount is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a size is too small + * - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the device + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetActiveVgpus(nvmlDevice_t device, unsigned int *vgpuCount, nvmlVgpuInstance_t *vgpuInstances); + +/** + * Retrieve the VM ID associated with a vGPU instance. + * + * The VM ID is returned as a string, not exceeding 80 characters in length (including the NUL terminator). + * See \ref nvmlConstants::NVML_DEVICE_UUID_BUFFER_SIZE. + * + * The format of the VM ID varies by platform, and is indicated by the type identifier returned in \a vmIdType. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param vmId Pointer to caller-supplied buffer to hold VM ID + * @param size Size of buffer in bytes + * @param vmIdType Pointer to hold VM ID type + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid, or \a vmId or \a vmIdType are NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a size is too small + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetVmID(nvmlVgpuInstance_t vgpuInstance, char *vmId, unsigned int size, nvmlVgpuVmIdType_t *vmIdType); + +/** + * Retrieve the UUID of a vGPU instance. + * + * The UUID is a globally unique identifier associated with the vGPU, and is returned as a 5-part hexadecimal string, + * not exceeding 80 characters in length (including the NULL terminator). + * See \ref nvmlConstants::NVML_DEVICE_UUID_BUFFER_SIZE. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param uuid Pointer to caller-supplied buffer to hold vGPU UUID + * @param size Size of buffer in bytes + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid, or \a uuid is NULL + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a size is too small + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetUUID(nvmlVgpuInstance_t vgpuInstance, char *uuid, unsigned int size); + +/** + * Retrieve the NVIDIA driver version installed in the VM associated with a vGPU. + * + * The version is returned as an alphanumeric string in the caller-supplied buffer \a version. The length of the version + * string will not exceed 80 characters in length (including the NUL terminator). + * See \ref nvmlConstants::NVML_SYSTEM_DRIVER_VERSION_BUFFER_SIZE. + * + * nvmlVgpuInstanceGetVmDriverVersion() may be called at any time for a vGPU instance. The guest VM driver version is + * returned as "Unknown" if no NVIDIA driver is installed in the VM, or the VM has not yet booted to the point where the + * NVIDIA driver is loaded and initialized. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param version Caller-supplied buffer to return driver version string + * @param length Size of \a version buffer + * + * @return + * - \ref NVML_SUCCESS if \a version has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a length is too small + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetVmDriverVersion(nvmlVgpuInstance_t vgpuInstance, char* version, unsigned int length); + +/** + * Retrieve the framebuffer usage in bytes. + * + * Framebuffer usage is the amont of vGPU framebuffer memory that is currently in use by the VM. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuInstance The identifier of the target instance + * @param fbUsage Pointer to framebuffer usage in bytes + * + * @return + * - \ref NVML_SUCCESS successful completion + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid, or \a fbUsage is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetFbUsage(nvmlVgpuInstance_t vgpuInstance, unsigned long long *fbUsage); + +/** + * Retrieve the current licensing state of the vGPU instance. + * + * If the vGPU is currently licensed, \a licensed is set to 1, otherwise it is set to 0. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param licensed Reference to return the licensing status + * + * @return + * - \ref NVML_SUCCESS if \a licensed has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid, or \a licensed is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetLicenseStatus(nvmlVgpuInstance_t vgpuInstance, unsigned int *licensed); + +/** + * Retrieve the vGPU type of a vGPU instance. + * + * Returns the vGPU type ID of vgpu assigned to the vGPU instance. + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param vgpuTypeId Reference to return the vgpuTypeId + * + * @return + * - \ref NVML_SUCCESS if \a vgpuTypeId has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid, or \a vgpuTypeId is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetType(nvmlVgpuInstance_t vgpuInstance, nvmlVgpuTypeId_t *vgpuTypeId); + +/** + * Retrieve the frame rate limit set for the vGPU instance. + * + * Returns the value of the frame rate limit set for the vGPU instance + * + * For Kepler &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param frameRateLimit Reference to return the frame rate limit + * + * @return + * - \ref NVML_SUCCESS if \a frameRateLimit has been set + * - \ref NVML_ERROR_NOT_SUPPORTED if frame rate limiter is turned off for the vGPU type + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid, or \a frameRateLimit is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetFrameRateLimit(nvmlVgpuInstance_t vgpuInstance, unsigned int *frameRateLimit); + +/** + * Retrieve the encoder Capacity of a vGPU instance, in macroblocks per second. + * + * For Maxwell &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param encoderCapacity Reference to an unsigned int for the encoder capacity + * + * @return + * - \ref NVML_SUCCESS if \a encoderCapacity has been retrived + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid, or \a encoderQueryType is invalid + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetEncoderCapacity(nvmlVgpuInstance_t vgpuInstance, unsigned int *encoderCapacity); + +/** + * Set the encoder Capacity of a vGPU instance, in macroblocks per second. + * + * For Maxwell &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param encoderCapacity Unsigned int for the encoder capacity value + * + * @return + * - \ref NVML_SUCCESS if \a encoderCapacity has been set + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is invalid + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceSetEncoderCapacity(nvmlVgpuInstance_t vgpuInstance, unsigned int encoderCapacity); + +/** + * Retrieves current utilization for vGPUs on a physical GPU (device). + * + * For Kepler &tm; or newer fully supported devices. + * + * Reads recent utilization of GPU SM (3D/Compute), framebuffer, video encoder, and video decoder for vGPU instances running + * on a device. Utilization values are returned as an array of utilization sample structures in the caller-supplied buffer + * pointed at by \a utilizationSamples. One utilization sample structure is returned per vGPU instance, and includes the + * CPU timestamp at which the samples were recorded. Individual utilization values are returned as "unsigned int" values + * in nvmlValue_t unions. The function sets the caller-supplied \a sampleValType to NVML_VALUE_TYPE_UNSIGNED_INT to + * indicate the returned value type. + * + * To read utilization values, first determine the size of buffer required to hold the samples by invoking the function with + * \a utilizationSamples set to NULL. The function will return NVML_ERROR_INSUFFICIENT_SIZE, with the current vGPU instance + * count in \a vgpuInstanceSamplesCount, or NVML_SUCCESS if the current vGPU instance count is zero. The caller should allocate + * a buffer of size vgpuInstanceSamplesCount * sizeof(nvmlVgpuInstanceUtilizationSample_t). Invoke the function again with + * the allocated buffer passed in \a utilizationSamples, and \a vgpuInstanceSamplesCount set to the number of entries the + * buffer is sized for. + * + * On successful return, the function updates \a vgpuInstanceSampleCount with the number of vGPU utilization sample + * structures that were actually written. This may differ from a previously read value as vGPU instances are created or + * destroyed. + * + * lastSeenTimeStamp represents the CPU timestamp in microseconds at which utilization samples were last read. Set it to 0 + * to read utilization based on all the samples maintained by the driver's internal sample buffer. Set lastSeenTimeStamp + * to a timeStamp retrieved from a previous query to read utilization since the previous query. + * + * @param device The identifier for the target device + * @param lastSeenTimeStamp Return only samples with timestamp greater than lastSeenTimeStamp. + * @param sampleValType Pointer to caller-supplied buffer to hold the type of returned sample values + * @param vgpuInstanceSamplesCount Pointer to caller-supplied array size, and returns number of vGPU instances + * @param utilizationSamples Pointer to caller-supplied buffer in which vGPU utilization samples are returned + + * @return + * - \ref NVML_SUCCESS if utilization samples are successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a vgpuInstanceSamplesCount or \a sampleValType is + * NULL, or a sample count of 0 is passed with a non-NULL \a utilizationSamples + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if supplied \a vgpuInstanceSamplesCount is too small to return samples for all + * vGPU instances currently executing on the device + * - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_NOT_FOUND if sample entries are not found + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetVgpuUtilization(nvmlDevice_t device, unsigned long long lastSeenTimeStamp, + nvmlValueType_t *sampleValType, unsigned int *vgpuInstanceSamplesCount, + nvmlVgpuInstanceUtilizationSample_t *utilizationSamples); + +/** + * Retrieves current utilization for processes running on vGPUs on a physical GPU (device). + * + * For Maxwell &tm; or newer fully supported devices. + * + * Reads recent utilization of GPU SM (3D/Compute), framebuffer, video encoder, and video decoder for processes running on + * vGPU instances active on a device. Utilization values are returned as an array of utilization sample structures in the + * caller-supplied buffer pointed at by \a utilizationSamples. One utilization sample structure is returned per process running + * on vGPU instances, that had some non-zero utilization during the last sample period. It includes the CPU timestamp at which + * the samples were recorded. Individual utilization values are returned as "unsigned int" values. + * + * To read utilization values, first determine the size of buffer required to hold the samples by invoking the function with + * \a utilizationSamples set to NULL. The function will return NVML_ERROR_INSUFFICIENT_SIZE, with the current vGPU instance + * count in \a vgpuProcessSamplesCount. The caller should allocate a buffer of size + * vgpuProcessSamplesCount * sizeof(nvmlVgpuProcessUtilizationSample_t). Invoke the function again with + * the allocated buffer passed in \a utilizationSamples, and \a vgpuProcessSamplesCount set to the number of entries the + * buffer is sized for. + * + * On successful return, the function updates \a vgpuSubProcessSampleCount with the number of vGPU sub process utilization sample + * structures that were actually written. This may differ from a previously read value depending on the number of processes that are active + * in any given sample period. + * + * lastSeenTimeStamp represents the CPU timestamp in microseconds at which utilization samples were last read. Set it to 0 + * to read utilization based on all the samples maintained by the driver's internal sample buffer. Set lastSeenTimeStamp + * to a timeStamp retrieved from a previous query to read utilization since the previous query. + * + * @param device The identifier for the target device + * @param lastSeenTimeStamp Return only samples with timestamp greater than lastSeenTimeStamp. + * @param vgpuProcessSamplesCount Pointer to caller-supplied array size, and returns number of processes running on vGPU instances + * @param utilizationSamples Pointer to caller-supplied buffer in which vGPU sub process utilization samples are returned + + * @return + * - \ref NVML_SUCCESS if utilization samples are successfully retrieved + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a vgpuProcessSamplesCount or a sample count of 0 is + * passed with a non-NULL \a utilizationSamples + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if supplied \a vgpuProcessSamplesCount is too small to return samples for all + * vGPU instances currently executing on the device + * - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the device + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_NOT_FOUND if sample entries are not found + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetVgpuProcessUtilization(nvmlDevice_t device, unsigned long long lastSeenTimeStamp, + unsigned int *vgpuProcessSamplesCount, + nvmlVgpuProcessUtilizationSample_t *utilizationSamples); +/** + * Retrieve the GRID licensable features. + * + * Identifies whether the system supports GRID Software Licensing. If it does, return the list of licensable feature(s) + * and their current license status. + * + * @param device Identifier of the target device + * @param pGridLicensableFeatures Pointer to structure in which GRID licensable features are returned + * + * @return + * - \ref NVML_SUCCESS if licensable features are successfully retrieved + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a pGridLicensableFeatures is NULL + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetGridLicensableFeatures(nvmlDevice_t device, nvmlGridLicensableFeatures_t *pGridLicensableFeatures); + +/** + * Retrieves the current encoder statistics of a vGPU Instance + * + * For Maxwell &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param sessionCount Reference to an unsigned int for count of active encoder sessions + * @param averageFps Reference to an unsigned int for trailing average FPS of all active sessions + * @param averageLatency Reference to an unsigned int for encode latency in microseconds + * + * @return + * - \ref NVML_SUCCESS if \a sessionCount, \a averageFps and \a averageLatency is fetched + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a sessionCount , or \a averageFps or \a averageLatency is NULL + * or \a vgpuInstance is invalid. + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetEncoderStats(nvmlVgpuInstance_t vgpuInstance, unsigned int *sessionCount, + unsigned int *averageFps, unsigned int *averageLatency); + +/** + * Retrieves information about all active encoder sessions on a vGPU Instance. + * + * An array of active encoder sessions is returned in the caller-supplied buffer pointed at by \a sessionInfo. The + * array elememt count is passed in \a sessionCount, and \a sessionCount is used to return the number of sessions + * written to the buffer. + * + * If the supplied buffer is not large enough to accomodate the active session array, the function returns + * NVML_ERROR_INSUFFICIENT_SIZE, with the element count of nvmlEncoderSessionInfo_t array required in \a sessionCount. + * To query the number of active encoder sessions, call this function with *sessionCount = 0. The code will return + * NVML_SUCCESS with number of active encoder sessions updated in *sessionCount. + * + * For Maxwell &tm; or newer fully supported devices. + * + * @param vgpuInstance Identifier of the target vGPU instance + * @param sessionCount Reference to caller supplied array size, and returns + * the number of sessions. + * @param sessionInfo Reference to caller supplied array in which the list + * of session information us returned. + * + * @return + * - \ref NVML_SUCCESS if \a sessionInfo is fetched + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INSUFFICIENT_SIZE if \a sessionCount is too small, array element count is + returned in \a sessionCount + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a sessionCount is NULL or \a vgpuInstance is invalid.. + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlVgpuInstanceGetEncoderSessions(nvmlVgpuInstance_t vgpuInstance, unsigned int *sessionCount, nvmlEncoderSessionInfo_t *sessionInfo); + +/** + * Retrieves the current utilization and process ID + * + * For Maxwell &tm; or newer fully supported devices. + * + * Reads recent utilization of GPU SM (3D/Compute), framebuffer, video encoder, and video decoder for processes running. + * Utilization values are returned as an array of utilization sample structures in the caller-supplied buffer pointed at + * by \a utilization. One utilization sample structure is returned per process running, that had some non-zero utilization + * during the last sample period. It includes the CPU timestamp at which the samples were recorded. Individual utilization values + * are returned as "unsigned int" values. + * + * To read utilization values, first determine the size of buffer required to hold the samples by invoking the function with + * \a utilization set to NULL. The caller should allocate a buffer of size + * processSamplesCount * sizeof(nvmlProcessUtilizationSample_t). Invoke the function again with the allocated buffer passed + * in \a utilization, and \a processSamplesCount set to the number of entries the buffer is sized for. + * + * On successful return, the function updates \a processSamplesCount with the number of process utilization sample + * structures that were actually written. This may differ from a previously read value as instances are created or + * destroyed. + * + * lastSeenTimeStamp represents the CPU timestamp in microseconds at which utilization samples were last read. Set it to 0 + * to read utilization based on all the samples maintained by the driver's internal sample buffer. Set lastSeenTimeStamp + * to a timeStamp retrieved from a previous query to read utilization since the previous query. + * + * @param device The identifier of the target device + * @param utilization Pointer to caller-supplied buffer in which guest process utilization samples are returned + * @param processSamplesCount Pointer to caller-supplied array size, and returns number of processes running + * @param lastSeenTimeStamp Return only samples with timestamp greater than lastSeenTimeStamp. + + * @return + * - \ref NVML_SUCCESS if \a utilization has been populated + * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized + * - \ref NVML_ERROR_INVALID_ARGUMENT if \a device is invalid, \a utilization is NULL, or \a samplingPeriodUs is NULL + * - \ref NVML_ERROR_NOT_SUPPORTED if the device does not support this feature + * - \ref NVML_ERROR_GPU_IS_LOST if the target GPU has fallen off the bus or is otherwise inaccessible + * - \ref NVML_ERROR_UNKNOWN on any unexpected error + */ +nvmlReturn_t DECLDIR nvmlDeviceGetProcessUtilization(nvmlDevice_t device, nvmlProcessUtilizationSample_t *utilization, + unsigned int *processSamplesCount, unsigned long long lastSeenTimeStamp); + +/** @} */ + +/** + * NVML API versioning support + */ +#if defined(__NVML_API_VERSION_INTERNAL) +#undef nvmlDeviceGetNvLinkRemotePciInfo +#undef nvmlDeviceGetPciInfo +#undef nvmlDeviceGetCount +#undef nvmlDeviceGetHandleByIndex +#undef nvmlDeviceGetHandleByPciBusId +#undef nvmlInit +#endif + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/polymer/README.chromium b/third_party/polymer/README.chromium index 47d91396..e038fc8 100644 --- a/third_party/polymer/README.chromium +++ b/third_party/polymer/README.chromium
@@ -44,6 +44,9 @@ handler code which was hiding ripples for pointer interactions. - Bundled and minified Polymer 2 with minify_polymer.py, since Polymer 2 repo does not distribute minified files (unlike Polymer 1). +- For iron-list, call event.preventDefault() when up/down arrow is pressed and + the focused item changes. This is to prevent outer vertical scroll from + scrolling when the iron-list vertical scroll has reached the top or bottom. To restore a content of the 'components-chromium' directory from scratch, run ./v1_0/reproduce.sh on a Linux machine.
diff --git a/third_party/polymer/v1_0/chromium.patch b/third_party/polymer/v1_0/chromium.patch index f7ae112..edc9030 100644 --- a/third_party/polymer/v1_0/chromium.patch +++ b/third_party/polymer/v1_0/chromium.patch
@@ -180,3 +180,29 @@ }); /** +diff --git a/components-chromium/iron-list/iron-list-extracted.js b/components-chromium/iron-list/iron-list-extracted.js +index 4fdfbdead5ae..dbfbc9ca3907 100644 +--- a/components-chromium/iron-list/iron-list-extracted.js ++++ b/components-chromium/iron-list/iron-list-extracted.js +@@ -1611,13 +1611,20 @@ + _keydownHandler: function(e) { + switch (e.keyCode) { + case /* ARROW_DOWN */ 40: +- e.preventDefault(); ++ // TODO (aee): remove when iron-list issue is fixed. ++ // https://github.com/PolymerElements/iron-list/issues/542 ++ if (this._focusedVirtualIndex < this._virtualCount - 1) ++ e.preventDefault(); + this._focusPhysicalItem(this._focusedVirtualIndex + (this.grid ? this._itemsPerRow : 1)); + break; + case /* ARROW_RIGHT */ 39: + if (this.grid) this._focusPhysicalItem(this._focusedVirtualIndex + (this._isRTL ? -1 : 1)); + break; + case /* ARROW_UP */ 38: ++ // TODO (aee): remove when iron-list issue is fixed. ++ // https://github.com/PolymerElements/iron-list/issues/542 ++ if (this._focusedVirtualIndex > 0) ++ e.preventDefault(); + this._focusPhysicalItem(this._focusedVirtualIndex - (this.grid ? this._itemsPerRow : 1)); + break; + case /* ARROW_LEFT */ 37:
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js index 4fdfbdead5..dbfbc9c 100644 --- a/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js
@@ -1611,13 +1611,20 @@ _keydownHandler: function(e) { switch (e.keyCode) { case /* ARROW_DOWN */ 40: - e.preventDefault(); + // TODO (aee): remove when iron-list issue is fixed. + // https://github.com/PolymerElements/iron-list/issues/542 + if (this._focusedVirtualIndex < this._virtualCount - 1) + e.preventDefault(); this._focusPhysicalItem(this._focusedVirtualIndex + (this.grid ? this._itemsPerRow : 1)); break; case /* ARROW_RIGHT */ 39: if (this.grid) this._focusPhysicalItem(this._focusedVirtualIndex + (this._isRTL ? -1 : 1)); break; case /* ARROW_UP */ 38: + // TODO (aee): remove when iron-list issue is fixed. + // https://github.com/PolymerElements/iron-list/issues/542 + if (this._focusedVirtualIndex > 0) + e.preventDefault(); this._focusPhysicalItem(this._focusedVirtualIndex - (this.grid ? this._itemsPerRow : 1)); break; case /* ARROW_LEFT */ 37:
diff --git a/third_party/pywebsocket/BUILD.gn b/third_party/pywebsocket/BUILD.gn index 3f2bf45..c39e56e2 100644 --- a/third_party/pywebsocket/BUILD.gn +++ b/third_party/pywebsocket/BUILD.gn
@@ -5,8 +5,8 @@ # pwebsocket is a Python program. Depend on this to get the data deps necessary # to run it in the test environment. group("pywebsocket") { - # For now, depend on the entire directory. + # For now, depend on the mod_pywebsocket directory. data = [ - "//third_party/pywebsocket/", + "//third_party/pywebsocket/src/mod_pywebsocket/", ] }
diff --git a/third_party/pywebsocket/README.chromium b/third_party/pywebsocket/README.chromium index 8f7963c..88c4b0aa 100644 --- a/third_party/pywebsocket/README.chromium +++ b/third_party/pywebsocket/README.chromium
@@ -3,7 +3,7 @@ URL: https://github.com/google/pywebsocket/ Version: 0 License: New BSD -License File: NOT_SHIPPED +License File: LICENSE Security Critical: no Description:
diff --git a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h index fd17c6e9..03fb7d5 100644 --- a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h +++ b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-client-protocol.h
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.13.0 */ +/* Generated by wayland-scanner 1.14.0 */ #ifndef REMOTE_SHELL_UNSTABLE_V1_CLIENT_PROTOCOL_H #define REMOTE_SHELL_UNSTABLE_V1_CLIENT_PROTOCOL_H @@ -843,8 +843,8 @@ */ void (*bounds_changed)(void *data, struct zcr_remote_surface_v1 *zcr_remote_surface_v1, - uint32_t workspace_id_hi, - uint32_t workspace_id_lo, + uint32_t display_id_hi, + uint32_t display_id_lo, int32_t x, int32_t y, int32_t width, @@ -934,6 +934,7 @@ #define ZCR_REMOTE_SURFACE_V1_SET_EXTRA_TITLE 38 #define ZCR_REMOTE_SURFACE_V1_SET_ORIENTATION_LOCK 39 #define ZCR_REMOTE_SURFACE_V1_PIP 40 +#define ZCR_REMOTE_SURFACE_V1_SET_BOUNDS 41 /** * @ingroup iface_zcr_remote_surface_v1 @@ -1128,6 +1129,10 @@ * @ingroup iface_zcr_remote_surface_v1 */ #define ZCR_REMOTE_SURFACE_V1_PIP_SINCE_VERSION 15 +/** + * @ingroup iface_zcr_remote_surface_v1 + */ +#define ZCR_REMOTE_SURFACE_V1_SET_BOUNDS_SINCE_VERSION 18 /** @ingroup iface_zcr_remote_surface_v1 */ static inline void @@ -1179,9 +1184,9 @@ /** * @ingroup iface_zcr_remote_surface_v1 * - * The window geometry of a window is its "visible bounds" from the - * user's perspective. Client-side decorations often have invisible - * portions like drop-shadows which should be ignored for the + * [Deprecated] The window geometry of a window is its "visible bounds" + * from the user's perspective. Client-side decorations often have + * invisible portions like drop-shadows which should be ignored for the * purposes of aligning, placing and constraining windows. * * The window geometry is double buffered, and will be applied at the @@ -1537,7 +1542,7 @@ /** * @ingroup iface_zcr_remote_surface_v1 * - * Start an interactive, user-driven move of the surface. + * [Deprecated] Start an interactive, user-driven move of the surface. * * The compositor responds to this request with a configure event that * transitions to the "moving" state. The client must only initiate motion @@ -1815,6 +1820,36 @@ ZCR_REMOTE_SURFACE_V1_PIP); } +/** + * @ingroup iface_zcr_remote_surface_v1 + * + * Set the "visible bounds" of a window from the user's perspective. + * Client-side decorations often have invisible portions like drop shadows + * which should be ignored for the purposes of aligning, placing and + * constraining windows. + * + * The bounds are double buffered, and will be applied at the + * time wl_surface.commit of the corresponding wl_surface is called. + * + * Once the bounds are set, it is not possible to unset them, and they will + * remain the same until set_bounds is called again, even if a new sub- + * surface or buffer is attached. + * + * If never set, the value is the surface content bounds. This updates + * dynamically on every commit. + * + * The bounds are relative to the given display. If the display is invalid, + * they are assumed to be relative to the primary display. + * + * The width and height must be greater than zero. + */ +static inline void +zcr_remote_surface_v1_set_bounds(struct zcr_remote_surface_v1 *zcr_remote_surface_v1, uint32_t display_id_hi, uint32_t display_id_lo, int32_t x, int32_t y, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) zcr_remote_surface_v1, + ZCR_REMOTE_SURFACE_V1_SET_BOUNDS, display_id_hi, display_id_lo, x, y, width, height); +} + #define ZCR_NOTIFICATION_SURFACE_V1_DESTROY 0 #define ZCR_NOTIFICATION_SURFACE_V1_SET_APP_ID 1
diff --git a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h index 555b6a34a..5be556df 100644 --- a/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h +++ b/third_party/wayland-protocols/include/protocol/remote-shell-unstable-v1-server-protocol.h
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.13.0 */ +/* Generated by wayland-scanner 1.14.0 */ #ifndef REMOTE_SHELL_UNSTABLE_V1_SERVER_PROTOCOL_H #define REMOTE_SHELL_UNSTABLE_V1_SERVER_PROTOCOL_H @@ -708,10 +708,11 @@ /** * set the new window geometry * - * The window geometry of a window is its "visible bounds" from - * the user's perspective. Client-side decorations often have - * invisible portions like drop-shadows which should be ignored for - * the purposes of aligning, placing and constraining windows. + * [Deprecated] The window geometry of a window is its "visible + * bounds" from the user's perspective. Client-side decorations + * often have invisible portions like drop-shadows which should be + * ignored for the purposes of aligning, placing and constraining + * windows. * * The window geometry is double buffered, and will be applied at * the time wl_surface.commit of the corresponding wl_surface is @@ -997,7 +998,8 @@ /** * start an interactive move * - * Start an interactive, user-driven move of the surface. + * [Deprecated] Start an interactive, user-driven move of the + * surface. * * The compositor responds to this request with a configure event * that transitions to the "moving" state. The client must only @@ -1231,6 +1233,38 @@ */ void (*pip)(struct wl_client *client, struct wl_resource *resource); + /** + * set window bounds + * + * Set the "visible bounds" of a window from the user's + * perspective. Client-side decorations often have invisible + * portions like drop shadows which should be ignored for the + * purposes of aligning, placing and constraining windows. + * + * The bounds are double buffered, and will be applied at the time + * wl_surface.commit of the corresponding wl_surface is called. + * + * Once the bounds are set, it is not possible to unset them, and + * they will remain the same until set_bounds is called again, even + * if a new sub- surface or buffer is attached. + * + * If never set, the value is the surface content bounds. This + * updates dynamically on every commit. + * + * The bounds are relative to the given display. If the display is + * invalid, they are assumed to be relative to the primary display. + * + * The width and height must be greater than zero. + * @since 18 + */ + void (*set_bounds)(struct wl_client *client, + struct wl_resource *resource, + uint32_t display_id_hi, + uint32_t display_id_lo, + int32_t x, + int32_t y, + int32_t width, + int32_t height); }; #define ZCR_REMOTE_SURFACE_V1_CLOSE 0 @@ -1434,6 +1468,10 @@ * @ingroup iface_zcr_remote_surface_v1 */ #define ZCR_REMOTE_SURFACE_V1_PIP_SINCE_VERSION 15 +/** + * @ingroup iface_zcr_remote_surface_v1 + */ +#define ZCR_REMOTE_SURFACE_V1_SET_BOUNDS_SINCE_VERSION 18 /** * @ingroup iface_zcr_remote_surface_v1 @@ -1485,9 +1523,9 @@ * @param resource_ The client's resource */ static inline void -zcr_remote_surface_v1_send_bounds_changed(struct wl_resource *resource_, uint32_t workspace_id_hi, uint32_t workspace_id_lo, int32_t x, int32_t y, int32_t width, int32_t height, uint32_t bounds_change_reason) +zcr_remote_surface_v1_send_bounds_changed(struct wl_resource *resource_, uint32_t display_id_hi, uint32_t display_id_lo, int32_t x, int32_t y, int32_t width, int32_t height, uint32_t bounds_change_reason) { - wl_resource_post_event(resource_, ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGED, workspace_id_hi, workspace_id_lo, x, y, width, height, bounds_change_reason); + wl_resource_post_event(resource_, ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGED, display_id_hi, display_id_lo, x, y, width, height, bounds_change_reason); } /**
diff --git a/third_party/wayland-protocols/protocol/remote-shell-protocol.c b/third_party/wayland-protocols/protocol/remote-shell-protocol.c index c0d09551..cbb688a 100644 --- a/third_party/wayland-protocols/protocol/remote-shell-protocol.c +++ b/third_party/wayland-protocols/protocol/remote-shell-protocol.c
@@ -1,4 +1,4 @@ -/* Generated by wayland-scanner 1.13.0 */ +/* Generated by wayland-scanner 1.14.0 */ /* * Copyright 2016 The Chromium Authors. @@ -74,7 +74,7 @@ }; WL_EXPORT const struct wl_interface zcr_remote_shell_v1_interface = { - "zcr_remote_shell_v1", 17, + "zcr_remote_shell_v1", 18, 4, zcr_remote_shell_v1_requests, 5, zcr_remote_shell_v1_events, }; @@ -121,6 +121,7 @@ { "set_extra_title", "13s", types + 0 }, { "set_orientation_lock", "14u", types + 0 }, { "pip", "15", types + 0 }, + { "set_bounds", "18uuiiii", types + 0 }, }; static const struct wl_message zcr_remote_surface_v1_events[] = { @@ -134,8 +135,8 @@ }; WL_EXPORT const struct wl_interface zcr_remote_surface_v1_interface = { - "zcr_remote_surface_v1", 15, - 41, zcr_remote_surface_v1_requests, + "zcr_remote_surface_v1", 18, + 42, zcr_remote_surface_v1_requests, 7, zcr_remote_surface_v1_events, };
diff --git a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml index ef9402df..be08b34 100644 --- a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml +++ b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml
@@ -38,7 +38,7 @@ reset. </description> - <interface name="zcr_remote_shell_v1" version="17"> + <interface name="zcr_remote_shell_v1" version="18"> <description summary="remote_shell"> The global interface that allows clients to turn a wl_surface into a "real window" which is remotely managed but can be stacked, activated @@ -195,7 +195,7 @@ </request> </interface> - <interface name="zcr_remote_surface_v1" version="15"> + <interface name="zcr_remote_surface_v1" version="18"> <description summary="A desktop window"> An interface that may be implemented by a wl_surface, for implementations that provide a desktop-style user interface @@ -252,9 +252,9 @@ <request name="set_window_geometry"> <description summary="set the new window geometry"> - The window geometry of a window is its "visible bounds" from the - user's perspective. Client-side decorations often have invisible - portions like drop-shadows which should be ignored for the + [Deprecated] The window geometry of a window is its "visible bounds" + from the user's perspective. Client-side decorations often have + invisible portions like drop-shadows which should be ignored for the purposes of aligning, placing and constraining windows. The window geometry is double buffered, and will be applied at the @@ -671,8 +671,8 @@ The client may ignore move request depending on the state, e.g, if it becomes resizable or other constrants. </description> - <arg name="workspace_id_hi" type="uint"/> - <arg name="workspace_id_lo" type="uint"/> + <arg name="display_id_hi" type="uint"/> + <arg name="display_id_lo" type="uint"/> <arg name="x" type="int"/> <arg name="y" type="int"/> <arg name="width" type="int"/> @@ -903,6 +903,38 @@ </description> </request> + <!-- Version 18 additions --> + + <request name="set_bounds" since="18"> + <description summary="set window bounds"> + Set the "visible bounds" of a window from the user's perspective. + Client-side decorations often have invisible portions like drop shadows + which should be ignored for the purposes of aligning, placing and + constraining windows. + + The bounds are double buffered, and will be applied at the + time wl_surface.commit of the corresponding wl_surface is called. + + Once the bounds are set, it is not possible to unset them, and they will + remain the same until set_bounds is called again, even if a new sub- + surface or buffer is attached. + + If never set, the value is the surface content bounds. This updates + dynamically on every commit. + + The bounds are relative to the given display. If the display is invalid, + they are assumed to be relative to the primary display. + + The width and height must be greater than zero. + </description> + <arg name="display_id_hi" type="uint"/> + <arg name="display_id_lo" type="uint"/> + <arg name="x" type="int"/> + <arg name="y" type="int"/> + <arg name="width" type="int"/> + <arg name="height" type="int"/> + </request> + </interface> <interface name="zcr_notification_surface_v1" version="16">
diff --git a/tools/android/audio_focus_grabber/OWNERS b/tools/android/audio_focus_grabber/OWNERS index 5ad525b..a45c7a3 100644 --- a/tools/android/audio_focus_grabber/OWNERS +++ b/tools/android/audio_focus_grabber/OWNERS
@@ -1 +1,2 @@ +mlamouri@chromium.org zqzhang@chromium.org
diff --git a/tools/battor_agent/BUILD.gn b/tools/battor_agent/BUILD.gn deleted file mode 100644 index f1f9f17..0000000 --- a/tools/battor_agent/BUILD.gn +++ /dev/null
@@ -1,63 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//testing/test.gni") - -# Works only on desktop platforms. -assert(is_win || is_linux || is_mac) - -executable("battor_agent") { - sources = [ - "battor_agent_bin.cc", - ] - deps = [ - ":battor_agent_lib", - "//base", - "//build/win:default_exe_manifest", - ] -} - -source_set("battor_agent_lib") { - sources = [ - "battor_agent.cc", - "battor_agent.h", - "battor_connection.cc", - "battor_connection.h", - "battor_connection_impl.cc", - "battor_connection_impl.h", - "battor_error.cc", - "battor_error.h", - "battor_finder.cc", - "battor_finder.h", - "battor_sample_converter.cc", - "battor_sample_converter.h", - "serial_utils.cc", - "serial_utils.h", - ] - deps = [ - "//base", - "//device/serial", - "//mojo/public/cpp/bindings", - "//net", - ] -} - -test("battor_agent_unittests") { - sources = [ - "battor_agent_unittest.cc", - "battor_connection_impl_unittest.cc", - "battor_protocol_types_unittest.cc", - "battor_sample_converter_unittest.cc", - "serial_utils_unittest.cc", - ] - deps = [ - ":battor_agent_lib", - "//base", - "//base/test:run_all_unittests", - "//base/test:test_support", - "//device/serial:test_support", - "//testing/gmock", - "//testing/gtest", - ] -}
diff --git a/tools/battor_agent/DEPS b/tools/battor_agent/DEPS deleted file mode 100644 index 9866dab..0000000 --- a/tools/battor_agent/DEPS +++ /dev/null
@@ -1,6 +0,0 @@ -include_rules = [ - "+device/serial", - "+mojo/public", - "+net/base", - "+services/device/public/mojom", -]
diff --git a/tools/battor_agent/OWNERS b/tools/battor_agent/OWNERS deleted file mode 100644 index a90dd82..0000000 --- a/tools/battor_agent/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -charliea@chromium.org -nednguyen@google.com -zhenw@chromium.org
diff --git a/tools/battor_agent/README b/tools/battor_agent/README deleted file mode 100644 index 3c0c2df..0000000 --- a/tools/battor_agent/README +++ /dev/null
@@ -1,25 +0,0 @@ -BattOr Agent -============ - -The BattOr Agent is a C++ library that acts as a means of -communicating with a BattOr. BattOrs is an external USB device, -typically connected to the host, that's capable of recording -accurate, high-frequency (2000Hz) power samples. - -The BattOr Agent accepts five high-level tracing commands: - -- **StartTracing**, which tells the BattOr to start collecting power -samples. -- **StopTracing**, which tells the BattOr to stop collecting power -samples and return its trace log. -- **SupportsExplicitClockSync**, which returns whether the BattOr is -able to record clock sync markers in its own trace log. -- **RecordClockSyncMarker**, which writes the specified string into the -BattOr trace log. Because this string is accompanied by a BattOr tracing -timestamp, we can use this as a way of correlating the BattOr timeline -and the host computer's timeline. -- **IssueClockSyncMarker**, which tells the BattOr to issue clock sync -markers to all other tracing agents that it's connected to. - -For those calling the agent from non-C++ code, we also provide a thin -binary wrapper around the C++ library.
diff --git a/tools/battor_agent/battor_agent.cc b/tools/battor_agent/battor_agent.cc deleted file mode 100644 index abc54c2..0000000 --- a/tools/battor_agent/battor_agent.cc +++ /dev/null
@@ -1,768 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#include "tools/battor_agent/battor_agent.h" - -#include <algorithm> -#include <iomanip> -#include <vector> - -#include "base/bind.h" -#include "base/strings/stringprintf.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "tools/battor_agent/battor_connection_impl.h" -#include "tools/battor_agent/battor_sample_converter.h" - -using base::StringPrintf; -using std::vector; - -namespace battor { - -namespace { - -// The maximum number of times to retry a command. -const uint8_t kMaxCommandAttempts = 10; - -// The maximum number of times to retry a sample frame. -const uint8_t kMaxFrameAttempts = 10; - -// The amount of time we need to wait after recording a clock sync marker in -// order to ensure that the sample we synced to doesn't get thrown out. -const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; - -// The number of seconds to wait before retrying a command. -const uint16_t kCommandRetryDelaySeconds = 2; - -// The number of milliseconds to wait before retrying a sample frame. -const uint16_t kFrameRetryDelayMilliseconds = 100; - -// The number of seconds allowed for a control message before timing out. -const uint8_t kBattOrControlMessageTimeoutSeconds = 2; - -// Returns true if the specified vector of bytes decodes to a message that is an -// ack for the specified control message type. -bool IsAckOfControlCommand(BattOrMessageType message_type, - BattOrControlMessageType control_message_type, - const vector<char>& msg) { - if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) - return false; - - if (msg.size() != sizeof(BattOrControlMessageAck)) - return false; - - const BattOrControlMessageAck* ack = - reinterpret_cast<const BattOrControlMessageAck*>(msg.data()); - - if (ack->type != control_message_type) - return false; - - return true; -} - -// Attempts to decode the specified vector of bytes decodes to a valid EEPROM. -// Returns the new EEPROM, or nullptr if unsuccessful. -std::unique_ptr<BattOrEEPROM> ParseEEPROM(BattOrMessageType message_type, - const vector<char>& msg) { - if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) - return nullptr; - - if (msg.size() != sizeof(BattOrEEPROM)) - return nullptr; - - std::unique_ptr<BattOrEEPROM> eeprom(new BattOrEEPROM()); - memcpy(eeprom.get(), msg.data(), sizeof(BattOrEEPROM)); - return eeprom; -} -} // namespace - -BattOrResults::BattOrResults() = default; - -BattOrResults::BattOrResults(std::string details, - std::vector<float> power_samples_W, - uint32_t sample_rate) - : details_(std::move(details)), - power_samples_W_(std::move(power_samples_W)), - sample_rate_(sample_rate) {} - -BattOrResults::BattOrResults(const BattOrResults&) = default; - -BattOrResults::~BattOrResults() = default; - -BattOrAgent::BattOrAgent( - const std::string& path, - Listener* listener, - scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) - : connection_(new BattOrConnectionImpl(path, this, ui_thread_task_runner)), - tick_clock_(base::DefaultTickClock::GetInstance()), - listener_(listener), - last_action_(Action::INVALID), - command_(Command::INVALID), - next_sequence_number_(0), - num_command_attempts_(0), - num_frame_attempts_(0) { - // We don't care what sequence the constructor is called on - we only care - // that all of the other method invocations happen on the same sequence. - DETACH_FROM_SEQUENCE(sequence_checker_); -} - -BattOrAgent::~BattOrAgent() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -void BattOrAgent::StartTracing() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - connection_->LogSerial("Starting command StartTracing."); - - // When tracing is restarted, all previous clock sync markers are invalid. - clock_sync_markers_.clear(); - last_clock_sync_time_ = base::TimeTicks(); - - command_ = Command::START_TRACING; - - if (connection_->IsOpen()) { - PerformAction(GetFirstAction(Command::START_TRACING)); - } else { - PerformAction(Action::REQUEST_CONNECTION); - } -} - -void BattOrAgent::StopTracing() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - connection_->LogSerial("Starting command StopTracing."); - - command_ = Command::STOP_TRACING; - - if (connection_->IsOpen()) { - PerformAction(GetFirstAction(Command::STOP_TRACING)); - } else { - PerformAction(Action::REQUEST_CONNECTION); - } -} - -void BattOrAgent::RecordClockSyncMarker(const std::string& marker) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - connection_->LogSerial("Starting command RecordClockSyncMarker."); - - command_ = Command::RECORD_CLOCK_SYNC_MARKER; - pending_clock_sync_marker_ = marker; - - if (connection_->IsOpen()) { - PerformAction(GetFirstAction(Command::RECORD_CLOCK_SYNC_MARKER)); - } else { - PerformAction(Action::REQUEST_CONNECTION); - } -} - -void BattOrAgent::GetFirmwareGitHash() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - connection_->LogSerial("Starting command GetFirmwareGitHash."); - - command_ = Command::GET_FIRMWARE_GIT_HASH; - - if (connection_->IsOpen()) { - PerformAction(GetFirstAction(Command::GET_FIRMWARE_GIT_HASH)); - } else { - PerformAction(Action::REQUEST_CONNECTION); - } -} - -void BattOrAgent::BeginConnect() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - connection_->Open(); -} - -void BattOrAgent::OnConnectionOpened(bool success) { - if (!success) { - CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); - return; - } - - PerformAction(Action::POST_CONNECT_FLUSH); -} - -void BattOrAgent::OnConnectionFlushed(bool success) { - if (!success) { - CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); - return; - } - - if (last_action_ == Action::POST_CONNECT_FLUSH) { - PerformAction(GetFirstAction(command_)); - } else if (last_action_ == Action::POST_READ_ERROR_FLUSH) { - base::TimeDelta request_samples_delay = - base::TimeDelta::FromMilliseconds(kFrameRetryDelayMilliseconds); - PerformDelayedAction(Action::SEND_SAMPLES_REQUEST, request_samples_delay); - } else { - NOTREACHED(); - } -} - -void BattOrAgent::OnBytesSent(bool success) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!success) { - CompleteCommand(BATTOR_ERROR_SEND_ERROR); - return; - } - - switch (last_action_) { - case Action::SEND_INIT: - PerformAction(Action::READ_INIT_ACK); - return; - case Action::SEND_SET_GAIN: - PerformAction(Action::READ_SET_GAIN_ACK); - return; - case Action::SEND_START_TRACING: - PerformAction(Action::READ_START_TRACING_ACK); - return; - case Action::SEND_EEPROM_REQUEST: - PerformAction(Action::READ_EEPROM); - return; - case Action::SEND_SAMPLES_REQUEST: - if (next_sequence_number_ == 0) - PerformAction(Action::READ_CALIBRATION_FRAME); - else - PerformAction(Action::READ_DATA_FRAME); - return; - case Action::SEND_CURRENT_SAMPLE_REQUEST: - PerformAction(Action::READ_CURRENT_SAMPLE); - return; - case Action::SEND_GIT_HASH_REQUEST: - PerformAction(Action::READ_GIT_HASH); - return; - default: - NOTREACHED(); - return; - } -} - -void BattOrAgent::OnMessageRead(bool success, - BattOrMessageType type, - std::unique_ptr<vector<char>> bytes) { - timeout_callback_.Cancel(); - - if (!success) { - switch (last_action_) { - case Action::READ_GIT_HASH: - case Action::READ_INIT_ACK: - case Action::READ_SET_GAIN_ACK: - case Action::READ_START_TRACING_ACK: - case Action::READ_EEPROM: - RetryCommand(); - return; - - case Action::READ_CALIBRATION_FRAME: - case Action::READ_DATA_FRAME: - RetryFrame(); - return; - - case Action::READ_CURRENT_SAMPLE: - CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); - return; - - default: - NOTREACHED(); - return; - } - } - - switch (last_action_) { - case Action::READ_INIT_ACK: - if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, - *bytes)) { - RetryCommand(); - return; - } - - switch (command_) { - case Command::START_TRACING: - PerformAction(Action::SEND_SET_GAIN); - return; - default: - NOTREACHED(); - return; - } - - case Action::READ_SET_GAIN_ACK: - if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, - *bytes)) { - RetryCommand(); - return; - } - - PerformAction(Action::SEND_START_TRACING); - return; - - case Action::READ_START_TRACING_ACK: - if (!IsAckOfControlCommand( - type, BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, *bytes)) { - RetryCommand(); - return; - } - - CompleteCommand(BATTOR_ERROR_NONE); - return; - - case Action::READ_EEPROM: { - battor_eeprom_ = ParseEEPROM(type, *bytes); - if (!battor_eeprom_) { - RetryCommand(); - return; - } - - // Make sure that we don't request samples until a safe amount of time has - // elapsed since recording the last clock sync marker: we need to ensure - // that the sample we synced to doesn't get thrown out. - base::TimeTicks min_request_samples_time = - last_clock_sync_time_ + base::TimeDelta::FromMilliseconds( - kStopTracingClockSyncDelayMilliseconds); - base::TimeDelta request_samples_delay = - std::max(min_request_samples_time - tick_clock_->NowTicks(), - base::TimeDelta()); - - num_frame_attempts_ = 1; - PerformDelayedAction(Action::SEND_SAMPLES_REQUEST, request_samples_delay); - return; - } - case Action::READ_CALIBRATION_FRAME: { - BattOrFrameHeader frame_header; - if (!ParseSampleFrame(type, *bytes, next_sequence_number_, &frame_header, - &calibration_frame_)) { - RetryFrame(); - return; - } - - // Make sure that the calibration frame has actual samples in it. - if (calibration_frame_.empty()) { - CompleteCommand(BATTOR_ERROR_FILE_NOT_FOUND); - return; - } - - next_sequence_number_++; - num_frame_attempts_ = 1; - PerformAction(Action::SEND_SAMPLES_REQUEST); - return; - } - - case Action::READ_DATA_FRAME: { - BattOrFrameHeader frame_header; - vector<RawBattOrSample> frame; - if (!ParseSampleFrame(type, *bytes, next_sequence_number_, &frame_header, - &frame)) { - RetryFrame(); - return; - } - - // Check for the empty frame the BattOr uses to indicate it's done - // streaming samples. - if (frame.empty()) { - CompleteCommand(BATTOR_ERROR_NONE); - return; - } - - samples_.insert(samples_.end(), frame.begin(), frame.end()); - - next_sequence_number_++; - num_frame_attempts_ = 1; - PerformAction(Action::SEND_SAMPLES_REQUEST); - return; - } - - case Action::READ_CURRENT_SAMPLE: - if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK || - bytes->size() != sizeof(uint32_t)) { - CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); - return; - } - - uint32_t sample_num; - memcpy(&sample_num, bytes->data(), sizeof(uint32_t)); - clock_sync_markers_[sample_num] = pending_clock_sync_marker_; - last_clock_sync_time_ = tick_clock_->NowTicks(); - CompleteCommand(BATTOR_ERROR_NONE); - return; - - case Action::READ_GIT_HASH: - if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) { - RetryCommand(); - return; - } - - firmware_git_hash_ = std::string(bytes->begin(), bytes->end()); - CompleteCommand(BATTOR_ERROR_NONE); - return; - - default: - NOTREACHED(); - return; - } -} - -void BattOrAgent::PerformAction(Action action) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - last_action_ = action; - - switch (action) { - case Action::REQUEST_CONNECTION: - BeginConnect(); - return; - case Action::POST_CONNECT_FLUSH: - case Action::POST_READ_ERROR_FLUSH: - connection_->Flush(); - return; - // The following actions are required for StartTracing: - case Action::SEND_INIT: - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); - return; - case Action::READ_INIT_ACK: - connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); - return; - case Action::SEND_SET_GAIN: - // Set the BattOr's gain. Setting the gain tells the BattOr the range of - // power measurements that we expect to see. - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, BATTOR_GAIN_LOW, - 0); - return; - case Action::READ_SET_GAIN_ACK: - connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); - return; - case Action::SEND_START_TRACING: - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, 0, 0); - return; - case Action::READ_START_TRACING_ACK: - connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); - return; - // The following actions are required for StopTracing: - case Action::SEND_EEPROM_REQUEST: - // Read the BattOr's EEPROM to get calibration information that's required - // to convert the raw samples to accurate ones. - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_EEPROM, - sizeof(BattOrEEPROM), 0); - return; - case Action::READ_EEPROM: - connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); - return; - case Action::SEND_SAMPLES_REQUEST: - // Send a request to the BattOr to tell it to start streaming the samples - // that it's stored on its SD card over the serial connection. - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, - next_sequence_number_); - return; - case Action::READ_CALIBRATION_FRAME: - // Data frames are numbered starting at zero and counting up by one each - // data frame. We keep track of the next frame sequence number we expect - // to see to ensure we don't miss any data. - next_sequence_number_ = 0; - - // Clear stored samples from prior attempts to read sample frames. - samples_.clear(); - calibration_frame_.clear(); - FALLTHROUGH; - case Action::READ_DATA_FRAME: - // The first frame sent back from the BattOr contains voltage and current - // data that excludes whatever device is being measured from the - // circuit. We use this first frame to establish a baseline voltage and - // current. - // - // All further frames contain real (but uncalibrated) voltage and current - // data. - SetActionTimeout(kBattOrControlMessageTimeoutSeconds); - connection_->ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES); - return; - - // The following actions are required for RecordClockSyncMarker: - case Action::SEND_CURRENT_SAMPLE_REQUEST: - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SAMPLE_COUNT, 0, 0); - return; - case Action::READ_CURRENT_SAMPLE: - connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); - return; - - case Action::SEND_GIT_HASH_REQUEST: - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_GET_FIRMWARE_GIT_HASH, 0, - 0); - return; - - case Action::READ_GIT_HASH: - connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); - return; - - case Action::INVALID: - NOTREACHED(); - return; - } -} - -void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), - delay); -} - -void BattOrAgent::OnActionTimeout() { - switch (last_action_) { - case Action::READ_INIT_ACK: - case Action::READ_SET_GAIN_ACK: - case Action::READ_START_TRACING_ACK: - case Action::READ_EEPROM: - case Action::READ_CALIBRATION_FRAME: - case Action::READ_DATA_FRAME: - case Action::READ_GIT_HASH: - connection_->CancelReadMessage(); - return; - - default: - CompleteCommand(BATTOR_ERROR_TIMEOUT); - timeout_callback_.Cancel(); - } -} - -void BattOrAgent::SendControlMessage(BattOrControlMessageType type, - uint16_t param1, - uint16_t param2) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - SetActionTimeout(kBattOrControlMessageTimeoutSeconds); - - BattOrControlMessage msg{type, param1, param2}; - connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); -} - -// Returns true if the specified vector of bytes decodes to a valid BattOr -// samples frame. The frame header and samples are returned via the frame_header -// and samples paramaters. -bool BattOrAgent::ParseSampleFrame(BattOrMessageType type, - const vector<char>& msg, - uint32_t expected_sequence_number, - BattOrFrameHeader* frame_header, - vector<RawBattOrSample>* samples) { - if (type != BATTOR_MESSAGE_TYPE_SAMPLES) { - connection_->LogSerial( - StringPrintf("ParseSampleFrame failed due to unexpected message type " - "number (wanted BATTOR_MESSAGE_TYPE_SAMPLES, but got %d).", - type)); - return false; - } - - // Each frame should contain a header and an integer number of BattOr samples. - if ((msg.size() - sizeof(BattOrFrameHeader)) % sizeof(RawBattOrSample) != 0) { - connection_->LogSerial( - "ParseSampleFrame failed due to containing a noninteger number of " - "BattOr samples."); - return false; - } - - // The first bytes in the frame contain the frame header. - const char* frame_ptr = reinterpret_cast<const char*>(msg.data()); - memcpy(frame_header, frame_ptr, sizeof(BattOrFrameHeader)); - frame_ptr += sizeof(BattOrFrameHeader); - - if (frame_header->sequence_number != expected_sequence_number) { - connection_->LogSerial( - StringPrintf("ParseSampleFrame failed due to unexpected sequence " - "number (wanted %d, but got %d).", - expected_sequence_number, frame_header->sequence_number)); - return false; - } - - size_t remaining_bytes = msg.size() - sizeof(BattOrFrameHeader); - if (remaining_bytes != frame_header->length) { - connection_->LogSerial(StringPrintf( - "ParseSampleFrame failed due to to a mismatch between the length of " - "the frame as stated in the frame header and the actual length of the " - "frame (frame header %d, actual length %zu).", - frame_header->length, remaining_bytes)); - return false; - } - - samples->resize(remaining_bytes / sizeof(RawBattOrSample)); - memcpy(samples->data(), frame_ptr, remaining_bytes); - - return true; -} - -void BattOrAgent::RetryCommand() { - if (++num_command_attempts_ >= kMaxCommandAttempts) { - connection_->LogSerial(StringPrintf( - "Exhausted command retry attempts (would have been attempt %d of %d).", - num_command_attempts_ + 1, kMaxCommandAttempts)); - CompleteCommand(BATTOR_ERROR_TOO_MANY_COMMAND_RETRIES); - return; - } - - connection_->LogSerial(StringPrintf("Retrying command (attempt %d of %d).", - num_command_attempts_ + 1, - kMaxCommandAttempts)); - - // Restart the serial connection to guarantee that the connection gets flushed - // before retrying the command. - connection_->Close(); - - // Failed to read response to message, retry current command. - base::Callback<void()> next_command; - switch (command_) { - case Command::START_TRACING: - next_command = base::Bind(&BattOrAgent::StartTracing, AsWeakPtr()); - break; - case Command::STOP_TRACING: - next_command = base::Bind(&BattOrAgent::StopTracing, AsWeakPtr()); - break; - case Command::GET_FIRMWARE_GIT_HASH: - next_command = base::Bind(&BattOrAgent::GetFirmwareGitHash, AsWeakPtr()); - break; - default: - NOTREACHED(); - } - - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, next_command, - base::TimeDelta::FromSeconds(kCommandRetryDelaySeconds)); -} - -void BattOrAgent::RetryFrame() { - if (++num_frame_attempts_ > kMaxFrameAttempts) { - connection_->LogSerial(StringPrintf( - "Exhausted frame retry attempts (would have been attempt %d of %d).", - num_frame_attempts_, kMaxFrameAttempts)); - CompleteCommand(BATTOR_ERROR_TOO_MANY_FRAME_RETRIES); - return; - } - - connection_->LogSerial(StringPrintf("Retrying frame (attempt %d of %d).", - num_frame_attempts_, - kMaxFrameAttempts)); - - PerformAction(Action::POST_READ_ERROR_FLUSH); -} - -void BattOrAgent::CompleteCommand(BattOrError error) { - connection_->LogSerial( - StringPrintf("Completing command with error code: %d.", error)); - - switch (command_) { - case Command::START_TRACING: - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&Listener::OnStartTracingComplete, - base::Unretained(listener_), error)); - break; - case Command::STOP_TRACING: - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&Listener::OnStopTracingComplete, - base::Unretained(listener_), SamplesToResults(), error)); - break; - case Command::RECORD_CLOCK_SYNC_MARKER: - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&Listener::OnRecordClockSyncMarkerComplete, - base::Unretained(listener_), error)); - break; - case Command::GET_FIRMWARE_GIT_HASH: - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&Listener::OnGetFirmwareGitHashComplete, - base::Unretained(listener_), firmware_git_hash_, error)); - break; - case Command::INVALID: - NOTREACHED(); - return; - } - - last_action_ = Action::INVALID; - command_ = Command::INVALID; - pending_clock_sync_marker_.clear(); - battor_eeprom_.reset(); - calibration_frame_.clear(); - samples_.clear(); - next_sequence_number_ = 0; - num_command_attempts_ = 0; -} - -BattOrResults BattOrAgent::SamplesToResults() { - if (calibration_frame_.empty() || samples_.empty() || !battor_eeprom_) - return BattOrResults(); - - BattOrSampleConverter converter(*battor_eeprom_, calibration_frame_); - - std::stringstream trace_stream; - trace_stream << std::fixed; - - // Create a header that indicates the BattOr's parameters for these samples. - BattOrSample min_sample = converter.MinSample(); - BattOrSample max_sample = converter.MaxSample(); - trace_stream << "# BattOr" << std::endl - << std::setprecision(1) << "# voltage_range [" - << min_sample.voltage_mV << ", " << max_sample.voltage_mV - << "] mV" << std::endl - << "# current_range [" << min_sample.current_mA << ", " - << max_sample.current_mA << "] mA" << std::endl - << "# sample_rate " << battor_eeprom_->sd_sample_rate << " Hz" - << ", gain " << battor_eeprom_->low_gain << "x" << std::endl; - - // Create a string representation of the BattOr samples. - for (size_t i = 0; i < samples_.size(); i++) { - BattOrSample sample = converter.ToSample(samples_[i], i); - trace_stream << std::setprecision(2) << sample.time_ms << " " - << std::setprecision(1) << sample.current_mA << " " - << sample.voltage_mV; - - // If there's a clock sync marker for the current sample, print it. - auto clock_sync_marker = clock_sync_markers_.find( - static_cast<uint32_t>(calibration_frame_.size() + i)); - if (clock_sync_marker != clock_sync_markers_.end()) - trace_stream << " <" << clock_sync_marker->second << ">"; - - trace_stream << std::endl; - } - - for (auto it = clock_sync_markers_.begin(); it != clock_sync_markers_.end(); - ++it) { - size_t total_sample_count = calibration_frame_.size() + samples_.size(); - if (it->first >= total_sample_count) { - connection_->LogSerial(StringPrintf( - "Clock sync occurred at a sample not included in the result (clock " - "sync sample index: %d, total sample count: %zu).", - it->first, total_sample_count)); - } - } - - // Convert to a vector of power in watts. - std::vector<float> samples(samples_.size()); - for (size_t i = 0; i < samples_.size(); i++) - samples[i] = converter.ToWatts(samples_[i]); - - return BattOrResults(trace_stream.str(), samples, - battor_eeprom_->sd_sample_rate); -} - -void BattOrAgent::SetActionTimeout(uint16_t timeout_seconds) { - timeout_callback_.Reset( - base::Bind(&BattOrAgent::OnActionTimeout, AsWeakPtr())); - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, timeout_callback_.callback(), - base::TimeDelta::FromSeconds(timeout_seconds)); -} - -BattOrAgent::Action BattOrAgent::GetFirstAction(BattOrAgent::Command command) { - switch (command_) { - case Command::START_TRACING: - return Action::SEND_INIT; - case Command::STOP_TRACING: - return Action::SEND_EEPROM_REQUEST; - case Command::RECORD_CLOCK_SYNC_MARKER: - return Action::SEND_CURRENT_SAMPLE_REQUEST; - case Command::GET_FIRMWARE_GIT_HASH: - return Action::SEND_GIT_HASH_REQUEST; - case Command::INVALID: - NOTREACHED(); - } - - return Action::INVALID; -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_agent.h b/tools/battor_agent/battor_agent.h deleted file mode 100644 index d33b8e0..0000000 --- a/tools/battor_agent/battor_agent.h +++ /dev/null
@@ -1,247 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_BATTOR_AGENT_H_ -#define TOOLS_BATTOR_AGENT_BATTOR_AGENT_H_ - -#include <map> -#include <vector> - -#include "base/cancelable_callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/sequence_checker.h" -#include "base/single_thread_task_runner.h" -#include "base/time/default_tick_clock.h" -#include "tools/battor_agent/battor_connection.h" -#include "tools/battor_agent/battor_error.h" - -namespace battor { - -// A BattOrResults object contains the results of BattOr tracing, including a -// summary and sample data in watts. -class BattOrResults { - public: - BattOrResults(); - BattOrResults(std::string details, - std::vector<float> power_samples_W, - uint32_t sample_rate); - BattOrResults(const BattOrResults&); - ~BattOrResults(); - - // Get a detailed textual representation of the data recorded. - const std::string& ToString() const { return details_; } - // Returns a vector of power samples (in watts). - const std::vector<float>& GetPowerSamples() const { return power_samples_W_; } - uint32_t GetSampleRate() const { return sample_rate_; } - - private: - std::string details_; - std::vector<float> power_samples_W_; - uint32_t sample_rate_ = 0; -}; - -// A BattOrAgent is a class used to asynchronously communicate with a BattOr for -// the purpose of collecting power samples. A BattOr is an external USB device -// that's capable of recording accurate, high-frequency (2000Hz) power samples. -// -// The serial connection is automatically opened when the first command -// (e.g. StartTracing(), StopTracing(), etc.) is issued, and automatically -// closed when either StopTracing() or the destructor is called. For Telemetry, -// this means that the connection must be reinitialized for every command that's -// issued because a new BattOrAgent is constructed. For Chromium, we use the -// same BattOrAgent for multiple commands and thus avoid having to reinitialize -// the serial connection. -// -// This class is NOT thread safe. Any interactions with this class that involve -// IO (i.e. any interactions that require a callback) must be done from the -// same IO thread, which must also have a running MessageLoop. -class BattOrAgent : public BattOrConnection::Listener, - public base::SupportsWeakPtr<BattOrAgent> { - public: - // The listener interface that must be implemented in order to interact with - // the BattOrAgent. - class Listener { - public: - virtual void OnStartTracingComplete(BattOrError error) = 0; - virtual void OnStopTracingComplete(const BattOrResults& trace, - BattOrError error) = 0; - virtual void OnRecordClockSyncMarkerComplete(BattOrError error) = 0; - virtual void OnGetFirmwareGitHashComplete(const std::string& version, - BattOrError error) = 0; - }; - - BattOrAgent( - const std::string& path, - Listener* listener, - scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); - virtual ~BattOrAgent(); - - void StartTracing(); - void StopTracing(); - void RecordClockSyncMarker(const std::string& marker); - void GetFirmwareGitHash(); - - // Returns whether the BattOr is able to record clock sync markers in its own - // trace log. - static bool SupportsExplicitClockSync() { return true; } - - // BattOrConnection::Listener implementation. - void OnConnectionOpened(bool success) override; - void OnConnectionFlushed(bool success) override; - void OnBytesSent(bool success) override; - void OnMessageRead(bool success, - BattOrMessageType type, - std::unique_ptr<std::vector<char>> bytes) override; - - protected: - // The connection that knows how to communicate with the BattOr in terms of - // protocol primitives. This is protected so that it can be replaced with a - // fake in testing. - std::unique_ptr<BattOrConnection> connection_; - - // A source of TimeTicks. Protected so that it can be faked in testing. - const base::TickClock* tick_clock_; - - // Timeout for when an action isn't completed within the allotted time. This - // is virtual and protected so that timeouts can be disabled in testing. The - // testing task runner that runs delayed tasks immediately deals poorly with - // timeouts posted as future tasks. - virtual void OnActionTimeout(); - - private: - enum class Command { - INVALID, - START_TRACING, - STOP_TRACING, - RECORD_CLOCK_SYNC_MARKER, - GET_FIRMWARE_GIT_HASH, - }; - - enum class Action { - INVALID, - - // Actions required to connect to a BattOr. - REQUEST_CONNECTION, - POST_CONNECT_FLUSH, - - // Actions required for starting tracing. - SEND_INIT, - READ_INIT_ACK, - SEND_SET_GAIN, - READ_SET_GAIN_ACK, - SEND_START_TRACING, - READ_START_TRACING_ACK, - - // Actions required for stopping tracing. - SEND_EEPROM_REQUEST, - READ_EEPROM, - SEND_SAMPLES_REQUEST, - READ_CALIBRATION_FRAME, - READ_DATA_FRAME, - POST_READ_ERROR_FLUSH, - - // Actions required for recording a clock sync marker. - SEND_CURRENT_SAMPLE_REQUEST, - READ_CURRENT_SAMPLE, - - // Actions required for returning firmware git hash. - SEND_GIT_HASH_REQUEST, - READ_GIT_HASH, - }; - - // Performs an action. - void PerformAction(Action action); - // Performs an action after a delay. - void PerformDelayedAction(Action action, base::TimeDelta delay); - - // Requests a connection to the BattOr. - void BeginConnect(); - - // Sends a control message over the connection. - void SendControlMessage(BattOrControlMessageType type, - uint16_t param1, - uint16_t param2); - - bool ParseSampleFrame(BattOrMessageType type, - const std::vector<char>& msg, - uint32_t expected_sequence_number, - BattOrFrameHeader* frame_header, - std::vector<RawBattOrSample>* samples); - - // Retry the last command. - void RetryCommand(); - - // Retry the last sample frame. - void RetryFrame(); - - // Completes the command with the specified error. - void CompleteCommand(BattOrError error); - - // Returns a formatted version of samples_ with timestamps and real units. - BattOrResults SamplesToResults(); - - // Sets and restarts the action timeout timer. - void SetActionTimeout(uint16_t timeout_seconds); - - // Returns the first action for the specified command (excluding connection - // actions). - Action GetFirstAction(Command command); - - // The listener that handles the commands' results. It must outlive the agent. - Listener* listener_; - - // The last action executed by the agent. This should only be updated in - // PerformAction(). - Action last_action_; - - // The tracing command currently being executed by the agent. - Command command_; - - // A map from the sample number (including samples from the calibration frame) - // to the ID of the clock sync marker that is associated with that sample - // number. If we ever have to store a large number of these, consider using an - // unordered map. - std::map<uint32_t, std::string> clock_sync_markers_; - - // The clock sync marker being recorded (if we're currently recording one). - std::string pending_clock_sync_marker_; - - // The time at which the last clock sync marker was recorded. - base::TimeTicks last_clock_sync_time_; - - // The BattOr's EEPROM (which is required for calibration). - std::unique_ptr<BattOrEEPROM> battor_eeprom_; - - // The first frame (required for calibration). - std::vector<RawBattOrSample> calibration_frame_; - - // The actual data samples recorded. - std::vector<RawBattOrSample> samples_; - - // The expected sequence number of the next frame. We use this to ensure that - // we receive frames in order. - uint32_t next_sequence_number_; - - // The number of times we've attempted a command. - uint8_t num_command_attempts_; - - // The number of times we've attempted receiving a frame. - uint8_t num_frame_attempts_; - - // The timeout that's run when an action times out. - base::CancelableClosure timeout_callback_; - - // The git hash of the BattOr firmware. - std::string firmware_git_hash_; - - SEQUENCE_CHECKER(sequence_checker_); - - DISALLOW_COPY_AND_ASSIGN(BattOrAgent); -}; - -} // namespace battor - -#endif // TOOLS_BATTOR_AGENT_BATTOR_AGENT_H_
diff --git a/tools/battor_agent/battor_agent_bin.cc b/tools/battor_agent/battor_agent_bin.cc deleted file mode 100644 index d37b2035..0000000 --- a/tools/battor_agent/battor_agent_bin.cc +++ /dev/null
@@ -1,459 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file provides a thin binary wrapper around the BattOr Agent -// library. This binary wrapper provides a means for non-C++ tracing -// controllers, such as Telemetry and Android Systrace, to issue high-level -// tracing commands to the BattOr through an interactive shell. -// -// Example usage of how an external trace controller might use this binary: -// -// 1) Telemetry's PowerTracingAgent is told to start recording power samples -// 2) PowerTracingAgent opens up a BattOr agent binary subprocess -// 3) PowerTracingAgent sends the subprocess the StartTracing message via -// STDIN -// 4) PowerTracingAgent waits for the subprocess to write a line to STDOUT -// ('Done.' if successful, some error message otherwise) -// 5) If the last command was successful, PowerTracingAgent waits for the -// duration of the trace -// 6) When the tracing should end, PowerTracingAgent records the clock sync -// start timestamp and sends the subprocess the -// 'RecordClockSyncMark <marker>' message via STDIN. -// 7) PowerTracingAgent waits for the subprocess to write a line to STDOUT -// ('Done.' if successful, some error message otherwise) -// 8) If the last command was successful, PowerTracingAgent records the clock -// sync end timestamp and sends the subprocess the StopTracing message via -// STDIN -// 9) PowerTracingAgent continues to read trace output lines from STDOUT until -// the binary exits with an exit code of 1 (indicating failure) or the -// 'Done.' line is printed to STDOUT, signaling the last line of the trace -// 10) PowerTracingAgent returns the battery trace to the Telemetry trace -// controller - -#include <stdint.h> - -#include <fstream> -#include <iomanip> -#include <iostream> - -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_tokenizer.h" -#include "base/strings/utf_string_conversions.h" -#include "base/task/task_scheduler/task_scheduler.h" -#include "base/threading/thread.h" -#include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "tools/battor_agent/battor_agent.h" -#include "tools/battor_agent/battor_error.h" -#include "tools/battor_agent/battor_finder.h" - -using std::endl; - -namespace battor { - -namespace { - -const char kIoThreadName[] = "BattOr IO Thread"; - -const char kUsage[] = - "Start the battor_agent shell with:\n" - "\n" - " battor_agent <switches>\n" - "\n" - "Switches: \n" - " --battor-path=<path> Uses the specified BattOr path.\n" - " --interactive Enables interactive power profiling." - "\n" - "Once in the shell, you can issue the following commands:\n" - "\n" - " StartTracing\n" - " StopTracing <optional file path>\n" - " SupportsExplicitClockSync\n" - " RecordClockSyncMarker <marker>\n" - " GetFirmwareGitHash\n" - " Exit\n" - " Help\n" - "\n"; - -// The command line switch used to enable interactive mode where starting and -// stopping is easily toggled. -const char kInteractiveSwitch[] = "interactive"; - -void PrintSupportsExplicitClockSync() { - std::cout << BattOrAgent::SupportsExplicitClockSync() << endl; -} - -// Logs the error and exits with an error code. -void HandleError(battor::BattOrError error) { - if (error != BATTOR_ERROR_NONE) - LOG(FATAL) << "Fatal error when communicating with the BattOr: " - << BattOrErrorToString(error); -} - -// Prints an error message and exits due to a required thread failing to start. -void ExitFromThreadStartFailure(const std::string& thread_name) { - LOG(FATAL) << "Failed to start " << thread_name; -} - -std::vector<std::string> TokenizeString(std::string cmd) { - base::StringTokenizer tokenizer(cmd, " "); - std::vector<std::string> tokens; - while (tokenizer.GetNext()) - tokens.push_back(tokenizer.token()); - return tokens; -} - -} // namespace - -// Wrapper class containing all state necessary for an independent binary to -// use a BattOrAgent to communicate with a BattOr. -class BattOrAgentBin : public BattOrAgent::Listener { - public: - BattOrAgentBin() : io_thread_(kIoThreadName) {} - - ~BattOrAgentBin() { DCHECK(!agent_); } - - // Starts the interactive BattOr agent shell and eventually returns an exit - // code. - int Run(int argc, char* argv[]) { - // If we don't have any BattOr to use, exit. - std::string path = BattOrFinder::FindBattOr(); - if (path.empty()) { - std::cout << "Unable to find a BattOr." << endl; -#if defined(OS_WIN) - std::cout << "Try \"--battor-path=<path>\" to specify the COM port where " - "the BattOr can be found, typically COM3." - << endl; -#endif - exit(1); - } - - SetUp(path); - - if (base::CommandLine::ForCurrentProcess()->HasSwitch(kInteractiveSwitch)) { - interactive_ = true; - std::cout << "Type <Enter> to toggle tracing, type Exit or Ctrl+C " - "to quit, or Help for help." - << endl; - } - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&BattOrAgentBin::RunNextCommand, base::Unretained(this))); - ui_thread_run_loop_.Run(); - - TearDown(); - return 0; - } - - // Performs any setup necessary for the BattOr binary to run. - void SetUp(const std::string& path) { - base::Thread::Options io_thread_options; - io_thread_options.message_loop_type = base::MessageLoopForIO::TYPE_IO; - if (!io_thread_.StartWithOptions(io_thread_options)) { - ExitFromThreadStartFailure(kIoThreadName); - } - - // Block until the creation of the BattOrAgent is complete. This doesn't - // seem necessary because we're posting the creation to the IO thread - // before posting any commands, so we're guaranteed that the creation - // will happen first. However, the crashes that happen without this sync - // mechanism in place say otherwise. - base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED); - io_thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&BattOrAgentBin::CreateAgent, base::Unretained(this), path, - base::ThreadTaskRunnerHandle::Get(), &done)); - done.Wait(); - } - - // Performs any cleanup necessary after the BattOr binary is done running. - void TearDown() { - base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED); - io_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&BattOrAgentBin::DeleteAgent, - base::Unretained(this), &done)); - done.Wait(); - } - - void RunNextCommand() { - std::string cmd; - std::getline(std::cin, cmd); - - if (interactive_) { - if (cmd == "") { - cmd = is_tracing_ ? "StopTracing" : "StartTracing"; - std::cout << cmd << endl; - is_tracing_ = !is_tracing_; - } - } - - if (cmd == "StartTracing") { - StartTracing(); - } else if (cmd.find("StopTracing") != std::string::npos) { - std::vector<std::string> tokens = TokenizeString(cmd); - - if (tokens[0] != "StopTracing" || tokens.size() > 2) { - std::cout << "Invalid StopTracing command." << endl; - std::cout << kUsage << endl; - PostRunNextCommand(); - return; - } - - // tokens[1] contains the optional output file argument, which allows - // users to dump the trace to a file instead instead of to STDOUT. - std::string trace_output_file = - tokens.size() == 2 ? tokens[1] : std::string(); - - StopTracing(trace_output_file); - if (interactive_) { - PostRunNextCommand(); - } - } else if (cmd == "SupportsExplicitClockSync") { - PrintSupportsExplicitClockSync(); - PostRunNextCommand(); - } else if (cmd.find("RecordClockSyncMarker") != std::string::npos) { - std::vector<std::string> tokens = TokenizeString(cmd); - if (tokens.size() != 2 || tokens[0] != "RecordClockSyncMarker") { - std::cout << "Invalid RecordClockSyncMarker command." << endl; - std::cout << kUsage << endl; - PostRunNextCommand(); - return; - } - - RecordClockSyncMarker(tokens[1]); - } else if (cmd == "GetFirmwareGitHash") { - GetFirmwareGitHash(); - return; - } else if (cmd == "Exit" || std::cin.eof()) { - ui_thread_message_loop_.task_runner()->PostTask( - FROM_HERE, ui_thread_run_loop_.QuitClosure()); - } else { - std::cout << kUsage << endl; - PostRunNextCommand(); - } - } - - void PostRunNextCommand() { - ui_thread_message_loop_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&BattOrAgentBin::RunNextCommand, base::Unretained(this))); - } - - void GetFirmwareGitHash() { - io_thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&BattOrAgent::GetFirmwareGitHash, - base::Unretained(agent_.get()))); - } - - void OnGetFirmwareGitHashComplete(const std::string& firmware_git_hash, - BattOrError error) override { - if (error == BATTOR_ERROR_NONE) - std::cout << firmware_git_hash << endl; - else - HandleError(error); - - PostRunNextCommand(); - } - - void StartTracing() { - io_thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&BattOrAgent::StartTracing, base::Unretained(agent_.get()))); - } - - void OnStartTracingComplete(BattOrError error) override { - if (error == BATTOR_ERROR_NONE) - std::cout << "Done." << endl; - else - HandleError(error); - - PostRunNextCommand(); - } - - void StopTracing(const std::string& trace_output_file) { - trace_output_file_ = trace_output_file; - io_thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&BattOrAgent::StopTracing, base::Unretained(agent_.get()))); - } - - std::string BattOrResultsToSummary(const BattOrResults& results) { - const uint32_t samples_per_second = results.GetSampleRate(); - - // Print a summary of a BattOr trace. These summaries are intended for human - // consumption and are subject to change at any moment. The summary is - // printed when using interactive mode. - std::stringstream trace_summary; - // Display floating-point numbers without exponents, in a five-character - // field, with two digits of precision. ie; - // 12.39 - // 8.40 - trace_summary << std::fixed << std::setw(5) << std::setprecision(2); - - // Scan through the sample data to summarize it. Report on average power and - // second-by-second power including min-second, median-second, and - // max-second. - double total_power = 0.0; - int num_seconds = 0; - std::vector<double> power_by_seconds; - const std::vector<float>& samples = results.GetPowerSamples(); - for (size_t i = 0; i < samples.size(); i += samples_per_second) { - size_t loop_count = samples.size() - i; - if (loop_count > samples_per_second) - loop_count = samples_per_second; - - double second_power = 0.0; - for (size_t j = i; j < i + loop_count; ++j) { - total_power += samples[i]; - second_power += samples[i]; - } - - // Print/store results for full seconds. - if (loop_count == samples_per_second) { - // Calculate power for one second in watts. - second_power /= samples_per_second; - trace_summary << "Second " << std::setw(2) << num_seconds - << " average power: " << std::setw(5) << second_power - << " W" << std::endl; - ++num_seconds; - power_by_seconds.push_back(second_power); - } - } - // Calculate average power in watts. - const double average_power_W = total_power / samples.size(); - const double duration_sec = - static_cast<double>(samples.size()) / samples_per_second; - trace_summary << "Average power over " << duration_sec - << " s : " << average_power_W << " W" << std::endl; - std::sort(power_by_seconds.begin(), power_by_seconds.end()); - if (power_by_seconds.size() >= 3) { - trace_summary << "Summary of power-by-seconds:" << std::endl - << "Minimum: " << power_by_seconds[0] << std::endl - << "Median: " - << power_by_seconds[power_by_seconds.size() / 2] - << std::endl - << "Maximum: " - << power_by_seconds[power_by_seconds.size() - 1] - << std::endl; - } else { - trace_summary << "Too short a trace to generate per-second summary."; - } - - return trace_summary.str(); - } - - void OnStopTracingComplete(const BattOrResults& results, - BattOrError error) override { - if (error == BATTOR_ERROR_NONE) { - std::string output_file = trace_output_file_; - if (trace_output_file_.empty()) { - // Save the detailed results in case they are needed. - base::FilePath default_path; - base::PathService::Get(base::DIR_USER_DESKTOP, &default_path); - default_path = default_path.Append(FILE_PATH_LITERAL("trace_data.txt")); - output_file = default_path.AsUTF8Unsafe().c_str(); - std::cout << "Saving detailed results to " << output_file << std::endl; - } - - if (interactive_) { - // Print a summary of the trace. - std::cout << BattOrResultsToSummary(results) << endl; - } - - std::ofstream trace_stream(output_file); - if (!trace_stream.is_open()) { - std::cout << "Tracing output file \"" << output_file - << "\" could not be opened." << endl; - exit(1); - } - trace_stream << results.ToString(); - trace_stream.close(); - std::cout << "Done." << endl; - } else { - HandleError(error); - } - - if (!interactive_) { - ui_thread_message_loop_.task_runner()->PostTask( - FROM_HERE, ui_thread_run_loop_.QuitClosure()); - } - } - - void RecordClockSyncMarker(const std::string& marker) { - io_thread_.task_runner()->PostTask( - FROM_HERE, base::Bind(&BattOrAgent::RecordClockSyncMarker, - base::Unretained(agent_.get()), marker)); - } - - void OnRecordClockSyncMarkerComplete(BattOrError error) override { - if (error == BATTOR_ERROR_NONE) - std::cout << "Done." << endl; - else - HandleError(error); - - PostRunNextCommand(); - } - - // Postable task for creating the BattOrAgent. Because the BattOrAgent has - // uber thread safe dependencies, all interactions with it, including creating - // and deleting it, MUST happen on the IO thread. - void CreateAgent( - const std::string& path, - scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner, - base::WaitableEvent* done) { - agent_.reset(new BattOrAgent(path, this, ui_thread_task_runner)); - done->Signal(); - } - - // Postable task for deleting the BattOrAgent. See the comment for - // CreateAgent() above regarding why this is necessary. - void DeleteAgent(base::WaitableEvent* done) { - agent_.reset(); - done->Signal(); - } - - private: - // NOTE: ui_thread_message_loop_ must appear before ui_thread_run_loop_ here - // because ui_thread_run_loop_ checks for the current MessageLoop during - // initialization. - base::MessageLoopForUI ui_thread_message_loop_; - base::RunLoop ui_thread_run_loop_; - - // Threads needed for serial communication. - base::Thread io_thread_; - - // The agent capable of asynchronously communicating with the BattOr. - std::unique_ptr<BattOrAgent> agent_; - - std::string trace_output_file_; - - // When true user can Start/Stop tracing by typing Enter. - bool interactive_ = false; - // Toggle to support alternating starting/stopping tracing. - bool is_tracing_ = false; -}; - -} // namespace battor - -int main(int argc, char* argv[]) { - base::AtExitManager exit_manager; - base::CommandLine::Init(argc, argv); - battor::BattOrAgentBin bin; - base::TaskScheduler::CreateAndStartWithDefaultParams("battor_agent"); - return bin.Run(argc, argv); -}
diff --git a/tools/battor_agent/battor_agent_unittest.cc b/tools/battor_agent/battor_agent_unittest.cc deleted file mode 100644 index d952fc31..0000000 --- a/tools/battor_agent/battor_agent_unittest.cc +++ /dev/null
@@ -1,1311 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> - -#include "tools/battor_agent/battor_agent.h" - -#include "base/test/test_mock_time_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "tools/battor_agent/battor_protocol_types.h" - -using namespace testing; - -using std::vector; - -namespace battor { - -namespace { - -BattOrControlMessageAck kInitAck{BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0}; -BattOrControlMessageAck kSetGainAck{BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, 0}; -BattOrControlMessageAck kStartTracingAck{ - BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, 0}; -const char kClockSyncId[] = "MY_MARKER"; - -// Creates a byte vector copy of the specified object. -template <typename T> -std::unique_ptr<std::vector<char>> ToCharVector(const T& object) { - return std::unique_ptr<std::vector<char>>(new std::vector<char>( - reinterpret_cast<const char*>(&object), - reinterpret_cast<const char*>(&object) + sizeof(T))); -} - -MATCHER_P2( - BufferEq, - expected_buffer, - expected_buffer_size, - "Makes sure that the argument has the same contents as the buffer.") { - return memcmp(reinterpret_cast<const void*>(arg), - reinterpret_cast<const void*>(expected_buffer), - expected_buffer_size) == 0; -} - -std::unique_ptr<vector<char>> CreateFrame(const BattOrFrameHeader& frame_header, - const RawBattOrSample* samples, - const size_t& num_samples) { - std::unique_ptr<vector<char>> bytes(new vector<char>( - sizeof(BattOrFrameHeader) + sizeof(RawBattOrSample) * num_samples)); - memcpy(bytes->data(), &frame_header, sizeof(BattOrFrameHeader)); - memcpy(bytes->data() + sizeof(BattOrFrameHeader), samples, - sizeof(RawBattOrSample) * num_samples); - - return bytes; -} - -class MockBattOrConnection : public BattOrConnection { - public: - MockBattOrConnection(BattOrConnection::Listener* listener) - : BattOrConnection(listener) {} - ~MockBattOrConnection() override = default; - - MOCK_METHOD0(Open, void()); - MOCK_METHOD0(Flush, void()); - MOCK_METHOD0(Close, void()); - MOCK_METHOD0(IsOpen, bool()); - MOCK_METHOD3(SendBytes, - void(BattOrMessageType type, - const void* buffer, - size_t bytes_to_send)); - MOCK_METHOD1(ReadMessage, void(BattOrMessageType type)); - MOCK_METHOD0(CancelReadMessage, void()); - MOCK_METHOD1(LogSerial, void(const std::string& str)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockBattOrConnection); -}; - -} // namespace - -// TestableBattOrAgent uses a fake BattOrConnection to be testable. -class TestableBattOrAgent : public BattOrAgent { - public: - TestableBattOrAgent(BattOrAgent::Listener* listener, - const base::TickClock* tick_clock) - : BattOrAgent("/dev/test", listener, nullptr) { - connection_ = - std::unique_ptr<BattOrConnection>(new MockBattOrConnection(this)); - tick_clock_ = tick_clock; - } - - MockBattOrConnection* GetConnection() { - return static_cast<MockBattOrConnection*>(connection_.get()); - } - - void OnActionTimeout() override {} -}; - -// BattOrAgentTest provides a BattOrAgent and captures the results of its -// tracing commands. -class BattOrAgentTest : public testing::Test, public BattOrAgent::Listener { - public: - BattOrAgentTest() - : task_runner_(new base::TestMockTimeTaskRunner()), - thread_task_runner_handle_(task_runner_) {} - - void OnStartTracingComplete(BattOrError error) override { - is_command_complete_ = true; - command_error_ = error; - } - - void OnStopTracingComplete(const BattOrResults& results, - BattOrError error) override { - is_command_complete_ = true; - command_error_ = error; - trace_ = results.ToString(); - } - - void OnRecordClockSyncMarkerComplete(BattOrError error) override { - is_command_complete_ = true; - command_error_ = error; - } - - void OnGetFirmwareGitHashComplete(const std::string& firmware_git_hash, - BattOrError error) override { - is_command_complete_ = true; - command_error_ = error; - firmware_git_hash_ = firmware_git_hash; - } - - void OnBytesSent(bool success) { - agent_->OnBytesSent(success); - task_runner_->RunUntilIdle(); - } - - void OnMessageRead(bool success, - BattOrMessageType type, - std::unique_ptr<std::vector<char>> bytes) { - agent_->OnMessageRead(success, type, std::move(bytes)); - task_runner_->RunUntilIdle(); - } - - void OnConnectionFlushed(bool success) { - agent_->OnConnectionFlushed(true); - task_runner_->RunUntilIdle(); - } - - protected: - void SetUp() override { - agent_.reset( - new TestableBattOrAgent(this, task_runner_->GetMockTickClock())); - task_runner_->ClearPendingTasks(); - is_command_complete_ = false; - command_error_ = BATTOR_ERROR_NONE; - } - - void AdvanceTickClock(base::TimeDelta delta) { - task_runner_->FastForwardBy(delta); - } - - // Possible states that the BattOrAgent can be in. - enum class BattOrAgentState { - // States required to connect to a BattOr. - CONNECTED, - - // States required to StartTracing. - INIT_SENT, - INIT_ACKED, - SET_GAIN_SENT, - GAIN_ACKED, - START_TRACING_SENT, - START_TRACING_COMPLETE, - - // States required to StopTracing. - EEPROM_REQUEST_SENT, - EEPROM_RECEIVED, - SAMPLES_REQUEST_SENT, - CALIBRATION_FRAME_RECEIVED, - SAMPLES_END_FRAME_RECEIVED, - - // States required to RecordClockSyncMarker. - CURRENT_SAMPLE_REQUEST_SENT, - RECORD_CLOCK_SYNC_MARKER_COMPLETE, - - // States required to GetFirmwareGitHash. - GIT_FIRMWARE_HASH_REQUEST_SENT, - READ_GIT_HASH_RECEIVED, - }; - - // Runs BattOrAgent::StartTracing until it reaches the specified state by - // feeding it the callbacks it needs to progress. - void RunStartTracingTo(BattOrAgentState end_state, bool connect) { - GetTaskRunner()->RunUntilIdle(); - - if (connect) { - GetAgent()->OnConnectionOpened(true); - GetTaskRunner()->RunUntilIdle(); - - GetAgent()->OnConnectionFlushed(true); - GetTaskRunner()->RunUntilIdle(); - } - - if (end_state == BattOrAgentState::CONNECTED) - return; - - OnBytesSent(true); - if (end_state == BattOrAgentState::INIT_SENT) - return; - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(kInitAck)); - if (end_state == BattOrAgentState::INIT_ACKED) - return; - - OnBytesSent(true); - if (end_state == BattOrAgentState::SET_GAIN_SENT) - return; - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(kSetGainAck)); - if (end_state == BattOrAgentState::GAIN_ACKED) - return; - - OnBytesSent(true); - if (end_state == BattOrAgentState::START_TRACING_SENT) - return; - - // Make sure that we're actually forwarding to a state in the start tracing - // state machine. - DCHECK(end_state == BattOrAgentState::START_TRACING_COMPLETE); - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(kStartTracingAck)); - } - - // Runs BattOrAgent::StopTracing until it reaches the specified state by - // feeding it the callbacks it needs to progress. - void RunStopTracingTo(BattOrAgentState end_state, bool connect) { - GetTaskRunner()->RunUntilIdle(); - - if (connect) { - GetAgent()->OnConnectionOpened(true); - GetTaskRunner()->RunUntilIdle(); - - OnConnectionFlushed(true); - } - - if (end_state == BattOrAgentState::CONNECTED) - return; - - OnBytesSent(true); - if (end_state == BattOrAgentState::EEPROM_REQUEST_SENT) - return; - - BattOrEEPROM eeprom; - eeprom.r1 = 1; - eeprom.r2 = 1; - eeprom.r3 = 1; - eeprom.low_gain = 1; - eeprom.low_gain_correction_offset = 0; - eeprom.low_gain_correction_factor = 1; - eeprom.sd_sample_rate = 1000; - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, ToCharVector(eeprom)); - if (end_state == BattOrAgentState::EEPROM_RECEIVED) - return; - - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromMilliseconds(100)); - OnBytesSent(true); - if (end_state == BattOrAgentState::SAMPLES_REQUEST_SENT) - return; - - BattOrFrameHeader cal_frame_header{0, sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(cal_frame_header, cal_frame, 1)); - OnBytesSent(true); - - if (end_state == BattOrAgentState::CALIBRATION_FRAME_RECEIVED) - return; - - DCHECK(end_state == BattOrAgentState::SAMPLES_END_FRAME_RECEIVED); - - BattOrFrameHeader frame_header{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header, nullptr, 0)); - } - - // Runs BattOrAgent::RecordClockSyncMarker until it reaches the specified - // state by feeding it the callbacks it needs to progress. - void RunRecordClockSyncMarkerTo(BattOrAgentState end_state, bool connect) { - GetTaskRunner()->RunUntilIdle(); - - if (connect) { - GetAgent()->OnConnectionOpened(true); - GetTaskRunner()->RunUntilIdle(); - - OnConnectionFlushed(true); - } - - if (end_state == BattOrAgentState::CONNECTED) - return; - - OnBytesSent(true); - if (end_state == BattOrAgentState::CURRENT_SAMPLE_REQUEST_SENT) - return; - - DCHECK(end_state == BattOrAgentState::RECORD_CLOCK_SYNC_MARKER_COMPLETE); - - uint32_t current_sample = 1; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(current_sample)); - } - - // Runs BattOrAgent::GetFirmwareGitHash until it reaches the specified - // state by feeding it the callbacks it needs to progress. - void RunGetFirmwareGitHashTo(BattOrAgentState end_state, bool connect) { - GetTaskRunner()->RunUntilIdle(); - - if (connect) { - GetAgent()->OnConnectionOpened(true); - GetTaskRunner()->RunUntilIdle(); - - OnConnectionFlushed(true); - } - - if (end_state == BattOrAgentState::CONNECTED) - return; - - OnBytesSent(true); - if (end_state == BattOrAgentState::GIT_FIRMWARE_HASH_REQUEST_SENT) - return; - - DCHECK(end_state == BattOrAgentState::READ_GIT_HASH_RECEIVED); - - std::unique_ptr<std::vector<char>> firmware_git_hash_vector( - new std::vector<char>{'G', 'I', 'T', 'H', 'A', 'S', 'H'}); - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - std::move(firmware_git_hash_vector)); - } - - TestableBattOrAgent* GetAgent() { return agent_.get(); } - - scoped_refptr<base::TestMockTimeTaskRunner> GetTaskRunner() { - return task_runner_; - } - - bool IsCommandComplete() { return is_command_complete_; } - BattOrError GetCommandError() { return command_error_; } - std::string GetTrace() { return trace_; } - std::string GetGitHash() { return firmware_git_hash_; } - - private: - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; - // Needed to support ThreadTaskRunnerHandle::Get() in code under test. - base::ThreadTaskRunnerHandle thread_task_runner_handle_; - - std::unique_ptr<TestableBattOrAgent> agent_; - bool is_command_complete_; - BattOrError command_error_; - std::string trace_; - std::string firmware_git_hash_; -}; - -TEST_F(BattOrAgentTest, StartTracing) { - testing::InSequence s; - EXPECT_CALL(*GetAgent()->GetConnection(), Open()); - - EXPECT_CALL(*GetAgent()->GetConnection(), Flush()); - - BattOrControlMessage init_msg{BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0}; - EXPECT_CALL( - *GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&init_msg, sizeof(init_msg)), sizeof(init_msg))); - - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK)); - - BattOrControlMessage set_gain_msg{BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, - BATTOR_GAIN_LOW, 0}; - EXPECT_CALL(*GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&set_gain_msg, sizeof(set_gain_msg)), - sizeof(set_gain_msg))); - - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK)); - - BattOrControlMessage start_tracing_msg{ - BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, 0, 0}; - EXPECT_CALL(*GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&start_tracing_msg, sizeof(start_tracing_msg)), - sizeof(start_tracing_msg))); - - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK)); - - GetAgent()->StartTracing(); - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingFailsWithoutConnection) { - GetAgent()->StartTracing(); - GetTaskRunner()->RunUntilIdle(); - - GetAgent()->OnConnectionOpened(false); - GetTaskRunner()->RunUntilIdle(); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_CONNECTION_FAILED, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingFailsIfInitSendFails) { - GetAgent()->StartTracing(); - RunStartTracingTo(BattOrAgentState::CONNECTED, true); - OnBytesSent(false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_SEND_ERROR, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingSucceedsAfterInitAckReadFails) { - GetAgent()->StartTracing(); - - RunStartTracingTo(BattOrAgentState::INIT_SENT, true); - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - EXPECT_FALSE(IsCommandComplete()); - - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingSucceedsAfterInitWrongAckRead) { - GetAgent()->StartTracing(); - - RunStartTracingTo(BattOrAgentState::INIT_SENT, true); - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(kStartTracingAck)); - - EXPECT_FALSE(IsCommandComplete()); - - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingFailsAfterSetGainSendFails) { - GetAgent()->StartTracing(); - - RunStartTracingTo(BattOrAgentState::INIT_SENT, true); - OnBytesSent(false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_SEND_ERROR, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingSucceedsAfterSetGainAckReadFails) { - GetAgent()->StartTracing(); - - RunStartTracingTo(BattOrAgentState::SET_GAIN_SENT, true); - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - EXPECT_FALSE(IsCommandComplete()); - - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingSucceedsAfterSetGainWrongAckRead) { - GetAgent()->StartTracing(); - - RunStartTracingTo(BattOrAgentState::SET_GAIN_SENT, true); - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(kStartTracingAck)); - - EXPECT_FALSE(IsCommandComplete()); - - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingFailsIfStartTracingSendFails) { - GetAgent()->StartTracing(); - RunStartTracingTo(BattOrAgentState::INIT_SENT, true); - OnBytesSent(false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_SEND_ERROR, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingSucceedsAfterWrongAckRead) { - GetAgent()->StartTracing(); - - // Go through the correct init sequence, but give the wrong ack to - // START_TRACING. - RunStartTracingTo(BattOrAgentState::START_TRACING_SENT, true); - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, ToCharVector(kInitAck)); - - EXPECT_FALSE(IsCommandComplete()); - - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingSucceedsAfterReadFails) { - GetAgent()->StartTracing(); - - // Go through the correct init sequence, but indicate that we failed to read - // the START_TRACING ack. - RunStartTracingTo(BattOrAgentState::START_TRACING_SENT, true); - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - EXPECT_FALSE(IsCommandComplete()); - - // On the last attempt, give the correct ack to START_TRACING. - RunStartTracingTo(BattOrAgentState::START_TRACING_SENT, true); - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(kStartTracingAck)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingSucceedsAfterSamplesReadDuringInit) { - GetAgent()->StartTracing(); - - RunStartTracingTo(BattOrAgentState::INIT_SENT, true); - - // Send some samples instead of an INIT ACK. This will force a command retry. - BattOrFrameHeader frame_header{1, 3 * sizeof(RawBattOrSample)}; - RawBattOrSample frame[] = { - RawBattOrSample{1, 1}, RawBattOrSample{2, 2}, RawBattOrSample{3, 3}, - }; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header, frame, 3)); - - EXPECT_FALSE(IsCommandComplete()); - - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingFailsAfterTooManyCumulativeFailures) { - GetAgent()->StartTracing(); - RunStartTracingTo(BattOrAgentState::SET_GAIN_SENT, true); - - for (int i = 0; i < 9; i++) { - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - AdvanceTickClock(base::TimeDelta::FromSeconds(2)); - RunStartTracingTo(BattOrAgentState::SET_GAIN_SENT, true); - - EXPECT_FALSE(IsCommandComplete()); - } - - RunStartTracingTo(BattOrAgentState::SET_GAIN_SENT, true); - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_TOO_MANY_COMMAND_RETRIES, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingRestartsConnectionUponRetry) { - GetAgent()->StartTracing(); - RunStartTracingTo(BattOrAgentState::INIT_SENT, true); - - EXPECT_CALL(*GetAgent()->GetConnection(), Close()); - - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StartTracingCanReuseExistingConnection) { - ON_CALL(*GetAgent()->GetConnection(), IsOpen()).WillByDefault(Return(true)); - - GetAgent()->StartTracing(); - RunStartTracingTo(BattOrAgentState::START_TRACING_COMPLETE, false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracing) { - testing::InSequence s; - EXPECT_CALL(*GetAgent()->GetConnection(), Open()); - - EXPECT_CALL(*GetAgent()->GetConnection(), Flush()); - - BattOrControlMessage request_eeprom_msg{ - BATTOR_CONTROL_MESSAGE_TYPE_READ_EEPROM, sizeof(BattOrEEPROM), 0}; - EXPECT_CALL( - *GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&request_eeprom_msg, sizeof(request_eeprom_msg)), - sizeof(request_eeprom_msg))); - - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK)); - - // The agent sends four frame request messages: one for a calibration frame, - // two for data frames with samples, and one for a zero-length data frame to - // indicate that we're done. - BattOrControlMessage request_samples_msg_frame0{ - BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 0}; - EXPECT_CALL(*GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&request_samples_msg_frame0, - sizeof(request_samples_msg_frame0)), - sizeof(request_samples_msg_frame0))); - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES)); - - BattOrControlMessage request_samples_msg_frame1{ - BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 1}; - EXPECT_CALL(*GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&request_samples_msg_frame1, - sizeof(request_samples_msg_frame1)), - sizeof(request_samples_msg_frame1))); - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES)); - - BattOrControlMessage request_samples_msg_frame2{ - BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 2}; - EXPECT_CALL(*GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&request_samples_msg_frame2, - sizeof(request_samples_msg_frame2)), - sizeof(request_samples_msg_frame2))); - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES)); - - BattOrControlMessage request_samples_msg_frame3{ - BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 3}; - EXPECT_CALL(*GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&request_samples_msg_frame3, - sizeof(request_samples_msg_frame3)), - sizeof(request_samples_msg_frame3))); - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES)); - - GetAgent()->StopTracing(); - RunStopTracingTo(BattOrAgentState::SAMPLES_REQUEST_SENT, true); - - // Send the calibration frame. - BattOrFrameHeader cal_frame_header{0, 2 * sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame[] = { - RawBattOrSample{1, 1}, RawBattOrSample{2, 2}, - }; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(cal_frame_header, cal_frame, 2)); - OnBytesSent(true); - - // Send the two real data frames. - BattOrFrameHeader frame_header1{1, 3 * sizeof(RawBattOrSample)}; - RawBattOrSample frame1[] = { - RawBattOrSample{1, 1}, RawBattOrSample{2, 2}, RawBattOrSample{3, 3}, - }; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header1, frame1, 3)); - OnBytesSent(true); - - BattOrFrameHeader frame_header2{2, 1 * sizeof(RawBattOrSample)}; - RawBattOrSample frame2[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header2, frame2, 1)); - OnBytesSent(true); - - // Send an empty last frame to indicate that we're done. - BattOrFrameHeader frame_header3{3, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header3, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); - EXPECT_EQ( - "# BattOr\n# voltage_range [-2401.8, 2398.2] mV\n# " - "current_range [-1200.9, 1199.1] mA\n" - "# sample_rate 1000 Hz, gain 1.0x\n" - "0.00 -0.3 -0.6\n1.00 0.3 0.6\n2.00 0.9 1.8\n3.00 -0.3 -0.6\n", - GetTrace()); -} - -TEST_F(BattOrAgentTest, StopTracingFailsWithoutConnection) { - GetAgent()->StopTracing(); - GetTaskRunner()->RunUntilIdle(); - - GetAgent()->OnConnectionOpened(false); - GetTaskRunner()->RunUntilIdle(); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_CONNECTION_FAILED, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingFailsIfEEPROMRequestSendFails) { - GetAgent()->StopTracing(); - RunStopTracingTo(BattOrAgentState::CONNECTED, true); - OnBytesSent(false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_SEND_ERROR, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterEEPROMReadFails) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::EEPROM_REQUEST_SENT, true); - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - EXPECT_FALSE(IsCommandComplete()); - - RunStopTracingTo(BattOrAgentState::SAMPLES_END_FRAME_RECEIVED, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterEEPROMWrongAckRead) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::EEPROM_REQUEST_SENT, true); - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, ToCharVector(kInitAck)); - - EXPECT_FALSE(IsCommandComplete()); - - RunStopTracingTo(BattOrAgentState::SAMPLES_END_FRAME_RECEIVED, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingFailsIfSendamplesRequestFails) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::EEPROM_RECEIVED, true); - OnBytesSent(false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_SEND_ERROR, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterCalibrationFrameReadFailure) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::SAMPLES_REQUEST_SENT, true); - - // Make a read fail in order to make sure that the agent will retry the frame. - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - EXPECT_FALSE(IsCommandComplete()); - - // Flush and advance time to send retry for calibration frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - BattOrFrameHeader cal_frame_header{0, sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(cal_frame_header, cal_frame, 1)); - OnBytesSent(true); - - BattOrFrameHeader frame_header{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterDataFrameReadFailure) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::CALIBRATION_FRAME_RECEIVED, true); - - // Make a read fail in order to make sure that the agent will retry. - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - EXPECT_FALSE(IsCommandComplete()); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - BattOrFrameHeader frame_header{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingFailsWithManyCalibrationFrameReadFailures) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::SAMPLES_REQUEST_SENT, true); - - for (int i = 0; i < 9; i++) { - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - // Flush and advance time to send retry for calibration frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - } - - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_TOO_MANY_FRAME_RETRIES, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingFailsWithManyDataFrameReadFailures) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::CALIBRATION_FRAME_RECEIVED, true); - - for (int i = 0; i < 9; i++) { - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - } - - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_TOO_MANY_FRAME_RETRIES, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsWithFewDataFrameReadFailures) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::CALIBRATION_FRAME_RECEIVED, true); - - // Fail to receive first data frame. - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Successfully receive the first data frame. - BattOrFrameHeader frame_header1{1, 1 * sizeof(RawBattOrSample)}; - RawBattOrSample frame1[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header1, frame1, 1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Fail to receive next data frame. - OnMessageRead(false, BATTOR_MESSAGE_TYPE_SAMPLES, nullptr); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Successfully receive the last data frame. - BattOrFrameHeader frame_header2{2, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header2, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterSamplesReadHasWrongType) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::CALIBRATION_FRAME_RECEIVED, true); - - // Send the incorrect type of frame. - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, ToCharVector(kInitAck)); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Successfully receive the last data frame. - BattOrFrameHeader frame_header{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterCalibrationFrameWrongLength) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::SAMPLES_REQUEST_SENT, true); - - // Send a calibration frame with a mismatch between the frame length in the - // header and the actual frame length. - BattOrFrameHeader cal_frame_header_bad{0, 1 * sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame_bad[] = { - RawBattOrSample{1, 1}, RawBattOrSample{2, 2}, - }; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(cal_frame_header_bad, cal_frame_bad, 2)); - - EXPECT_FALSE(IsCommandComplete()); - - // Flush and advance time to send retry for calibration frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - BattOrFrameHeader cal_frame_header_good{0, 2 * sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame_good[] = { - RawBattOrSample{1, 1}, RawBattOrSample{2, 2}, - }; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(cal_frame_header_good, cal_frame_good, 2)); - OnBytesSent(true); - - // Successfully receive the last data frame. - BattOrFrameHeader frame_header{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterDataFrameHasWrongLength) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::CALIBRATION_FRAME_RECEIVED, true); - - // Send a data frame with a mismatch between the frame length in the - // header and the actual frame length. - BattOrFrameHeader frame_header_bad{1, 2 * sizeof(RawBattOrSample)}; - RawBattOrSample frame_bad[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header_bad, frame_bad, 1)); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Send a data frame with the correct frame length. - BattOrFrameHeader frame_header_good{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header_good, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterCalibrationFrameMissingByte) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::SAMPLES_REQUEST_SENT, true); - - BattOrFrameHeader cal_frame_header_bad{0, 2 * sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame_bad[] = { - RawBattOrSample{1, 1}, RawBattOrSample{2, 2}, - }; - - // Remove the last byte from the frame to make it invalid. - std::unique_ptr<vector<char>> cal_frame_bad_bytes = - CreateFrame(cal_frame_header_bad, cal_frame_bad, 2); - cal_frame_bad_bytes->pop_back(); - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - std::move(cal_frame_bad_bytes)); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Send correct calibration frame and data frame. - BattOrFrameHeader cal_frame_header_good{0, 2 * sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame_good[] = { - RawBattOrSample{1, 1}, RawBattOrSample{2, 2}, - }; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(cal_frame_header_good, cal_frame_good, 2)); - OnBytesSent(true); - - // Successfully receive the last data frame. - BattOrFrameHeader frame_header{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterDataFrameMissingByte) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::CALIBRATION_FRAME_RECEIVED, true); - - BattOrFrameHeader frame_header_bad{1, 1 * sizeof(RawBattOrSample)}; - RawBattOrSample frame_bad[] = {RawBattOrSample{1, 1}}; - - // Remove the last byte from the frame to make it invalid. - std::unique_ptr<vector<char>> frame_bytes_bad = - CreateFrame(frame_header_bad, frame_bad, 1); - frame_bytes_bad->pop_back(); - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, std::move(frame_bytes_bad)); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Successfully receive the last data frame. - BattOrFrameHeader frame_header_good{1, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header_good, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingSucceedsAfterDataFrameArrivesOutOfOrder) { - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::CALIBRATION_FRAME_RECEIVED, true); - - // Frame with sequence number 1. - BattOrFrameHeader frame_header1{1, 1 * sizeof(RawBattOrSample)}; - RawBattOrSample frame1[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header1, frame1, 1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Skip frame with sequence number 2. - BattOrFrameHeader frame_header3{3, 1 * sizeof(RawBattOrSample)}; - RawBattOrSample frame3[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header3, frame3, 1)); - - // Flush and advance time to send retry for data frame. - OnConnectionFlushed(true); - AdvanceTickClock(base::TimeDelta::FromSeconds(1)); - OnBytesSent(true); - - EXPECT_FALSE(IsCommandComplete()); - - // Final frame with sequence number 2. - BattOrFrameHeader frame_header2{2, 0}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header2, nullptr, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, StopTracingCanReuseExistingConnection) { - ON_CALL(*GetAgent()->GetConnection(), IsOpen()).WillByDefault(Return(true)); - - GetAgent()->StopTracing(); - - RunStopTracingTo(BattOrAgentState::SAMPLES_END_FRAME_RECEIVED, false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, RecordClockSyncMarker) { - testing::InSequence s; - EXPECT_CALL(*GetAgent()->GetConnection(), Open()); - - BattOrControlMessage request_current_sample_msg{ - BATTOR_CONTROL_MESSAGE_TYPE_READ_SAMPLE_COUNT, 0, 0}; - EXPECT_CALL(*GetAgent()->GetConnection(), - SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - BufferEq(&request_current_sample_msg, - sizeof(request_current_sample_msg)), - sizeof(request_current_sample_msg))); - - EXPECT_CALL(*GetAgent()->GetConnection(), - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK)); - - GetAgent()->RecordClockSyncMarker(kClockSyncId); - RunRecordClockSyncMarkerTo( - BattOrAgentState::RECORD_CLOCK_SYNC_MARKER_COMPLETE, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, RecordClockSyncMarkerPrintsInStopTracingResult) { - // Record a clock sync marker that says CLOCK_SYNC_ID happened at sample #2. - GetAgent()->RecordClockSyncMarker(kClockSyncId); - - RunRecordClockSyncMarkerTo(BattOrAgentState::CURRENT_SAMPLE_REQUEST_SENT, - true); - - uint32_t current_sample = 1; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - ToCharVector(current_sample)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); - - GetTaskRunner()->FastForwardBy(base::TimeDelta::FromMilliseconds(100)); - GetAgent()->StopTracing(); - RunStopTracingTo(BattOrAgentState::SAMPLES_REQUEST_SENT, true); - - // Now run StopTracing, and make sure that CLOCK_SYNC_ID gets printed out with - // sample #2 (including calibration frame samples). - BattOrFrameHeader cal_frame_header{0, 1 * sizeof(RawBattOrSample)}; - RawBattOrSample cal_frame[] = {RawBattOrSample{1, 1}}; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(cal_frame_header, cal_frame, 1)); - OnBytesSent(true); - - BattOrFrameHeader frame_header1{1, 2 * sizeof(RawBattOrSample)}; - RawBattOrSample frame1[] = {RawBattOrSample{1, 1}, RawBattOrSample{2, 2}}; - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header1, frame1, 2)); - OnBytesSent(true); - - BattOrFrameHeader frame_header2{2, 0}; - - OnMessageRead(true, BATTOR_MESSAGE_TYPE_SAMPLES, - CreateFrame(frame_header2, {}, 0)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); - EXPECT_EQ( - "# BattOr\n# voltage_range [-2401.2, 2398.8] mV\n# " - "current_range [-1200.6, 1199.4] mA\n" - "# sample_rate 1000 Hz, gain 1.0x\n" - "0.00 0.0 0.0 <MY_MARKER>\n" - "1.00 0.6 1.2\n", - GetTrace()); -} - -TEST_F(BattOrAgentTest, RecordClockSyncMarkerFailsWithoutConnection) { - GetAgent()->RecordClockSyncMarker("my_marker"); - GetTaskRunner()->RunUntilIdle(); - - GetAgent()->OnConnectionOpened(false); - GetTaskRunner()->RunUntilIdle(); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_CONNECTION_FAILED, GetCommandError()); -} - -TEST_F(BattOrAgentTest, RecordClockSyncMarkerFailsIfSampleRequestSendFails) { - GetAgent()->RecordClockSyncMarker(kClockSyncId); - - RunRecordClockSyncMarkerTo(BattOrAgentState::CONNECTED, true); - OnBytesSent(false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_SEND_ERROR, GetCommandError()); -} - -TEST_F(BattOrAgentTest, RecordClockSyncMarkerFailsIfCurrentSampleReadFails) { - GetAgent()->RecordClockSyncMarker(kClockSyncId); - - RunRecordClockSyncMarkerTo(BattOrAgentState::CURRENT_SAMPLE_REQUEST_SENT, - true); - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_RECEIVE_ERROR, GetCommandError()); -} - -TEST_F(BattOrAgentTest, - RecordClockSyncMarkerFailsIfCurrentSampleReadHasWrongType) { - GetAgent()->RecordClockSyncMarker(kClockSyncId); - - RunRecordClockSyncMarkerTo(BattOrAgentState::CURRENT_SAMPLE_REQUEST_SENT, - true); - - uint32_t current_sample = 1; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL, - ToCharVector(current_sample)); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_UNEXPECTED_MESSAGE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, RecordClockSyncMarkerCanReuseExistingConnection) { - ON_CALL(*GetAgent()->GetConnection(), IsOpen()).WillByDefault(Return(true)); - - GetAgent()->RecordClockSyncMarker(kClockSyncId); - - RunRecordClockSyncMarkerTo( - BattOrAgentState::RECORD_CLOCK_SYNC_MARKER_COMPLETE, false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, GetFirmwareGitHash) { - GetAgent()->GetFirmwareGitHash(); - - RunGetFirmwareGitHashTo(BattOrAgentState::READ_GIT_HASH_RECEIVED, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); - EXPECT_EQ("GITHASH", GetGitHash()); -} - -TEST_F(BattOrAgentTest, GetFirmwareGitHashFailsWithoutConnection) { - GetAgent()->GetFirmwareGitHash(); - - GetTaskRunner()->RunUntilIdle(); - - GetAgent()->OnConnectionOpened(false); - GetTaskRunner()->RunUntilIdle(); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_CONNECTION_FAILED, GetCommandError()); -} - -TEST_F(BattOrAgentTest, GetFirmwareGitHashSucceedsReadHasWrongType) { - GetAgent()->GetFirmwareGitHash(); - - RunGetFirmwareGitHashTo(BattOrAgentState::GIT_FIRMWARE_HASH_REQUEST_SENT, - true); - - uint32_t current_sample = 1; - OnMessageRead(true, BATTOR_MESSAGE_TYPE_CONTROL, - ToCharVector(current_sample)); - - EXPECT_FALSE(IsCommandComplete()); - - RunGetFirmwareGitHashTo(BattOrAgentState::READ_GIT_HASH_RECEIVED, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, GetFirmwareRestartsConnectionUponRetry) { - GetAgent()->GetFirmwareGitHash(); - RunGetFirmwareGitHashTo(BattOrAgentState::GIT_FIRMWARE_HASH_REQUEST_SENT, - true); - - EXPECT_CALL(*GetAgent()->GetConnection(), Close()); - - OnMessageRead(false, BATTOR_MESSAGE_TYPE_CONTROL_ACK, nullptr); - - RunGetFirmwareGitHashTo(BattOrAgentState::READ_GIT_HASH_RECEIVED, true); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -TEST_F(BattOrAgentTest, GetFirmwareGitHashCanReuseExistingConnection) { - ON_CALL(*GetAgent()->GetConnection(), IsOpen()).WillByDefault(Return(true)); - - GetAgent()->GetFirmwareGitHash(); - - RunGetFirmwareGitHashTo(BattOrAgentState::READ_GIT_HASH_RECEIVED, false); - - EXPECT_TRUE(IsCommandComplete()); - EXPECT_EQ(BATTOR_ERROR_NONE, GetCommandError()); -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_connection.cc b/tools/battor_agent/battor_connection.cc deleted file mode 100644 index e6befa1..0000000 --- a/tools/battor_agent/battor_connection.cc +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/battor_connection.h" - -#include "base/bind.h" -#include "base/callback.h" -#include "device/serial/buffer.h" -#include "device/serial/serial_io_handler.h" -#include "net/base/io_buffer.h" - -namespace battor { - -BattOrConnection::BattOrConnection(Listener* listener) : listener_(listener) {} -BattOrConnection::~BattOrConnection() = default; - -} // namespace battor
diff --git a/tools/battor_agent/battor_connection.h b/tools/battor_agent/battor_connection.h deleted file mode 100644 index 3e4fc54..0000000 --- a/tools/battor_agent/battor_connection.h +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_H_ -#define TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_H_ - -#include <memory> -#include <vector> - -#include "base/macros.h" -#include "base/single_thread_task_runner.h" -#include "tools/battor_agent/battor_protocol_types.h" - -namespace battor { - -// A BattOrConnection is a wrapper around the serial connection to the BattOr -// that handles conversion of a message to and from the byte-level BattOr -// protocol. -// -// At a high-level, all BattOr messages consist of: -// -// 0x00 (1 byte start marker) -// uint8_t (1 byte header indicating the message type) -// data (message data, with 0x00s and 0x01s escaped with 0x02) -// 0x01 (1 byte end marker) -// -// For a more in-depth description of the protocol, see http://bit.ly/1NvNVc3. -class BattOrConnection { - public: - // The listener interface that must be implemented in order to interact with - // the BattOrConnection. - class Listener { - public: - virtual void OnConnectionOpened(bool success) = 0; - virtual void OnConnectionFlushed(bool success) = 0; - virtual void OnBytesSent(bool success) = 0; - virtual void OnMessageRead(bool success, - BattOrMessageType type, - std::unique_ptr<std::vector<char>> bytes) = 0; - }; - - BattOrConnection(Listener* listener); - virtual ~BattOrConnection() = 0; - - // Opens and initializes the serial connection to the BattOr and calls the - // listener's OnConnectionOpened() when complete. As part of this - // initialization, the serial connection is flushed by reading and throwing - // away bytes until the serial connection remains quiet for a sufficiently - // long time. This function must be called before using the - // BattOrConnection. If the connection is already open, calling this method - // reflushes the connection and then calls the listener's OnConnectionOpened - // method. - virtual void Open() = 0; - // Closes the serial connection and releases any handles being held. - virtual void Close() = 0; - // Returns true if the connection is currently open. - virtual bool IsOpen() = 0; - // Flushes the serial connection by reading and throwing away bytes until the - // serial connection remains quiet for a sufficiently long time. - virtual void Flush() = 0; - - // Sends the specified buffer over the serial connection and calls the - // listener's OnBytesSent() when complete. Note that bytes_to_send should not - // include the start, end, type, or escape bytes required by the BattOr - // protocol. - virtual void SendBytes(BattOrMessageType type, - const void* buffer, - size_t bytes_to_send) = 0; - - // Gets the next message available from the serial connection, reading the - // correct number of bytes based on the specified message type, and calls the - // listener's OnMessageRead() when complete. - virtual void ReadMessage(BattOrMessageType type) = 0; - - // Cancels the current message read operation. - virtual void CancelReadMessage() = 0; - - // Appends |str| to the serial log file if it exists. - virtual void LogSerial(const std::string& str) = 0; - - protected: - // The listener receiving the results of the commands being executed. - Listener* listener_; - - private: - DISALLOW_COPY_AND_ASSIGN(BattOrConnection); -}; - -} // namespace battor - -#endif // TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_H_
diff --git a/tools/battor_agent/battor_connection_impl.cc b/tools/battor_agent/battor_connection_impl.cc deleted file mode 100644 index 91b9fb8..0000000 --- a/tools/battor_agent/battor_connection_impl.cc +++ /dev/null
@@ -1,460 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/battor_connection_impl.h" - -#include <memory> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/memory/ptr_util.h" -#include "base/strings/stringprintf.h" -#include "base/threading/sequenced_task_runner_handle.h" -#include "base/time/default_tick_clock.h" -#include "device/serial/buffer.h" -#include "device/serial/serial_io_handler.h" -#include "net/base/io_buffer.h" -#include "tools/battor_agent/serial_utils.h" - -using base::StringPrintf; -using std::vector; - -namespace battor { - -namespace { - -// The command line switch used to specify a file to which serial communication -// is logged. -const char kSerialLogPathSwitch[] = "battor-serial-log"; - -// Serial configuration parameters for the BattOr. -const uint32_t kBattOrBitrate = 2000000; -const device::mojom::SerialDataBits kBattOrDataBits = - device::mojom::SerialDataBits::EIGHT; -const device::mojom::SerialParityBit kBattOrParityBit = - device::mojom::SerialParityBit::NONE; -const device::mojom::SerialStopBits kBattOrStopBit = - device::mojom::SerialStopBits::ONE; -const bool kBattOrCtsFlowControl = true; -const bool kBattOrHasCtsFlowControl = true; -// The maximum BattOr message is 50kB long. -const size_t kMaxMessageSizeBytes = 50000; -// The number of seconds allowed for the connection to open before timing out. -const uint8_t kConnectTimeoutSeconds = 10; -const size_t kFlushBufferSize = 50000; -// The length of time that must pass without receiving any bytes in order for a -// flush to be considered complete. -const uint16_t kFlushQuietPeriodThresholdMs = 50; - -// Returns the maximum number of bytes that could be required to read a message -// of the specified type. -size_t GetMaxBytesForMessageType(BattOrMessageType type) { - switch (type) { - case BATTOR_MESSAGE_TYPE_CONTROL: - return 2 * sizeof(BattOrControlMessage) + 3; - case BATTOR_MESSAGE_TYPE_CONTROL_ACK: - // The BattOr EEPROM is sent back with this type, even though it's - // technically more of a response than an ack. We have to make sure that - // we read enough bytes to accommodate this behavior. - return 2 * sizeof(BattOrEEPROM) + 3; - case BATTOR_MESSAGE_TYPE_SAMPLES: - return 2 * kMaxMessageSizeBytes + 3; - default: - return 0; - } -} - -} // namespace - -BattOrConnectionImpl::BattOrConnectionImpl( - const std::string& path, - BattOrConnection::Listener* listener, - scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) - : BattOrConnection(listener), - path_(path), - is_open_(false), - ui_thread_task_runner_(ui_thread_task_runner) { - std::string serial_log_path = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - kSerialLogPathSwitch); - if (!serial_log_path.empty()) { - serial_log_.open(serial_log_path.c_str(), - std::fstream::out | std::fstream::trunc); - } - tick_clock_ = base::DefaultTickClock::GetInstance(); -} - -BattOrConnectionImpl::~BattOrConnectionImpl() = default; - -void BattOrConnectionImpl::Open() { - if (io_handler_) { - LogSerial("Serial connection already open."); - - // Skip flushing the connection because it's already open. - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&Listener::OnConnectionOpened, - base::Unretained(listener_), true)); - return; - } - - io_handler_ = CreateIoHandler(); - - device::mojom::SerialConnectionOptions options; - options.bitrate = kBattOrBitrate; - options.data_bits = kBattOrDataBits; - options.parity_bit = kBattOrParityBit; - options.stop_bits = kBattOrStopBit; - options.cts_flow_control = kBattOrCtsFlowControl; - options.has_cts_flow_control = kBattOrHasCtsFlowControl; - - LogSerial("Opening serial connection."); - SetTimeout(base::TimeDelta::FromSeconds(kConnectTimeoutSeconds)); - io_handler_->Open( - path_, options, - base::BindOnce(&BattOrConnectionImpl::OnOpened, AsWeakPtr())); -} - -void BattOrConnectionImpl::OnOpened(bool success) { - LogSerial(StringPrintf("Serial connection open finished with success: %d.", - success)); - timeout_callback_.Cancel(); - - if (!success) { - Close(); - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&Listener::OnConnectionOpened, - base::Unretained(listener_), false)); - return; - } - - is_open_ = true; - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&Listener::OnConnectionOpened, - base::Unretained(listener_), true)); -} - -void BattOrConnectionImpl::Close() { - LogSerial("Serial connection closed."); - io_handler_ = nullptr; - is_open_ = false; -} - -bool BattOrConnectionImpl::IsOpen() { - return is_open_; -} - -void BattOrConnectionImpl::SendBytes(BattOrMessageType type, - const void* buffer, - size_t bytes_to_send) { - const uint8_t* bytes = reinterpret_cast<const uint8_t*>(buffer); - - // Reserve a send buffer with enough extra bytes for the start, type, end, and - // escape bytes. - vector<uint8_t> data; - data.reserve(2 * bytes_to_send + 3); - - data.push_back(BATTOR_CONTROL_BYTE_START); - data.push_back(type); - - for (size_t i = 0; i < bytes_to_send; i++) { - if (bytes[i] == BATTOR_CONTROL_BYTE_START || - bytes[i] == BATTOR_CONTROL_BYTE_END || - bytes[i] == BATTOR_CONTROL_BYTE_ESCAPE) - data.push_back(BATTOR_CONTROL_BYTE_ESCAPE); - - data.push_back(bytes[i]); - } - - data.push_back(BATTOR_CONTROL_BYTE_END); - - LogSerial(StringPrintf("Bytes sent: %s.", ByteVectorToString(data).c_str())); - - pending_write_length_ = data.size(); - io_handler_->Write(std::make_unique<device::SendBuffer>( - data, base::BindOnce(&BattOrConnectionImpl::OnBytesSent, AsWeakPtr()))); -} - -void BattOrConnectionImpl::ReadMessage(BattOrMessageType type) { - LogSerial("Read requested."); - - pending_read_message_type_ = type; - size_t message_max_bytes = GetMaxBytesForMessageType(type); - - LogSerial( - "Before doing a serial read, checking to see if we already have a " - "complete message in the 'already read' buffer."); - - BattOrMessageType parsed_type; - std::unique_ptr<vector<char>> bytes(new vector<char>()); - bytes->reserve(message_max_bytes); - ParseMessageError parse_message_error = - ParseMessage(&parsed_type, bytes.get()); - if (parse_message_error == ParseMessageError::NONE) { - LogSerial("Complete message found."); - EndReadBytesForMessage(true, parsed_type, std::move(bytes)); - return; - } - - if (parse_message_error != ParseMessageError::NOT_ENOUGH_BYTES) { - LogSerial(StringPrintf( - "Read failed because, before performing a serial read, the message in " - "the 'already read' buffer had an irrecoverable error with code: %d.", - parse_message_error)); - EndReadBytesForMessage(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); - return; - } - - LogSerial("No complete message found in the 'already read' buffer."); - BeginReadBytesForMessage(message_max_bytes - already_read_buffer_.size()); -} - -void BattOrConnectionImpl::CancelReadMessage() { - LogSerial("Canceling read due to timeout."); - io_handler_->CancelRead(device::mojom::SerialReceiveError::TIMEOUT); -} - -scoped_refptr<device::SerialIoHandler> BattOrConnectionImpl::CreateIoHandler() { - return device::SerialIoHandler::Create(ui_thread_task_runner_); -} - -void BattOrConnectionImpl::BeginReadBytesForMessage(size_t max_bytes_to_read) { - LogSerial(StringPrintf("(message) Starting read of up to %zu bytes.", - max_bytes_to_read)); - - pending_read_buffer_ = base::MakeRefCounted<net::IOBuffer>(max_bytes_to_read); - - io_handler_->Read(std::make_unique<device::ReceiveBuffer>( - pending_read_buffer_, static_cast<uint32_t>(max_bytes_to_read), - base::BindOnce(&BattOrConnectionImpl::OnBytesReadForMessage, - AsWeakPtr()))); -} - -void BattOrConnectionImpl::OnBytesReadForMessage( - int bytes_read, - device::mojom::SerialReceiveError error) { - if (error != device::mojom::SerialReceiveError::NONE) { - LogSerial(StringPrintf( - "(message) Read failed due to serial read failure with error code: %d.", - static_cast<int>(error))); - EndReadBytesForMessage(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); - return; - } - - // NOTE: Zero bytes may have been read. - - if (pending_read_message_type_ == BATTOR_MESSAGE_TYPE_SAMPLES) { - // If we're reading samples, don't log every byte that we receive. This - // exacerbates a problem on Mac wherein we can't process sample frames - // quickly enough to prevent the serial buffer from overflowing, causing us - // to drop frames. - LogSerial(StringPrintf("(message) %d more bytes read.", bytes_read)); - } else { - LogSerial(StringPrintf( - "(message) %d more bytes read: %s.", bytes_read, - CharArrayToString(pending_read_buffer_->data(), bytes_read).c_str())); - } - - already_read_buffer_.insert(already_read_buffer_.end(), - pending_read_buffer_->data(), - pending_read_buffer_->data() + bytes_read); - - BattOrMessageType type; - size_t message_max_bytes = - GetMaxBytesForMessageType(pending_read_message_type_); - std::unique_ptr<vector<char>> bytes(new vector<char>()); - bytes->reserve(message_max_bytes); - - ParseMessageError parse_message_error = ParseMessage(&type, bytes.get()); - if (parse_message_error == ParseMessageError::NOT_ENOUGH_BYTES) { - if (already_read_buffer_.size() >= message_max_bytes) { - LogSerial( - "(message) Read failed due to no complete message after max read " - "length."); - EndReadBytesForMessage(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); - return; - } - - LogSerial("(message) Still incomplete: reading more bytes.)"); - BeginReadBytesForMessage(message_max_bytes - already_read_buffer_.size()); - return; - } - - if (parse_message_error != ParseMessageError::NONE) { - LogSerial( - StringPrintf("(message) Read failed due to the message containing an " - "irrecoverable error: %d.", - parse_message_error)); - EndReadBytesForMessage(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); - return; - } - - if (type != pending_read_message_type_) { - LogSerial( - "(message) Read failed due to receiving a message of the wrong type."); - EndReadBytesForMessage(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr); - return; - } - - EndReadBytesForMessage(true, type, std::move(bytes)); -} - -void BattOrConnectionImpl::EndReadBytesForMessage( - bool success, - BattOrMessageType type, - std::unique_ptr<vector<char>> bytes) { - LogSerial(StringPrintf("(message) Read finished with success: %d.", success)); - - pending_read_buffer_ = nullptr; - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&Listener::OnMessageRead, base::Unretained(listener_), success, - type, base::Passed(std::move(bytes)))); -} - -void BattOrConnectionImpl::Flush() { - already_read_buffer_.clear(); - flush_quiet_period_start_ = tick_clock_->NowTicks(); - BeginReadBytesForFlush(); -} - -void BattOrConnectionImpl::BeginReadBytesForFlush() { - base::TimeDelta quiet_period_duration = - tick_clock_->NowTicks() - flush_quiet_period_start_; - LogSerial( - StringPrintf("(flush) Starting read (quiet period has lasted %f ms).", - quiet_period_duration.InMillisecondsF())); - - pending_read_buffer_ = base::MakeRefCounted<net::IOBuffer>(kFlushBufferSize); - - io_handler_->Read(std::make_unique<device::ReceiveBuffer>( - pending_read_buffer_, static_cast<uint32_t>(kFlushBufferSize), - base::BindOnce(&BattOrConnectionImpl::OnBytesReadForFlush, - base::Unretained(this)))); - SetTimeout(base::TimeDelta::FromMilliseconds(kFlushQuietPeriodThresholdMs)); -} - -void BattOrConnectionImpl::SetTimeout(base::TimeDelta timeout) { - timeout_callback_.Reset( - base::Bind(&BattOrConnectionImpl::CancelReadMessage, AsWeakPtr())); - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, timeout_callback_.callback(), timeout); -} - -void BattOrConnectionImpl::OnBytesReadForFlush( - int bytes_read, - device::mojom::SerialReceiveError error) { - timeout_callback_.Cancel(); - - if (error != device::mojom::SerialReceiveError::NONE && - error != device::mojom::SerialReceiveError::TIMEOUT) { - LogSerial(StringPrintf( - "(flush) Read failed due to serial read failure with error code: %d.", - static_cast<int>(error))); - pending_read_buffer_ = nullptr; - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&Listener::OnConnectionFlushed, - base::Unretained(listener_), false)); - return; - } - - LogSerial(StringPrintf("(flush) %i additional bytes read.", bytes_read)); - if (bytes_read == 0 || error == device::mojom::SerialReceiveError::TIMEOUT) { - // Reading zero bytes or a serial read timeout both indicate that the - // connection was quiet. - base::TimeDelta quiet_period_duration = - tick_clock_->NowTicks() - flush_quiet_period_start_; - if (quiet_period_duration >= - base::TimeDelta::FromMilliseconds(kFlushQuietPeriodThresholdMs)) { - LogSerial("(flush) Quiet period has finished."); - pending_read_buffer_ = nullptr; - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&Listener::OnConnectionFlushed, - base::Unretained(listener_), true)); - return; - } - - // If we didn't receive bytes but the quiet period hasn't elapsed, try to - // read again after a delay. - LogSerial(StringPrintf("(flush) Reading more bytes after %u ms delay.", - kFlushQuietPeriodThresholdMs)); - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&BattOrConnectionImpl::BeginReadBytesForFlush, - AsWeakPtr()), - base::TimeDelta::FromMilliseconds(kFlushQuietPeriodThresholdMs)); - return; - } - - // We received additional bytes: restart the quiet period and read more bytes. - flush_quiet_period_start_ = tick_clock_->NowTicks(); - BeginReadBytesForFlush(); -} - -BattOrConnectionImpl::ParseMessageError BattOrConnectionImpl::ParseMessage( - BattOrMessageType* type, - vector<char>* bytes) { - if (already_read_buffer_.size() <= 3) - return ParseMessageError::NOT_ENOUGH_BYTES; - - // The first byte is the start byte. - if (already_read_buffer_[0] != BATTOR_CONTROL_BYTE_START) - return ParseMessageError::MISSING_START_BYTE; - - // The second byte specifies the message type. - *type = static_cast<BattOrMessageType>(already_read_buffer_[1]); - - if (*type < static_cast<uint8_t>(BATTOR_MESSAGE_TYPE_CONTROL) || - *type > static_cast<uint8_t>(BATTOR_MESSAGE_TYPE_PRINT)) - return ParseMessageError::INVALID_MESSAGE_TYPE; - - // After that comes the message bytes. - bool escape_next_byte = false; - for (size_t i = 2; i < already_read_buffer_.size(); i++) { - char next_byte = already_read_buffer_[i]; - - if (escape_next_byte) { - bytes->push_back(next_byte); - escape_next_byte = false; - continue; - } - - switch (next_byte) { - case BATTOR_CONTROL_BYTE_START: - // Two start bytes in a message is invalid. - return ParseMessageError::TOO_MANY_START_BYTES; - - case BATTOR_CONTROL_BYTE_END: - already_read_buffer_.erase(already_read_buffer_.begin(), - already_read_buffer_.begin() + i + 1); - return ParseMessageError::NONE; - - case BATTOR_CONTROL_BYTE_ESCAPE: - escape_next_byte = true; - continue; - - default: - bytes->push_back(next_byte); - } - } - - // If we made it to the end of the read buffer and no end byte was seen, then - // we don't have a complete message. - return ParseMessageError::NOT_ENOUGH_BYTES; -} - -void BattOrConnectionImpl::OnBytesSent(int bytes_sent, - device::mojom::SerialSendError error) { - bool success = (error == device::mojom::SerialSendError::NONE) && - (pending_write_length_ == static_cast<size_t>(bytes_sent)); - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&Listener::OnBytesSent, base::Unretained(listener_), success)); -} - -void BattOrConnectionImpl::LogSerial(const std::string& str) { - serial_log_ << base::Time::Now() << ": " << str << std::endl << std::endl; -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_connection_impl.h b/tools/battor_agent/battor_connection_impl.h deleted file mode 100644 index ee2cc39..0000000 --- a/tools/battor_agent/battor_connection_impl.h +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_ -#define TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_ - -#include <fstream> -#include <memory> -#include <vector> - -#include "base/callback_forward.h" -#include "base/cancelable_callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "base/time/tick_clock.h" -#include "services/device/public/mojom/serial.mojom.h" -#include "tools/battor_agent/battor_connection.h" -#include "tools/battor_agent/battor_error.h" -#include "tools/battor_agent/battor_protocol_types.h" - -namespace device { -class SerialIoHandler; -} -namespace net { -class IOBuffer; -} - -namespace battor { - -// A BattOrConnectionImpl is a concrete implementation of a BattOrConnection. -class BattOrConnectionImpl - : public BattOrConnection, - public base::SupportsWeakPtr<BattOrConnectionImpl> { - public: - BattOrConnectionImpl( - const std::string& path, - BattOrConnection::Listener* listener, - scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); - ~BattOrConnectionImpl() override; - - void Open() override; - void Close() override; - bool IsOpen() override; - void SendBytes(BattOrMessageType type, - const void* buffer, - size_t bytes_to_send) override; - void ReadMessage(BattOrMessageType type) override; - void CancelReadMessage() override; - void LogSerial(const std::string& str) override; - - // Flushes the serial connection to the BattOr, reading and throwing away - // bytes from the serial connection until the connection is quiet for a - // sufficiently long time. This also discards any trailing bytes from past - // successful reads. - void Flush() override; - - protected: - // Overridden by the test to use a fake serial connection. - virtual scoped_refptr<device::SerialIoHandler> CreateIoHandler(); - - // IO handler capable of reading and writing from the serial connection. - scoped_refptr<device::SerialIoHandler> io_handler_; - - const base::TickClock* tick_clock_; - - private: - void OnOpened(bool success); - - // Reads the specified number of additional bytes and adds them to the pending - // read buffer. - void BeginReadBytesForMessage(size_t bytes_to_read); - - // Internal callback for when bytes are read. This method may trigger - // additional reads if any newly read bytes are escape bytes. - void OnBytesReadForMessage(int bytes_read, - device::mojom::SerialReceiveError error); - - void EndReadBytesForMessage(bool success, - BattOrMessageType type, - std::unique_ptr<std::vector<char>> data); - - void BeginReadBytesForFlush(); - void OnBytesReadForFlush(int bytes_read, - device::mojom::SerialReceiveError error); - void SetTimeout(base::TimeDelta timeout); - - // Pulls off the next complete message from already_read_buffer_, returning - // its type and contents through out parameters and any error that occurred - // through the return value. - enum ParseMessageError { - NONE = 0, - NOT_ENOUGH_BYTES = 1, - MISSING_START_BYTE = 2, - INVALID_MESSAGE_TYPE = 3, - TOO_MANY_START_BYTES = 4 - }; - - ParseMessageError ParseMessage(BattOrMessageType* type, - std::vector<char>* data); - - // Internal callback for when bytes are sent. - void OnBytesSent(int bytes_sent, device::mojom::SerialSendError error); - - // The path of the BattOr. - std::string path_; - - // Indicates whether the connection is currently open. - bool is_open_; - - // All bytes that have already been read from the serial stream, but have not - // yet been given to the listener as a complete message. - std::vector<char> already_read_buffer_; - // The bytes that were read in the pending read. - scoped_refptr<net::IOBuffer> pending_read_buffer_; - // The type of message we're looking for in the pending read. - BattOrMessageType pending_read_message_type_; - - // The total number of bytes that we're expecting to send. - size_t pending_write_length_; - - // The start of the period over which no bytes must be read from the serial - // connection in order for Flush() to be considered complete. - base::TimeTicks flush_quiet_period_start_; - - // The timeout for the current action. - base::CancelableClosure timeout_callback_; - - // Threads needed for serial communication. - scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; - - std::fstream serial_log_; - - DISALLOW_COPY_AND_ASSIGN(BattOrConnectionImpl); -}; - -} // namespace battor - -#endif // TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_
diff --git a/tools/battor_agent/battor_connection_impl_unittest.cc b/tools/battor_agent/battor_connection_impl_unittest.cc deleted file mode 100644 index eddce4d..0000000 --- a/tools/battor_agent/battor_connection_impl_unittest.cc +++ /dev/null
@@ -1,731 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/battor_connection_impl.h" - -#include <memory> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/memory/ptr_util.h" -#include "base/memory/weak_ptr.h" -#include "base/test/simple_test_tick_clock.h" -#include "base/test/test_mock_time_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "device/serial/test_serial_io_handler.h" -#include "services/device/public/mojom/serial.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "tools/battor_agent/battor_protocol_types.h" - -namespace { - -void NullWriteCallback(int, device::mojom::SerialSendError) {} -void NullReadCallback(int, device::mojom::SerialReceiveError) {} - -} // namespace - -namespace battor { - -// TestableBattOrConnection uses a fake serial connection be testable. -class TestableBattOrConnection : public BattOrConnectionImpl { - public: - TestableBattOrConnection(BattOrConnection::Listener* listener, - const base::TickClock* tick_clock) - : BattOrConnectionImpl("/dev/test", listener, nullptr) { - tick_clock_ = tick_clock; - } - scoped_refptr<device::SerialIoHandler> CreateIoHandler() override { - return device::TestSerialIoHandler::Create(); - } - - device::TestSerialIoHandler* GetIoHandler() { - return reinterpret_cast<device::TestSerialIoHandler*>(io_handler_.get()); - } -}; - -// BattOrConnectionImplTest provides a BattOrConnection and captures the -// results of all its commands. -class BattOrConnectionImplTest : public testing::Test, - public BattOrConnection::Listener { - public: - BattOrConnectionImplTest() - : task_runner_(new base::TestMockTimeTaskRunner()), - thread_task_runner_handle_(task_runner_) {} - - void OnConnectionOpened(bool success) override { - is_open_complete_ = true; - open_success_ = success; - }; - void OnConnectionFlushed(bool success) override { - is_flush_complete_ = true; - flush_success_ = success; - }; - void OnBytesSent(bool success) override { send_success_ = success; } - void OnMessageRead(bool success, - BattOrMessageType type, - std::unique_ptr<std::vector<char>> bytes) override { - is_read_complete_ = true; - read_success_ = success; - read_type_ = type; - read_bytes_ = std::move(bytes); - } - - protected: - void SetUp() override { - connection_.reset( - new TestableBattOrConnection(this, task_runner_->GetMockTickClock())); - task_runner_->ClearPendingTasks(); - } - - void OpenConnection() { - is_open_complete_ = false; - connection_->Open(); - task_runner_->RunUntilIdle(); - } - - void FlushConnection() { - is_flush_complete_ = false; - connection_->Flush(); - task_runner_->RunUntilIdle(); - } - - bool IsConnectionOpen() { return connection_->IsOpen(); } - - void CloseConnection() { connection_->Close(); } - - void ReadMessage(BattOrMessageType type) { - is_read_complete_ = false; - connection_->ReadMessage(type); - task_runner_->RunUntilIdle(); - } - - // Reads the specified number of bytes directly from the serial connection. - scoped_refptr<net::IOBuffer> ReadMessageRaw(int bytes_to_read) { - scoped_refptr<net::IOBuffer> buffer( - new net::IOBuffer((size_t)bytes_to_read)); - - connection_->GetIoHandler()->Read(std::make_unique<device::ReceiveBuffer>( - buffer, bytes_to_read, base::BindOnce(&NullReadCallback))); - task_runner_->RunUntilIdle(); - - return buffer; - } - - void SendControlMessage(BattOrControlMessageType type, - uint16_t param1, - uint16_t param2) { - BattOrControlMessage msg{type, param1, param2}; - connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, - reinterpret_cast<char*>(&msg), sizeof(msg)); - task_runner_->RunUntilIdle(); - } - - void ForceReceiveError(device::mojom::SerialReceiveError error) { - connection_->GetIoHandler()->ForceReceiveError(error); - task_runner_->RunUntilIdle(); - } - - // Writes the specified bytes directly to the serial connection. - void SendBytesRaw(const char* data, uint16_t bytes_to_send) { - connection_->GetIoHandler()->Write(std::make_unique<device::SendBuffer>( - std::vector<uint8_t>(data, data + bytes_to_send), - base::BindOnce(&NullWriteCallback))); - task_runner_->RunUntilIdle(); - } - - void AdvanceTickClock(base::TimeDelta delta) { - task_runner_->FastForwardBy(delta); - } - - bool GetOpenSuccess() { return open_success_; } - bool GetFlushSuccess() { return flush_success_; } - bool IsOpenComplete() { return is_open_complete_; } - bool IsFlushComplete() { return is_flush_complete_; } - bool GetSendSuccess() { return send_success_; } - bool IsReadComplete() { return is_read_complete_; } - bool GetReadSuccess() { return read_success_; } - BattOrMessageType GetReadType() { return read_type_; } - std::vector<char>* GetReadMessage() { return read_bytes_.get(); } - - private: - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; - base::ThreadTaskRunnerHandle thread_task_runner_handle_; - - std::unique_ptr<TestableBattOrConnection> connection_; - - // Result from the last connect command. - bool open_success_; - // Results from the last flush command. - bool flush_success_; - bool is_open_complete_; - bool is_flush_complete_; - // Result from the last send command. - bool send_success_; - // Results from the last read command. - bool is_read_complete_; - bool read_success_; - BattOrMessageType read_type_; - std::unique_ptr<std::vector<char>> read_bytes_; -}; - -TEST_F(BattOrConnectionImplTest, OpenConnectionSucceedsImmediately) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - ASSERT_TRUE(IsConnectionOpen()); -} - -TEST_F(BattOrConnectionImplTest, IsOpenFalseAfterClosingConnection) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - ASSERT_TRUE(IsConnectionOpen()); - - CloseConnection(); - - ASSERT_FALSE(IsConnectionOpen()); -} - -TEST_F(BattOrConnectionImplTest, FlushConnectionSucceedsOnlyAfterTimeout) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - FlushConnection(); - ASSERT_FALSE(IsFlushComplete()); - - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - ASSERT_TRUE(IsFlushComplete()); - ASSERT_TRUE(GetFlushSuccess()); -} - -#if defined(ADDRESS_SANITIZER) -// https://crbug.com/843729 -#define MAYBE_FlushConnectionFlushesAlreadyReadBuffer \ - DISABLED_FlushConnectionFlushesAlreadyReadBuffer -#else -#define MAYBE_FlushConnectionFlushesAlreadyReadBuffer \ - FlushConnectionFlushesAlreadyReadBuffer -#endif -TEST_F(BattOrConnectionImplTest, - MAYBE_FlushConnectionFlushesAlreadyReadBuffer) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - // Send two data frames and only read one of them. When reading data frames, - // we try to read a large chunk from the wire due to the large potential size - // of a data frame (~100kB). By sending two tiny data frames on the wire and - // reading back one of them, we know that we read past the end of the first - // message and all of the second message because the data frames were so - // small. These extra bytes that were unnecesssary for the first message were - // storied internally by BattOrConnectionImpl, and we want to ensure that - // Flush() clears this internal data. - const char data[] = { - BATTOR_CONTROL_BYTE_START, - BATTOR_MESSAGE_TYPE_SAMPLES, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 9); - SendBytesRaw(data, 9); - ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES); - - CloseConnection(); - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - FlushConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES); - - // The read should be incomplete due to no data being on the wire - the second - // control message was cleared by the slow flush. - ASSERT_FALSE(IsReadComplete()); -} - -TEST_F(BattOrConnectionImplTest, FlushConnectionNewBytesRestartQuietPeriod) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - FlushConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(49)); - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 4, 7); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(49)); - - // The connection should not yet be opened because we received new bytes at - // t=49ms, and at t=98ms the new 50ms quiet period hasn't yet elapsed. - ASSERT_FALSE(IsFlushComplete()); - - AdvanceTickClock(base::TimeDelta::FromMilliseconds(1)); - - ASSERT_TRUE(IsFlushComplete()); -} - -#if defined(ADDRESS_SANITIZER) -// https://crbug.com/843729 -#define MAYBE_FlushConnectionFlushesBytesReceivedInQuietPeriod \ - DISABLED_FlushConnectionFlushesBytesReceivedInQuietPeriod -#else -#define MAYBE_FlushConnectionFlushesBytesReceivedInQuietPeriod \ - FlushConnectionFlushesBytesReceivedInQuietPeriod -#endif -TEST_F(BattOrConnectionImplTest, - MAYBE_FlushConnectionFlushesBytesReceivedInQuietPeriod) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - FlushConnection(); - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 4, 7); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(5)); - ASSERT_FALSE(IsFlushComplete()); - - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 4, 7); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - ASSERT_TRUE(IsFlushComplete()); - ASSERT_TRUE(GetFlushSuccess()); - - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - // The read should hang because the control message that arrived mid quiet - // period was thrown out. - ASSERT_FALSE(IsReadComplete()); -} - -TEST_F(BattOrConnectionImplTest, FlushConnectionFlushesMultipleReadsOfData) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - // Send 10 full flush buffers worth of data. - char data[50000]; - for (size_t i = 0; i < 50000; i++) - data[i] = '0'; - for (int i = 0; i < 10; i++) - SendBytesRaw(data, 50000); - - FlushConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 4, 7); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - // Even though 500kB of garbage data was sent before the valid control - // message on the serial connection, the slow flush should have cleared it - // all, resulting in a successful read. - ASSERT_TRUE(IsReadComplete()); - ASSERT_TRUE(GetReadSuccess()); -} - -#if defined(ADDRESS_SANITIZER) -// https://crbug.com/843729 -#define MAYBE_FlushIncompleteBeforeTimeout DISABLED_FlushIncompleteBeforeTimeout -#else -#define MAYBE_FlushIncompleteBeforeTimeout FlushIncompleteBeforeTimeout -#endif -TEST_F(BattOrConnectionImplTest, MAYBE_FlushIncompleteBeforeTimeout) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - FlushConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(49)); - - ASSERT_FALSE(IsFlushComplete()); -} - -TEST_F(BattOrConnectionImplTest, FlushFailsWithNonTimeoutError) { - OpenConnection(); - ASSERT_TRUE(IsOpenComplete()); - ASSERT_TRUE(GetOpenSuccess()); - - FlushConnection(); - ForceReceiveError(device::mojom::SerialReceiveError::DISCONNECTED); - - ASSERT_FALSE(GetFlushSuccess()); -} - -TEST_F(BattOrConnectionImplTest, ControlSendEscapesStartBytesCorrectly) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - SendControlMessage( - BATTOR_CONTROL_MESSAGE_TYPE_INIT, - BATTOR_CONTROL_BYTE_START, - BATTOR_CONTROL_BYTE_START); - - const char expected_data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_MESSAGE_TYPE_INIT, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_BYTE_START, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_BYTE_START, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_END, - }; - - ASSERT_TRUE(GetSendSuccess()); - ASSERT_EQ(0, std::memcmp(ReadMessageRaw(13)->data(), expected_data, 13)); -} - -TEST_F(BattOrConnectionImplTest, ControlSendEscapesEndBytesCorrectly) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - SendControlMessage( - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - BATTOR_CONTROL_BYTE_END, - BATTOR_CONTROL_BYTE_END); - - const char expected_data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_MESSAGE_TYPE_RESET, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_BYTE_END, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_BYTE_END, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_END, - }; - - ASSERT_TRUE(GetSendSuccess()); - ASSERT_EQ(0, std::memcmp(ReadMessageRaw(13)->data(), expected_data, 13)); -} - -TEST_F(BattOrConnectionImplTest, ControlSendEscapesEscapeBytesCorrectly) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - SendControlMessage( - BATTOR_CONTROL_MESSAGE_TYPE_SELF_TEST, - BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_BYTE_ESCAPE); - - const char expected_data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_MESSAGE_TYPE_SELF_TEST, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_END, - }; - - ASSERT_TRUE(GetSendSuccess()); - ASSERT_EQ(0, std::memcmp(ReadMessageRaw(13)->data(), expected_data, 13)); -} - -TEST_F(BattOrConnectionImplTest, ControlSendEscapesParametersCorrectly) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - // Check if the two control parameters are ordered and escaped properly. - // This also checks the byte ordering of the two 16-bit control message - // parameters, which should be little-endian on the wire. - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0x0100, 0x0002); - - const char expected_data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, 0x01, - BATTOR_CONTROL_BYTE_ESCAPE, 0x02, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_END, - }; - - ASSERT_TRUE(GetSendSuccess()); - ASSERT_EQ(0, std::memcmp(ReadMessageRaw(12)->data(), expected_data, 12)); -} - -TEST_F(BattOrConnectionImplTest, InitSendsCorrectBytes) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); - - const char expected_data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_MESSAGE_TYPE_INIT, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_END, - }; - - ASSERT_TRUE(GetSendSuccess()); - ASSERT_EQ(0, std::memcmp(ReadMessageRaw(13)->data(), expected_data, 13)); -} - -TEST_F(BattOrConnectionImplTest, ResetSendsCorrectBytes) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0); - - const char expected_data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, BATTOR_CONTROL_MESSAGE_TYPE_RESET, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_ESCAPE, 0x00, - BATTOR_CONTROL_BYTE_END, - }; - - ASSERT_TRUE(GetSendSuccess()); - ASSERT_EQ(0, std::memcmp(ReadMessageRaw(13)->data(), expected_data, 13)); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageControlMessage) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, - BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - 0x04, - 0x04, - 0x04, - 0x04, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 9); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x04, 0x04, 0x04, - 0x04}; - - ASSERT_TRUE(IsReadComplete()); - ASSERT_TRUE(GetReadSuccess()); - ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, GetReadType()); - ASSERT_EQ(0, std::memcmp(GetReadMessage()->data(), expected, 5)); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageInvalidType) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, - static_cast<char>(UINT8_MAX), - BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - 0x04, - 0x04, - 0x04, - 0x04, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 7); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - ASSERT_TRUE(IsReadComplete()); - ASSERT_FALSE(GetReadSuccess()); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageEndsMidMessage) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, - BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - 0x04, - }; - SendBytesRaw(data, 5); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - // The first read should recognize that a second read is necessary. - ASSERT_FALSE(IsReadComplete()); - - ForceReceiveError(device::mojom::SerialReceiveError::TIMEOUT); - - // The second read should fail due to the time out. - ASSERT_TRUE(IsReadComplete()); - ASSERT_FALSE(GetReadSuccess()); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageMissingEndByte) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, - BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - 0x04, - 0x04, - 0x04, - 0x04, - }; - SendBytesRaw(data, 6); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - // The first read should recognize that a second read is necessary. - ASSERT_FALSE(IsReadComplete()); - - ForceReceiveError(device::mojom::SerialReceiveError::TIMEOUT); - - // The second read should fail due to the time out. - ASSERT_TRUE(IsReadComplete()); - ASSERT_FALSE(GetReadSuccess()); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageWithEscapeCharacters) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, - BATTOR_MESSAGE_TYPE_CONTROL, - BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - BATTOR_CONTROL_BYTE_ESCAPE, - 0x00, - 0x04, - 0x04, - 0x04, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 10); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - const char expected[] = {BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x00}; - - ASSERT_TRUE(IsReadComplete()); - ASSERT_TRUE(GetReadSuccess()); - ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, GetReadType()); - ASSERT_EQ(0, std::memcmp(GetReadMessage()->data(), expected, 2)); -} - -TEST_F(BattOrConnectionImplTest, ReadControlMessage) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 4, 7); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - ASSERT_TRUE(IsReadComplete()); - ASSERT_TRUE(GetReadSuccess()); - ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, GetReadType()); - - BattOrControlMessage* msg = - reinterpret_cast<BattOrControlMessage*>(GetReadMessage()->data()); - - ASSERT_EQ(BATTOR_CONTROL_MESSAGE_TYPE_RESET, msg->type); - ASSERT_EQ(4, msg->param1); - ASSERT_EQ(7, msg->param2); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageExtraBytesStoredBetweenReads) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - // Send a samples frame with length and sequence number of zero. - const char data[] = { - BATTOR_CONTROL_BYTE_START, - BATTOR_MESSAGE_TYPE_SAMPLES, - 0x02, - 0x00, - 0x02, - 0x00, - 0x02, - 0x00, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 9); - SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 5, 8); - - // When reading sample frames, we're forced to read lots because each frame - // could be up to 50kB long. By reading a really short sample frame (like - // the zero-length one above), the BattOrConnection is forced to store - // whatever extra data it finds in the serial stream - in this case, the - // init control message that we sent. - ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES); - - ASSERT_TRUE(IsReadComplete()); - ASSERT_TRUE(GetReadSuccess()); - ASSERT_EQ(BATTOR_MESSAGE_TYPE_SAMPLES, GetReadType()); - - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - ASSERT_TRUE(IsReadComplete()); - ASSERT_TRUE(GetReadSuccess()); - ASSERT_EQ(BATTOR_MESSAGE_TYPE_CONTROL, GetReadType()); - - BattOrControlMessage* init_msg = - reinterpret_cast<BattOrControlMessage*>(GetReadMessage()->data()); - - ASSERT_EQ(BATTOR_CONTROL_MESSAGE_TYPE_INIT, init_msg->type); - ASSERT_EQ(5, init_msg->param1); - ASSERT_EQ(8, init_msg->param2); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageFailsWithControlButExpectingAck) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, - BATTOR_MESSAGE_TYPE_CONTROL_ACK, - BATTOR_CONTROL_BYTE_ESCAPE, - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - 0x04, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 6); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - ASSERT_TRUE(IsReadComplete()); - ASSERT_FALSE(GetReadSuccess()); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageFailsWithAckButExpectingControl) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_CONTROL_ACK, - BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0x04, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 5); - ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL); - - ASSERT_TRUE(IsReadComplete()); - ASSERT_FALSE(GetReadSuccess()); -} - -TEST_F(BattOrConnectionImplTest, ReadMessageControlTypePrintFails) { - OpenConnection(); - AdvanceTickClock(base::TimeDelta::FromMilliseconds(50)); - - const char data[] = { - BATTOR_CONTROL_BYTE_START, BATTOR_MESSAGE_TYPE_PRINT, - BATTOR_CONTROL_BYTE_END, - }; - SendBytesRaw(data, 3); - ReadMessage(BATTOR_MESSAGE_TYPE_PRINT); - - ASSERT_TRUE(IsReadComplete()); - ASSERT_FALSE(GetReadSuccess()); -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_error.cc b/tools/battor_agent/battor_error.cc deleted file mode 100644 index 5575140..0000000 --- a/tools/battor_agent/battor_error.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/battor_error.h" - -#include "base/logging.h" - -namespace battor { - -std::string BattOrErrorToString(BattOrError error) { - switch (error) { - case BATTOR_ERROR_NONE: - return "NONE"; - case BATTOR_ERROR_CONNECTION_FAILED: - return "CONNECTION FAILED"; - case BATTOR_ERROR_TIMEOUT: - return "TIMEOUT"; - case BATTOR_ERROR_SEND_ERROR: - return "SEND ERROR"; - case BATTOR_ERROR_RECEIVE_ERROR: - return "RECEIVE ERROR"; - case BATTOR_ERROR_UNEXPECTED_MESSAGE: - return "UNEXPECTED MESSAGE"; - case BATTOR_ERROR_TOO_MANY_COMMAND_RETRIES: - return "TOO MANY COMMAND RETRIES"; - case BATTOR_ERROR_TOO_MANY_FRAME_RETRIES: - return "TOO MANY FRAME RETRIES"; - case BATTOR_ERROR_FILE_NOT_FOUND: - return "FILE NOT FOUND"; - } - - NOTREACHED(); - return std::string(); -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_error.h b/tools/battor_agent/battor_error.h deleted file mode 100644 index a8d7fc5..0000000 --- a/tools/battor_agent/battor_error.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_BATTOR_ERROR_H_ -#define TOOLS_BATTOR_AGENT_BATTOR_ERROR_H_ - -#include <string> - -namespace battor { - -// A BattOrError is an error that occurs when communicating with a BattOr. -enum BattOrError { - BATTOR_ERROR_NONE, - BATTOR_ERROR_CONNECTION_FAILED, - BATTOR_ERROR_TIMEOUT, - BATTOR_ERROR_SEND_ERROR, - BATTOR_ERROR_RECEIVE_ERROR, - BATTOR_ERROR_UNEXPECTED_MESSAGE, - BATTOR_ERROR_TOO_MANY_COMMAND_RETRIES, - BATTOR_ERROR_TOO_MANY_FRAME_RETRIES, - BATTOR_ERROR_FILE_NOT_FOUND, -}; - -std::string BattOrErrorToString(BattOrError error); - -} - -#endif // TOOLS_BATTOR_AGENT_BATTOR_ERROR_H_
diff --git a/tools/battor_agent/battor_finder.cc b/tools/battor_agent/battor_finder.cc deleted file mode 100644 index cceb427..0000000 --- a/tools/battor_agent/battor_finder.cc +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/battor_finder.h" - -#include "base/command_line.h" -#include "base/logging.h" -#include "device/serial/serial_device_enumerator.h" -#include "services/device/public/mojom/serial.mojom.h" - -namespace battor { - -namespace { - -// The USB display name prefix that all BattOrs have. -const char kBattOrDisplayNamePrefix[] = "BattOr"; - -// The command line switch used to hard-code a BattOr path. Hard-coding -// this path disables the normal method of finding a BattOr, which is to -// search through serial devices for one with a matching display name. -const char kBattOrPathSwitch[] = "battor-path"; - -} // namespace - -std::string BattOrFinder::FindBattOr() { - std::unique_ptr<device::SerialDeviceEnumerator> serial_device_enumerator = - device::SerialDeviceEnumerator::Create(); - - std::vector<device::mojom::SerialDeviceInfoPtr> devices = - serial_device_enumerator->GetDevices(); - - std::string switch_specified_path = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - kBattOrPathSwitch); - if (switch_specified_path.empty()) { - // If we have no switch-specified path, look for a device with the right - // display name. See crbug.com/588244 for why this never works on Windows. - for (size_t i = 0; i < devices.size(); i++) { - if (!devices[i]->display_name) - continue; - const auto& display_name = devices[i]->display_name.value(); - if (display_name.find(kBattOrDisplayNamePrefix) != std::string::npos) { - LOG(INFO) << "Found BattOr with display name " << display_name - << " at path " << devices[i]->path; - return devices[i]->path; - } - } - } else { - // If we have a switch-specified path, make sure it actually exists before - // returning it. - for (size_t i = 0; i < devices.size(); i++) { - if (devices[i]->path == switch_specified_path) - return switch_specified_path; - } - } - - return std::string(); -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_finder.h b/tools/battor_agent/battor_finder.h deleted file mode 100644 index 06d24ab9..0000000 --- a/tools/battor_agent/battor_finder.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_BATTOR_FINDER_H_ -#define TOOLS_BATTOR_AGENT_BATTOR_FINDER_H_ - -#include <string> - -#include "base/macros.h" - -namespace battor { - -class BattOrFinder { - public: - // Returns the path of the first BattOr that we find. - static std::string FindBattOr(); - - DISALLOW_COPY_AND_ASSIGN(BattOrFinder); -}; - -} // namespace battor - -#endif // TOOLS_BATTOR_AGENT_BATTOR_FINDER_H_
diff --git a/tools/battor_agent/battor_protocol_types.h b/tools/battor_agent/battor_protocol_types.h deleted file mode 100644 index 11ac531..0000000 --- a/tools/battor_agent/battor_protocol_types.h +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_BATTOR_PROTOCOL_H_ -#define TOOLS_BATTOR_AGENT_BATTOR_PROTOCOL_H_ - -#include <stdint.h> - -namespace battor { - -// Control characters in the BattOr protocol. -enum BattOrControlByte : uint8_t { - // Indicates the start of a message in the protocol. All other instances of - // this byte must be escaped (with BATTOR_SPECIAL_BYTE_ESCAPE). - BATTOR_CONTROL_BYTE_START = 0x00, - // Indicates the end of a message in the protocol. All other instances of - // this byte must be escaped (with BATTOR_SPECIAL_BYTE_ESCAPE). - BATTOR_CONTROL_BYTE_END = 0x01, - // Indicates that the next byte should not be interpreted as a special - // character, but should instead be interpreted as itself. - BATTOR_CONTROL_BYTE_ESCAPE = 0x02, -}; - -// Types of BattOr messages that can be sent. -enum BattOrMessageType : uint8_t { - // Indicates a control message sent from the client to the BattOr to tell the - // BattOr to do something. - BATTOR_MESSAGE_TYPE_CONTROL = 0x03, - // Indicates a control message ack sent from the BattOr back to the client to - // signal that the BattOr received the control message. - BATTOR_MESSAGE_TYPE_CONTROL_ACK, - // Indicates that the message contains Voltage and current measurements. - BATTOR_MESSAGE_TYPE_SAMPLES, - // TODO(charliea): Figure out what this is. - BATTOR_MESSAGE_TYPE_PRINT, -}; - -// Types of BattOr control messages that can be sent. -enum BattOrControlMessageType : uint8_t { - // Tells the BattOr to initialize itself. - BATTOR_CONTROL_MESSAGE_TYPE_INIT = 0x00, - // Tells the BattOr to reset itself. - BATTOR_CONTROL_MESSAGE_TYPE_RESET, - // Tells the BattOr to run a self test. - BATTOR_CONTROL_MESSAGE_TYPE_SELF_TEST, - // Tells the BattOr to send its EEPROM contents over the serial connection. - BATTOR_CONTROL_MESSAGE_TYPE_READ_EEPROM, - // Sets the current measurement's gain. - BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, - // Tells the BattOr to start taking samples and sending them over the - // connection. - BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_UART, - // Tells the BattOr to start taking samples and storing them on its SD card. - BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, - // Tells the BattOr to start streaming the samples stored on its SD card over - // the connection. - BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, - // Tells the BattOr to send back the number of samples it's collected so far. - // This is used for syncing the clocks between the agent and the BattOr. - BATTOR_CONTROL_MESSAGE_TYPE_READ_SAMPLE_COUNT, - // Tells the BattOr to send back the git hash of the firmware. - BATTOR_CONTROL_MESSAGE_TYPE_GET_FIRMWARE_GIT_HASH, - // Read if the BattOr is portable or not. - BATTOR_CONTROL_MESSAGE_TYPE_GET_MODE_PORTABLE, - // Write the RTC seconds. - BATTOR_CONTROL_MESSAGE_TYPE_SET_RTC, - // Read the RTC seconds. - BATTOR_CONTROL_MESSAGE_TYPE_GET_RTC, -}; - -// The gain level for the BattOr to use. -enum BattOrGain : uint8_t { BATTOR_GAIN_LOW = 0, BATTOR_GAIN_HIGH }; - -// The data types below are packed to ensure byte-compatibility with the BattOr -// firmware. -#pragma pack(push, 1) - -// See: BattOrMessageType::BATTOR_MESSAGE_TYPE_CONTROL above. -struct BattOrControlMessage { - BattOrControlMessageType type; - uint16_t param1; - uint16_t param2; -}; - -// See: BattOrMessageType::BATTOR_MESSAGE_TYPE_CONTROL_ACK above. -struct BattOrControlMessageAck { - BattOrControlMessageType type; - uint8_t param; -}; - -// TODO(charliea, aschulman): Write better descriptions for the EEPROM fields -// when we actually start doing the math to convert raw BattOr readings to -// accurate ones. - -// The BattOr's EEPROM is persistent storage that contains information that we -// need in order to convert raw BattOr readings into accurate voltage and -// current measurements. -struct BattOrEEPROM { - uint8_t magic[4]; - uint16_t version; - char serial_num[20]; - uint32_t timestamp; - float r1; - float r2; - float r3; - float low_gain; - float low_gain_correction_factor; - float low_gain_correction_offset; - uint16_t low_gain_amppot; - float high_gain; - float high_gain_correction_factor; - float high_gain_correction_offset; - uint16_t high_gain_amppot; - uint32_t sd_sample_rate; - uint16_t sd_tdiv; - uint16_t sd_tovf; - uint16_t sd_filpot; - uint32_t uart_sr; - uint16_t uart_tdiv; - uint16_t uart_tovf; - uint16_t uart_filpot; - uint32_t crc32; -}; - -// The BattOrFrameHeader begins every frame containing BattOr samples. -struct BattOrFrameHeader { - // The number of frames that have preceded this one. - uint32_t sequence_number; - // The number of bytes of raw samples in this frame. - uint16_t length; -}; - -// A single BattOr sample. These samples are raw because they come directly from -// the BattOr's analog to digital converter and comprise only part of the -// equation to calculate meaningful voltage and current measurements. -struct RawBattOrSample { - int16_t voltage_raw; - int16_t current_raw; -}; - -// A single BattOr sample after timestamp assignment and conversion to unitful -// numbers. -struct BattOrSample { - double time_ms; - double voltage_mV; - double current_mA; -}; - -#pragma pack(pop) - -} // namespace battor - -#endif // TOOLS_BATTOR_AGENT_BATTOR_PROTOCOL_H_
diff --git a/tools/battor_agent/battor_protocol_types_unittest.cc b/tools/battor_agent/battor_protocol_types_unittest.cc deleted file mode 100644 index cdd9ec1..0000000 --- a/tools/battor_agent/battor_protocol_types_unittest.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/battor_protocol_types.h" - -#include <iostream> -#include <string> - -#include "testing/gtest/include/gtest/gtest.h" -#include "tools/battor_agent/serial_utils.h" - -using namespace testing; - -namespace battor { - -namespace { - -const BattOrEEPROM kUnserializedEEPROM{ - {0, 0, 0, 1}, 2, "serialno", 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, -}; - -// The serialized version of the above EEPROM. -const unsigned char kSerializedEEPROM[] = { - 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, - 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x10, 0x41, 0x0a, 0x00, 0x00, 0x00, 0x30, 0x41, - 0x00, 0x00, 0x40, 0x41, 0x00, 0x00, 0x50, 0x41, 0x0e, 0x00, 0x0f, 0x00, - 0x00, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x18, 0x00, 0x00, 0x00, -}; - -} // namespace - -TEST(BattOrProtocolTypeTest, EEPROMSerializesCorrectly) { - // The easier way to write this test would be using memcmp. However, because - // the EEPROM will change in the future and we'll need to update the - // serialized version when it does, it makes sense to print the bytes as a - // string that can just be copied and pasted into kSerializedEEPROM. - const char* eeprom_bytes = - reinterpret_cast<const char*>(&kUnserializedEEPROM); - - ASSERT_EQ(CharArrayToString(reinterpret_cast<const char*>(kSerializedEEPROM), - sizeof(kSerializedEEPROM)), - CharArrayToString(eeprom_bytes, sizeof(kUnserializedEEPROM))); -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_sample_converter.cc b/tools/battor_agent/battor_sample_converter.cc deleted file mode 100644 index efbf046..0000000 --- a/tools/battor_agent/battor_sample_converter.cc +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "battor_sample_converter.h" - -#include <stdlib.h> - -namespace battor { - -namespace { - -// The analog to digital converts an analog signal to a signed 12 bit integer, -// meaning that it can output numbers in the range [-2048, 2047]. -const int16_t kAnalogDigitalConverterMinValue = -2048; -const int16_t kAnalogDigitalConverterMaxValue = 2047; - -// The maximum voltage that the BattOr is capable of measuring. -const double kMaxVoltage = 1.2; - -// Converts a raw voltage to a unitful one. -double ToUnitfulVoltage(double voltage_raw) { - // Raw voltage samples are collected directly from the BattOr's analog to - // digital converter, which converts numbers in the domain [-1.2V, 1.2V] to - // numbers in the range [-2048, 2047]. A zero voltage has the same meaning in - // both the domain and range. Because of this, one negative unit in that range - // represents a slightly smaller domain (1.2 / 2048) than one positive unit - // in that range (1.2 / 2047). We take this into account when reversing the - // transformation here. - int16_t extreme_value = voltage_raw >= 0 ? kAnalogDigitalConverterMaxValue - : kAnalogDigitalConverterMinValue; - - return voltage_raw / abs(extreme_value) * kMaxVoltage; -} - -} // namespace - -BattOrSampleConverter::BattOrSampleConverter( - const BattOrEEPROM& eeprom, - const std::vector<RawBattOrSample>& calibration_frame) - : eeprom_(eeprom) { - baseline_current_ = baseline_voltage_ = 0; - for (auto sample : calibration_frame) { - baseline_current_ += ToUnitfulVoltage(sample.current_raw); - baseline_voltage_ += ToUnitfulVoltage(sample.voltage_raw); - } - - baseline_current_ /= calibration_frame.size(); - baseline_voltage_ /= calibration_frame.size(); -} - -BattOrSampleConverter::~BattOrSampleConverter() = default; - -BattOrSample BattOrSampleConverter::ToSample(const RawBattOrSample& sample, - size_t sample_number) const { - // Subtract out the baseline current and voltage that the BattOr reads even - // when it's not attached to anything. - double current = ToUnitfulVoltage(sample.current_raw) - baseline_current_; - double voltage = ToUnitfulVoltage(sample.voltage_raw) - baseline_voltage_; - - // The BattOr has to amplify the voltage so that it's on a similar scale as - // the reference voltage. This is done in the circuit using resistors (with - // known resistances r2 and r3). Here we undo that amplification. - double voltage_divider = eeprom_.r3 / (eeprom_.r2 + eeprom_.r3); - voltage /= voltage_divider; - - // Convert to millivolts. - voltage *= 1000; - - // The BattOr multiplies the current by the gain, so we have to undo that - // amplification, too. - current /= eeprom_.low_gain; - - // The current is measured indirectly and is actually given to us as a voltage - // across a resistor with a known resistance r1. Because - // - // V (voltage) = i (current) * R (resistance) - // - // we can get the current by dividing this voltage by the resistance. - current /= eeprom_.r1; - - // Convert to milliamps. - current *= 1000; - - // Each BattOr is individually factory-calibrated. Apply these calibrations. - current -= eeprom_.low_gain_correction_offset; - current /= eeprom_.low_gain_correction_factor; - - double time_ms = double(sample_number) / eeprom_.sd_sample_rate * 1000; - - return BattOrSample{time_ms, voltage, current}; -} - -float BattOrSampleConverter::ToWatts(const RawBattOrSample& raw_sample) const { - BattOrSample sample = ToSample(raw_sample, 0); - - return sample.current_mA * sample.voltage_mV * 1e-6f; -} - -BattOrSample BattOrSampleConverter::MinSample() const { - // Create a minimum raw sample. - RawBattOrSample sample_raw = {kAnalogDigitalConverterMinValue, - kAnalogDigitalConverterMinValue}; - return ToSample(sample_raw, 0); -} - -BattOrSample BattOrSampleConverter::MaxSample() const { - // Create a maximum raw sample. - RawBattOrSample sample_raw = {kAnalogDigitalConverterMaxValue, - kAnalogDigitalConverterMaxValue}; - return ToSample(sample_raw, 0); -} - -} // namespace battor
diff --git a/tools/battor_agent/battor_sample_converter.h b/tools/battor_agent/battor_sample_converter.h deleted file mode 100644 index 23915e9..0000000 --- a/tools/battor_agent/battor_sample_converter.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_BATTOR_SAMPLE_CONVERTER_H_ -#define TOOLS_BATTOR_AGENT_BATTOR_SAMPLE_CONVERTER_H_ - -#include <stddef.h> -#include <vector> - -#include "base/macros.h" -#include "tools/battor_agent/battor_protocol_types.h" - -namespace battor { - -// Converter capable of taking raw samples from the BattOr and using -// configuration information to turn them into samples with real units. -class BattOrSampleConverter { - public: - // Constructs a BattOrSampleConverter. - // - // - eeprom: The BattOr's EEPROM, which contains some required conversion - // parameters. - // - calibration_frame: The first frame sent back from the BattOr when - // streaming samples. This frame gives current and voltage measurements - // that ignore whatever the BattOr's connected to, and therefore provide - // a means for us to determine baseline current and voltage. - BattOrSampleConverter(const BattOrEEPROM& eeprom, - const std::vector<RawBattOrSample>& calibration_frame); - virtual ~BattOrSampleConverter(); - - // Converts a raw sample to a unitful one with a timestamp. - BattOrSample ToSample(const RawBattOrSample& sample, - size_t sample_number) const; - - // Converts a raw sample to watts. - float ToWatts(const RawBattOrSample& sample) const; - - // Returns the lowest magnitude sample that the BattOr can collect. - BattOrSample MinSample() const; - - // Returns the highest magnitude sample that the BattOr can collect. - BattOrSample MaxSample() const; - - private: - // The BattOr's EEPROM, which stores some conversion parameters we need. - BattOrEEPROM eeprom_; - - // The baseline current and voltage calculated from the calibration frame. - double baseline_current_; - double baseline_voltage_; - - DISALLOW_COPY_AND_ASSIGN(BattOrSampleConverter); -}; - -} // namespace battor - -#endif // TOOLS_BATTOR_AGENT_BATTOR_SAMPLE_CONVERTER_H_
diff --git a/tools/battor_agent/battor_sample_converter_unittest.cc b/tools/battor_agent/battor_sample_converter_unittest.cc deleted file mode 100644 index 01ad5e5..0000000 --- a/tools/battor_agent/battor_sample_converter_unittest.cc +++ /dev/null
@@ -1,161 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/battor_sample_converter.h" - -#include <vector> - -#include "testing/gtest/include/gtest/gtest.h" -#include "tools/battor_agent/battor_protocol_types.h" - -using namespace testing; - -namespace battor { - -TEST(BattOrSampleConverterTest, ToSampleSimple) { - BattOrEEPROM eeprom; - eeprom.r1 = 1.0f; - eeprom.r2 = 1.0f; - eeprom.r3 = 1.0f; - eeprom.low_gain = 1.0f; - eeprom.low_gain_correction_offset = 0.0f; - eeprom.low_gain_correction_factor = 1.0f; - eeprom.sd_sample_rate = 1000; - - // Create a calibration frame with a baseline voltage and current of zero. - std::vector<RawBattOrSample> calibration_frame; - calibration_frame.push_back(RawBattOrSample{0, 0}); - BattOrSampleConverter converter(eeprom, calibration_frame); - - // Set both the voltage and current to their max values. - RawBattOrSample raw_one{2048, 2048}; - BattOrSample one = converter.ToSample(raw_one, 0); - - ASSERT_DOUBLE_EQ(0, one.time_ms); - ASSERT_DOUBLE_EQ(2401.172447484123, one.voltage_mV); - ASSERT_DOUBLE_EQ(1200.5862237420615, one.current_mA); -} - -TEST(BattOrSampleConverterTest, ToSampleNonZeroBaseline) { - BattOrEEPROM eeprom; - eeprom.r1 = 1.0f; - eeprom.r2 = 1.0f; - eeprom.r3 = 1.0f; - eeprom.low_gain = 1.0f; - eeprom.low_gain_correction_offset = 0.0f; - eeprom.low_gain_correction_factor = 1.0f; - eeprom.sd_sample_rate = 1000; - - // Create a calibration frame with a baseline voltage and current of zero. - std::vector<RawBattOrSample> calibration_frame; - calibration_frame.push_back(RawBattOrSample{1024, 1024}); - BattOrSampleConverter converter(eeprom, calibration_frame); - - // Set both the voltage and current to their max values. - RawBattOrSample raw_one{2048, 2048}; - BattOrSample one = converter.ToSample(raw_one, 0); - - ASSERT_DOUBLE_EQ(0, one.time_ms); - ASSERT_DOUBLE_EQ(1200.586223742061, one.voltage_mV); - ASSERT_DOUBLE_EQ(600.29311187103076, one.current_mA); -} - -TEST(BattOrSampleConverterTest, ToSampleNonZeroMultiSampleBaseline) { - BattOrEEPROM eeprom; - eeprom.r1 = 1.0f; - eeprom.r2 = 1.0f; - eeprom.r3 = 1.0f; - eeprom.low_gain = 1.0f; - eeprom.low_gain_correction_offset = 0.0f; - eeprom.low_gain_correction_factor = 1.0f; - eeprom.sd_sample_rate = 1000; - - // Create a calibration frame with a baseline voltage and current of zero. - std::vector<RawBattOrSample> calibration_frame; - calibration_frame.push_back(RawBattOrSample{1000, 1000}); - calibration_frame.push_back(RawBattOrSample{1048, 1048}); - BattOrSampleConverter converter(eeprom, calibration_frame); - - // Set both the voltage and current to their max values. - RawBattOrSample raw_one{2048, 2048}; - BattOrSample one = converter.ToSample(raw_one, 0); - - ASSERT_DOUBLE_EQ(0, one.time_ms); - ASSERT_DOUBLE_EQ(1200.5862237420615, one.voltage_mV); - ASSERT_DOUBLE_EQ(600.29311187103076, one.current_mA); -} - -TEST(BattOrSampleConverterTest, ToSampleRealValues) { - BattOrEEPROM eeprom; - eeprom.r1 = 10.0f; - eeprom.r2 = 14.0f; - eeprom.r3 = 17.0f; - eeprom.low_gain = 1.5; - eeprom.low_gain_correction_offset = 0.03f; - eeprom.low_gain_correction_factor = 4.0f; - eeprom.sd_sample_rate = 1000; - - // Create a calibration frame with a baseline voltage and current of zero. - std::vector<RawBattOrSample> calibration_frame; - calibration_frame.push_back(RawBattOrSample{800, 900}); - calibration_frame.push_back(RawBattOrSample{1000, 1100}); - BattOrSampleConverter converter(eeprom, calibration_frame); - - // Set both the voltage and current to their max values. - RawBattOrSample raw_one{1900, 2000}; - BattOrSample one = converter.ToSample(raw_one, 0); - - ASSERT_DOUBLE_EQ(0, one.time_ms); - ASSERT_DOUBLE_EQ(1068.996209287540, one.voltage_mV); - ASSERT_DOUBLE_EQ(9.7628957011935285, one.current_mA); -} - -TEST(BattOrSampleConverterTest, ToSampleRealNegativeValues) { - BattOrEEPROM eeprom; - eeprom.r1 = 10.0f; - eeprom.r2 = 14.0f; - eeprom.r3 = 17.0f; - eeprom.low_gain = 1.5; - eeprom.low_gain_correction_offset = 0.03f; - eeprom.low_gain_correction_factor = 4.0f; - eeprom.sd_sample_rate = 1000; - - // Create a calibration frame with a baseline voltage and current of zero. - std::vector<RawBattOrSample> calibration_frame; - calibration_frame.push_back(RawBattOrSample{800, 900}); - BattOrSampleConverter converter(eeprom, calibration_frame); - - // Set both the voltage and current to their max values. - RawBattOrSample raw_one{-1900, -2000}; - BattOrSample one = converter.ToSample(raw_one, 0); - - ASSERT_DOUBLE_EQ(0, one.time_ms); - ASSERT_DOUBLE_EQ(-2885.2980205462577, one.voltage_mV); - ASSERT_DOUBLE_EQ(-28.332106130755665, one.current_mA); -} - -TEST(BattOrSampleConverterTest, ToSampleMultipleSamples) { - BattOrEEPROM eeprom; - eeprom.r1 = 1.0f; - eeprom.r2 = 1.0f; - eeprom.r3 = 1.0f; - eeprom.low_gain = 1.0f; - eeprom.low_gain_correction_offset = 0.0f; - eeprom.low_gain_correction_factor = 1.0f; - eeprom.sd_sample_rate = 50; - - std::vector<RawBattOrSample> calibration_frame; - calibration_frame.push_back(RawBattOrSample{0, 0}); - BattOrSampleConverter converter(eeprom, calibration_frame); - - BattOrSample one = converter.ToSample(RawBattOrSample{0, 0}, 0); - BattOrSample two = converter.ToSample(RawBattOrSample{0, 0}, 1); - BattOrSample three = converter.ToSample(RawBattOrSample{0, 0}, 2); - - ASSERT_DOUBLE_EQ(0, one.time_ms); - ASSERT_DOUBLE_EQ(20, two.time_ms); - ASSERT_DOUBLE_EQ(40, three.time_ms); -} - -} // namespace battor
diff --git a/tools/battor_agent/serial_utils.cc b/tools/battor_agent/serial_utils.cc deleted file mode 100644 index 314d714..0000000 --- a/tools/battor_agent/serial_utils.cc +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/serial_utils.h" - -namespace battor { - -std::string ByteVectorToString(const std::vector<uint8_t>& data) { - std::string s; - - // Reserve enough bytes for '0x', the two data characters, a space, and a null - // terminating byte. - char num_buff[6]; - for (uint8_t d : data) { - // We use sprintf because stringstream's hex support wants to print our - // characters as signed. - sprintf(num_buff, "0x%02hhx ", d); - s += num_buff; - } - - return s.substr(0, s.size() - 1); -} - -std::string CharArrayToString(const char* bytes, size_t len) { - return ByteVectorToString(std::vector<uint8_t>(bytes, bytes + len)); -} - -} // namespace battor
diff --git a/tools/battor_agent/serial_utils.h b/tools/battor_agent/serial_utils.h deleted file mode 100644 index 560b9768..0000000 --- a/tools/battor_agent/serial_utils.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef TOOLS_BATTOR_AGENT_SERIAL_UTILS_H_ -#define TOOLS_BATTOR_AGENT_SERIAL_UTILS_H_ - -#include <string> -#include <vector> - -namespace battor { - -// Prints |bytes| as a space separated list of hex numbers (e.g. {'A', 'J'} -// would return "0x41 0x4A"). -std::string CharArrayToString(const char* bytes, size_t len); -std::string ByteVectorToString(const std::vector<uint8_t>& bytes); - -} // namespace battor - -#endif // TOOLS_BATTOR_AGENT_SERIAL_UTILS_H_
diff --git a/tools/battor_agent/serial_utils_unittest.cc b/tools/battor_agent/serial_utils_unittest.cc deleted file mode 100644 index 2f17653f..0000000 --- a/tools/battor_agent/serial_utils_unittest.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "tools/battor_agent/serial_utils.h" - -#include "testing/gtest/include/gtest/gtest.h" - -using namespace testing; - -namespace battor { - -TEST(SerialUtilsTest, ByteVectorToStringLengthZero) { - EXPECT_EQ("", ByteVectorToString(std::vector<uint8_t>())); -} - -TEST(SerialUtilsTest, ByteVectorToStringLengthOne) { - EXPECT_EQ("0x41", ByteVectorToString(std::vector<uint8_t>({'A'}))); -} - -TEST(SerialUtilsTest, ByteVectorToStringLengthTwo) { - EXPECT_EQ("0x41 0x4a", ByteVectorToString(std::vector<uint8_t>({'A', 'J'}))); -} - -TEST(SerialUtilsTest, CharArrayToStringLengthOne) { - const char arr[] = {'A'}; - EXPECT_EQ("0x41", CharArrayToString(arr, sizeof(arr))); -} - -TEST(SerialUtilsTest, CharArrayToStringLengthTwo) { - const char arr[] = {'A', 'J'}; - EXPECT_EQ("0x41 0x4a", CharArrayToString(arr, sizeof(arr))); -} - -} // namespace battor
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index ad6fc41c..cc10768e 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -146,10 +146,15 @@ # See comment in _CalculatePadding() about when this can happen. Don't # process names for non-native sections. - if (full_name.startswith('*') or + if symbol.IsPak(): + # full_name: "about_ui_resources.grdp: IDR_ABOUT_UI_CREDITS_HTML". + space_idx = full_name.rindex(' ') + name = full_name[space_idx + 1:] + symbol.template_name = name + symbol.name = name + elif (full_name.startswith('*') or symbol.IsOverhead() or - symbol.IsOther() or - symbol.IsPak()): + symbol.IsOther()): symbol.template_name = full_name symbol.name = full_name elif symbol.IsDex(): @@ -685,10 +690,10 @@ return ret -def LoadAndPostProcessSizeInfo(path, fileobj=None): +def LoadAndPostProcessSizeInfo(path, file_obj=None): """Returns a SizeInfo for the given |path|.""" logging.debug('Loading results from: %s', path) - size_info = file_format.LoadSizeInfo(path, fileobj) + size_info = file_format.LoadSizeInfo(path, file_obj=file_obj) logging.info('Normalizing symbol names') _NormalizeNames(size_info.raw_symbols) logging.info('Calculating padding')
diff --git a/tools/binary_size/libsupersize/diff.py b/tools/binary_size/libsupersize/diff.py index 793754b..0915f99 100644 --- a/tools/binary_size/libsupersize/diff.py +++ b/tools/binary_size/libsupersize/diff.py
@@ -39,13 +39,18 @@ "._468", "._467" ".L__unnamed_1193", ".L__unnamed_712" """ - name = _STRIP_NUMBER_SUFFIX_PATTERN.sub('', symbol.full_name) - clone_idx = name.find(' [clone ') - if clone_idx != -1: - name = name[:clone_idx] - if name.startswith('*'): - # "symbol gap 3 (bar)" -> "symbol gaps" - name = _NORMALIZE_STAR_SYMBOLS_PATTERN.sub('s', name) + if symbol.IsPak(): + # full_name looks like "about_ui_resources.grdp: IDR_ABOUT_UI_CREDITS_HTML". + # name is just "IDR_ABOUT_UI_CREDITS_HTML". + name = symbol.name + else: + name = _STRIP_NUMBER_SUFFIX_PATTERN.sub('', symbol.full_name) + clone_idx = name.find(' [clone ') + if clone_idx != -1: + name = name[:clone_idx] + if name.startswith('*'): + # "symbol gap 3 (bar)" -> "symbol gaps" + name = _NORMALIZE_STAR_SYMBOLS_PATTERN.sub('s', name) return symbol.section, symbol.object_path, name
diff --git a/tools/binary_size/libsupersize/file_format.py b/tools/binary_size/libsupersize/file_format.py index 23d31fc..db534e0 100644 --- a/tools/binary_size/libsupersize/file_format.py +++ b/tools/binary_size/libsupersize/file_format.py
@@ -341,17 +341,21 @@ @contextlib.contextmanager -def _OpenGzipForWrite(path): +def _OpenGzipForWrite(path, file_obj=None): # Open in a way that doesn't set any gzip header fields. - with open(path, 'wb') as f: - with gzip.GzipFile(filename='', mode='wb', fileobj=f, mtime=0) as fz: + if file_obj: + with gzip.GzipFile(filename='', mode='wb', fileobj=file_obj, mtime=0) as fz: yield fz + else: + with open(path, 'wb') as f: + with gzip.GzipFile(filename='', mode='wb', fileobj=f, mtime=0) as fz: + yield fz -def SaveSizeInfo(size_info, path): +def SaveSizeInfo(size_info, path, file_obj=None): """Saves |size_info| to |path}.""" if os.environ.get('SUPERSIZE_MEASURE_GZIP') == '1': - with _OpenGzipForWrite(path) as f: + with _OpenGzipForWrite(path, file_obj=file_obj) as f: _SaveSizeInfoToFile(size_info, f) else: # It is seconds faster to do gzip in a separate step. 6s -> 3.5s. @@ -360,11 +364,11 @@ logging.debug('Serialization complete. Gzipping...') stringio.seek(0) - with _OpenGzipForWrite(path) as f: + with _OpenGzipForWrite(path, file_obj=file_obj) as f: shutil.copyfileobj(stringio, f) -def LoadSizeInfo(filename, fileobj=None): +def LoadSizeInfo(filename, file_obj=None): """Returns a SizeInfo loaded from |filename|.""" - with gzip.GzipFile(filename=filename, fileobj=fileobj) as f: + with gzip.GzipFile(filename=filename, fileobj=file_obj) as f: return _LoadSizeInfoFromFile(f, filename)
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py index 01c6343..a7e7f82 100755 --- a/tools/binary_size/libsupersize/integration_test.py +++ b/tools/binary_size/libsupersize/integration_test.py
@@ -3,6 +3,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import cStringIO import contextlib import copy import difflib @@ -326,8 +327,8 @@ @_CompareWithGolden() def test_Diff_Basic(self): - size_info1 = self._CloneSizeInfo(use_elf=False) - size_info2 = self._CloneSizeInfo(use_elf=False) + size_info1 = self._CloneSizeInfo(use_elf=False, use_pak=True) + size_info2 = self._CloneSizeInfo(use_elf=False, use_pak=True) size_info1.metadata = {"foo": 1, "bar": [1,2,3], "baz": "yes"} size_info2.metadata = {"foo": 1, "bar": [1,3], "baz": "yes"} @@ -338,16 +339,30 @@ padding_sym = size_info2.raw_symbols.WhereNameMatches('symbol gap 0')[0] padding_sym.padding += 20 padding_sym.size += 20 + pak_sym = size_info2.raw_symbols.WhereInSection( + models.SECTION_PAK_TRANSLATIONS)[0] + pak_sym.full_name = 'foo: ' + pak_sym.full_name.split()[-1] + + # Serialize & de-serialize so that name normalization runs again for the pak + # symbol. + stringio = cStringIO.StringIO() + file_format.SaveSizeInfo(size_info2, 'path', file_obj=stringio) + stringio.seek(0) + size_info2 = archive.LoadAndPostProcessSizeInfo('path', file_obj=stringio) + d = diff.Diff(size_info1, size_info2) d.raw_symbols = d.raw_symbols.Sorted() self.assertEquals(d.raw_symbols.CountsByDiffStatus()[1:], [2, 2, 3]) changed_sym = d.raw_symbols.WhereNameMatches('Patcher::Name_')[0] padding_sym = d.raw_symbols.WhereNameMatches('symbol gap 0')[0] + bss_sym = d.raw_symbols.WhereInSection(models.SECTION_BSS)[0] # Padding-only deltas should sort after all non-padding changes. padding_idx = d.raw_symbols.index(padding_sym) - self.assertLess(d.raw_symbols.index(changed_sym), padding_idx) + changed_idx = d.raw_symbols.index(changed_sym) + bss_idx = d.raw_symbols.index(bss_sym) + self.assertLess(changed_idx, padding_idx) # And before bss. - self.assertTrue(d.raw_symbols[padding_idx + 1].IsBss()) + self.assertLess(padding_idx, bss_idx) return describe.GenerateLines(d, verbose=True)
diff --git a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden index 65e3c5c..c6ee462 100644 --- a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden +++ b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
@@ -10,6 +10,7 @@ .bss: 0 bytes (0 bytes) (not included in totals) .data: 0 bytes (0 bytes) (0.0%) .data.rel.ro: 0 bytes (0 bytes) (0.0%) + .pak.translations: 0 bytes (0 bytes) (0.0%) .rel.dyn: 0 bytes (0 bytes) (0.0%) .rodata: 0 bytes (0 bytes) (0.0%) .text: 0 bytes (0 bytes) (0.0%) @@ -38,42 +39,45 @@ .strtab: 0 bytes (0 bytes) .symtab: 0 bytes (0 bytes) -2 symbols added (+), 2 changed (~), 3 removed (-), 34 unchanged (not shown) -Of changed symbols, 4 grew, 3 shrank -Number of unique symbols 44 -> 43 (-1) +2 symbols added (+), 2 changed (~), 3 removed (-), 242 unchanged (not shown) +Of changed symbols, 3 grew, 4 shrank +Number of unique symbols 251 -> 250 (-1) 0 paths added, 0 removed, 2 changed Changed files: third_party/container/container.c -Showing 7 symbols (5 -> 4 unique) with total pss: 38 bytes +Showing 7 symbols (5 -> 4 unique) with total pss: -112 bytes Histogram of symbols based on PSS: - (-256,-128]: 1 (-32,-16]: 1 (-8,-4]: 1 [4,8): 2 [8,16): 1 [16,32): 1 -.text=0 bytes .rodata=10 bytes .data.rel.ro=0 bytes .data=28 bytes .bss=-232 bytes total=38 bytes -Number of unique paths: 4 + (-128,-64]: 1 (-32,-16]: 2 (-16,-8]: 1 [4,8): 2 [8,16): 1 +.text=0 bytes .rodata=10 bytes .data.rel.ro=0 bytes .data=8 bytes .bss=0 bytes .pak.translations=-130 bytes total=-112 bytes +Number of unique paths: 3 -Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss +Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, p=.pak.translations Index | Running Total | Section@Address | ... ------------------------------------------------------------ -~ 0) 10 (26.3%) r@0x284e398 +10 (22->32) num_aliases=1 +- 0) -80 (71.4%) p@0x0 -80 (80->0) num_aliases=1 + source_path= object_path= + flags={} name=IDS_AW_WEBPAGE_PARENTAL_PERMISSION_NEEDED + full_name=../../android_webview/ui/aw_strings.grd: IDS_AW_WEBPAGE_PARENTAL_PERMISSION_NEEDED +- 1) -103 (92.0%) p@0x0 -23 (23->0) num_aliases=1 + source_path= object_path= + flags={} name=IDS_WEB_FONT_FAMILY + full_name=../../ui/strings/app_locale_settings.grd: IDS_WEB_FONT_FAMILY +- 2) -112 (100.0%) p@0x0 -9 (9->0) num_aliases=1 + source_path= object_path= + flags={} name=IDS_WEB_FONT_SIZE + full_name=../../ui/strings/app_locale_settings.grd: IDS_WEB_FONT_SIZE +~ 3) -130 (116.1%) p@0x0 -18 (0->0) num_aliases=1 + source_path= object_path= + flags={} name=../../../mock_apk/assets/en-US.pak + full_name=foo: ../../../mock_apk/assets/en-US.pak +~ 4) -120 (107.1%) r@0x284e398 +10 (22->32) num_aliases=1 source_path=third_party/container/container.c object_path=third_party/sub/ContiguousContainer.o flags={} name=chrome::mojom::FilePatcher::Name_ -+ 1) 14 (36.8%) d@0x2de7000 +4 (0->4) num_aliases=1 ++ 5) -116 (103.6%) d@0x2de7000 +4 (0->4) num_aliases=1 source_path=base/page_allocator.cc object_path=base/base/page_allocator.o flags={} name=google::protobuf::internal::pLinuxKernelCmpxchg -+ 2) 18 (47.4%) d@0x2de7004 +4 (0->4) num_aliases=1 ++ 6) -112 (100.0%) d@0x2de7004 +4 (0->4) num_aliases=1 source_path=third_party/container/container.c object_path=third_party/sub/ContiguousContainer.o flags={} name=google::protobuf::internal::pLinuxKernelMemoryBarrier -~ 3) 38 (100.0%) d@0x2dffd88 20 (0->0) num_aliases=1 - source_path= object_path= - flags={} name=** symbol gap 0 (end of section) -- 4) 38 (100.0%) b@0x0 -200 (4->0) num_aliases=1 - source_path=third_party/icu/ucnv_ext.c object_path=third_party/icu/icuuc/ucnv_ext.o - flags={gen} name=SaveHistogram::atomic_histogram_pointer - full_name=SaveHistogram(_JNIEnv*, base::android::JavaParamRef<_jobject*> const&, base::android::JavaParamRef<_jstring*> const&, base::android::JavaParamRef<_jlongArray*> const&, int)::atomic_histogram_pointer -- 5) 38 (100.0%) b@0x0 -28 (28->0) num_aliases=1 - source_path=third_party/icu/ucnv_ext.c object_path=third_party/icu/icuuc/ucnv_ext.o - flags={gen} name=g_chrome_content_browser_client -- 6) 38 (100.0%) b@0x0 -4 (4->0) num_aliases=1 - source_path=third_party/icu/ucnv_ext.c object_path=third_party/icu/icuuc/ucnv_ext.o - flags={anon,gen} name=g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py index f1e51a1..3003d55 100755 --- a/tools/checklicenses/checklicenses.py +++ b/tools/checklicenses/checklicenses.py
@@ -461,6 +461,9 @@ 'third_party/modp_b64': [ 'UNKNOWN', ], + 'third_party/nvml': [ + 'UNKNOWN', + ], # Missing license headers in openh264 sources: https://github.com/cisco/openh264/issues/2233 'third_party/openh264/src': [ 'UNKNOWN',
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py index ead68d3..5a4707c 100755 --- a/tools/clang/scripts/package.py +++ b/tools/clang/scripts/package.py
@@ -8,6 +8,7 @@ import argparse import fnmatch +import glob import itertools import os import shutil @@ -383,6 +384,23 @@ filter=PrintTarProgress) MaybeUpload(args, cfiverifydir, platform) + # Zip up the SafeStack runtime for Linux + safestackdir = 'safestack-' + stamp + shutil.rmtree(safestackdir, ignore_errors=True) + os.makedirs(os.path.join(safestackdir, 'lib')) + for build in glob.glob(os.path.join(LLVM_RELEASE_DIR, 'lib', 'clang', '*')): + version = os.path.basename(build) + dest_dir = os.path.join(safestackdir, 'lib', 'clang', version, + 'lib', 'linux') + os.makedirs(dest_dir) + for lib in glob.glob(os.path.join(build, 'lib', 'linux', + '*libclang_rt.safestack*')): + shutil.copy(lib, dest_dir) + with tarfile.open(safestackdir + '.tgz', 'w:gz') as tar: + tar.add(os.path.join(safestackdir, 'lib'), arcname='lib', + filter=PrintTarProgress) + MaybeUpload(args, safestackdir, platform) + # On Mac, lld isn't part of the main zip. Upload it in a separate zip. if sys.platform == 'darwin': llddir = 'lld-' + stamp
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl index f8dd093..b30818d 100644 --- a/tools/determinism/deterministic_build_whitelist.pyl +++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -39,7 +39,6 @@ 'ar_sample_test_driver', 'audio_unittests', 'base_unittests', - 'battor_agent_unittests', 'blink_heap_unittests', 'blink_platform_perftests', 'blink_platform_unittests',
diff --git a/tools/grit/grit/format/html_inline.py b/tools/grit/grit/format/html_inline.py index 59ff535f..d777019 100755 --- a/tools/grit/grit/format/html_inline.py +++ b/tools/grit/grit/format/html_inline.py
@@ -28,6 +28,9 @@ mimetypes.init([]) mimetypes.add_type('image/svg+xml', '.svg') +# webm video type is not always available if mimetype package is outdated. +mimetypes.add_type('video/webm', '.webm') + DIST_DEFAULT = 'chromium' DIST_ENV_VAR = 'CHROMIUM_BUILD' DIST_SUBSTR = '%DISTRIBUTION%'
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index f4f9380e..10f4687d 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -377,9 +377,6 @@ 'Android arm64 Builder Perf FYI': 'official_goma_minimal_symbols_android_arm64', 'Android CFI Builder Perf FYI': 'official_goma_minimal_symbols_android_thin_lto', 'Android CFI arm64 Builder Perf FYI': 'official_goma_minimal_symbols_android_thin_lto_arm64', - 'Battor Agent Linux': 'release_bot', - 'Battor Agent Mac': 'release_bot', - 'Battor Agent Win': 'release_bot', 'Mac Builder Perf FYI': 'official_goma', 'Win Builder Perf FYI': 'official_goma_x86', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d27c545d..c7c6693d 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -19260,7 +19260,6 @@ <int value="2230" label="ReplaceCharsetInXHR"/> <int value="2231" label="RespondToSameOriginRequestWithCrossOriginResponse"/> <int value="2232" label="LinkRelModulePreload"/> - <int value="2235" label="HTMLFrameSetElementNonNullAnonymousNamedGetter"/> <int value="2236" label="CSPWithUnsafeEval"/> <int value="2237" label="WebAssemblyInstantiation"/> <int value="2238" label="V8IndexAccessor"/> @@ -19500,7 +19499,6 @@ <int value="2461" label="ShapeOutsideContentBoxDifferentFromMarginBox"/> <int value="2462" label="ShapeOutsidePaddingBoxDifferentFromMarginBox"/> <int value="2463" label="CSSContainLayoutPositionedDescendants"/> - <int value="2464" label="HTMLFrameSetElementAnonymousNamedGetter"/> <int value="2465" label="CanvasConvertToBlob"/> <int value="2466" label="PolymerV1Detected"/> <int value="2467" label="PolymerV2Detected"/> @@ -28607,6 +28605,7 @@ <int value="-141516902" label="UseModernMediaControls:enabled"/> <int value="-138983372" label="DesktopPWAWindowing:disabled"/> <int value="-138773929" label="PassiveDocumentEventListeners:enabled"/> + <int value="-137303226" label="enable-chromevox-developer-option"/> <int value="-135223364" label="AutofillShowTypePredictions:disabled"/> <int value="-127231994" label="VrBrowsingNativeAndroidUi:disabled"/> <int value="-122492389" label="enable-browser-task-scheduler"/> @@ -34596,6 +34595,7 @@ <int value="10" label="Streamer not ready when GetSource called"/> <int value="11" label="Internal script"/> <int value="12" label="Streaming was never started"/> + <int value="13" label="An error had occurred before GetSource was called"/> </enum> <enum name="NPAPIPluginStatus"> @@ -40306,6 +40306,7 @@ <int value="9" label="Disabled by config"/> <int value="10" label="Path degrading not enabled"/> <int value="11" label="Timeout with no new network"/> + <int value="12" label="Path degrading before handshake confirmed"/> </enum> <enum name="QuicDisabledReason"> @@ -46184,6 +46185,11 @@ <int value="1" label="Synced favicons not full"/> </enum> +<enum name="SyncFeatureOrTransport"> + <int value="0" label="Full Sync feature."/> + <int value="1" label="Sync transport only."/> +</enum> + <enum name="SyncFSConflictResolutionPolicy"> <int value="0" label="Unknown"/> <int value="1" label="LastWriteWin"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 37f81557..174af7b 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -86532,14 +86532,19 @@ </histogram> <histogram name="SBClientDownload.PPAPIDownloadRequest.RequestDuration" - units="ms" expires_after="2018-08-30"> + units="ms"> + <obsolete> + Removed in 08/2018. + </obsolete> <owner>asanka@chromium.org</owner> <summary>Time taken to complete a PPAPIDownloadRequest.</summary> </histogram> <histogram name="SBClientDownload.PPAPIDownloadRequest.RequestOutcome" - enum="SBClientDownloadPPAPIDownloadRequestOutcome" - expires_after="2018-08-30"> + enum="SBClientDownloadPPAPIDownloadRequestOutcome"> + <obsolete> + Removed in 08/2018. + </obsolete> <owner>asanka@chromium.org</owner> <summary> Outcome of running CheckPPAPIDownloadRequest. Most failure modes cause an @@ -86551,7 +86556,10 @@ </histogram> <histogram name="SBClientDownload.PPAPIDownloadRequest.Result" - enum="SBClientDownloadCheckResult" expires_after="2018-08-30"> + enum="SBClientDownloadCheckResult"> + <obsolete> + Removed in 08/2018. + </obsolete> <owner>asanka@chromium.org</owner> <summary>Result returned to the caller of CheckPPAPIDownloadRequest.</summary> </histogram> @@ -100444,6 +100452,18 @@ </summary> </histogram> +<histogram name="Sync.ConfigureDataTypeManagerOption" + enum="SyncFeatureOrTransport"> + <owner>treib@chromium.org</owner> + <summary> + Whether the full Sync feature or only the Sync transport layer is being + configured. Recorded when configuring the data types for any reason: Most + commonly during browser startup, but also after initial setup, after a + reconfiguration by the user, or when switching between full feature mode and + transport mode. + </summary> +</histogram> + <histogram name="Sync.ConfigureDataTypes" enum="SyncModelTypes"> <owner>zea@chromium.org</owner> <summary> @@ -101152,8 +101172,8 @@ wouldn't be able to start, or that it probably can start. The user having turned off sync on mobile will be logged as "turned off by user". A dashboard stop and clear will fall under "turned off and setup not - completed". See the SyncInitialState enum in profile_sync_service.h for - more information. + completed". See the SyncInitialState enum in profile_sync_service.cc + for more information. </summary> </histogram> @@ -105982,6 +106002,14 @@ </summary> </histogram> +<histogram name="UKM.LogUploader.UploadSize" units="bytes"> + <owner>asvitkine@chromium.org</owner> + <owner>holte@chromium.org</owner> + <summary> + Reports total upload length in bytes when the UKM service type is used. + </summary> +</histogram> + <histogram name="UKM.PersistentLogRecall.Status" enum="PersistedLogsLogReadStatus"> <owner>holte@chromium.org</owner> @@ -106675,6 +106703,14 @@ </summary> </histogram> +<histogram name="UMA.LogUploader.UploadSize" units="bytes"> + <owner>asvitkine@chromium.org</owner> + <owner>holte@chromium.org</owner> + <summary> + Reports total upload length in bytes when the UMA service type is used. + </summary> +</histogram> + <histogram name="UMA.LowEntropySourceValue" expires_after="2018-08-30"> <owner>asvitkine@chromium.org</owner> <summary>
diff --git a/tools/perf/core/perf_benchmark_unittest.py b/tools/perf/core/perf_benchmark_unittest.py index 9e81950..e5140255 100644 --- a/tools/perf/core/perf_benchmark_unittest.py +++ b/tools/perf/core/perf_benchmark_unittest.py
@@ -8,6 +8,7 @@ import tempfile import unittest +from telemetry import decorators from telemetry.internal.browser import browser_finder from telemetry.testing import options_for_unittests @@ -34,6 +35,7 @@ self.assertEqual(num_expected_matches, len(ruleset_data_to_copy)) + @decorators.Disabled('chromeos') # crbug.com/871600. def testVariationArgs(self): benchmark = perf_benchmark.PerfBenchmark() options = options_for_unittests.GetCopy()
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 03115809..391405e 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -326,7 +326,7 @@ 'tests': [ { 'isolate': 'performance_test_suite', - 'num_shards': 5, + 'num_shards': 26, 'extra_args': [ '--run-ref-build', '--test-shard-map-filename=win10_shard_map.json',
diff --git a/tools/perf/core/shard_maps/timing_data/win10_story_timing.json b/tools/perf/core/shard_maps/timing_data/win10_story_timing.json index c35cc3a8..43fd7e1 100644 --- a/tools/perf/core/shard_maps/timing_data/win10_story_timing.json +++ b/tools/perf/core/shard_maps/timing_data/win10_story_timing.json
@@ -1,5662 +1,4090 @@ [ { - "duration": "19.996899", + "duration": "9.0", "name": "blink_perf.bindings/append-child.html" }, { - "duration": "9.156232333333337", + "duration": "9.0", "name": "blink_perf.bindings/create-element.html" }, { - "duration": "8.43875755959596", + "duration": "9.0", "name": "blink_perf.bindings/document-implementation.html" }, { - "duration": "8.30231310909091", + "duration": "9.0", "name": "blink_perf.bindings/dom-attribute-on-prototoype.html" }, { - "duration": "8.511131287878786", + "duration": "9.0", "name": "blink_perf.bindings/first-child.html" }, { - "duration": "4.966787875757576", + "duration": "6.0", "name": "blink_perf.bindings/gc-forest.html" }, { - "duration": "5.425777770707072", + "duration": "6.0", "name": "blink_perf.bindings/gc-mini-tree.html" }, { - "duration": "13.764999969696973", + "duration": "15.0", "name": "blink_perf.bindings/gc-tree.html" }, { - "duration": "8.376131291919192", + "duration": "9.0", "name": "blink_perf.bindings/get-attribute-rare.html" }, { - "duration": "8.406201976767678", + "duration": "9.0", "name": "blink_perf.bindings/get-attribute.html" }, { - "duration": "8.361707043434341", + "duration": "9.0", "name": "blink_perf.bindings/get-element-by-id.html" }, { - "duration": "8.36879796161616", + "duration": "9.0", "name": "blink_perf.bindings/get-elements-by-tag-name.html" }, { - "duration": "8.370595921212116", + "duration": "9.0", "name": "blink_perf.bindings/id-getter.html" }, { - "duration": "8.392090883838385", + "duration": "9.0", "name": "blink_perf.bindings/id-setter.html" }, { - "duration": "8.37116158282828", + "duration": "9.0", "name": "blink_perf.bindings/indexed-getter.html" }, { - "duration": "8.370979846464643", + "duration": "9.0", "name": "blink_perf.bindings/insert-before.html" }, { - "duration": "8.35701008383838", + "duration": "9.0", "name": "blink_perf.bindings/named-property-enumerator.html" }, { - "duration": "19.448999979797986", + "duration": "29.0", "name": "blink_perf.bindings/node-list-access.html" }, { - "duration": "8.215616140404043", + "duration": "9.0", "name": "blink_perf.bindings/node-type.html" }, { - "duration": "3.2637171666666673", + "duration": "4.0", "name": "blink_perf.bindings/post-message.html" }, { - "duration": "8.835181823232325", + "duration": "9.0", "name": "blink_perf.bindings/sequence-conversion-array.html" }, { - "duration": "10.57738384343434", + "duration": "11.0", "name": "blink_perf.bindings/sequence-conversion-custom-iterator.html" }, { - "duration": "3.319979792929293", + "duration": "4.0", "name": "blink_perf.bindings/serialize-array.html" }, { - "duration": "3.145494944444445", + "duration": "4.0", "name": "blink_perf.bindings/serialize-long-string.html" }, { - "duration": "4.366848494949494", + "duration": "5.0", "name": "blink_perf.bindings/serialize-map.html" }, { - "duration": "3.8737272787878783", + "duration": "4.0", "name": "blink_perf.bindings/serialize-nested-array.html" }, { - "duration": "9.2633434989899", + "duration": "9.0", "name": "blink_perf.bindings/set-attribute-rare.html" }, { - "duration": "8.423212149494947", + "duration": "9.0", "name": "blink_perf.bindings/set-attribute.html" }, { - "duration": "7.112868693939398", + "duration": "8.0", "name": "blink_perf.bindings/structured-clone-json-deserialize.html" }, { - "duration": "7.0847777656565665", + "duration": "8.0", "name": "blink_perf.bindings/structured-clone-json-serialize.html" }, { - "duration": "4.828333351515152", + "duration": "5.0", "name": "blink_perf.bindings/structured-clone-long-string-deserialize.html" }, { - "duration": "4.825535373737372", + "duration": "5.0", "name": "blink_perf.bindings/structured-clone-long-string-serialize.html" }, { - "duration": "8.398313140404037", + "duration": "10.0", "name": "blink_perf.bindings/typed-array-construct-from-array.html" }, { - "duration": "8.286191913131317", + "duration": "9.0", "name": "blink_perf.bindings/typed-array-construct-from-same-type.html" }, { - "duration": "8.383909067676763", + "duration": "9.0", "name": "blink_perf.bindings/typed-array-construct-from-typed.html" }, { - "duration": "8.382272715151514", + "duration": "9.0", "name": "blink_perf.bindings/typed-array-set-from-typed.html" }, { - "duration": "8.291282852525253", + "duration": "9.0", "name": "blink_perf.bindings/undefined-first-child.html" }, { - "duration": "8.195070692929294", + "duration": "9.0", "name": "blink_perf.bindings/undefined-get-element-by-id.html" }, { - "duration": "8.380313166666667", + "duration": "9.0", "name": "blink_perf.bindings/undefined-id-getter.html" }, { - "duration": "17.35878788383838", + "duration": "13.0", + "name": "blink_perf.bindings/worker-structured-clone-json-roundtrip.html" + }, + { + "duration": "13.0", + "name": "blink_perf.bindings/worker-structured-clone-json-serialize.html" + }, + { + "duration": "9.0", "name": "blink_perf.canvas/createImageBitmapFromImageData.html" }, { - "duration": "5.463151526262625", + "duration": "6.0", "name": "blink_perf.canvas/draw-dynamic-canvas-2d-to-hw-accelerated-canvas-2d.html" }, { - "duration": "9.78419193939394", + "duration": "10.0", "name": "blink_perf.canvas/draw-dynamic-webgl-to-hw-accelerated-canvas-2d.html" }, { - "duration": "3.3580100989898996", + "duration": "4.0", "name": "blink_perf.canvas/draw-hw-accelerated-canvas-2d-to-sw-canvas-2d.html" }, { - "duration": "4.187777782828281", + "duration": "5.0", "name": "blink_perf.canvas/draw-static-canvas-2d-to-hw-accelerated-canvas-2d.html" }, { - "duration": "4.316737364646463", + "duration": "5.0", "name": "blink_perf.canvas/draw-static-webgl-to-hw-accelerated-canvas-2d.html" }, { - "duration": "5.465969692929293", + "duration": "6.0", "name": "blink_perf.canvas/draw-video-to-hw-accelerated-canvas-2d.html" }, { - "duration": "9.203727292929292", + "duration": "10.0", "name": "blink_perf.canvas/drawimage-not-pixelaligned.html" }, { - "duration": "8.625272782828286", + "duration": "9.0", "name": "blink_perf.canvas/drawimage.html" }, { - "duration": "8.994323237373736", + "duration": "10.0", "name": "blink_perf.canvas/getImageData.html" }, { - "duration": "9.997010131313134", + "duration": "9.0", "name": "blink_perf.canvas/getImageDataColorManaged.html" }, { - "duration": "8.6022726969697", + "duration": "9.0", "name": "blink_perf.canvas/putImageData.html" }, { - "duration": "4.57739395959596", + "duration": "5.0", "name": "blink_perf.canvas/toBlob_duration.html" }, { - "duration": "4.4193939434343426", + "duration": "5.0", "name": "blink_perf.canvas/toBlob_duration_jpeg.html" }, { - "duration": "3.9589596020202023", + "duration": "5.0", "name": "blink_perf.canvas/transferFromImageBitmap.html" }, { - "duration": "4.83388886161616", + "duration": "6.0", "name": "blink_perf.canvas/upload-canvas-2d-to-texture.html" }, { - "duration": "10.408202035353534", + "duration": "11.0", "name": "blink_perf.canvas/upload-video-to-sub-texture.html" }, { - "duration": "4.488111119191919", + "duration": "5.0", "name": "blink_perf.canvas/upload-video-to-texture.html" }, { - "duration": "4.474373743434344", + "duration": "5.0", "name": "blink_perf.canvas/upload-webgl-to-texture.html" }, { - "duration": "22.907646414141407", + "duration": "16.0", "name": "blink_perf.css/AttributeDescendantSelector.html" }, { - "duration": "8.595363611111113", + "duration": "9.0", "name": "blink_perf.css/CSSPropertySetterGetter.html" }, { - "duration": "8.476989914141416", + "duration": "9.0", "name": "blink_perf.css/CSSPropertySetterGetterMethods.html" }, { - "duration": "8.610393959595962", + "duration": "9.0", "name": "blink_perf.css/CSSPropertyUpdateValue.html" }, { - "duration": "7.437707064646462", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleChildClassSelector.html" }, { - "duration": "7.415909092929293", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleChildElementSelectors.html" }, { - "duration": "7.398494929292931", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleElementSelector.html" }, { - "duration": "7.389262617171715", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleGrandChildElementSelector.html" }, { - "duration": "7.380636365656567", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleMultipleClassSelector.html" }, { - "duration": "7.376888870707073", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleMultipleQualifiedDataAttributesWithValuesSelector.html" }, { - "duration": "7.392999971717171", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleNestedPseudoSelector.html" }, { - "duration": "7.377353527272726", + "duration": "8.0", "name": "blink_perf.css/ChangeStylePairOfNthChildSelector.html" }, { - "duration": "7.329000001010102", + "duration": "8.0", "name": "blink_perf.css/ChangeStylePartialAttributeMatchingSelector.html" }, { - "duration": "7.402767671717169", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleQualifiedDataAttributeSelector.html" }, { - "duration": "7.3826363515151545", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleQualifiedDataAttributeWithValueSelector.html" }, { - "duration": "8.161272755555558", + "duration": "9.0", "name": "blink_perf.css/ChangeStyleShallowTree.html" }, { - "duration": "7.332252533333335", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleSingleClassSelector.html" }, { - "duration": "7.333636354545453", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleSingleNthChildSelector.html" }, { - "duration": "7.334646465656564", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleSinglePseudoSelector.html" }, { - "duration": "7.352949464646463", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleUniversalSelector.html" }, { - "duration": "7.337292902020198", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeSelector.html" }, { - "duration": "7.345141414141416", + "duration": "8.0", "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeWithValueSelector.html" }, { - "duration": "11.310242439393942", + "duration": "12.0", "name": "blink_perf.css/ClassDescendantSelector.html" }, { - "duration": "8.640323222222223", + "duration": "9.0", "name": "blink_perf.css/ClassInvalidation.html" }, { - "duration": "10.3898888989899", + "duration": "11.0", "name": "blink_perf.css/FocusUpdate.html" }, { - "duration": "7.606757575757573", + "duration": "8.0", "name": "blink_perf.css/LoadBootstrapBlog.html" }, { - "duration": "7.589444408080805", + "duration": "8.0", "name": "blink_perf.css/LoadMaterializeStarterPage.html" }, { - "duration": "7.826080848484851", + "duration": "8.0", "name": "blink_perf.css/LoadSemanticPageExample.html" }, { - "duration": "8.388262628282828", + "duration": "9.0", "name": "blink_perf.css/PseudoClassSelectors.html" }, { - "duration": "8.893141429292932", + "duration": "9.0", "name": "blink_perf.css/SelectorCountScaling.html" }, { - "duration": "17.572676757575756", + "duration": "6.0", "name": "blink_perf.dom/addRange.html" }, { - "duration": "3.935171708080808", + "duration": "4.0", "name": "blink_perf.dom/delete-in-password-field.html" }, { - "duration": "9.663727282828281", + "duration": "10.0", "name": "blink_perf.dom/div-editable.html" }, { - "duration": "3.364191908080807", + "duration": "4.0", "name": "blink_perf.dom/inner_html_with_selection.html" }, { - "duration": "14.697616196969697", + "duration": "19.0", "name": "blink_perf.dom/long-sibling-list.html" }, { - "duration": "4.027606073737373", + "duration": "5.0", "name": "blink_perf.dom/modify-element-classname.html" }, { - "duration": "3.6468585707070718", + "duration": "4.0", "name": "blink_perf.dom/modify-element-id.html" }, { - "duration": "3.698080822222223", + "duration": "4.0", "name": "blink_perf.dom/modify-element-title.html" }, { - "duration": "3.652434341414141", + "duration": "4.0", "name": "blink_perf.dom/move-down-with-hidden-elements.html" }, { - "duration": "3.544151515151514", + "duration": "5.0", "name": "blink_perf.dom/move-up-with-hidden-elements.html" }, { - "duration": "3.617484854545455", + "duration": "4.0", "name": "blink_perf.dom/remove_child_with_selection.html" }, { - "duration": "8.782686893939388", + "duration": "9.0", "name": "blink_perf.dom/select-multiple-add.html" }, { - "duration": "8.637939409090908", + "duration": "9.0", "name": "blink_perf.dom/select-single-add.html" }, { - "duration": "8.717414171717175", + "duration": "9.0", "name": "blink_perf.dom/select-single-remove.html" }, { - "duration": "8.921020191919192", + "duration": "9.0", "name": "blink_perf.dom/textarea-dom.html" }, { - "duration": "8.796272751515147", + "duration": "9.0", "name": "blink_perf.dom/textarea-edit.html" }, { - "duration": "16.206686873737382", + "duration": "17.0", "name": "blink_perf.events/EventsDispatching.html" }, { - "duration": "9.35467675757576", + "duration": "10.0", "name": "blink_perf.events/EventsDispatchingInDeeplyNestedShadowTrees.html" }, { - "duration": "12.775090868686865", + "duration": "16.0", "name": "blink_perf.events/EventsDispatchingInShadowTrees.html" }, { - "duration": "8.086616182828283", + "duration": "11.0", "name": "blink_perf.events/hit-test-lots-of-layers.html" }, { - "duration": "65.56014138383837", + "duration": "15.0", "name": "blink_perf.image_decoder/decode-gif.html" }, { - "duration": "9.819111131313132", + "duration": "10.0", "name": "blink_perf.image_decoder/decode-jpeg.html" }, { - "duration": "13.537434308080812", + "duration": "13.0", "name": "blink_perf.image_decoder/decode-lossless-webp.html" }, { - "duration": "9.061585903030302", + "duration": "9.0", "name": "blink_perf.image_decoder/decode-lossy-webp.html" }, { - "duration": "10.58182828282828", + "duration": "10.0", "name": "blink_perf.image_decoder/decode-png-palette-opaque.html" }, { - "duration": "9.544272696969697", + "duration": "9.0", "name": "blink_perf.image_decoder/decode-png-palette.html" }, { - "duration": "12.752656585858585", + "duration": "13.0", "name": "blink_perf.image_decoder/decode-png.html" }, { - "duration": "18.947606092929295", + "duration": "12.0", "name": "blink_perf.layout/ArabicLineLayout.html" }, { - "duration": "3.509444423232323", + "duration": "4.0", "name": "blink_perf.layout/Shapes/MultipleShapes.html" }, { - "duration": "8.547484808080808", + "duration": "9.0", "name": "blink_perf.layout/SimpleTextPathLineLayout.html" }, { - "duration": "11.027383853535351", + "duration": "9.0", "name": "blink_perf.layout/add-remove-inline-floats.html" }, { - "duration": "8.954101007070706", + "duration": "9.0", "name": "blink_perf.layout/attach-inlines-2.html" }, { - "duration": "8.298616216161616", + "duration": "9.0", "name": "blink_perf.layout/attach-inlines.html" }, { - "duration": "9.218161585858589", + "duration": "9.0", "name": "blink_perf.layout/auto-grid-lots-of-data.html" }, { - "duration": "9.579525222222223", + "duration": "11.0", + "name": "blink_perf.layout/change-text-css-contain.html" + }, + { + "duration": "9.0", "name": "blink_perf.layout/chapter-reflow-once-random.html" }, { - "duration": "8.9726465", + "duration": "10.0", "name": "blink_perf.layout/chapter-reflow-once.html" }, { - "duration": "8.197999997979798", + "duration": "9.0", "name": "blink_perf.layout/chapter-reflow-thrice.html" }, { - "duration": "8.205798000000003", + "duration": "9.0", "name": "blink_perf.layout/chapter-reflow-twice.html" }, { - "duration": "8.074090939393937", + "duration": "9.0", "name": "blink_perf.layout/chapter-reflow.html" }, { - "duration": "5.536888917171718", + "duration": "7.0", "name": "blink_perf.layout/character_fallback.html" }, { - "duration": "3.261747474747475", + "duration": "4.0", "name": "blink_perf.layout/character_fallback_aat.html" }, { - "duration": "9.281595989898989", + "duration": "9.0", "name": "blink_perf.layout/fixed-grid-lots-of-data.html" }, { - "duration": "9.146888848484847", + "duration": "9.0", "name": "blink_perf.layout/fixed-grid-lots-of-stretched-data.html" }, { - "duration": "8.400161631313136", + "duration": "9.0", "name": "blink_perf.layout/flexbox-column-nowrap.html" }, { - "duration": "8.462201997979799", + "duration": "9.0", "name": "blink_perf.layout/flexbox-column-wrap.html" }, { - "duration": "8.362212107070707", + "duration": "9.0", "name": "blink_perf.layout/flexbox-deeply-nested-column-flow.html" }, { - "duration": "8.58810097979798", + "duration": "10.0", "name": "blink_perf.layout/flexbox-lots-of-data.html" }, { - "duration": "8.248353522222226", + "duration": "9.0", "name": "blink_perf.layout/flexbox-row-nowrap.html" }, { - "duration": "8.221979809090909", + "duration": "9.0", "name": "blink_perf.layout/flexbox-row-wrap.html" }, { - "duration": "9.274141398989899", + "duration": "10.0", "name": "blink_perf.layout/flexbox-with-stretch-layout.html" }, { - "duration": "7.264454541414142", + "duration": "8.0", "name": "blink_perf.layout/floats_100_100.html" }, { - "duration": "7.287424223232322", + "duration": "8.0", "name": "blink_perf.layout/floats_100_100_nested.html" }, { - "duration": "5.380808066666666", + "duration": "6.0", "name": "blink_perf.layout/floats_10_1000.html" }, { - "duration": "4.327999992929294", + "duration": "5.0", "name": "blink_perf.layout/floats_20_100.html" }, { - "duration": "4.65909091111111", + "duration": "5.0", "name": "blink_perf.layout/floats_20_100_nested.html" }, { - "duration": "3.805828268686869", + "duration": "5.0", "name": "blink_perf.layout/floats_2_100.html" }, { - "duration": "3.869171721212122", + "duration": "4.0", "name": "blink_perf.layout/floats_2_100_nested.html" }, { - "duration": "4.985525238383841", + "duration": "5.0", "name": "blink_perf.layout/floats_50_100.html" }, { - "duration": "5.068727260606062", + "duration": "6.0", "name": "blink_perf.layout/floats_50_100_nested.html" }, { - "duration": "8.537181798989899", + "duration": "9.0", "name": "blink_perf.layout/hindi-line-layout.html" }, { - "duration": "7.121080791919193", + "duration": "9.0", + "name": "blink_perf.layout/large-spanning-grid-item.html" + }, + { + "duration": "8.0", "name": "blink_perf.layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html" }, { - "duration": "7.105181829292929", + "duration": "8.0", "name": "blink_perf.layout/large-table-with-collapsed-borders-and-colspans.html" }, { - "duration": "7.045474754545456", + "duration": "8.0", "name": "blink_perf.layout/large-table-with-collapsed-borders-and-no-colspans.html" }, { - "duration": "3.346484848484849", - "name": "blink_perf.layout/latin-complex-text.html" + "duration": "42.0", + "name": "blink_perf.layout/latin-ebook-resize.html" }, { - "duration": "3.6330707060606056", + "duration": "12.0", + "name": "blink_perf.layout/latin-ebook.html" + }, + { + "duration": "4.0", "name": "blink_perf.layout/layers_overlap_2d.html" }, { - "duration": "3.752888907070708", + "duration": "4.0", "name": "blink_perf.layout/layers_overlap_3d.html" }, { - "duration": "7.253565652525253", + "duration": "8.0", "name": "blink_perf.layout/line-layout-line-height.html" }, { - "duration": "8.558373762626262", + "duration": "9.0", "name": "blink_perf.layout/line-layout-repeat-append.html" }, { - "duration": "8.186737343434345", + "duration": "9.0", "name": "blink_perf.layout/line-layout.html" }, { - "duration": "3.327555552525252", + "duration": "4.0", "name": "blink_perf.layout/long-line-nowrap-collapse.html" }, { - "duration": "3.3382929383838387", + "duration": "4.0", "name": "blink_perf.layout/long-line-nowrap-spans-collapse.html" }, { - "duration": "4.858424242424244", + "duration": "5.0", "name": "blink_perf.layout/long-line-nowrap.html" }, { - "duration": "9.10998988383838", + "duration": "9.0", "name": "blink_perf.layout/multicol/deeply-nested-tables.html" }, { - "duration": "8.83554547070707", + "duration": "9.0", "name": "blink_perf.layout/multicol/fixed-height-with-spanner-and-nested-tables.html" }, { - "duration": "8.304888890909089", + "duration": "9.0", "name": "blink_perf.layout/multicol/lots-of-text-autofill.html" }, { - "duration": "8.313949487878789", + "duration": "9.0", "name": "blink_perf.layout/multicol/lots-of-text-balanced-orphans-widows.html" }, { - "duration": "8.073010090909087", + "duration": "9.0", "name": "blink_perf.layout/multicol/lots-of-text-balanced.html" }, { - "duration": "8.377909106060606", + "duration": "9.0", "name": "blink_perf.layout/multicol/tall-content-short-columns-realistic.html" }, { - "duration": "8.295161604040402", + "duration": "9.0", "name": "blink_perf.layout/multicol/tall-content-short-columns.html" }, { - "duration": "8.375201976767677", + "duration": "9.0", "name": "blink_perf.layout/nested-blocks-with-percent-height-and-max-height.html" }, { - "duration": "8.208010116161617", + "duration": "9.0", "name": "blink_perf.layout/nested-grid.html" }, { - "duration": "8.243555550505057", + "duration": "9.0", "name": "blink_perf.layout/nested-percent-height-tables.html" }, { - "duration": "32.9910606060606", + "duration": "34.0", "name": "blink_perf.layout/subtree-detaching.html" }, { - "duration": "3.89325253030303", + "duration": "4.0", "name": "blink_perf.layout/vertical-japanese-kokoro-insert.html" }, { - "duration": "4.3011010040404045", + "duration": "5.0", "name": "blink_perf.layout/word-break-break-all.html" }, { - "duration": "4.459707066666663", + "duration": "5.0", "name": "blink_perf.layout/word-break-break-word.html" }, { - "duration": "4.607626281818178", + "duration": "5.0", "name": "blink_perf.layout/word-wrap-break-word.html" }, { - "duration": "32.56997982828283", + "duration": "20.0", "name": "blink_perf.owp_storage/blob-perf-files.html" }, { - "duration": "9.272777772727274", + "duration": "9.0", "name": "blink_perf.owp_storage/blob-perf-ipc.html" }, { - "duration": "8.302111108080808", + "duration": "9.0", "name": "blink_perf.owp_storage/blob-perf-shm.html" }, { - "duration": "9.117333297979796", + "duration": "10.0", "name": "blink_perf.owp_storage/blob-perf-tiny.html" }, { - "duration": "13.110434323232322", + "duration": "13.0", "name": "blink_perf.owp_storage/idb-load-docs.html" }, { - "duration": "16.175020202020203", + "duration": "9.0", "name": "blink_perf.paint/appending-text.html" }, { - "duration": "12.853030308080807", + "duration": "13.0", "name": "blink_perf.paint/color-changes.html" }, { - "duration": "12.522818196969695", + "duration": "13.0", "name": "blink_perf.paint/complex-content-slow-scroll.html" }, { - "duration": "10.464747479797984", + "duration": "11.0", "name": "blink_perf.paint/containment-resize.html" }, { - "duration": "10.300272747474747", + "duration": "11.0", "name": "blink_perf.paint/fixed-and-many-layers-scroll.html" }, { - "duration": "11.4118888989899", + "duration": "12.0", "name": "blink_perf.paint/large-table-background-change-with-invisible-collapsed-borders.html" }, { - "duration": "9.514404085858587", + "duration": "10.0", "name": "blink_perf.paint/large-table-background-change-with-visible-collapsed-borders.html" }, { - "duration": "11.730878752525253", + "duration": "12.0", "name": "blink_perf.paint/large-table-background-change-with-zero-width-collapsed-borders.html" }, { - "duration": "9.963010126262631", + "duration": "11.0", "name": "blink_perf.paint/large-table-collapsed-border-change-with-backgrounds.html" }, { - "duration": "10.524818131313129", + "duration": "11.0", "name": "blink_perf.paint/large-table-collapsed-border-change-with-text.html" }, { - "duration": "8.973393934343438", + "duration": "9.0", "name": "blink_perf.paint/large-table-collapsed-border-change.html" }, { - "duration": "10.428828242424247", + "duration": "11.0", "name": "blink_perf.paint/large-table-repaint.html" }, { - "duration": "8.833666651515154", + "duration": "9.0", "name": "blink_perf.paint/move-text-with-mask.html" }, { - "duration": "10.244737388888883", + "duration": "11.0", "name": "blink_perf.paint/paint-offset-changes.html" }, { - "duration": "13.593020191919194", + "duration": "18.0", "name": "blink_perf.paint/transform-changes.html" }, { - "duration": "18.802565686868693", + "duration": "12.0", "name": "blink_perf.parser/css-parser-yui.html" }, { - "duration": "7.583060596969697", + "duration": "8.0", "name": "blink_perf.parser/html-parser-threaded.html" }, { - "duration": "7.217404042424242", + "duration": "8.0", "name": "blink_perf.parser/html-parser.html" }, { - "duration": "21.312282767676773", + "duration": "21.0", "name": "blink_perf.parser/html5-full-render.html" }, { - "duration": "9.200919196969691", + "duration": "10.0", "name": "blink_perf.parser/iframe-append-remove.html" }, { - "duration": "8.843555555555556", + "duration": "9.0", "name": "blink_perf.parser/innerHTML-setter-siblings.html" }, { - "duration": "8.766969702020198", + "duration": "9.0", "name": "blink_perf.parser/innerHTML-setter.html" }, { - "duration": "8.663414116161618", + "duration": "9.0", "name": "blink_perf.parser/query-selector-all-attribute-complex.html" }, { - "duration": "8.576505040404038", + "duration": "9.0", "name": "blink_perf.parser/query-selector-all-attribute.html" }, { - "duration": "8.474474765656568", + "duration": "9.0", "name": "blink_perf.parser/query-selector-all-class-deep.html" }, { - "duration": "9.299161575757577", + "duration": "10.0", "name": "blink_perf.parser/query-selector-all-class-first.html" }, { - "duration": "8.414717176767676", + "duration": "9.0", "name": "blink_perf.parser/query-selector-all-class-last.html" }, { - "duration": "8.55489894848485", + "duration": "9.0", "name": "blink_perf.parser/query-selector-all-class.html" }, { - "duration": "8.514272675757574", + "duration": "9.0", "name": "blink_perf.parser/query-selector-all-deep.html" }, { - "duration": "9.268101030303031", + "duration": "10.0", "name": "blink_perf.parser/query-selector-all-first.html" }, { - "duration": "9.338040449494953", + "duration": "10.0", "name": "blink_perf.parser/query-selector-all-id-deep.html" }, { - "duration": "9.265838373737374", + "duration": "10.0", "name": "blink_perf.parser/query-selector-all-id-first.html" }, { - "duration": "9.477414116161622", + "duration": "10.0", "name": "blink_perf.parser/query-selector-all-id-last.html" }, { - "duration": "8.46759596969697", + "duration": "9.0", "name": "blink_perf.parser/query-selector-all-last.html" }, { - "duration": "8.296292951515149", + "duration": "9.0", "name": "blink_perf.parser/query-selector-deep.html" }, { - "duration": "8.269939439393939", + "duration": "9.0", "name": "blink_perf.parser/query-selector-first.html" }, { - "duration": "8.322747490909089", + "duration": "9.0", "name": "blink_perf.parser/query-selector-id-deep.html" }, { - "duration": "8.530777778787877", + "duration": "9.0", "name": "blink_perf.parser/query-selector-id-last.html" }, { - "duration": "8.417727281818184", + "duration": "9.0", "name": "blink_perf.parser/query-selector-last.html" }, { - "duration": "8.109979769696968", + "duration": "9.0", "name": "blink_perf.parser/simple-url.html" }, { - "duration": "8.719798020202017", + "duration": "9.0", "name": "blink_perf.parser/textarea-parsing.html" }, { - "duration": "8.91624238888889", + "duration": "9.0", "name": "blink_perf.parser/tiny-innerHTML.html" }, { - "duration": "9.241100984848485", + "duration": "10.0", "name": "blink_perf.parser/url-parser.html" }, { - "duration": "7.880505068686869", + "duration": "9.0", "name": "blink_perf.parser/xml-parser.html" }, { - "duration": "12.34037373838384", + "duration": "4.0", "name": "blink_perf.shadow_dom/shadow-style-share-attr-selectors.html" }, { - "duration": "4.270252529292932", + "duration": "4.0", "name": "blink_perf.shadow_dom/shadow-style-share-media-query.html" }, { - "duration": "4.241000009090909", + "duration": "4.0", "name": "blink_perf.shadow_dom/shadow-style-share-with-distribution.html" }, { - "duration": "4.8917171757575755", + "duration": "4.0", "name": "blink_perf.shadow_dom/shadow-style-share.html" }, { - "duration": "4.796333336363637", + "duration": "5.0", "name": "blink_perf.shadow_dom/style-sheet-insert.html" }, { - "duration": "3.6853737434343428", + "duration": "4.0", "name": "blink_perf.shadow_dom/v0-changing-classname-with-shadow-dom.html" }, { - "duration": "3.764878785858585", + "duration": "4.0", "name": "blink_perf.shadow_dom/v0-changing-classname-without-shadow-dom.html" }, { - "duration": "4.745979779797979", + "duration": "5.0", "name": "blink_perf.shadow_dom/v0-changing-select-with-shadow-dom.html" }, { - "duration": "5.141030298989901", + "duration": "5.0", "name": "blink_perf.shadow_dom/v0-changing-select-without-shadow-dom.html" }, { - "duration": "3.947484861616161", + "duration": "4.0", "name": "blink_perf.shadow_dom/v0-content-reprojection.html" }, { - "duration": "3.6637878797979817", + "duration": "4.0", "name": "blink_perf.shadow_dom/v0-large-distribution-without-layout.html" }, { - "duration": "3.6803737383838393", + "duration": "4.0", "name": "blink_perf.shadow_dom/v0-multiple-insertion-points.html" }, { - "duration": "3.9176767656565654", + "duration": "4.0", "name": "blink_perf.shadow_dom/v0-shadow-reprojection.html" }, { - "duration": "4.389949510101011", + "duration": "4.0", "name": "blink_perf.shadow_dom/v0-small-distribution-with-layout.html" }, { - "duration": "12.176565601010097", + "duration": "11.0", "name": "blink_perf.shadow_dom/v1-distribution-disconnected-and-reconnected.html" }, { - "duration": "3.3039191898989895", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-distribution.html" }, { - "duration": "3.3323939343434335", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-host-child-append.html" }, { - "duration": "11.572313095959593", + "duration": "11.0", "name": "blink_perf.shadow_dom/v1-large-deep-distribution.html" }, { - "duration": "20.463808090909094", + "duration": "19.0", "name": "blink_perf.shadow_dom/v1-large-deep-layout.html" }, { - "duration": "3.2629191868686855", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-large-shallow-distribution.html" }, { - "duration": "3.305262635353534", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-large-shallow-layout.html" }, { - "duration": "3.6749494919191936", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-re-layout.html" }, { - "duration": "4.031222225252525", + "duration": "5.0", "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-slot-assigned-nodes.html" }, { - "duration": "3.9982626252525235", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-slot-flatten.html" }, { - "duration": "3.6141312919191932", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-re-layout.html" }, { - "duration": "3.3712222191919192", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-slot-assigned-nodes.html" }, { - "duration": "3.6590605939393925", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-slot-flatten.html" }, { - "duration": "4.0200605959595945", + "duration": "5.0", "name": "blink_perf.shadow_dom/v1-slot-append.html" }, { - "duration": "4.957868676767677", + "duration": "5.0", "name": "blink_perf.shadow_dom/v1-small-deep-distribution.html" }, { - "duration": "4.538727265656566", + "duration": "5.0", "name": "blink_perf.shadow_dom/v1-small-deep-layout.html" }, { - "duration": "3.4889697050505046", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-small-shallow-distribution.html" }, { - "duration": "3.5975454494949495", + "duration": "4.0", "name": "blink_perf.shadow_dom/v1-small-shallow-layout.html" }, { - "duration": "11.494909038383836", + "duration": "4.0", "name": "blink_perf.svg/AzLizardBenjiPark.html" }, { - "duration": "4.6980404", + "duration": "4.0", "name": "blink_perf.svg/Bamboo.html" }, { - "duration": "4.092404045454544", + "duration": "4.0", "name": "blink_perf.svg/Cactus.html" }, { - "duration": "4.094000000000001", + "duration": "4.0", "name": "blink_perf.svg/Cowboy.html" }, { - "duration": "5.061656557575756", - "name": "blink_perf.svg/Cowboy_transform.html" - }, - { - "duration": "3.5484646515151526", + "duration": "4.0", "name": "blink_perf.svg/CrawFishGanson.html" }, { - "duration": "3.5005454444444446", + "duration": "4.0", "name": "blink_perf.svg/Debian.html" }, { - "duration": "3.4699696919191907", + "duration": "4.0", "name": "blink_perf.svg/DropsOnABlade.html" }, { - "duration": "3.81215153131313", + "duration": "4.0", "name": "blink_perf.svg/FlowerFromMyGarden.html" }, { - "duration": "4.067505039393939", + "duration": "4.0", "name": "blink_perf.svg/FoodLeifLodahl.html" }, { - "duration": "3.9484242545454546", + "duration": "4.0", "name": "blink_perf.svg/France.html" }, { - "duration": "3.616010100000001", + "duration": "4.0", "name": "blink_perf.svg/FrancoBolloGnomeEzechi.html" }, { - "duration": "3.8947171717171725", + "duration": "4.0", "name": "blink_perf.svg/GearFlowers.html" }, { - "duration": "4.045040398989902", + "duration": "4.0", "name": "blink_perf.svg/HarveyRayner.html" }, { - "duration": "4.13256565050505", + "duration": "4.0", "name": "blink_perf.svg/HereGear.html" }, { - "duration": "4.843080801010103", + "duration": "5.0", "name": "blink_perf.svg/MtSaintHelens.html" }, { - "duration": "3.4929293050505046", + "duration": "4.0", "name": "blink_perf.svg/Samurai.html" }, { - "duration": "23.492767656565654", + "duration": "27.0", "name": "blink_perf.svg/SierpinskiCarpet.html" }, { - "duration": "3.878919172727274", + "duration": "4.0", "name": "blink_perf.svg/SvgCubics.html" }, { - "duration": "3.6388484787878794", + "duration": "4.0", "name": "blink_perf.svg/SvgHitTesting.html" }, { - "duration": "9.364565661616163", + "duration": "9.0", "name": "blink_perf.svg/SvgNestedUse.html" }, { - "duration": "3.458737377777778", + "duration": "4.0", "name": "blink_perf.svg/UnderTheSee.html" }, { - "duration": "3.574141404040404", + "duration": "4.0", "name": "blink_perf.svg/WorldIso.html" }, { - "duration": "4.211555554545455", + "duration": "5.0", "name": "blink_perf.svg/Worldcup.html" }, { - "duration": "41.77264644444443", + "duration": "42.0", "name": "dromaeo/http://dromaeo.com?dom-attr" }, { - "duration": "33.883939313131314", + "duration": "34.0", "name": "dromaeo/http://dromaeo.com?dom-modify" }, { - "duration": "48.964242363636345", + "duration": "49.0", "name": "dromaeo/http://dromaeo.com?dom-query" }, { - "duration": "30.013323232323227", + "duration": "30.0", "name": "dromaeo/http://dromaeo.com?dom-traverse" }, { - "duration": "22.23553537878789", - "name": "dummy_benchmark.histogram_benchmark_1/dummy_page.html" - }, - { - "duration": "16.528737389898993", + "duration": "3.0", "name": "dummy_benchmark.noisy_benchmark_1/dummy_page.html" }, { - "duration": "10.877414132323226", - "name": "dummy_benchmark.stable_benchmark_1/dummy_page.html" - }, - { - "duration": "178.4075252525252", + "duration": "178.0", "name": "jetstream/http://browserbench.org/JetStream/" }, { - "duration": "29.704030292929282", + "duration": "20.0", "name": "kraken/http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html" }, { - "duration": "78.57620210101011", - "name": "loading.desktop/24h" - }, - { - "duration": "34.89154563636364", + "duration": "18.0", "name": "loading.desktop/24h_cold" }, { - "duration": "42.348090909090914", + "duration": "22.0", "name": "loading.desktop/24h_warm" }, { - "duration": "0.00150001045", - "name": "loading.desktop/2ch" - }, - { - "duration": "110.41564648484851", - "name": "loading.desktop/AirBnB" - }, - { - "duration": "44.22172736363637", + "duration": "23.0", "name": "loading.desktop/AirBnB_cold" }, { - "duration": "62.84945436363635", + "duration": "32.0", "name": "loading.desktop/AirBnB_warm" }, { - "duration": "59.46995958585859", - "name": "loading.desktop/Aljayyash" - }, - { - "duration": "27.844090727272725", + "duration": "21.0", "name": "loading.desktop/Aljayyash_cold" }, { - "duration": "31.365636636363636", + "duration": "16.0", "name": "loading.desktop/Aljayyash_warm" }, { - "duration": "126.35130305050508", - "name": "loading.desktop/AllRecipes" - }, - { - "duration": "51.872454545454545", + "duration": "27.0", "name": "loading.desktop/AllRecipes_cold" }, { - "duration": "73.06945454545453", + "duration": "37.0", "name": "loading.desktop/AllRecipes_warm" }, { - "duration": "118.84544441414144", - "name": "loading.desktop/ArsTechnica" - }, - { - "duration": "46.56990909090909", + "duration": "23.0", "name": "loading.desktop/ArsTechnica_cold" }, { - "duration": "70.74781818181818", + "duration": "35.0", "name": "loading.desktop/ArsTechnica_warm" }, { - "duration": "61.44041423232327", - "name": "loading.desktop/Baidu" - }, - { - "duration": "28.274181909090906", + "duration": "14.0", "name": "loading.desktop/Baidu_cold" }, { - "duration": "31.373181954545455", + "duration": "16.0", "name": "loading.desktop/Baidu_warm" }, { - "duration": "95.69785862626262", - "name": "loading.desktop/Bhaskar" - }, - { - "duration": "41.749999909090896", + "duration": "21.0", "name": "loading.desktop/Bhaskar_cold" }, { - "duration": "51.47263627272727", + "duration": "30.0", "name": "loading.desktop/Bhaskar_warm" }, { - "duration": "77.03323236363636", - "name": "loading.desktop/Chosun" - }, - { - "duration": "34.634181909090906", + "duration": "17.0", "name": "loading.desktop/Chosun_cold" }, { - "duration": "40.61872754545455", + "duration": "21.0", "name": "loading.desktop/Chosun_warm" }, { - "duration": "78.14680811111107", - "name": "loading.desktop/Colorado.edu" - }, - { - "duration": "34.05109081818182", + "duration": "18.0", "name": "loading.desktop/Colorado.edu_cold" }, { - "duration": "42.41045463636363", + "duration": "21.0", "name": "loading.desktop/Colorado.edu_warm" }, { - "duration": "73.46498984343432", - "name": "loading.desktop/Danawa" - }, - { - "duration": "32.620818", + "duration": "17.0", "name": "loading.desktop/Danawa_cold" }, { - "duration": "39.22545454545454", + "duration": "20.0", "name": "loading.desktop/Danawa_warm" }, { - "duration": "71.1682221969697", - "name": "loading.desktop/Daum" - }, - { - "duration": "31.564181909090905", + "duration": "16.0", "name": "loading.desktop/Daum_cold" }, { - "duration": "38.23954554545454", + "duration": "20.0", "name": "loading.desktop/Daum_warm" }, { - "duration": "82.40019187878787", - "name": "loading.desktop/Donga" - }, - { - "duration": "36.052727272727275", + "duration": "19.0", "name": "loading.desktop/Donga_cold" }, { - "duration": "44.36727281818182", + "duration": "22.0", "name": "loading.desktop/Donga_warm" }, { - "duration": "102.11448485858584", - "name": "loading.desktop/Economist" - }, - { - "duration": "41.82954545454546", + "duration": "21.0", "name": "loading.desktop/Economist_cold" }, { - "duration": "58.38845454545455", + "duration": "29.0", "name": "loading.desktop/Economist_warm" }, { - "duration": "180.4631415050505", - "name": "loading.desktop/Elmundo" - }, - { - "duration": "56.766363727272726", + "duration": "29.0", "name": "loading.desktop/Elmundo_cold" }, { - "duration": "124.10299999999998", - "name": "loading.desktop/Elmundo_warm" - }, - { - "duration": "69.69703034848486", - "name": "loading.desktop/FC2Blog" - }, - { - "duration": "31.68309081818182", + "duration": "16.0", "name": "loading.desktop/FC2Blog_cold" }, { - "duration": "36.056", + "duration": "19.0", "name": "loading.desktop/FC2Blog_warm" }, { - "duration": "9.999275E-4", - "name": "loading.desktop/FDA" - }, - { - "duration": "75.79931317171716", - "name": "loading.desktop/FIFA" - }, - { - "duration": "32.85509090909091", + "duration": "17.0", "name": "loading.desktop/FIFA_cold" }, { - "duration": "42.29836363636364", + "duration": "21.0", "name": "loading.desktop/FIFA_warm" }, { - "duration": "143.38708084848486", - "name": "loading.desktop/FarsNews" - }, - { - "duration": "141.6059089545454", + "duration": "27.0", "name": "loading.desktop/FarsNews_cold" }, { - "duration": "40.50745454545454", + "duration": "20.0", "name": "loading.desktop/FarsNews_warm" }, { - "duration": "75.53585861616165", - "name": "loading.desktop/Flickr" - }, - { - "duration": "32.13345436363637", + "duration": "16.0", "name": "loading.desktop/Flickr_cold" }, { - "duration": "40.053636454545455", + "duration": "20.0", "name": "loading.desktop/Flickr_warm" }, { - "duration": "73.68077771717172", - "name": "loading.desktop/FlipKart" - }, - { - "duration": "31.75018181818182", + "duration": "19.0", "name": "loading.desktop/FlipKart_cold" }, { - "duration": "40.299818181818175", + "duration": "20.0", "name": "loading.desktop/FlipKart_warm" }, { - "duration": "61.55254540404039", - "name": "loading.desktop/Free.fr" - }, - { - "duration": "28.31327281818182", + "duration": "14.0", "name": "loading.desktop/Free.fr_cold" }, { - "duration": "32.280272818181814", + "duration": "18.0", "name": "loading.desktop/Free.fr_warm" }, { - "duration": "58.197777631313116", - "name": "loading.desktop/HTML5Rocks" - }, - { - "duration": "26.86945463636364", + "duration": "14.0", "name": "loading.desktop/HTML5Rocks_cold" }, { - "duration": "30.446181772727268", + "duration": "16.0", "name": "loading.desktop/HTML5Rocks_warm" }, { - "duration": "63.899545444444435", - "name": "loading.desktop/Haraj" - }, - { - "duration": "29.686454545454545", + "duration": "15.0", "name": "loading.desktop/Haraj_cold" }, { - "duration": "33.44236372727273", + "duration": "17.0", "name": "loading.desktop/Haraj_warm" }, { - "duration": "92.08967675757577", - "name": "loading.desktop/HatenaBookmark" - }, - { - "duration": "39.44172727272727", + "duration": "19.0", "name": "loading.desktop/HatenaBookmark_cold" }, { - "duration": "51.46272736363637", + "duration": "27.0", "name": "loading.desktop/HatenaBookmark_warm" }, { - "duration": "80.91992933333333", - "name": "loading.desktop/IGN" - }, - { - "duration": "35.35863645454546", + "duration": "18.0", "name": "loading.desktop/IGN_cold" }, { - "duration": "42.52245436363636", + "duration": "22.0", "name": "loading.desktop/IGN_warm" }, { - "duration": "79.23717173737374", - "name": "loading.desktop/IMDB" - }, - { - "duration": "34.606363636363646", + "duration": "17.0", "name": "loading.desktop/IMDB_cold" }, { - "duration": "43.98918190909091", + "duration": "22.0", "name": "loading.desktop/IMDB_warm" }, { - "duration": "80.78213134343434", - "name": "loading.desktop/IndiaTimes" - }, - { - "duration": "35.079181909090906", + "duration": "17.0", "name": "loading.desktop/IndiaTimes_cold" }, { - "duration": "44.12018190909091", + "duration": "22.0", "name": "loading.desktop/IndiaTimes_warm" }, { - "duration": "81.66095963636364", - "name": "loading.desktop/Kakaku" - }, - { - "duration": "35.228727272727276", + "duration": "18.0", "name": "loading.desktop/Kakaku_cold" }, { - "duration": "42.783091000000006", + "duration": "22.0", "name": "loading.desktop/Kakaku_warm" }, { - "duration": "115.41123235353534", - "name": "loading.desktop/Kenh14" - }, - { - "duration": "47.85572736363636", + "duration": "25.0", "name": "loading.desktop/Kenh14_cold" }, { - "duration": "64.74309072727273", + "duration": "34.0", "name": "loading.desktop/Kenh14_warm" }, { - "duration": "0.0020000934", - "name": "loading.desktop/Leboncoin" - }, - { - "duration": "73.09690900000003", - "name": "loading.desktop/Mercadolivre" - }, - { - "duration": "34.15090913636364", + "duration": "16.0", "name": "loading.desktop/Mercadolivre_cold" }, { - "duration": "39.20309081818181", + "duration": "20.0", "name": "loading.desktop/Mercadolivre_warm" }, { - "duration": "83.10848609722224", - "name": "loading.desktop/NatGeo" - }, - { - "duration": "67.53106070202023", - "name": "loading.desktop/Naver" - }, - { - "duration": "31.20118168181818", + "duration": "16.0", "name": "loading.desktop/Naver_cold" }, { - "duration": "35.56554554545455", + "duration": "18.0", "name": "loading.desktop/Naver_warm" }, { - "duration": "9.999275E-4", - "name": "loading.desktop/Orange" - }, - { - "duration": "69.13476764646464", - "name": "loading.desktop/Pantip" - }, - { - "duration": "31.22127277272728", + "duration": "16.0", "name": "loading.desktop/Pantip_cold" }, { - "duration": "37.04663627272728", + "duration": "19.0", "name": "loading.desktop/Pantip_warm" }, { - "duration": "91.78712126262629", - "name": "loading.desktop/PremierLeague" - }, - { - "duration": "43.34336363636363", + "duration": "21.0", "name": "loading.desktop/PremierLeague_cold" }, { - "duration": "51.15399981818182", + "duration": "27.0", "name": "loading.desktop/PremierLeague_warm" }, { - "duration": "93.61086858585857", - "name": "loading.desktop/QQ" - }, - { - "duration": "41.02945454545454", + "duration": "21.0", "name": "loading.desktop/QQ_cold" }, { - "duration": "50.887818181818176", + "duration": "26.0", "name": "loading.desktop/QQ_warm" }, { - "duration": "79.76416155555557", - "name": "loading.desktop/REI" - }, - { - "duration": "34.89572727272727", + "duration": "18.0", "name": "loading.desktop/REI_cold" }, { - "duration": "43.998636363636365", + "duration": "22.0", "name": "loading.desktop/REI_warm" }, { - "duration": "65.75473735858588", - "name": "loading.desktop/Ruten" - }, - { - "duration": "30.167090999999996", + "duration": "15.0", "name": "loading.desktop/Ruten_cold" }, { - "duration": "33.726090818181824", + "duration": "17.0", "name": "loading.desktop/Ruten_warm" }, { - "duration": "106.65854540404042", - "name": "loading.desktop/Sina" - }, - { - "duration": "46.67527245454546", + "duration": "25.0", "name": "loading.desktop/Sina_cold" }, { - "duration": "61.8140000909091", + "duration": "32.0", "name": "loading.desktop/Sina_warm" }, { - "duration": "100.36073740404039", - "name": "loading.desktop/Taobao" - }, - { - "duration": "44.00036363636363", + "duration": "25.0", "name": "loading.desktop/Taobao_cold" }, { - "duration": "55.31509109090909", + "duration": "31.0", "name": "loading.desktop/Taobao_warm" }, { - "duration": "97.96895952525253", - "name": "loading.desktop/TheOnion" - }, - { - "duration": "40.10881827272727", + "duration": "22.0", "name": "loading.desktop/TheOnion_cold" }, { - "duration": "56.237818272727274", + "duration": "29.0", "name": "loading.desktop/TheOnion_warm" }, { - "duration": "103.5693131010101", - "name": "loading.desktop/TheVerge" - }, - { - "duration": "43.66945454545455", + "duration": "23.0", "name": "loading.desktop/TheVerge_cold" }, { - "duration": "57.977090909090904", + "duration": "29.0", "name": "loading.desktop/TheVerge_warm" }, { - "duration": "97.86764656565656", - "name": "loading.desktop/TicketMaster" - }, - { - "duration": "41.81781818181818", + "duration": "22.0", "name": "loading.desktop/TicketMaster_cold" }, { - "duration": "53.691181818181825", + "duration": "28.0", "name": "loading.desktop/TicketMaster_warm" }, { - "duration": "129.45020208080805", - "name": "loading.desktop/Vietnamnet" - }, - { - "duration": "54.56272718181819", + "duration": "29.0", "name": "loading.desktop/Vietnamnet_cold" }, { - "duration": "71.455", + "duration": "37.0", "name": "loading.desktop/Vietnamnet_warm" }, { - "duration": "110.85240404040401", - "name": "loading.desktop/Vnexpress" - }, - { - "duration": "45.840818181818186", + "duration": "24.0", "name": "loading.desktop/Vnexpress_cold" }, { - "duration": "62.674091", + "duration": "32.0", "name": "loading.desktop/Vnexpress_warm" }, { - "duration": "128.95016167676764", - "name": "loading.desktop/Walgreens" - }, - { - "duration": "48.86699999999999", + "duration": "27.0", "name": "loading.desktop/Walgreens_cold" }, { - "duration": "66.59363645454546", + "duration": "36.0", "name": "loading.desktop/Walgreens_warm" }, { - "duration": "60.92042428282829", - "name": "loading.desktop/Yandex" - }, - { - "duration": "28.47527263636364", + "duration": "14.0", "name": "loading.desktop/Yandex_cold" }, { - "duration": "32.07054540909091", + "duration": "16.0", "name": "loading.desktop/Yandex_warm" }, { - "duration": "0.0020000934", - "name": "loading.desktop/Ynet" - }, - { - "duration": "95.01235352525256", - "name": "loading.desktop/amazon.co.jp" - }, - { - "duration": "41.30800009090909", + "duration": "21.0", "name": "loading.desktop/amazon.co.jp_cold" }, { - "duration": "52.254363454545455", + "duration": "26.0", "name": "loading.desktop/amazon.co.jp_warm" }, { - "duration": "0.0010001659", - "name": "loading.desktop/goo.ne.jp" - }, - { - "duration": "64.14469705555557", - "name": "loading.desktop/ja.wikipedia" - }, - { - "duration": "29.452091", + "duration": "15.0", "name": "loading.desktop/ja.wikipedia_cold" }, { - "duration": "33.31909127272728", + "duration": "17.0", "name": "loading.desktop/ja.wikipedia_warm" }, { - "duration": "116.1541918585859", - "name": "loading.desktop/money.cnn" - }, - { - "duration": "48.49163618181819", + "duration": "25.0", "name": "loading.desktop/money.cnn_cold" }, { - "duration": "66.35827281818182", + "duration": "35.0", "name": "loading.desktop/money.cnn_warm" }, { - "duration": "65.59816158585858", - "name": "loading.desktop/ru.wikipedia" - }, - { - "duration": "30.597272909090908", + "duration": "15.0", "name": "loading.desktop/ru.wikipedia_cold" }, { - "duration": "34.24136363636364", + "duration": "17.0", "name": "loading.desktop/ru.wikipedia_warm" }, { - "duration": "130.93452529292935", - "name": "loading.desktop/uol.com.br" - }, - { - "duration": "55.8129999090909", + "duration": "28.0", "name": "loading.desktop/uol.com.br_cold" }, { - "duration": "73.41581818181818", + "duration": "36.0", "name": "loading.desktop/uol.com.br_warm" }, { - "duration": "77.21720199999999", - "name": "loading.desktop/yahoo.co.jp" - }, - { - "duration": "35.536000090909084", + "duration": "18.0", "name": "loading.desktop/yahoo.co.jp_cold" }, { - "duration": "40.967363818181816", + "duration": "21.0", "name": "loading.desktop/yahoo.co.jp_warm" }, { - "duration": "14.284727297979792", + "duration": "14.0", "name": "media.desktop/mse.html?media=aac_audio.mp4" }, { - "duration": "15.291282838383838", + "duration": "15.0", "name": "media.desktop/mse.html?media=aac_audio.mp4,h264_video.mp4" }, { - "duration": "15.404494974747472", + "duration": "15.0", "name": "media.desktop/mse.html?media=aac_audio.mp4,h264_video.mp4&waitForPageLoaded=true" }, { - "duration": "14.54688892929293", + "duration": "15.0", "name": "media.desktop/mse.html?media=h264_video.mp4" }, { - "duration": "30.074434353535352", + "duration": "22.0", "name": "media.desktop/video.html?src=crowd.ogg&type=audio" }, { - "duration": "22.585696989898995", + "duration": "23.0", "name": "media.desktop/video.html?src=crowd1080.mp4" }, { - "duration": "22.32874746464647", + "duration": "23.0", "name": "media.desktop/video.html?src=crowd1080.webm" }, { - "duration": "20.64434349494949", + "duration": "21.0", "name": "media.desktop/video.html?src=crowd1080_vp9.webm" }, { - "duration": "11.109717166666664", + "duration": "12.0", "name": "media.desktop/video.html?src=crowd1080_vp9.webm&seek" }, { - "duration": "20.519212151515166", + "duration": "21.0", "name": "media.desktop/video.html?src=crowd720_vp9.webm" }, { - "duration": "22.698989939393936", + "duration": "23.0", "name": "media.desktop/video.html?src=garden2_10s.mp4" }, { - "duration": "13.125444494949496", + "duration": "14.0", "name": "media.desktop/video.html?src=garden2_10s.mp4&seek" }, { - "duration": "21.584535383838386", + "duration": "22.0", "name": "media.desktop/video.html?src=garden2_10s.webm" }, { - "duration": "11.604767681818181", + "duration": "12.0", "name": "media.desktop/video.html?src=garden2_10s.webm&seek" }, { - "duration": "13.741343424242428", + "duration": "14.0", "name": "media.desktop/video.html?src=smpte_3840x2160_60fps_vp9.webm&seek" }, { - "duration": "28.402000010101023", + "duration": "29.0", "name": "media.desktop/video.html?src=tulip2.m4a&type=audio" }, { - "duration": "28.308464636363627", + "duration": "29.0", "name": "media.desktop/video.html?src=tulip2.mp3&type=audio" }, { - "duration": "10.517202010101009", + "duration": "11.0", "name": "media.desktop/video.html?src=tulip2.mp3&type=audio&seek" }, { - "duration": "30.34575756565656", + "duration": "31.0", "name": "media.desktop/video.html?src=tulip2.mp4" }, { - "duration": "31.075262636363636", + "duration": "32.0", "name": "media.desktop/video.html?src=tulip2.mp4&busyjs" }, { - "duration": "12.047656540404038", + "duration": "13.0", "name": "media.desktop/video.html?src=tulip2.mp4&seek" }, { - "duration": "28.44826266666668", + "duration": "29.0", "name": "media.desktop/video.html?src=tulip2.ogg&type=audio" }, { - "duration": "10.554030308080806", + "duration": "11.0", "name": "media.desktop/video.html?src=tulip2.ogg&type=audio&seek" }, { - "duration": "30.347424181818187", + "duration": "31.0", "name": "media.desktop/video.html?src=tulip2.vp9.webm" }, { - "duration": "22.295969666666664", + "duration": "23.0", "name": "media.desktop/video.html?src=tulip2.vp9.webm&background" }, { - "duration": "12.51783844444445", + "duration": "13.0", "name": "media.desktop/video.html?src=tulip2.vp9.webm&seek" }, { - "duration": "30.544848464646467", - "name": "media.desktop/video.html?src=tulip2.vp9.webm_Regular-3G" - }, - { - "duration": "28.388313070707053", + "duration": "29.0", "name": "media.desktop/video.html?src=tulip2.wav&type=audio" }, { - "duration": "10.554636378787874", + "duration": "11.0", "name": "media.desktop/video.html?src=tulip2.wav&type=audio&seek" }, { - "duration": "127.33676775757577", + "duration": "95.0", "name": "memory.desktop/TrivialAnimationPageSharedPageState" }, { - "duration": "145.83215154545456", + "duration": "80.0", "name": "memory.desktop/TrivialBlinkingCursorPageSharedPageState" }, { - "duration": "139.11132333333333", + "duration": "77.0", "name": "memory.desktop/TrivialBlurAnimationPageSharedPageState" }, { - "duration": "140.222798010101", + "duration": "82.0", "name": "memory.desktop/TrivialCanvasPageSharedPageState" }, { - "duration": "146.12095961616163", + "duration": "85.0", "name": "memory.desktop/TrivialFullscreenVideoPageSharedPageState" }, { - "duration": "139.2347374848485", + "duration": "82.0", "name": "memory.desktop/TrivialGifPageSharedPageState" }, { - "duration": "151.88948483838388", + "duration": "87.0", "name": "memory.desktop/TrivialScrollingPageSharedPageState" }, { - "duration": "140.38805041414145", + "duration": "76.0", "name": "memory.desktop/TrivialWebGLPageSharedPageState" }, { - "duration": "176.53833333333338", + "duration": "224.0", "name": "memory.long_running_idle_gmail_background_tbmv2/https://mail.google.com/mail/" }, { - "duration": "179.30326292929288", + "duration": "182.0", "name": "memory.long_running_idle_gmail_tbmv2/https://mail.google.com/mail/" }, { - "duration": "51.14163640404042", + "duration": "37.0", "name": "octane/http://chromium.github.io/octane/index.html?auto=1" }, { - "duration": "0.016000032", - "name": "oortonline_tbmv2/http://oortonline.gl/#run" - }, - { - "duration": "45.30037377777777", + "duration": "46.0", "name": "power.desktop/TrivialAnimationPageSharedPageState" }, { - "duration": "42.370767616161636", + "duration": "43.0", "name": "power.desktop/TrivialBlinkingCursorPageSharedPageState" }, { - "duration": "45.103060626262646", + "duration": "46.0", "name": "power.desktop/TrivialBlurAnimationPageSharedPageState" }, { - "duration": "44.91517175757577", + "duration": "45.0", "name": "power.desktop/TrivialCanvasPageSharedPageState" }, { - "duration": "43.55830305050504", + "duration": "44.0", "name": "power.desktop/TrivialFullscreenVideoPageSharedPageState" }, { - "duration": "41.65617175757575", + "duration": "43.0", "name": "power.desktop/TrivialGifPageSharedPageState" }, { - "duration": "60.67017167676768", + "duration": "45.0", "name": "power.desktop/TrivialScrollingPageSharedPageState" }, { - "duration": "45.631141434343434", + "duration": "46.0", "name": "power.desktop/TrivialWebGLPageSharedPageState" }, { - "duration": "48.99010101010105", + "duration": "50.0", "name": "power.desktop/abcnews" }, { - "duration": "42.73526260606061", + "duration": "44.0", "name": "power.desktop/indiatimes" }, { - "duration": "45.23994945454546", + "duration": "46.0", "name": "power.desktop/instagram" }, { - "duration": "42.91129294949496", + "duration": "44.0", "name": "power.desktop/microsoft" }, { - "duration": "44.993212141414126", + "duration": "45.0", "name": "power.desktop/sina" }, { - "duration": "45.198464585858595", + "duration": "46.0", "name": "power.desktop/slideshare" }, { - "duration": "51.8506162020202", + "duration": "54.0", "name": "power.desktop/uol" }, { - "duration": "44.42340401717171", + "duration": "7.0", "name": "rasterize_and_record_micro.partial_invalidation/800_relpos_divs.html" }, { - "duration": "40.14971717171717", + "duration": "19.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/amazon.html" }, { - "duration": "10.36961614141414", + "duration": "11.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/blogger.html" }, { - "duration": "11.474747515151515", + "duration": "12.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/booking.html" }, { - "duration": "14.137484863636368", + "duration": "14.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/cnn.html" }, { - "duration": "11.30878783838383", + "duration": "12.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/ebay.html" }, { - "duration": "18.503888858585857", + "duration": "19.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/espn.html" }, { - "duration": "10.994060601010094", + "duration": "11.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/facebook.html" }, { - "duration": "10.46459592929293", + "duration": "11.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/gmail.html" }, { - "duration": "9.05187877777778", + "duration": "10.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/google.html" }, { - "duration": "7.8801414030303025", + "duration": "8.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/googlecalendar.html" }, { - "duration": "8.841080797979798", + "duration": "9.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/googledocs.html" }, { - "duration": "14.022161646464642", + "duration": "15.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/googleimagesearch.html" }, { - "duration": "23.136989878787876", + "duration": "23.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/googleplus.html" }, { - "duration": "9.614131297979798", + "duration": "10.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/linkedin.html" }, { - "duration": "8.085515150505051", + "duration": "9.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/pinterest.html" }, { - "duration": "27.01127273737374", + "duration": "27.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/techcrunch.html" }, { - "duration": "17.37996967676768", + "duration": "18.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/twitter.html" }, { - "duration": "13.90968686363636", + "duration": "14.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/weather.html" }, { - "duration": "0.0015000105", - "name": "rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html" - }, - { - "duration": "17.52616165656566", + "duration": "20.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/wordpress.html" }, { - "duration": "12.048848499999997", + "duration": "13.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahooanswers.html" }, { - "duration": "23.689646464646458", + "duration": "24.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoogames.html" }, { - "duration": "101.4227676363636", + "duration": "102.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoonews.html" }, { - "duration": "87.58763624242427", + "duration": "88.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoosports.html" }, { - "duration": "25.368646454545452", + "duration": "26.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/youtube.html" }, { - "duration": "11.749513483783783", + "duration": "34.0", + "name": "rendering.desktop/accu_weather_2018" + }, + { + "duration": "6.0", + "name": "rendering.desktop/accu_weather_pinch_2018" + }, + { + "duration": "33.0", + "name": "rendering.desktop/amazon_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/amazon_pinch" }, { - "duration": "29.648757585858586", + "duration": "6.0", + "name": "rendering.desktop/amazon_pinch_2018" + }, + { + "duration": "26.0", "name": "rendering.desktop/analog_clock_svg" }, { - "duration": "31.3422702972973", + "duration": "27.0", "name": "rendering.desktop/animometer_webgl" }, { - "duration": "25.6781891891892", + "duration": "27.0", "name": "rendering.desktop/aquarium" }, { - "duration": "33.15567567567567", + "duration": "36.0", "name": "rendering.desktop/aquarium_20k" }, { - "duration": "26.025228571428574", + "duration": "28.0", "name": "rendering.desktop/background_color_animation" }, { - "duration": "27.911499971428572", + "duration": "30.0", "name": "rendering.desktop/background_color_animation_with_gradient" }, { - "duration": "23.35797962244898", + "duration": "26.0", "name": "rendering.desktop/balls_css_key_frame_animations" }, { - "duration": "22.68637757142857", + "duration": "25.0", "name": "rendering.desktop/balls_css_key_frame_animations_composited_transform" }, { - "duration": "28.071877602040814", + "duration": "31.0", "name": "rendering.desktop/balls_css_transition_2_properties" }, { - "duration": "28.14669385714286", + "duration": "31.0", "name": "rendering.desktop/balls_css_transition_40_properties" }, { - "duration": "28.141449020408146", + "duration": "31.0", "name": "rendering.desktop/balls_css_transition_all_properties" }, { - "duration": "28.019132591836726", + "duration": "28.0", "name": "rendering.desktop/balls_javascript_canvas" }, { - "duration": "23.552336744897968", + "duration": "28.0", "name": "rendering.desktop/balls_javascript_css" }, { - "duration": "26.56185711224489", + "duration": "29.0", "name": "rendering.desktop/balls_svg_animations" }, { - "duration": "21.239837851351353", + "duration": "23.0", "name": "rendering.desktop/blob" }, { - "duration": "27.214393919191902", - "name": "rendering.desktop/blogspot" + "duration": "37.0", + "name": "rendering.desktop/blogspot_2018" }, { - "duration": "3.398148660810811", + "duration": "4.0", "name": "rendering.desktop/blogspot_pinch" }, { - "duration": "16.276090944444448", - "name": "rendering.desktop/booking.com" + "duration": "6.0", + "name": "rendering.desktop/blogspot_pinch_2018" }, { - "duration": "3.3600540621621624", + "duration": "21.0", + "name": "rendering.desktop/booking.com_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/booking_pinch" }, { - "duration": "16.071454550505045", + "duration": "6.0", + "name": "rendering.desktop/booking_pinch_2018" + }, + { + "duration": "18.0", "name": "rendering.desktop/bouncing_balls_15" }, { - "duration": "16.618626292929292", + "duration": "22.0", "name": "rendering.desktop/bouncing_balls_shadow" }, { - "duration": "17.947232348484853", + "duration": "22.0", "name": "rendering.desktop/bouncing_clipped_rectangles" }, { - "duration": "18.87498991414141", + "duration": "19.0", "name": "rendering.desktop/bouncing_gradient_circles" }, { - "duration": "13.914151474747479", + "duration": "15.0", "name": "rendering.desktop/bouncing_png_images" }, { - "duration": "25.59261617171718", + "duration": "29.0", "name": "rendering.desktop/bouncing_svg_images" }, { - "duration": "19.723135148648645", + "duration": "21.0", "name": "rendering.desktop/canvas_05000_pixels_per_second" }, { - "duration": "18.904567567567568", + "duration": "20.0", "name": "rendering.desktop/canvas_10000_pixels_per_second" }, { - "duration": "16.27175674324324", + "duration": "17.0", "name": "rendering.desktop/canvas_15000_pixels_per_second" }, { - "duration": "14.953283729729732", + "duration": "16.0", "name": "rendering.desktop/canvas_20000_pixels_per_second" }, { - "duration": "13.580216250000005", + "duration": "14.0", "name": "rendering.desktop/canvas_30000_pixels_per_second" }, { - "duration": "12.205743222972975", + "duration": "13.0", "name": "rendering.desktop/canvas_40000_pixels_per_second" }, { - "duration": "11.751648675675678", + "duration": "13.0", "name": "rendering.desktop/canvas_50000_pixels_per_second" }, { - "duration": "11.394418939189187", + "duration": "12.0", "name": "rendering.desktop/canvas_60000_pixels_per_second" }, { - "duration": "11.054716209459457", + "duration": "12.0", "name": "rendering.desktop/canvas_75000_pixels_per_second" }, { - "duration": "10.93420270945946", + "duration": "12.0", "name": "rendering.desktop/canvas_90000_pixels_per_second" }, { - "duration": "18.635040444444442", + "duration": "22.0", "name": "rendering.desktop/canvas_animation_no_clear" }, { - "duration": "17.480787883838378", + "duration": "18.0", "name": "rendering.desktop/canvas_arcs" }, { - "duration": "16.069838378787882", + "duration": "18.0", "name": "rendering.desktop/canvas_font_cycler" }, { - "duration": "16.083666671717182", + "duration": "18.0", "name": "rendering.desktop/canvas_lines" }, { - "duration": "16.040707101010103", + "duration": "18.0", "name": "rendering.desktop/canvas_to_blob" }, { - "duration": "14.130229729729738", + "duration": "14.0", "name": "rendering.desktop/cats_unscaled" }, { - "duration": "11.663405418918924", + "duration": "13.0", "name": "rendering.desktop/cats_viewport_width" }, { - "duration": "19.4661413939394", + "duration": "27.0", + "name": "rendering.desktop/cc_poster_circle" + }, + { + "duration": "25.0", + "name": "rendering.desktop/cc_scroll_200_layer_grid" + }, + { + "duration": "18.0", + "name": "rendering.desktop/cc_scroll_text_only" + }, + { + "duration": "22.0", "name": "rendering.desktop/chip_tune" }, { - "duration": "9.999275E-4", - "name": "rendering.desktop/cnn" + "duration": "38.0", + "name": "rendering.desktop/cnn_2018" }, { - "duration": "3.355621628378379", + "duration": "4.0", "name": "rendering.desktop/cnn_pinch" }, { - "duration": "21.967346938775506", + "duration": "6.0", + "name": "rendering.desktop/cnn_pinch_2018" + }, + { + "duration": "24.0", "name": "rendering.desktop/compositor_heavy_animation" }, { - "duration": "18.872939378787883", + "duration": "21.0", "name": "rendering.desktop/crafty_mind" }, { - "duration": "21.48962241836734", + "duration": "24.0", "name": "rendering.desktop/css_animations_many_keyframes" }, { - "duration": "21.739224469387757", + "duration": "24.0", "name": "rendering.desktop/css_animations_simultaneous_inline_style" }, { - "duration": "22.285142887755097", + "duration": "25.0", "name": "rendering.desktop/css_animations_simultaneous_new_element" }, { - "duration": "21.638183663265313", + "duration": "24.0", "name": "rendering.desktop/css_animations_simultaneous_style_element" }, { - "duration": "21.801836724489807", + "duration": "24.0", "name": "rendering.desktop/css_animations_simultaneous_updating_class" }, { - "duration": "20.921612224489795", + "duration": "23.0", "name": "rendering.desktop/css_animations_staggered_infinite_iterations" }, { - "duration": "23.98542856122449", + "duration": "27.0", "name": "rendering.desktop/css_animations_staggered_inline_style" }, { - "duration": "25.03437756122449", + "duration": "28.0", "name": "rendering.desktop/css_animations_staggered_new_element" }, { - "duration": "24.63691838775511", + "duration": "28.0", "name": "rendering.desktop/css_animations_staggered_style_element" }, { - "duration": "24.100163255102036", + "duration": "27.0", "name": "rendering.desktop/css_animations_staggered_updating_class" }, { - "duration": "24.08099997959184", + "duration": "27.0", "name": "rendering.desktop/css_animations_triggered_inline_style" }, { - "duration": "25.08975509183673", + "duration": "28.0", "name": "rendering.desktop/css_animations_triggered_new_element" }, { - "duration": "24.66866327551021", + "duration": "28.0", "name": "rendering.desktop/css_animations_triggered_style_element" }, { - "duration": "24.05020411224491", + "duration": "27.0", "name": "rendering.desktop/css_animations_triggered_updating_class" }, { - "duration": "21.854663255102032", + "duration": "24.0", "name": "rendering.desktop/css_transitions_inline_style" }, { - "duration": "22.405316326530603", + "duration": "25.0", "name": "rendering.desktop/css_transitions_new_element" }, { - "duration": "22.588540826530604", + "duration": "25.0", "name": "rendering.desktop/css_transitions_staggered_inline_style" }, { - "duration": "22.92858166326531", + "duration": "26.0", "name": "rendering.desktop/css_transitions_staggered_new_element" }, { - "duration": "22.545020357142857", + "duration": "25.0", "name": "rendering.desktop/css_transitions_staggered_style_element" }, { - "duration": "22.164714285714282", + "duration": "25.0", "name": "rendering.desktop/css_transitions_staggered_updating_class" }, { - "duration": "21.855704112244904", + "duration": "24.0", "name": "rendering.desktop/css_transitions_style_element" }, { - "duration": "24.090683673469385", + "duration": "27.0", "name": "rendering.desktop/css_transitions_triggered_inline_style" }, { - "duration": "24.180387755102036", + "duration": "27.0", "name": "rendering.desktop/css_transitions_triggered_new_element" }, { - "duration": "24.250428520408153", + "duration": "27.0", "name": "rendering.desktop/css_transitions_triggered_style_element" }, { - "duration": "24.188265285714287", + "duration": "27.0", "name": "rendering.desktop/css_transitions_triggered_updating_class" }, { - "duration": "22.349540795918358", + "duration": "24.0", "name": "rendering.desktop/css_transitions_updating_class" }, { - "duration": "21.67029589795918", + "duration": "24.0", "name": "rendering.desktop/css_value_type_color" }, { - "duration": "46.88489804081632", + "duration": "52.0", "name": "rendering.desktop/css_value_type_filter" }, { - "duration": "22.139653020408165", + "duration": "25.0", "name": "rendering.desktop/css_value_type_length" }, { - "duration": "23.012999989795908", + "duration": "24.0", "name": "rendering.desktop/css_value_type_length_complex" }, { - "duration": "22.605897989795913", + "duration": "24.0", "name": "rendering.desktop/css_value_type_length_simple" }, { - "duration": "23.596938744897944", + "duration": "26.0", "name": "rendering.desktop/css_value_type_path" }, { - "duration": "24.968959183673462", + "duration": "28.0", "name": "rendering.desktop/css_value_type_shadow" }, { - "duration": "22.006602020408145", + "duration": "25.0", "name": "rendering.desktop/css_value_type_transform_complex" }, { - "duration": "22.39977551020408", + "duration": "25.0", "name": "rendering.desktop/css_value_type_transform_simple" }, { - "duration": "22.424216216216212", + "duration": "24.0", "name": "rendering.desktop/dynamic_cube_map" }, { - "duration": "22.056729675675676", + "duration": "23.0", "name": "rendering.desktop/earth" }, { - "duration": "14.417717176767686", - "name": "rendering.desktop/ebay" + "duration": "24.0", + "name": "rendering.desktop/ebay_2018" }, { - "duration": "3.3867432459459463", + "duration": "4.0", "name": "rendering.desktop/ebay_pinch" }, { - "duration": "20.23591921212121", + "duration": "6.0", + "name": "rendering.desktop/ebay_pinch_2018" + }, + { + "duration": "22.0", "name": "rendering.desktop/effect_games" }, { - "duration": "17.596323212121213", - "name": "rendering.desktop/espn" + "duration": "28.0", + "name": "rendering.desktop/espn_2018" }, { - "duration": "1.9492026716216213", + "duration": "4.0", "name": "rendering.desktop/espn_pinch" }, { - "duration": "24.38280001428571", + "duration": "6.0", + "name": "rendering.desktop/espn_pinch_2018" + }, + { + "duration": "27.0", "name": "rendering.desktop/extra_large_texture_uploads" }, { - "duration": "16.001151525252535", - "name": "rendering.desktop/facebook" + "duration": "22.0", + "name": "rendering.desktop/facebook_2018" }, { - "duration": "3.3825405540540543", + "duration": "4.0", "name": "rendering.desktop/facebook_pinch" }, { - "duration": "17.90641415656566", + "duration": "6.0", + "name": "rendering.desktop/facebook_pinch_2018" + }, + { + "duration": "19.0", "name": "rendering.desktop/fill_shapes" }, { - "duration": "24.849848494949494", + "duration": "26.0", "name": "rendering.desktop/filter_terrain_svg" }, { - "duration": "16.42275757070707", + "duration": "17.0", "name": "rendering.desktop/geo_apis" }, { - "duration": "46.080464656565645", - "name": "rendering.desktop/gmail" + "duration": "25.0", + "name": "rendering.desktop/gmail_2018" }, { - "duration": "3.430027028378378", + "duration": "53.0", + "name": "rendering.desktop/gmail_move_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/gmail_pinch" }, { - "duration": "2.003162155405405", + "duration": "6.0", + "name": "rendering.desktop/gmail_pinch_2018" + }, + { + "duration": "21.0", + "name": "rendering.desktop/google_calendar_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/google_calendar_pinch" }, { - "duration": "1.9667432216216216", + "duration": "6.0", + "name": "rendering.desktop/google_calendar_pinch_2018" + }, + { + "duration": "22.0", + "name": "rendering.desktop/google_docs_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/google_image_pinch" }, { - "duration": "9.999275E-4", - "name": "rendering.desktop/google_image_search" + "duration": "6.0", + "name": "rendering.desktop/google_image_pinch_2018" }, { - "duration": "3.4238783621621613", + "duration": "23.0", + "name": "rendering.desktop/google_image_search_2018" + }, + { + "duration": "23.0", + "name": "rendering.desktop/google_plus_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/google_search_pinch" }, { - "duration": "13.695181843434337", - "name": "rendering.desktop/google_web_search" + "duration": "6.0", + "name": "rendering.desktop/google_search_pinch_2018" }, { - "duration": "24.932464656565646", + "duration": "20.0", + "name": "rendering.desktop/google_web_search_2018" + }, + { + "duration": "27.0", "name": "rendering.desktop/guimark_vector_chart" }, { - "duration": "18.654545434343426", + "duration": "21.0", "name": "rendering.desktop/hakim" }, { - "duration": "33.754171707070725", + "duration": "35.0", "name": "rendering.desktop/ie_chalkboard" }, { - "duration": "28.128818171717178", + "duration": "31.0", "name": "rendering.desktop/ie_pirate_mark" }, { - "duration": "19.5751313131313", + "duration": "24.0", "name": "rendering.desktop/jarro_doverson" }, { - "duration": "18.821999989898988", + "duration": "36.0", + "name": "rendering.desktop/js_full_screen_invalidation" + }, + { + "duration": "28.0", + "name": "rendering.desktop/js_poster_circle" + }, + { + "duration": "25.0", + "name": "rendering.desktop/js_scroll_200_layer_grid" + }, + { + "duration": "25.0", + "name": "rendering.desktop/js_scroll_text_only" + }, + { + "duration": "21.0", "name": "rendering.desktop/kevs_3d" }, { - "duration": "20.936061244897964", + "duration": "23.0", "name": "rendering.desktop/keyframed_animations" }, { - "duration": "24.960199999999997", + "duration": "27.0", "name": "rendering.desktop/large_texture_uploads" }, { - "duration": "16.06519193939393", - "name": "rendering.desktop/linkedin" + "duration": "26.0", + "name": "rendering.desktop/linkedin_2018" }, { - "duration": "3.3957837581081085", + "duration": "4.0", "name": "rendering.desktop/linkedin_pinch" }, { - "duration": "19.803989898989897", + "duration": "6.0", + "name": "rendering.desktop/linkedin_pinch_2018" + }, + { + "duration": "22.0", "name": "rendering.desktop/man_in_blue" }, { - "duration": "20.679333343434344", + "duration": "24.0", "name": "rendering.desktop/many_images" }, { - "duration": "21.30737837837838", + "duration": "23.0", "name": "rendering.desktop/many_planets_deep" }, { - "duration": "20.254111121212123", - "name": "rendering.desktop/maps_move" + "duration": "24.0", + "name": "rendering.desktop/maps_move_2018" }, { - "duration": "23.513500000000004", + "duration": "26.0", "name": "rendering.desktop/maps_perf_test" }, { - "duration": "23.8306857", + "duration": "26.0", "name": "rendering.desktop/medium_texture_uploads" }, { - "duration": "17.122121166666663", + "duration": "19.0", "name": "rendering.desktop/megi_dish" }, { - "duration": "17.747333348484844", + "duration": "20.0", "name": "rendering.desktop/microsoft_asteroid_belt" }, { - "duration": "25.96921209090908", + "duration": "28.0", "name": "rendering.desktop/microsoft_fireflies" }, { - "duration": "17.80268685858586", + "duration": "20.0", "name": "rendering.desktop/microsoft_fish_ie_tank" }, { - "duration": "17.789606075757575", + "duration": "19.0", "name": "rendering.desktop/microsoft_snow" }, { - "duration": "16.500323262626264", + "duration": "18.0", "name": "rendering.desktop/microsoft_speed_reading" }, { - "duration": "17.030828313131316", + "duration": "19.0", "name": "rendering.desktop/microsoft_tweet_map" }, { - "duration": "22.418767666666664", + "duration": "25.0", "name": "rendering.desktop/microsoft_video_city" }, { - "duration": "17.979404080808084", + "duration": "20.0", "name": "rendering.desktop/microsoft_worker_fountains" }, { - "duration": "16.28039394949495", + "duration": "18.0", "name": "rendering.desktop/mix_10k" }, { - "duration": "20.562163306122454", + "duration": "22.0", "name": "rendering.desktop/mix_blend_mode_animation_difference" }, { - "duration": "20.540653061224486", + "duration": "22.0", "name": "rendering.desktop/mix_blend_mode_animation_hue" }, { - "duration": "23.503153051020416", + "duration": "26.0", "name": "rendering.desktop/mix_blend_mode_animation_propagating_isolation" }, { - "duration": "21.31911221428572", + "duration": "24.0", "name": "rendering.desktop/mix_blend_mode_animation_screen" }, { - "duration": "25.787787888888882", + "duration": "26.0", "name": "rendering.desktop/motion_mark_canvas_fill_shapes" }, { - "duration": "29.423434353535352", + "duration": "25.0", "name": "rendering.desktop/motion_mark_canvas_stroke_shapes" }, { - "duration": "29.478848494949478", + "duration": "32.0", "name": "rendering.desktop/motion_mark_focus" }, { - "duration": "22.122202648648646", + "duration": "32.0", + "name": "rendering.desktop/new_tilings" + }, + { + "duration": "23.0", "name": "rendering.desktop/nvidia_vertex_buffer_object" }, { - "duration": "43.261857081632634", + "duration": "45.0", "name": "rendering.desktop/overlay_background_color_css_transitions_page" }, { - "duration": "19.93382433783784", + "duration": "22.0", "name": "rendering.desktop/particles" }, { - "duration": "22.1771211919192", - "name": "rendering.desktop/pinterest" + "duration": "31.0", + "name": "rendering.desktop/pinterest_2018" }, { - "duration": "17.12040403030303", + "duration": "20.0", "name": "rendering.desktop/put_get_image_data" }, { - "duration": "20.72282862857143", + "duration": "21.0", "name": "rendering.desktop/raf" }, { - "duration": "19.898342842857137", + "duration": "21.0", "name": "rendering.desktop/raf_animation" }, { - "duration": "19.21491427142857", + "duration": "21.0", "name": "rendering.desktop/raf_canvas" }, { - "duration": "19.894214342857143", + "duration": "21.0", "name": "rendering.desktop/raf_touch_animation" }, { - "duration": "16.730949545454546", + "duration": "18.0", "name": "rendering.desktop/runway" }, { - "duration": "20.584945932432436", + "duration": "22.0", "name": "rendering.desktop/san_angeles" }, { - "duration": "11.322185735714287", + "duration": "12.0", "name": "rendering.desktop/second_batch_js_heavy" }, { - "duration": "11.337228557142856", + "duration": "12.0", "name": "rendering.desktop/second_batch_js_light" }, { - "duration": "11.281528657142855", + "duration": "12.0", "name": "rendering.desktop/second_batch_js_medium" }, { - "duration": "18.043371428571433", + "duration": "20.0", "name": "rendering.desktop/simple_text_page" }, { - "duration": "14.075828578571427", + "duration": "15.0", "name": "rendering.desktop/simple_touch_drag" }, { - "duration": "23.387328628571424", + "duration": "25.0", "name": "rendering.desktop/small_texture_uploads" }, { - "duration": "19.919131328282827", + "duration": "23.0", "name": "rendering.desktop/smash_cat" }, { - "duration": "15.738959590909094", + "duration": "17.0", "name": "rendering.desktop/spielzeugz" }, { - "duration": "20.060242444444444", + "duration": "18.0", "name": "rendering.desktop/stroke_shapes" }, { - "duration": "16.70578568571429", + "duration": "18.0", "name": "rendering.desktop/sync_scroll_offset" }, { - "duration": "45.047010141414134", - "name": "rendering.desktop/techcrunch" + "duration": "31.0", + "name": "rendering.desktop/techcrunch_2018" }, { - "duration": "18.489094567567573", + "duration": "20.0", "name": "rendering.desktop/text_05000_pixels_per_second" }, { - "duration": "18.111351310810807", + "duration": "19.0", "name": "rendering.desktop/text_10000_pixels_per_second" }, { - "duration": "15.123216229729724", + "duration": "16.0", "name": "rendering.desktop/text_15000_pixels_per_second" }, { - "duration": "13.47327028378379", + "duration": "15.0", "name": "rendering.desktop/text_20000_pixels_per_second" }, { - "duration": "12.086702675675676", + "duration": "13.0", "name": "rendering.desktop/text_30000_pixels_per_second" }, { - "duration": "11.470148682432429", + "duration": "12.0", "name": "rendering.desktop/text_40000_pixels_per_second" }, { - "duration": "11.046702682432436", + "duration": "12.0", "name": "rendering.desktop/text_50000_pixels_per_second" }, { - "duration": "10.755243263513508", + "duration": "12.0", "name": "rendering.desktop/text_60000_pixels_per_second" }, { - "duration": "10.538932418918922", + "duration": "11.0", "name": "rendering.desktop/text_75000_pixels_per_second" }, { - "duration": "10.363324270270269", + "duration": "11.0", "name": "rendering.desktop/text_90000_pixels_per_second" }, { - "duration": "21.405027054054052", + "duration": "23.0", "name": "rendering.desktop/text_constant_full_page_raster_05000_pixels_per_second" }, { - "duration": "19.808581067567566", + "duration": "21.0", "name": "rendering.desktop/text_constant_full_page_raster_10000_pixels_per_second" }, { - "duration": "16.666972959459454", + "duration": "18.0", "name": "rendering.desktop/text_constant_full_page_raster_15000_pixels_per_second" }, { - "duration": "15.047608114864863", + "duration": "16.0", "name": "rendering.desktop/text_constant_full_page_raster_20000_pixels_per_second" }, { - "duration": "13.516743189189185", + "duration": "15.0", "name": "rendering.desktop/text_constant_full_page_raster_30000_pixels_per_second" }, { - "duration": "12.877716236486489", + "duration": "14.0", "name": "rendering.desktop/text_constant_full_page_raster_40000_pixels_per_second" }, { - "duration": "12.335959466216215", + "duration": "13.0", "name": "rendering.desktop/text_constant_full_page_raster_50000_pixels_per_second" }, { - "duration": "12.58914870945946", + "duration": "13.0", "name": "rendering.desktop/text_constant_full_page_raster_60000_pixels_per_second" }, { - "duration": "11.68462166891892", + "duration": "13.0", "name": "rendering.desktop/text_constant_full_page_raster_75000_pixels_per_second" }, { - "duration": "11.416162202702703", + "duration": "12.0", "name": "rendering.desktop/text_constant_full_page_raster_90000_pixels_per_second" }, { - "duration": "19.79178378378379", + "duration": "20.0", "name": "rendering.desktop/text_hover_05000_pixels_per_second" }, { - "duration": "17.201121675675672", + "duration": "19.0", "name": "rendering.desktop/text_hover_10000_pixels_per_second" }, { - "duration": "14.721054000000002", + "duration": "16.0", "name": "rendering.desktop/text_hover_15000_pixels_per_second" }, { - "duration": "13.377202729729728", + "duration": "14.0", "name": "rendering.desktop/text_hover_20000_pixels_per_second" }, { - "duration": "11.969635047297293", + "duration": "13.0", "name": "rendering.desktop/text_hover_30000_pixels_per_second" }, { - "duration": "11.293837891891894", + "duration": "12.0", "name": "rendering.desktop/text_hover_40000_pixels_per_second" }, { - "duration": "10.92344593243244", + "duration": "12.0", "name": "rendering.desktop/text_hover_50000_pixels_per_second" }, { - "duration": "10.592013520270271", + "duration": "12.0", "name": "rendering.desktop/text_hover_60000_pixels_per_second" }, { - "duration": "10.378459466216217", + "duration": "11.0", "name": "rendering.desktop/text_hover_75000_pixels_per_second" }, { - "duration": "10.215054013513514", + "duration": "11.0", "name": "rendering.desktop/text_hover_90000_pixels_per_second" }, { - "duration": "18.392042857142854", + "duration": "20.0", "name": "rendering.desktop/touch_handler_scrolling" }, { - "duration": "25.805744938775508", + "duration": "29.0", "name": "rendering.desktop/transform_transitions" }, { - "duration": "20.99041835714286", + "duration": "23.0", "name": "rendering.desktop/transform_transitions_js_block" }, { - "duration": "15.923585843434344", - "name": "rendering.desktop/twitter" + "duration": "20.0", + "name": "rendering.desktop/twitch_2018" }, { - "duration": "3.4048243364864867", + "duration": "6.0", + "name": "rendering.desktop/twitch_pinch_2018" + }, + { + "duration": "30.0", + "name": "rendering.desktop/twitter_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/twitter_pinch" }, { - "duration": "19.73749497979798", - "name": "rendering.desktop/weather.com" + "duration": "6.0", + "name": "rendering.desktop/twitter_pinch_2018" }, { - "duration": "3.4737837824324322", + "duration": "4.0", "name": "rendering.desktop/weather_pinch" }, { - "duration": "22.22325510204082", + "duration": "24.0", "name": "rendering.desktop/web_animation_value_type_color" }, { - "duration": "22.554367326530606", + "duration": "25.0", "name": "rendering.desktop/web_animation_value_type_length_3d" }, { - "duration": "22.776071438775503", + "duration": "25.0", "name": "rendering.desktop/web_animation_value_type_length_complex" }, { - "duration": "22.66179593877551", + "duration": "24.0", "name": "rendering.desktop/web_animation_value_type_length_simple" }, { - "duration": "23.72888772448981", + "duration": "26.0", "name": "rendering.desktop/web_animation_value_type_path" }, { - "duration": "25.027612244897966", + "duration": "28.0", "name": "rendering.desktop/web_animation_value_type_shadow" }, { - "duration": "22.083030591836728", + "duration": "25.0", "name": "rendering.desktop/web_animation_value_type_transform_complex" }, { - "duration": "22.058132642857146", + "duration": "25.0", "name": "rendering.desktop/web_animation_value_type_transform_simple" }, { - "duration": "22.424530581632656", + "duration": "25.0", "name": "rendering.desktop/web_animations_many_keyframes" }, { - "duration": "22.372724520408173", + "duration": "25.0", "name": "rendering.desktop/web_animations_set_current_time" }, { - "duration": "22.111806132653076", + "duration": "25.0", "name": "rendering.desktop/web_animations_simultaneous" }, { - "duration": "24.110938775510206", + "duration": "27.0", "name": "rendering.desktop/web_animations_staggered_chaining" }, { - "duration": "21.042408183673473", + "duration": "23.0", "name": "rendering.desktop/web_animations_staggered_infinite_iterations" }, { - "duration": "24.131163224489793", + "duration": "27.0", "name": "rendering.desktop/web_animations_staggered_triggering_page" }, { - "duration": "20.867535313131317", - "name": "rendering.desktop/wikipedia" + "duration": "27.0", + "name": "rendering.desktop/wikipedia_2018" }, { - "duration": "24.202080787878785", - "name": "rendering.desktop/wordpress" + "duration": "27.0", + "name": "rendering.desktop/wordpress_2018" }, { - "duration": "13.9063132020202", - "name": "rendering.desktop/yahoo_answers" + "duration": "17.0", + "name": "rendering.desktop/yahoo_answers_2018" }, { - "duration": "27.36668688888889", - "name": "rendering.desktop/yahoo_games" - }, - { - "duration": "3.4052567567567564", + "duration": "4.0", "name": "rendering.desktop/yahoo_games_pinch" }, { - "duration": "19.204212101010096", - "name": "rendering.desktop/yahoo_news" + "duration": "29.0", + "name": "rendering.desktop/yahoo_news_2018" }, { - "duration": "3.4164054040540535", + "duration": "4.0", "name": "rendering.desktop/yahoo_news_pinch" }, { - "duration": "22.487202030303028", - "name": "rendering.desktop/yahoo_sports" + "duration": "6.0", + "name": "rendering.desktop/yahoo_news_pinch_2018" }, { - "duration": "3.3848513635135125", + "duration": "31.0", + "name": "rendering.desktop/yahoo_sports_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/yahoo_sports_pinch" }, { - "duration": "9.999275E-4", - "name": "rendering.desktop/youtube" + "duration": "6.0", + "name": "rendering.desktop/yahoo_sports_pinch_2018" }, { - "duration": "1.9590675567567566", + "duration": "22.0", + "name": "rendering.desktop/youtube_2018" + }, + { + "duration": "4.0", "name": "rendering.desktop/youtube_pinch" }, { - "duration": "20.702314357142857", + "duration": "6.0", + "name": "rendering.desktop/youtube_pinch_2018" + }, + { + "duration": "24.0", "name": "rendering.desktop/yuv_decoding" }, { - "duration": "15.15833721511628", - "name": "scheduler.tough_scheduling_cases/raf" - }, - { - "duration": "15.31183841414141", - "name": "scheduler.tough_scheduling_cases/raf.html" - }, - { - "duration": "15.034860482558132", - "name": "scheduler.tough_scheduling_cases/raf_animation" - }, - { - "duration": "15.171404075757577", - "name": "scheduler.tough_scheduling_cases/raf_animation.html" - }, - { - "duration": "14.807779133720935", - "name": "scheduler.tough_scheduling_cases/raf_canvas" - }, - { - "duration": "14.98819193434343", - "name": "scheduler.tough_scheduling_cases/raf_canvas.html" - }, - { - "duration": "14.879592994186039", - "name": "scheduler.tough_scheduling_cases/raf_touch_animation" - }, - { - "duration": "15.083070686868682", - "name": "scheduler.tough_scheduling_cases/raf_touch_animation.html" - }, - { - "duration": "9.181262631313125", - "name": "scheduler.tough_scheduling_cases/second_batch_js.html?heavy" - }, - { - "duration": "9.228717186868687", - "name": "scheduler.tough_scheduling_cases/second_batch_js.html?light" - }, - { - "duration": "9.221727313131312", - "name": "scheduler.tough_scheduling_cases/second_batch_js.html?medium" - }, - { - "duration": "8.993337197674421", - "name": "scheduler.tough_scheduling_cases/second_batch_js_heavy" - }, - { - "duration": "8.918407005813952", - "name": "scheduler.tough_scheduling_cases/second_batch_js_light" - }, - { - "duration": "8.976790680232556", - "name": "scheduler.tough_scheduling_cases/second_batch_js_medium" - }, - { - "duration": "25.921860453488375", - "name": "scheduler.tough_scheduling_cases/simple_text_page" - }, - { - "duration": "31.042393898989896", - "name": "scheduler.tough_scheduling_cases/simple_text_page.html" - }, - { - "duration": "10.525232575581398", - "name": "scheduler.tough_scheduling_cases/simple_touch_drag" - }, - { - "duration": "10.714030252525257", - "name": "scheduler.tough_scheduling_cases/simple_touch_drag.html" - }, - { - "duration": "13.158895395348843", - "name": "scheduler.tough_scheduling_cases/sync_scroll_offset" - }, - { - "duration": "13.382323227272725", - "name": "scheduler.tough_scheduling_cases/sync_scroll_offset.html" - }, - { - "duration": "14.508546488372092", - "name": "scheduler.tough_scheduling_cases/touch_handler_scrolling" - }, - { - "duration": "14.925191853535352", - "name": "scheduler.tough_scheduling_cases/touch_handler_scrolling.html" - }, - { - "duration": "19.795979777777774", - "name": "smoothness.gpu_rasterization.tough_filters_cases/Analog_Clock_SVG" - }, - { - "duration": "19.78323232323232", - "name": "smoothness.gpu_rasterization.tough_filters_cases/Filter_Terrain_SVG" - }, - { - "duration": "21.751252545454545", - "name": "smoothness.gpu_rasterization.tough_filters_cases/IE_PirateMark" - }, - { - "duration": "41.54438378787879", - "name": "smoothness.gpu_rasterization.tough_filters_cases/MotionMark_Focus" - }, - { - "duration": "19.681757515151514", - "name": "smoothness.gpu_rasterization.tough_filters_cases/analog_clock_svg" - }, - { - "duration": "20.197171707070705", - "name": "smoothness.gpu_rasterization.tough_filters_cases/filter_terrain_svg" - }, - { - "duration": "22.312787909090904", - "name": "smoothness.gpu_rasterization.tough_filters_cases/ie_pirate_mark" - }, - { - "duration": "44.81907065656564", - "name": "smoothness.gpu_rasterization.tough_filters_cases/motion_mark_focus" - }, - { - "duration": "51.9720706969697", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/GUIMark_Vector_Chart_Test" - }, - { - "duration": "29.101070707070715", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/IE_Chalkboard" - }, - { - "duration": "20.926070777777785", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/MotionMark_Canvas_Fill_Shapes" - }, - { - "duration": "20.384282818181816", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/MotionMark_Canvas_Stroke_Shapes" - }, - { - "duration": "52.746656565656565", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/guimark_vector_chart" - }, - { - "duration": "29.01680805050505", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/ie_chalkboard" - }, - { - "duration": "20.63228283838384", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/motion_mark_canvas_fill_shapes" - }, - { - "duration": "20.179828292929287", - "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/motion_mark_canvas_stroke_shapes" - }, - { - "duration": "15.131030378787882", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_05000_pixels_per_second" - }, - { - "duration": "14.56143430808081", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_10000_pixels_per_second" - }, - { - "duration": "12.14886865656566", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_15000_pixels_per_second" - }, - { - "duration": "11.244898974747475", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_20000_pixels_per_second" - }, - { - "duration": "10.16179801515152", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_30000_pixels_per_second" - }, - { - "duration": "9.630282818181815", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_40000_pixels_per_second" - }, - { - "duration": "9.26740403030303", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_50000_pixels_per_second" - }, - { - "duration": "8.999141434343434", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_60000_pixels_per_second" - }, - { - "duration": "8.813020227272727", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_75000_pixels_per_second" - }, - { - "duration": "8.673272720202023", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_90000_pixels_per_second" - }, - { - "duration": "30.59284860606062", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_05000_pixels_per_second" - }, - { - "duration": "14.88858582828283", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_10000_pixels_per_second" - }, - { - "duration": "11.81005052020202", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_15000_pixels_per_second" - }, - { - "duration": "10.872798010101011", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_20000_pixels_per_second" - }, - { - "duration": "10.478525227272726", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_30000_pixels_per_second" - }, - { - "duration": "9.897767702020204", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_40000_pixels_per_second" - }, - { - "duration": "9.042797954545454", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_50000_pixels_per_second" - }, - { - "duration": "8.830888904040403", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_60000_pixels_per_second" - }, - { - "duration": "8.550494941414142", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_75000_pixels_per_second" - }, - { - "duration": "8.431555533333336", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_90000_pixels_per_second" - }, - { - "duration": "15.589919191919195", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second" - }, - { - "duration": "14.418969676767679", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second" - }, - { - "duration": "12.280929227272722", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second" - }, - { - "duration": "11.269858580808082", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second" - }, - { - "duration": "10.318515111111115", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second" - }, - { - "duration": "9.928242409090911", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second" - }, - { - "duration": "10.569131398989896", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second" - }, - { - "duration": "9.399424242424246", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second" - }, - { - "duration": "9.649555500000002", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second" - }, - { - "duration": "9.578818176767674", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second" - }, - { - "duration": "15.15427264646465", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_05000_pixels_per_second" - }, - { - "duration": "13.536212106060606", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_10000_pixels_per_second" - }, - { - "duration": "11.618383838383835", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_15000_pixels_per_second" - }, - { - "duration": "10.623737333333333", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_20000_pixels_per_second" - }, - { - "duration": "9.625353520202022", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_30000_pixels_per_second" - }, - { - "duration": "9.088282823232323", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_40000_pixels_per_second" - }, - { - "duration": "8.84143434848485", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_50000_pixels_per_second" - }, - { - "duration": "8.61992928787879", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_60000_pixels_per_second" - }, - { - "duration": "8.38473734848485", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_75000_pixels_per_second" - }, - { - "duration": "8.279404068686873", - "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_90000_pixels_per_second" - }, - { - "duration": "38.04753491860465", - "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases/yuv_decoding" - }, - { - "duration": "33.75913132323232", - "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases/yuv_decoding.html" - }, - { - "duration": "40.28665120930233", - "name": "smoothness.image_decoding_cases/yuv_decoding" - }, - { - "duration": "29.01557576767676", - "name": "smoothness.image_decoding_cases/yuv_decoding.html" - }, - { - "duration": "27.1506969090909", - "name": "smoothness.key_desktop_move_cases/Maps" - }, - { - "duration": "24.607070717171723", - "name": "smoothness.key_desktop_move_cases/maps_move" - }, - { - "duration": "27.847868666666667", - "name": "smoothness.maps/maps_perf_test" - }, - { - "duration": "17.11933334343434", - "name": "smoothness.top_25_smooth/blogspot" - }, - { - "duration": "12.75833332323233", - "name": "smoothness.top_25_smooth/booking.com" - }, - { - "duration": "0.0010000864333333333", - "name": "smoothness.top_25_smooth/cnn" - }, - { - "duration": "10.977151525252527", - "name": "smoothness.top_25_smooth/ebay" - }, - { - "duration": "14.301929267676769", - "name": "smoothness.top_25_smooth/espn" - }, - { - "duration": "13.018010116161616", - "name": "smoothness.top_25_smooth/facebook" - }, - { - "duration": "27.640929323232317", - "name": "smoothness.top_25_smooth/gmail" - }, - { - "duration": "0.0010000069666666665", - "name": "smoothness.top_25_smooth/google_calendar" - }, - { - "duration": "0.0010001659", - "name": "smoothness.top_25_smooth/google_docs" - }, - { - "duration": "9.999275E-4", - "name": "smoothness.top_25_smooth/google_image_search" - }, - { - "duration": "10.507616191919194", - "name": "smoothness.top_25_smooth/google_web_search" - }, - { - "duration": "13.958949494949497", - "name": "smoothness.top_25_smooth/linkedin" - }, - { - "duration": "16.310515161616166", - "name": "smoothness.top_25_smooth/pinterest" - }, - { - "duration": "20.70723233333334", - "name": "smoothness.top_25_smooth/techcrunch" - }, - { - "duration": "15.03598987878789", - "name": "smoothness.top_25_smooth/twitter" - }, - { - "duration": "12.585848464646466", - "name": "smoothness.top_25_smooth/weather.com" - }, - { - "duration": "17.645787878787885", - "name": "smoothness.top_25_smooth/wikipedia" - }, - { - "duration": "16.997292959595967", - "name": "smoothness.top_25_smooth/wordpress" - }, - { - "duration": "11.186515176767678", - "name": "smoothness.top_25_smooth/yahoo_answers" - }, - { - "duration": "18.221848464646463", - "name": "smoothness.top_25_smooth/yahoo_games" - }, - { - "duration": "12.568686863636373", - "name": "smoothness.top_25_smooth/yahoo_news" - }, - { - "duration": "13.60135346969697", - "name": "smoothness.top_25_smooth/yahoo_sports" - }, - { - "duration": "27.779818151515148", - "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgICQ15a9NxDIARjIASgBMghBC1XuTk8ezw.swiffy72.html" - }, - { - "duration": "20.038121222222227", - "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgIDQ2Pb-MxCsAhj6ASgBMgi5DLoSO0gPbQ.swiffy72.html" - }, - { - "duration": "20.01881821212121", - "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgKCN39CopQEQoAEY2AQoATIID59gK5hjjIg.swiffy72.html" - }, - { - "duration": "20.017929262626264", - "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgKCNj4HgyAEQeBjYBCgBMgjQpPkOjyWNdw.1.swiffy72.html" - }, - { - "duration": "19.9578686969697", - "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgMDOrcnRGRB4GNgEKAEyCP_ZBSfwUFsj.swiffy72.html" - }, - { - "duration": "20.21655556565656", - "name": "smoothness.tough_ad_cases/http://localhost:8000/CNP2xe_LmqPEKBCsAhj6ASgBMggnyMqth81h8Q.swiffy72.html" - }, - { - "duration": "20.237212191919188", - "name": "smoothness.tough_ad_cases/http://localhost:8000/clip-paths-CICAgMDO7Ye9-gEQ2AUYWigBMgjZxDii6aoK9w.swiffy72.html" - }, - { - "duration": "20.021727272727272", - "name": "smoothness.tough_ad_cases/http://localhost:8000/clip-paths-CILZhLqO_-27bxB4GNgEKAEyCC46kMLBXnMT.swiffy72.html" - }, - { - "duration": "20.125565686868683", - "name": "smoothness.tough_ad_cases/http://localhost:8000/filters-CNLa0t2T47qJ_wEQoAEY2AQoATIIFaIdc7VMBr4.swiffy72.html" - }, - { - "duration": "20.035535333333332", - "name": "smoothness.tough_ad_cases/http://localhost:8000/shapes-CICAgMDO7cfIzwEQ1AMYPCgBMghqY8tqyRCArQ.swiffy72.html" - }, - { - "duration": "20.25348484848485", - "name": "smoothness.tough_ad_cases/http://localhost:8000/shapes-CK7ptO3F8bi2KxDQAhiYAigBMgij6QBQtD2gyA.swiffy72.html" - }, - { - "duration": "18.995739562500003", - "name": "smoothness.tough_animation_cases/balls_css_key_frame_animations" - }, - { - "duration": "19.07282293749999", - "name": "smoothness.tough_animation_cases/balls_css_key_frame_animations_composited_transform" - }, - { - "duration": "18.985282787878788", - "name": "smoothness.tough_animation_cases/balls_css_keyframe_animations.html" - }, - { - "duration": "19.10113132323232", - "name": "smoothness.tough_animation_cases/balls_css_keyframe_animations_composited_transform.html" - }, - { - "duration": "20.622604156249995", - "name": "smoothness.tough_animation_cases/balls_css_transition_2_properties" - }, - { - "duration": "20.401262616161617", - "name": "smoothness.tough_animation_cases/balls_css_transition_2_properties.html" - }, - { - "duration": "21.073812510416662", - "name": "smoothness.tough_animation_cases/balls_css_transition_40_properties" - }, - { - "duration": "20.43532321212121", - "name": "smoothness.tough_animation_cases/balls_css_transition_40_properties.html" - }, - { - "duration": "20.624104187500006", - "name": "smoothness.tough_animation_cases/balls_css_transition_all_properties" - }, - { - "duration": "20.497686858585855", - "name": "smoothness.tough_animation_cases/balls_css_transition_all_properties.html" - }, - { - "duration": "18.86768755208333", - "name": "smoothness.tough_animation_cases/balls_javascript_canvas" - }, - { - "duration": "19.023666616161623", - "name": "smoothness.tough_animation_cases/balls_javascript_canvas.html" - }, - { - "duration": "19.211802093750006", - "name": "smoothness.tough_animation_cases/balls_javascript_css" - }, - { - "duration": "18.6277071010101", - "name": "smoothness.tough_animation_cases/balls_javascript_css.html" - }, - { - "duration": "34.084863136842124", - "name": "smoothness.tough_animation_cases/balls_svg_animations" - }, - { - "duration": "36.266121232323215", - "name": "smoothness.tough_animation_cases/balls_svg_animations.html" - }, - { - "duration": "19.251333333333335", - "name": "smoothness.tough_animation_cases/compositor_heavy_animation" - }, - { - "duration": "19.60129290909091", - "name": "smoothness.tough_animation_cases/compositor_heavy_animation.html?N=0200" - }, - { - "duration": "18.196791708333333", - "name": "smoothness.tough_animation_cases/css_animations_many_keyframes" - }, - { - "duration": "18.194101040404046", - "name": "smoothness.tough_animation_cases/css_animations_many_keyframes.html?N=0316" - }, - { - "duration": "18.63116163636364", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_inserting_new_element.html?N=0316" - }, - { - "duration": "18.246262595959593", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_inserting_style_element.html?N=0316" - }, - { - "duration": "18.311121222222223", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_updating_class.html?N=0316" - }, - { - "duration": "18.330899030303023", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_updating_inline_style.html?N=0316" - }, - { - "duration": "18.268979135416668", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_inline_style" - }, - { - "duration": "18.691406281250003", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_new_element" - }, - { - "duration": "18.238843739583338", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_style_element" - }, - { - "duration": "18.312645822916668", - "name": "smoothness.tough_animation_cases/css_animations_simultaneous_updating_class" - }, - { - "duration": "21.245686878787886", - "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_inserting_new_element.html?N=0316" - }, - { - "duration": "19.75654544444445", - "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_inserting_style_element.html?N=0316" - }, - { - "duration": "19.803212141414143", - "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_updating_class.html?N=0316" - }, - { - "duration": "19.86957578787879", - "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_updating_inline_style.html?N=0316" - }, - { - "duration": "18.382333302083335", - "name": "smoothness.tough_animation_cases/css_animations_staggered_infinite_iterations" - }, - { - "duration": "17.866676777777776", - "name": "smoothness.tough_animation_cases/css_animations_staggered_infinite_iterations.html?N=0316" - }, - { - "duration": "19.611937479166674", - "name": "smoothness.tough_animation_cases/css_animations_staggered_inline_style" - }, - { - "duration": "20.707750020833334", - "name": "smoothness.tough_animation_cases/css_animations_staggered_new_element" - }, - { - "duration": "20.166864531250003", - "name": "smoothness.tough_animation_cases/css_animations_staggered_style_element" - }, - { - "duration": "20.309242393939392", - "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_inserting_new_element.html?N=0316" - }, - { - "duration": "19.252131323232323", - "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_inserting_style_element.html?N=0316" - }, - { - "duration": "19.578141464646457", - "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_updating_class.html?N=0316" - }, - { - "duration": "19.645373787878782", - "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_updating_inline_style.html?N=0316" - }, - { - "duration": "19.586749989583343", - "name": "smoothness.tough_animation_cases/css_animations_staggered_updating_class" - }, - { - "duration": "19.620125031249994", - "name": "smoothness.tough_animation_cases/css_animations_triggered_inline_style" - }, - { - "duration": "20.291874968749994", - "name": "smoothness.tough_animation_cases/css_animations_triggered_new_element" - }, - { - "duration": "19.25103125", - "name": "smoothness.tough_animation_cases/css_animations_triggered_style_element" - }, - { - "duration": "19.981968791666667", - "name": "smoothness.tough_animation_cases/css_animations_triggered_updating_class" - }, - { - "duration": "18.430041645833338", - "name": "smoothness.tough_animation_cases/css_transitions_inline_style" - }, - { - "duration": "19.208312489583328", - "name": "smoothness.tough_animation_cases/css_transitions_new_element" - }, - { - "duration": "19.17046462626263", - "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_inserting_new_element.html?N=0316" - }, - { - "duration": "18.457161616161617", - "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_inserting_style_element.html?N=0316" - }, - { - "duration": "18.358232353535353", - "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_updating_class.html?N=0316" - }, - { - "duration": "19.094171737373735", - "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_updating_inline_style.html?N=0316" - }, - { - "duration": "18.72763637373738", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_inserting_new_element.html?N=0316" - }, - { - "duration": "19.171090858585867", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_inserting_style_element.html?N=0316" - }, - { - "duration": "18.470212111111106", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_updating_class.html?N=0316" - }, - { - "duration": "18.443808060606063", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_updating_inline_style.html?N=0316" - }, - { - "duration": "18.98592709375", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_inline_style" - }, - { - "duration": "18.699604145833334", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_new_element" - }, - { - "duration": "18.505510416666667", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_style_element" - }, - { - "duration": "19.13276768686869", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_inserting_new_element.html?N=0316" - }, - { - "duration": "19.08491921212121", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_inserting_style_element.html?N=0316" - }, - { - "duration": "19.090141414141424", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_updating_class.html?N=0316" - }, - { - "duration": "19.13597980808081", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_updating_inline_style.html?N=0316" - }, - { - "duration": "18.45888540625", - "name": "smoothness.tough_animation_cases/css_transitions_staggered_updating_class" - }, - { - "duration": "18.38427084375", - "name": "smoothness.tough_animation_cases/css_transitions_style_element" - }, - { - "duration": "19.10522916666668", - "name": "smoothness.tough_animation_cases/css_transitions_triggered_inline_style" - }, - { - "duration": "19.587666635416667", - "name": "smoothness.tough_animation_cases/css_transitions_triggered_new_element" - }, - { - "duration": "19.055364520833336", - "name": "smoothness.tough_animation_cases/css_transitions_triggered_style_element" - }, - { - "duration": "19.098031281249998", - "name": "smoothness.tough_animation_cases/css_transitions_triggered_updating_class" - }, - { - "duration": "18.81317707291667", - "name": "smoothness.tough_animation_cases/css_transitions_updating_class" - }, - { - "duration": "17.882895802083336", - "name": "smoothness.tough_animation_cases/css_value_type_color" - }, - { - "duration": "18.851525242424238", - "name": "smoothness.tough_animation_cases/css_value_type_color.html?api=css_animations&N=0316" - }, - { - "duration": "17.91474749494948", - "name": "smoothness.tough_animation_cases/css_value_type_color.html?api=web_animations&N=0316" - }, - { - "duration": "18.352031249999996", - "name": "smoothness.tough_animation_cases/css_value_type_filter" - }, - { - "duration": "18.871242424242425", - "name": "smoothness.tough_animation_cases/css_value_type_filter.html?api=css_animations&N=0316" - }, - { - "duration": "18.141958302083335", - "name": "smoothness.tough_animation_cases/css_value_type_length" - }, - { - "duration": "18.14075756565656", - "name": "smoothness.tough_animation_cases/css_value_type_length_3d.html?api=css_animations&N=0316" - }, - { - "duration": "18.116585888888885", - "name": "smoothness.tough_animation_cases/css_value_type_length_3d.html?api=web_animations&N=0316" - }, - { - "duration": "18.307833364583328", - "name": "smoothness.tough_animation_cases/css_value_type_length_complex" - }, - { - "duration": "18.34028282828283", - "name": "smoothness.tough_animation_cases/css_value_type_length_complex.html?api=css_animations&N=0316" - }, - { - "duration": "18.367717171717175", - "name": "smoothness.tough_animation_cases/css_value_type_length_complex.html?api=web_animations&N=0316" - }, - { - "duration": "18.294760447916666", - "name": "smoothness.tough_animation_cases/css_value_type_length_simple" - }, - { - "duration": "18.33121211111111", - "name": "smoothness.tough_animation_cases/css_value_type_length_simple.html?api=css_animations&N=0316" - }, - { - "duration": "18.371161626262616", - "name": "smoothness.tough_animation_cases/css_value_type_length_simple.html?api=web_animations&N=0316" - }, - { - "duration": "18.535250000000005", - "name": "smoothness.tough_animation_cases/css_value_type_path" - }, - { - "duration": "18.657717171717174", - "name": "smoothness.tough_animation_cases/css_value_type_path.html?api=css_animations&N=0316" - }, - { - "duration": "18.624141404040405", - "name": "smoothness.tough_animation_cases/css_value_type_path.html?api=web_animations&N=0316" - }, - { - "duration": "19.706625010416673", - "name": "smoothness.tough_animation_cases/css_value_type_shadow" - }, - { - "duration": "19.307636383838375", - "name": "smoothness.tough_animation_cases/css_value_type_shadow.html?api=css_animations&N=0316" - }, - { - "duration": "19.312888878787888", - "name": "smoothness.tough_animation_cases/css_value_type_shadow.html?api=web_animations&N=0316" - }, - { - "duration": "18.157479145833324", - "name": "smoothness.tough_animation_cases/css_value_type_transform_complex" - }, - { - "duration": "18.156878808080815", - "name": "smoothness.tough_animation_cases/css_value_type_transform_complex.html?api=css_animations&N=0316" - }, - { - "duration": "18.171424272727275", - "name": "smoothness.tough_animation_cases/css_value_type_transform_complex.html?api=web_animations&N=0316" - }, - { - "duration": "18.445604156250003", - "name": "smoothness.tough_animation_cases/css_value_type_transform_simple" - }, - { - "duration": "18.214363626262628", - "name": "smoothness.tough_animation_cases/css_value_type_transform_simple.html?api=css_animations&N=0316" - }, - { - "duration": "18.497404090909093", - "name": "smoothness.tough_animation_cases/css_value_type_transform_simple.html?api=web_animations&N=0316" - }, - { - "duration": "17.814864572916672", - "name": "smoothness.tough_animation_cases/keyframed_animations" - }, - { - "duration": "17.770919212121214", - "name": "smoothness.tough_animation_cases/keyframed_animations.html" - }, - { - "duration": "18.126718760416672", - "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_difference" - }, - { - "duration": "18.123292959595968", - "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_difference.html" - }, - { - "duration": "18.138885447916664", - "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_hue" - }, - { - "duration": "18.112222212121207", - "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_hue.html" - }, - { - "duration": "18.936708364583332", - "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_propagating_isolation" - }, - { - "duration": "18.07853129166666", - "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_screen" - }, - { - "duration": "18.513646474747482", - "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_screen.html" - }, - { - "duration": "18.41735356565656", - "name": "smoothness.tough_animation_cases/mix_blend_mode_propagating_isolation.html" - }, - { - "duration": "29.211747454545442", - "name": "smoothness.tough_animation_cases/overlay_background_color_css_transitions.html" - }, - { - "duration": "30.778989604166668", - "name": "smoothness.tough_animation_cases/overlay_background_color_css_transitions_page" - }, - { - "duration": "9.999751799999999E-4", - "name": "smoothness.tough_animation_cases/robohornetpro" - }, - { - "duration": "17.711919171717174", - "name": "smoothness.tough_animation_cases/transform_transition_js_block.html" - }, - { - "duration": "17.865125052083336", - "name": "smoothness.tough_animation_cases/transform_transitions" - }, - { - "duration": "17.92824241414142", - "name": "smoothness.tough_animation_cases/transform_transitions.html" - }, - { - "duration": "17.659677052083335", - "name": "smoothness.tough_animation_cases/transform_transitions_js_block" - }, - { - "duration": "17.881927083333334", - "name": "smoothness.tough_animation_cases/web_animation_value_type_color" - }, - { - "duration": "18.113531229166664", - "name": "smoothness.tough_animation_cases/web_animation_value_type_length_3d" - }, - { - "duration": "18.301187520833327", - "name": "smoothness.tough_animation_cases/web_animation_value_type_length_complex" - }, - { - "duration": "18.336427062499997", - "name": "smoothness.tough_animation_cases/web_animation_value_type_length_simple" - }, - { - "duration": "18.919083343750003", - "name": "smoothness.tough_animation_cases/web_animation_value_type_path" - }, - { - "duration": "19.342729145833335", - "name": "smoothness.tough_animation_cases/web_animation_value_type_shadow" - }, - { - "duration": "18.19162503125", - "name": "smoothness.tough_animation_cases/web_animation_value_type_transform_complex" - }, - { - "duration": "18.532947906249998", - "name": "smoothness.tough_animation_cases/web_animation_value_type_transform_simple" - }, - { - "duration": "19.584781291666665", - "name": "smoothness.tough_animation_cases/web_animations_many_keyframes" - }, - { - "duration": "18.753343444444443", - "name": "smoothness.tough_animation_cases/web_animations_many_keyframes.html?N=0316" - }, - { - "duration": "18.605364572916667", - "name": "smoothness.tough_animation_cases/web_animations_set_current_time" - }, - { - "duration": "18.16735348484848", - "name": "smoothness.tough_animation_cases/web_animations_set_current_time_in_raf.html?N=0316" - }, - { - "duration": "19.416145781250005", - "name": "smoothness.tough_animation_cases/web_animations_simultaneous" - }, - { - "duration": "18.401323232323236", - "name": "smoothness.tough_animation_cases/web_animations_simultaneous.html?N=0316" - }, - { - "duration": "19.539427093750003", - "name": "smoothness.tough_animation_cases/web_animations_staggered_chaining" - }, - { - "duration": "19.539565676767673", - "name": "smoothness.tough_animation_cases/web_animations_staggered_chaining.html?N=0316" - }, - { - "duration": "17.936749999999996", - "name": "smoothness.tough_animation_cases/web_animations_staggered_infinite_iterations" - }, - { - "duration": "17.872737363636364", - "name": "smoothness.tough_animation_cases/web_animations_staggered_infinite_iterations.html?N=0316" - }, - { - "duration": "19.639808060606057", - "name": "smoothness.tough_animation_cases/web_animations_staggered_triggering.html?N=0316" - }, - { - "duration": "19.546645864583326", - "name": "smoothness.tough_animation_cases/web_animations_staggered_triggering_page" - }, - { - "duration": "14.892676767676765", - "name": "smoothness.tough_canvas_cases/../../../chrome/test/data/perf/canvas_bench/many_images.html" - }, - { - "duration": "13.032020181818181", - "name": "smoothness.tough_canvas_cases/bouncing_balls_15" - }, - { - "duration": "14.014707045454545", - "name": "smoothness.tough_canvas_cases/bouncing_balls_shadow" - }, - { - "duration": "13.722242434343437", - "name": "smoothness.tough_canvas_cases/bouncing_clipped_rectangles" - }, - { - "duration": "13.715616181818184", - "name": "smoothness.tough_canvas_cases/bouncing_gradient_circles" - }, - { - "duration": "12.263353550505055", - "name": "smoothness.tough_canvas_cases/bouncing_png_images" - }, - { - "duration": "19.126242414141416", - "name": "smoothness.tough_canvas_cases/bouncing_svg_images" - }, - { - "duration": "14.204727262626262", - "name": "smoothness.tough_canvas_cases/canvas_animation_no_clear" - }, - { - "duration": "13.648717186868682", - "name": "smoothness.tough_canvas_cases/canvas_arcs" - }, - { - "duration": "13.0385960050505", - "name": "smoothness.tough_canvas_cases/canvas_font_cycler" - }, - { - "duration": "12.954828252525251", - "name": "smoothness.tough_canvas_cases/canvas_lines" - }, - { - "duration": "12.981747449494945", - "name": "smoothness.tough_canvas_cases/canvas_to_blob" - }, - { - "duration": "13.81446464646465", - "name": "smoothness.tough_canvas_cases/chip_tune" - }, - { - "duration": "13.592616106060598", - "name": "smoothness.tough_canvas_cases/crafty_mind" - }, - { - "duration": "14.312555565656565", - "name": "smoothness.tough_canvas_cases/effect_games" - }, - { - "duration": "13.661171696969694", - "name": "smoothness.tough_canvas_cases/fill_shapes" - }, - { - "duration": "21.97107068686869", - "name": "smoothness.tough_canvas_cases/geo_apis" - }, - { - "duration": "13.620181873737378", - "name": "smoothness.tough_canvas_cases/hakim" - }, - { - "duration": "21.673343429292927", - "name": "smoothness.tough_canvas_cases/http://geoapis.appspot.com/agdnZW9hcGlzchMLEgtFeGFtcGxlQ29kZRjh1wIM" - }, - { - "duration": "13.790323222222218", - "name": "smoothness.tough_canvas_cases/http://hakim.se/experiments/html5/magnetic/02/" - }, - { - "duration": "13.672020207070709", - "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/TweetMap/Default.html" - }, - { - "duration": "14.644050409090902", - "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/VideoCity/Default.html" - }, - { - "duration": "13.928010080808086", - "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/WorkerFountains/Default.html" - }, - { - "duration": "14.03984847979799", - "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/AsteroidBelt/Default.html" - }, - { - "duration": "14.388626277777773", - "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/FishIETank/Default.html" - }, - { - "duration": "14.050181828282827", - "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/LetItSnow/" - }, - { - "duration": "13.589656545454547", - "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/SpeedReading/Default.html" - }, - { - "duration": "14.830646479797982", - "name": "smoothness.tough_canvas_cases/http://jarrodoverson.com/static/demos/particleSystem/" - }, - { - "duration": "13.506060545454552", - "name": "smoothness.tough_canvas_cases/http://mix10k.visitmix.com/Entry/Details/169" - }, - { - "duration": "13.030030252525256", - "name": "smoothness.tough_canvas_cases/http://runway.countlessprojects.com/prototype/performance_test.html" - }, - { - "duration": "13.271333348484845", - "name": "smoothness.tough_canvas_cases/http://spielzeugz.de/html5/liquid-particles.html" - }, - { - "duration": "13.991646489898987", - "name": "smoothness.tough_canvas_cases/http://themaninblue.com/experiment/AnimationBenchmark/canvas/" - }, - { - "duration": "13.987404055555553", - "name": "smoothness.tough_canvas_cases/http://www.chiptune.com/starfield/starfield.html" - }, - { - "duration": "13.795262611111111", - "name": "smoothness.tough_canvas_cases/http://www.craftymind.com/factory/guimark2/HTML5ChartingTest.html" - }, - { - "duration": "14.554939444444447", - "name": "smoothness.tough_canvas_cases/http://www.effectgames.com/demos/canvascycle/" - }, - { - "duration": "13.672161651515143", - "name": "smoothness.tough_canvas_cases/http://www.kevs3d.co.uk/dev/canvask3d/k3d_test.html" - }, - { - "duration": "13.39483832828283", - "name": "smoothness.tough_canvas_cases/http://www.megidish.net/awjs/" - }, - { - "duration": "13.659070752525253", - "name": "smoothness.tough_canvas_cases/http://www.smashcat.org/av/canvas_test/" - }, - { - "duration": "14.654686888888882", - "name": "smoothness.tough_canvas_cases/jarro_doverson" - }, - { - "duration": "13.519656565656557", - "name": "smoothness.tough_canvas_cases/kevs_3d" - }, - { - "duration": "13.875070676767676", - "name": "smoothness.tough_canvas_cases/man_in_blue" - }, - { - "duration": "14.753404030303027", - "name": "smoothness.tough_canvas_cases/many_images" - }, - { - "duration": "13.235101015151516", - "name": "smoothness.tough_canvas_cases/megi_dish" - }, - { - "duration": "13.945575752525258", - "name": "smoothness.tough_canvas_cases/microsoft_asteroid_belt" - }, - { - "duration": "13.882080727272733", - "name": "smoothness.tough_canvas_cases/microsoft_fish_ie_tank" - }, - { - "duration": "13.864191944444444", - "name": "smoothness.tough_canvas_cases/microsoft_snow" - }, - { - "duration": "13.368444454545452", - "name": "smoothness.tough_canvas_cases/microsoft_speed_reading" - }, - { - "duration": "13.469030272727272", - "name": "smoothness.tough_canvas_cases/microsoft_tweet_map" - }, - { - "duration": "14.487484823232322", - "name": "smoothness.tough_canvas_cases/microsoft_video_city" - }, - { - "duration": "13.82361620707071", - "name": "smoothness.tough_canvas_cases/microsoft_worker_fountains" - }, - { - "duration": "13.387747494949497", - "name": "smoothness.tough_canvas_cases/mix_10k" - }, - { - "duration": "13.637989909090907", - "name": "smoothness.tough_canvas_cases/put_get_image_data" - }, - { - "duration": "12.897272752525247", - "name": "smoothness.tough_canvas_cases/runway" - }, - { - "duration": "13.57649502020203", - "name": "smoothness.tough_canvas_cases/smash_cat" - }, - { - "duration": "13.635020156565654", - "name": "smoothness.tough_canvas_cases/spielzeugz" - }, - { - "duration": "14.029888848484836", - "name": "smoothness.tough_canvas_cases/stroke_shapes" - }, - { - "duration": "14.316868702020203", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas-animation-no-clear.html" - }, - { - "duration": "13.108666666666663", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas-font-cycler.html" - }, - { - "duration": "14.26334342929293", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=image_with_shadow&back=image" - }, - { - "duration": "13.128424222222216", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=text&back=white&ball_count=15" - }, - { - "duration": "13.124646525252526", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas_toBlob.html" - }, - { - "duration": "13.93056563636364", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_clipped_rectangles.html" - }, - { - "duration": "13.79218181313132", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_gradient_circles.html" - }, - { - "duration": "12.822212131313137", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_png_images.html" - }, - { - "duration": "20.561161606060615", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_svg_images.html" - }, - { - "duration": "13.860545414141415", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/canvas_arcs.html" - }, - { - "duration": "13.07291912626263", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/canvas_lines.html" - }, - { - "duration": "13.70785862121212", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/fill_shapes.html" - }, - { - "duration": "13.70504037878788", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/put_get_image_data.html" - }, - { - "duration": "14.17184845959596", - "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/stroke_shapes.html" - }, - { - "duration": "20.041484828282833", - "name": "smoothness.tough_filters_cases/Analog_Clock_SVG" - }, - { - "duration": "20.04446463636364", - "name": "smoothness.tough_filters_cases/Filter_Terrain_SVG" - }, - { - "duration": "22.60951514141414", - "name": "smoothness.tough_filters_cases/IE_PirateMark" - }, - { - "duration": "31.47287877777778", - "name": "smoothness.tough_filters_cases/MotionMark_Focus" - }, - { - "duration": "19.892101050505044", - "name": "smoothness.tough_filters_cases/analog_clock_svg" - }, - { - "duration": "19.93245452525253", - "name": "smoothness.tough_filters_cases/filter_terrain_svg" - }, - { - "duration": "22.09837376767677", - "name": "smoothness.tough_filters_cases/ie_pirate_mark" - }, - { - "duration": "35.45863639393937", - "name": "smoothness.tough_filters_cases/motion_mark_focus" - }, - { - "duration": "16.984195109756097", - "name": "smoothness.tough_image_decode_cases/cats_unscaled" - }, - { - "duration": "10.023646371951218", - "name": "smoothness.tough_image_decode_cases/cats_viewport_width" - }, - { - "duration": "17.949525313131318", - "name": "smoothness.tough_image_decode_cases/http://localhost:9000/cats-unscaled.html" - }, - { - "duration": "10.156555525252525", - "name": "smoothness.tough_image_decode_cases/http://localhost:9000/cats-viewport-width.html" - }, - { - "duration": "31.122909101010105", - "name": "smoothness.tough_path_rendering_cases/GUIMark_Vector_Chart_Test" - }, - { - "duration": "28.501939393939395", - "name": "smoothness.tough_path_rendering_cases/IE_Chalkboard" - }, - { - "duration": "19.635505060606054", - "name": "smoothness.tough_path_rendering_cases/MotionMark_Canvas_Fill_Shapes" - }, - { - "duration": "19.80110101010101", - "name": "smoothness.tough_path_rendering_cases/MotionMark_Canvas_Stroke_Shapes" - }, - { - "duration": "29.954878808080817", - "name": "smoothness.tough_path_rendering_cases/guimark_vector_chart" - }, - { - "duration": "28.844555575757568", - "name": "smoothness.tough_path_rendering_cases/ie_chalkboard" - }, - { - "duration": "19.630232292929293", - "name": "smoothness.tough_path_rendering_cases/motion_mark_canvas_fill_shapes" - }, - { - "duration": "20.12891921212121", - "name": "smoothness.tough_path_rendering_cases/motion_mark_canvas_stroke_shapes" - }, - { - "duration": "15.180777787878789", - "name": "smoothness.tough_scrolling_cases/canvas_05000_pixels_per_second" - }, - { - "duration": "14.441070717171714", - "name": "smoothness.tough_scrolling_cases/canvas_10000_pixels_per_second" - }, - { - "duration": "12.058010116161618", - "name": "smoothness.tough_scrolling_cases/canvas_15000_pixels_per_second" - }, - { - "duration": "11.204575828282824", - "name": "smoothness.tough_scrolling_cases/canvas_20000_pixels_per_second" - }, - { - "duration": "10.155232348484848", - "name": "smoothness.tough_scrolling_cases/canvas_30000_pixels_per_second" - }, - { - "duration": "9.644656570707069", - "name": "smoothness.tough_scrolling_cases/canvas_40000_pixels_per_second" - }, - { - "duration": "9.331323252525253", - "name": "smoothness.tough_scrolling_cases/canvas_50000_pixels_per_second" - }, - { - "duration": "9.060535383838387", - "name": "smoothness.tough_scrolling_cases/canvas_60000_pixels_per_second" - }, - { - "duration": "8.858262641414147", - "name": "smoothness.tough_scrolling_cases/canvas_75000_pixels_per_second" - }, - { - "duration": "8.705191974747473", - "name": "smoothness.tough_scrolling_cases/canvas_90000_pixels_per_second" - }, - { - "duration": "24.019505095959598", - "name": "smoothness.tough_scrolling_cases/text_05000_pixels_per_second" - }, - { - "duration": "14.298757530303027", - "name": "smoothness.tough_scrolling_cases/text_10000_pixels_per_second" - }, - { - "duration": "11.874373686868683", - "name": "smoothness.tough_scrolling_cases/text_15000_pixels_per_second" - }, - { - "duration": "10.94608081313131", - "name": "smoothness.tough_scrolling_cases/text_20000_pixels_per_second" - }, - { - "duration": "9.978000010101013", - "name": "smoothness.tough_scrolling_cases/text_30000_pixels_per_second" - }, - { - "duration": "9.453595989898991", - "name": "smoothness.tough_scrolling_cases/text_40000_pixels_per_second" - }, - { - "duration": "9.029161595959591", - "name": "smoothness.tough_scrolling_cases/text_50000_pixels_per_second" - }, - { - "duration": "8.890696934343437", - "name": "smoothness.tough_scrolling_cases/text_60000_pixels_per_second" - }, - { - "duration": "8.645333313131315", - "name": "smoothness.tough_scrolling_cases/text_75000_pixels_per_second" - }, - { - "duration": "8.589212116161614", - "name": "smoothness.tough_scrolling_cases/text_90000_pixels_per_second" - }, - { - "duration": "15.68423229797979", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second" - }, - { - "duration": "14.530595974747476", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second" - }, - { - "duration": "12.455717222222216", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second" - }, - { - "duration": "11.375646449494948", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second" - }, - { - "duration": "10.343777782828282", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second" - }, - { - "duration": "9.986505065656562", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second" - }, - { - "duration": "9.666070712121211", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second" - }, - { - "duration": "9.342262631313131", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second" - }, - { - "duration": "9.122434373737375", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second" - }, - { - "duration": "9.015292873737373", - "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second" - }, - { - "duration": "14.869282883838395", - "name": "smoothness.tough_scrolling_cases/text_hover_05000_pixels_per_second" - }, - { - "duration": "13.661353484848481", - "name": "smoothness.tough_scrolling_cases/text_hover_10000_pixels_per_second" - }, - { - "duration": "11.692808101010097", - "name": "smoothness.tough_scrolling_cases/text_hover_15000_pixels_per_second" - }, - { - "duration": "10.661373737373735", - "name": "smoothness.tough_scrolling_cases/text_hover_20000_pixels_per_second" - }, - { - "duration": "9.761899015151517", - "name": "smoothness.tough_scrolling_cases/text_hover_30000_pixels_per_second" - }, - { - "duration": "9.131212075757578", - "name": "smoothness.tough_scrolling_cases/text_hover_40000_pixels_per_second" - }, - { - "duration": "8.879999959595958", - "name": "smoothness.tough_scrolling_cases/text_hover_50000_pixels_per_second" - }, - { - "duration": "8.706353547474746", - "name": "smoothness.tough_scrolling_cases/text_hover_60000_pixels_per_second" - }, - { - "duration": "8.438535354545454", - "name": "smoothness.tough_scrolling_cases/text_hover_75000_pixels_per_second" - }, - { - "duration": "8.315111121212121", - "name": "smoothness.tough_scrolling_cases/text_hover_90000_pixels_per_second" - }, - { - "duration": "29.886767441860478", - "name": "smoothness.tough_texture_upload_cases/background_color_animation" - }, - { - "duration": "28.699414171717184", - "name": "smoothness.tough_texture_upload_cases/background_color_animation.html" - }, - { - "duration": "19.755744197674424", - "name": "smoothness.tough_texture_upload_cases/background_color_animation_with_gradient" - }, - { - "duration": "19.950798010101018", - "name": "smoothness.tough_texture_upload_cases/background_color_animation_with_gradient.html" - }, - { - "duration": "19.849395325581398", - "name": "smoothness.tough_texture_upload_cases/extra_large_texture_uploads" - }, - { - "duration": "20.30039388888889", - "name": "smoothness.tough_texture_upload_cases/extra_large_texture_uploads.html" - }, - { - "duration": "19.17227911627907", - "name": "smoothness.tough_texture_upload_cases/large_texture_uploads" - }, - { - "duration": "19.28512119191919", - "name": "smoothness.tough_texture_upload_cases/large_texture_uploads.html" - }, - { - "duration": "18.354534930232557", - "name": "smoothness.tough_texture_upload_cases/medium_texture_uploads" - }, - { - "duration": "18.428697020202023", - "name": "smoothness.tough_texture_upload_cases/medium_texture_uploads.html" - }, - { - "duration": "18.1792325", - "name": "smoothness.tough_texture_upload_cases/small_texture_uploads" - }, - { - "duration": "19.252555535353537", - "name": "smoothness.tough_texture_upload_cases/small_texture_uploads.html" - }, - { - "duration": "30.229717141414145", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgICQ15a9NxDIARjIASgBMghBC1XuTk8ezw.swf.webglbeta.html" - }, - { - "duration": "20.40264642424243", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgIDQ2Pb-MxCsAhj6ASgBMgi5DLoSO0gPbQ.swf.webglbeta.html" - }, - { - "duration": "19.99770706060605", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgKCN39CopQEQoAEY2AQoATIID59gK5hjjIg.swf.webglbeta.html" - }, - { - "duration": "20.02665654545454", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgKCNj4HgyAEQeBjYBCgBMgjQpPkOjyWNdw.1.swf.webglbeta.html" - }, - { - "duration": "19.954383838383837", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgMDOrcnRGRB4GNgEKAEyCP_ZBSfwUFsj.swf.webglbeta.html" - }, - { - "duration": "20.538060606060597", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CNP2xe_LmqPEKBCsAhj6ASgBMggnyMqth81h8Q.swf.webglbeta.html" - }, - { - "duration": "20.12783833333334", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/clip-paths-CICAgMDO7Ye9-gEQ2AUYWigBMgjZxDii6aoK9w.swf.webglbeta.html" - }, - { - "duration": "19.999000030303034", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/clip-paths-CILZhLqO_-27bxB4GNgEKAEyCC46kMLBXnMT.swf.webglbeta.html" - }, - { - "duration": "20.088707121212124", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/filters-CNLa0t2T47qJ_wEQoAEY2AQoATIIFaIdc7VMBr4.swf.webglbeta.html" - }, - { - "duration": "20.021525252525247", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/shapes-CICAgMDO7cfIzwEQ1AMYPCgBMghqY8tqyRCArQ.swf.webglbeta.html" - }, - { - "duration": "20.14841417171717", - "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/shapes-CK7ptO3F8bi2KxDQAhiYAigBMgij6QBQtD2gyA.swf.webglbeta.html" - }, - { - "duration": "16.541040434343433", - "name": "smoothness.tough_webgl_cases/animometer_webgl" - }, - { - "duration": "18.563606060606055", - "name": "smoothness.tough_webgl_cases/aquarium" - }, - { - "duration": "21.121060595959595", - "name": "smoothness.tough_webgl_cases/aquarium_20k" - }, - { - "duration": "15.86016162121212", - "name": "smoothness.tough_webgl_cases/blob" - }, - { - "duration": "16.49357573737374", - "name": "smoothness.tough_webgl_cases/dynamic_cube_map" - }, - { - "duration": "15.625080803030297", - "name": "smoothness.tough_webgl_cases/earth" - }, - { - "duration": "16.60389903030303", - "name": "smoothness.tough_webgl_cases/http://kenrussell.github.io/webgl-animometer/Animometer/tests/3d/webgl.html" - }, - { - "duration": "18.649969696969695", - "name": "smoothness.tough_webgl_cases/http://webglsamples.org/aquarium/aquarium.html" - }, - { - "duration": "15.994959540404041", - "name": "smoothness.tough_webgl_cases/http://webglsamples.org/blob/blob.html" - }, - { - "duration": "16.567424242424238", - "name": "smoothness.tough_webgl_cases/http://webglsamples.org/dynamic-cubemap/dynamic-cubemap.html" - }, - { - "duration": "28.61602022222223", - "name": "smoothness.tough_webgl_cases/http://www.khronos.org/registry/webgl/sdk/demos/google/nvidia-vertex-buffer-object/index.html" - }, - { - "duration": "15.775545419191914", - "name": "smoothness.tough_webgl_cases/http://www.khronos.org/registry/webgl/sdk/demos/google/particles/index.html" - }, - { - "duration": "15.79988885858585", - "name": "smoothness.tough_webgl_cases/http://www.khronos.org/registry/webgl/sdk/demos/google/san-angeles/index.html" - }, - { - "duration": "15.770232247474745", - "name": "smoothness.tough_webgl_cases/http://www.khronos.org/registry/webgl/sdk/demos/webkit/Earth.html" - }, - { - "duration": "15.938393969696973", - "name": "smoothness.tough_webgl_cases/http://www.khronos.org/registry/webgl/sdk/demos/webkit/ManyPlanetsDeep.html" - }, - { - "duration": "16.562124999999998", - "name": "smoothness.tough_webgl_cases/ken_russell" - }, - { - "duration": "15.782767686868688", - "name": "smoothness.tough_webgl_cases/many_planets_deep" - }, - { - "duration": "28.8214140909091", - "name": "smoothness.tough_webgl_cases/nvidia_vertex_buffer_object" - }, - { - "duration": "15.608212101010103", - "name": "smoothness.tough_webgl_cases/particles" - }, - { - "duration": "15.810010050505046", - "name": "smoothness.tough_webgl_cases/san_angeles" - }, - { - "duration": "15.779000000000002", - "name": "smoothness.tough_webgl_cases/sans_angeles" - }, - { - "duration": "47.1619898989899", + "duration": "36.0", "name": "speedometer-future/http://browserbench.org/Speedometer/" }, { - "duration": "40.33910105050508", + "duration": "32.0", "name": "speedometer/http://browserbench.org/Speedometer/" }, { - "duration": "74.26140400000001", + "duration": "64.0", "name": "speedometer2-future/Speedometer2" }, { - "duration": "76.93698989898992", + "duration": "61.0", "name": "speedometer2/Speedometer2" }, { - "duration": "0.0010000069666666665", + "duration": "76.0", "name": "system_health.common_desktop/browse:media:flickr_infinite_scroll" }, { - "duration": "97.96902020202019", + "duration": "104.0", "name": "system_health.common_desktop/browse:media:imgur" }, { - "duration": "70.31925256565656", + "duration": "69.0", "name": "system_health.common_desktop/browse:media:pinterest" }, { - "duration": "0.0010001659", + "duration": "114.0", "name": "system_health.common_desktop/browse:media:tumblr" }, { - "duration": "76.16398993939394", + "duration": "91.0", "name": "system_health.common_desktop/browse:media:youtube" }, { - "duration": "85.68606060606061", + "duration": "87.0", "name": "system_health.common_desktop/browse:news:cnn" }, { - "duration": "59.89001010101009", + "duration": "66.0", "name": "system_health.common_desktop/browse:news:flipboard" }, { - "duration": "9.999275E-4", + "duration": "57.0", "name": "system_health.common_desktop/browse:news:hackernews" }, { - "duration": "97.49339393939397", + "duration": "106.0", "name": "system_health.common_desktop/browse:news:nytimes" }, { - "duration": "73.19825248484852", + "duration": "73.0", "name": "system_health.common_desktop/browse:news:reddit" }, { - "duration": "9.999275E-4", + "duration": "54.0", "name": "system_health.common_desktop/browse:search:google" }, { - "duration": "39.52054541414144", + "duration": "40.0", "name": "system_health.common_desktop/browse:search:google_india" }, { - "duration": "73.92602016161615", + "duration": "84.0", "name": "system_health.common_desktop/browse:social:facebook_infinite_scroll" }, { - "duration": "84.5228484444444", + "duration": "88.0", "name": "system_health.common_desktop/browse:social:tumblr_infinite_scroll" }, { - "duration": "51.05947468686869", + "duration": "51.0", "name": "system_health.common_desktop/browse:social:twitter" }, { - "duration": "92.67472727272722", - "name": "system_health.common_desktop/browse:social:twitter_infinite_scroll" - }, - { - "duration": "76.19918181818181", + "duration": "81.0", "name": "system_health.common_desktop/browse:tech:discourse_infinite_scroll" }, { - "duration": "72.87380812121211", + "duration": "75.0", "name": "system_health.common_desktop/browse:tools:earth" }, { - "duration": "60.475020181818174", + "duration": "62.0", "name": "system_health.common_desktop/browse:tools:maps" }, { - "duration": "24.86998991919193", + "duration": "25.0", "name": "system_health.common_desktop/browse_accessibility:tech:codesearch" }, { - "duration": "9.999871E-4", - "name": "system_health.common_desktop/browse_accessibility:tools:gmail_compose" - }, - { - "duration": "17.385585858585856", + "duration": "18.0", "name": "system_health.common_desktop/load:chrome:blank" }, { - "duration": "21.503313111111105", + "duration": "22.0", "name": "system_health.common_desktop/load:games:alphabetty" }, { - "duration": "23.74739394949495", + "duration": "24.0", "name": "system_health.common_desktop/load:games:bubbles" }, { - "duration": "20.517969707070705", + "duration": "21.0", "name": "system_health.common_desktop/load:games:lazors" }, { - "duration": "25.57121216161616", + "duration": "30.0", "name": "system_health.common_desktop/load:games:miniclip" }, { - "duration": "28.07942426262626", + "duration": "29.0", "name": "system_health.common_desktop/load:games:spychase" }, { - "duration": "36.58223230303031", + "duration": "38.0", "name": "system_health.common_desktop/load:media:9gag" }, { - "duration": "24.818383868686865", + "duration": "24.0", "name": "system_health.common_desktop/load:media:dailymotion" }, { - "duration": "22.30925253535352", + "duration": "22.0", "name": "system_health.common_desktop/load:media:google_images" }, { - "duration": "26.987484828282835", + "duration": "28.0", "name": "system_health.common_desktop/load:media:imgur" }, { - "duration": "28.178050515151515", + "duration": "30.0", "name": "system_health.common_desktop/load:media:soundcloud" }, { - "duration": "25.553939373737386", + "duration": "25.0", "name": "system_health.common_desktop/load:media:youtube" }, { - "duration": "23.236858545454556", + "duration": "24.0", "name": "system_health.common_desktop/load:news:bbc" }, { - "duration": "28.328363606060613", + "duration": "30.0", "name": "system_health.common_desktop/load:news:cnn" }, { - "duration": "22.742545464646454", + "duration": "23.0", "name": "system_health.common_desktop/load:news:flipboard" }, { - "duration": "20.078616202020207", + "duration": "21.0", "name": "system_health.common_desktop/load:news:hackernews" }, { - "duration": "26.382060595959594", + "duration": "27.0", "name": "system_health.common_desktop/load:news:nytimes" }, { - "duration": "29.068868676767686", + "duration": "29.0", "name": "system_health.common_desktop/load:news:qq" }, { - "duration": "22.08726263636364", + "duration": "23.0", "name": "system_health.common_desktop/load:news:reddit" }, { - "duration": "22.229707101010117", + "duration": "34.0", "name": "system_health.common_desktop/load:news:wikipedia" }, { - "duration": "22.9858282929293", + "duration": "23.0", "name": "system_health.common_desktop/load:search:amazon" }, { - "duration": "21.70505047474748", + "duration": "22.0", "name": "system_health.common_desktop/load:search:baidu" }, { - "duration": "23.59198991919192", + "duration": "24.0", "name": "system_health.common_desktop/load:search:ebay" }, { - "duration": "21.68789897979799", + "duration": "22.0", "name": "system_health.common_desktop/load:search:google" }, { - "duration": "23.68709085858585", + "duration": "23.0", "name": "system_health.common_desktop/load:search:taobao" }, { - "duration": "21.300454545454535", + "duration": "21.0", "name": "system_health.common_desktop/load:search:yahoo" }, { - "duration": "21.575919202020202", + "duration": "22.0", "name": "system_health.common_desktop/load:search:yandex" }, { - "duration": "23.479161626262627", + "duration": "31.0", "name": "system_health.common_desktop/load:social:instagram" }, { - "duration": "23.819525292929296", + "duration": "25.0", "name": "system_health.common_desktop/load:social:pinterest" }, { - "duration": "23.02353537373738", + "duration": "23.0", "name": "system_health.common_desktop/load:social:vk" }, { - "duration": "36.22334343434344", + "duration": "37.0", "name": "system_health.common_desktop/load:tools:docs" }, { - "duration": "34.85987873737375", + "duration": "33.0", "name": "system_health.common_desktop/load:tools:drive" }, { - "duration": "23.937070686868697", + "duration": "23.0", "name": "system_health.common_desktop/load:tools:dropbox" }, { - "duration": "28.185252515151504", + "duration": "26.0", "name": "system_health.common_desktop/load:tools:gmail" }, { - "duration": "22.791636343434334", + "duration": "23.0", "name": "system_health.common_desktop/load:tools:stackoverflow" }, { - "duration": "28.935212131313133", + "duration": "31.0", "name": "system_health.common_desktop/load:tools:weather" }, { - "duration": "22.45317169696969", + "duration": "24.0", "name": "system_health.common_desktop/load_accessibility:media:wikipedia" }, { - "duration": "30.412717171717173", + "duration": "24.0", "name": "system_health.common_desktop/load_accessibility:shopping:amazon" }, { - "duration": "133.43395949494948", + "duration": "131.0", "name": "system_health.common_desktop/long_running:tools:gmail-background" }, { - "duration": "344.60642424242434", + "duration": "135.0", "name": "system_health.common_desktop/long_running:tools:gmail-foreground" }, { - "duration": "147.41508084848485", + "duration": "215.0", "name": "system_health.common_desktop/multitab:misc:typical24" }, { - "duration": "9.999275E-4", + "duration": "55.0", "name": "system_health.common_desktop/play:media:google_play_music" }, { - "duration": "9.999275E-4", - "name": "system_health.common_desktop/play:media:pandora" - }, - { - "duration": "9.999672333333334E-4", + "duration": "56.0", "name": "system_health.common_desktop/play:media:soundcloud" }, { - "duration": "0.0013333955999999998", - "name": "system_health.memory_desktop/browse:media:flickr_infinite_scroll" - }, - { - "duration": "207.39890913131316", + "duration": "70.0", "name": "system_health.memory_desktop/browse:media:imgur" }, { - "duration": "187.18185864646463", + "duration": "61.0", "name": "system_health.memory_desktop/browse:media:pinterest" }, { - "duration": "177.29151511111118", - "name": "system_health.memory_desktop/browse:media:tumblr" - }, - { - "duration": "181.09774749494943", + "duration": "61.0", "name": "system_health.memory_desktop/browse:media:youtube" }, { - "duration": "177.24176769696976", + "duration": "58.0", "name": "system_health.memory_desktop/browse:news:cnn" }, { - "duration": "148.48966658585857", + "duration": "51.0", "name": "system_health.memory_desktop/browse:news:flipboard" }, { - "duration": "202.7948484848485", + "duration": "71.0", "name": "system_health.memory_desktop/browse:news:nytimes" }, { - "duration": "182.0874342828282", + "duration": "61.0", "name": "system_health.memory_desktop/browse:news:reddit" }, { - "duration": "0.0010001659", + "duration": "48.0", "name": "system_health.memory_desktop/browse:search:google" }, { - "duration": "106.84377775757571", + "duration": "36.0", "name": "system_health.memory_desktop/browse:search:google_india" }, { - "duration": "189.3297878989899", + "duration": "64.0", "name": "system_health.memory_desktop/browse:social:facebook_infinite_scroll" }, { - "duration": "192.46958583838384", + "duration": "65.0", "name": "system_health.memory_desktop/browse:social:tumblr_infinite_scroll" }, { - "duration": "138.19091905050504", + "duration": "46.0", "name": "system_health.memory_desktop/browse:social:twitter" }, { - "duration": "185.25912117171723", + "duration": "63.0", "name": "system_health.memory_desktop/browse:tech:discourse_infinite_scroll" }, { - "duration": "160.87625256565656", + "duration": "55.0", "name": "system_health.memory_desktop/browse:tools:earth" }, { - "duration": "151.4894545050505", + "duration": "52.0", "name": "system_health.memory_desktop/browse:tools:maps" }, { - "duration": "61.42696967676766", + "duration": "21.0", "name": "system_health.memory_desktop/browse_accessibility:tech:codesearch" }, { - "duration": "45.698888939393946", + "duration": "16.0", "name": "system_health.memory_desktop/load:chrome:blank" }, { - "duration": "57.96254540404042", + "duration": "19.0", "name": "system_health.memory_desktop/load:games:alphabetty" }, { - "duration": "58.257434343434355", + "duration": "21.0", "name": "system_health.memory_desktop/load:games:bubbles" }, { - "duration": "55.09436368686868", + "duration": "19.0", "name": "system_health.memory_desktop/load:games:lazors" }, { - "duration": "63.40618178787878", + "duration": "22.0", "name": "system_health.memory_desktop/load:games:miniclip" }, { - "duration": "71.10260595959596", + "duration": "24.0", "name": "system_health.memory_desktop/load:games:spychase" }, { - "duration": "84.00951517171718", + "duration": "28.0", "name": "system_health.memory_desktop/load:media:9gag" }, { - "duration": "60.009393949494964", + "duration": "21.0", "name": "system_health.memory_desktop/load:media:dailymotion" }, { - "duration": "59.327474686868676", + "duration": "20.0", "name": "system_health.memory_desktop/load:media:google_images" }, { - "duration": "67.76846467676766", + "duration": "23.0", "name": "system_health.memory_desktop/load:media:imgur" }, { - "duration": "66.54091918181817", + "duration": "23.0", "name": "system_health.memory_desktop/load:media:soundcloud" }, { - "duration": "60.26443433333334", + "duration": "21.0", "name": "system_health.memory_desktop/load:media:youtube" }, { - "duration": "60.99940404040403", + "duration": "21.0", "name": "system_health.memory_desktop/load:news:bbc" }, { - "duration": "69.40436362626264", + "duration": "25.0", "name": "system_health.memory_desktop/load:news:cnn" }, { - "duration": "58.610505070707056", + "duration": "20.0", "name": "system_health.memory_desktop/load:news:flipboard" }, { - "duration": "55.72650505050506", + "duration": "19.0", "name": "system_health.memory_desktop/load:news:hackernews" }, { - "duration": "64.24272723232322", + "duration": "22.0", "name": "system_health.memory_desktop/load:news:nytimes" }, { - "duration": "72.04975757575758", + "duration": "24.0", "name": "system_health.memory_desktop/load:news:qq" }, { - "duration": "57.99711107070705", + "duration": "20.0", "name": "system_health.memory_desktop/load:news:reddit" }, { - "duration": "58.940464545454546", + "duration": "20.0", "name": "system_health.memory_desktop/load:news:wikipedia" }, { - "duration": "58.136141434343436", + "duration": "20.0", "name": "system_health.memory_desktop/load:search:amazon" }, { - "duration": "56.168050494949505", + "duration": "19.0", "name": "system_health.memory_desktop/load:search:baidu" }, { - "duration": "60.537070666666665", + "duration": "21.0", "name": "system_health.memory_desktop/load:search:ebay" }, { - "duration": "57.24329293939396", + "duration": "20.0", "name": "system_health.memory_desktop/load:search:google" }, { - "duration": "59.78401011111112", + "duration": "21.0", "name": "system_health.memory_desktop/load:search:taobao" }, { - "duration": "56.21350507070709", + "duration": "19.0", "name": "system_health.memory_desktop/load:search:yahoo" }, { - "duration": "56.70408086868685", + "duration": "20.0", "name": "system_health.memory_desktop/load:search:yandex" }, { - "duration": "60.89545452525254", + "duration": "21.0", "name": "system_health.memory_desktop/load:social:instagram" }, { - "duration": "62.79710105050507", + "duration": "22.0", "name": "system_health.memory_desktop/load:social:pinterest" }, { - "duration": "59.54065657575757", + "duration": "20.0", "name": "system_health.memory_desktop/load:social:vk" }, { - "duration": "64.36946467676769", + "duration": "23.0", "name": "system_health.memory_desktop/load:tools:docs" }, { - "duration": "74.16734335353536", + "duration": "23.0", "name": "system_health.memory_desktop/load:tools:drive" }, { - "duration": "60.080949515151495", + "duration": "20.0", "name": "system_health.memory_desktop/load:tools:dropbox" }, { - "duration": "68.31734332323238", + "duration": "22.0", "name": "system_health.memory_desktop/load:tools:gmail" }, { - "duration": "60.53708079797982", + "duration": "21.0", "name": "system_health.memory_desktop/load:tools:stackoverflow" }, { - "duration": "70.34837381818183", + "duration": "24.0", "name": "system_health.memory_desktop/load:tools:weather" }, { - "duration": "57.45111111111114", + "duration": "20.0", "name": "system_health.memory_desktop/load_accessibility:media:wikipedia" }, { - "duration": "64.16678783838383", + "duration": "20.0", "name": "system_health.memory_desktop/load_accessibility:shopping:amazon" }, { - "duration": "428.346282828283", + "duration": "143.0", "name": "system_health.memory_desktop/long_running:tools:gmail-background" }, { - "duration": "428.1560403030304", + "duration": "141.0", "name": "system_health.memory_desktop/long_running:tools:gmail-foreground" }, { - "duration": "315.44431313131315", + "duration": "121.0", "name": "system_health.memory_desktop/multitab:misc:typical24" }, { - "duration": "0.0012000083599999999", - "name": "system_health.memory_desktop/play:media:google_play_music" - }, - { - "duration": "0.0013333955999999998", - "name": "system_health.memory_desktop/play:media:pandora" - }, - { - "duration": "9.999275E-4", - "name": "system_health.memory_desktop/play:media:soundcloud" - }, - { - "duration": "108.51674743434346", + "duration": "113.0", "name": "tab_switching.typical_25/multitab:misc:typical24" }, { - "duration": "28.172494989898983", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/beqojupo/1/quiet?JS_FULL_SCREEN_INVALIDATION" - }, - { - "duration": "25.57725252525252", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/covoqi/1/quiet?NEW_TILINGS" - }, - { - "duration": "22.48349491919191", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/falefice/1/quiet?CC_POSTER_CIRCLE" - }, - { - "duration": "23.398585858585854", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/giqafofe/1/quiet?JS_POSTER_CIRCLE" - }, - { - "duration": "20.92841416161616", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/jevibahi/4/quiet?JS_SCROLL_200_LAYER_GRID" - }, - { - "duration": "25.13015147474748", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/pixavefe/1/quiet?CC_SCROLL_TEXT_ONLY" - }, - { - "duration": "21.05167675757576", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/wixadinu/2/quiet?JS_SCROLL_TEXT_ONLY" - }, - { - "duration": "21.248201999999996", - "name": "thread_times.tough_compositor_cases/http://jsbin.com/yakagevo/1/quiet?CC_SCROLL_200_LAYER_GRID" - }, - { - "duration": "16.63638385858586", - "name": "thread_times.tough_scrolling_cases/canvas_05000_pixels_per_second" - }, - { - "duration": "16.0447171969697", - "name": "thread_times.tough_scrolling_cases/canvas_10000_pixels_per_second" - }, - { - "duration": "13.038454540404034", - "name": "thread_times.tough_scrolling_cases/canvas_15000_pixels_per_second" - }, - { - "duration": "12.044838328282829", - "name": "thread_times.tough_scrolling_cases/canvas_20000_pixels_per_second" - }, - { - "duration": "10.640030348484846", - "name": "thread_times.tough_scrolling_cases/canvas_30000_pixels_per_second" - }, - { - "duration": "10.076363641414142", - "name": "thread_times.tough_scrolling_cases/canvas_40000_pixels_per_second" - }, - { - "duration": "9.683828292929297", - "name": "thread_times.tough_scrolling_cases/canvas_50000_pixels_per_second" - }, - { - "duration": "9.447575792929293", - "name": "thread_times.tough_scrolling_cases/canvas_60000_pixels_per_second" - }, - { - "duration": "9.145929297979794", - "name": "thread_times.tough_scrolling_cases/canvas_75000_pixels_per_second" - }, - { - "duration": "8.961777838383837", - "name": "thread_times.tough_scrolling_cases/canvas_90000_pixels_per_second" - }, - { - "duration": "34.83318177777777", - "name": "thread_times.tough_scrolling_cases/text_05000_pixels_per_second" - }, - { - "duration": "15.313626257575756", - "name": "thread_times.tough_scrolling_cases/text_10000_pixels_per_second" - }, - { - "duration": "12.59582825252525", - "name": "thread_times.tough_scrolling_cases/text_15000_pixels_per_second" - }, - { - "duration": "11.91569700505051", - "name": "thread_times.tough_scrolling_cases/text_20000_pixels_per_second" - }, - { - "duration": "10.25633334848485", - "name": "thread_times.tough_scrolling_cases/text_30000_pixels_per_second" - }, - { - "duration": "10.671505040404043", - "name": "thread_times.tough_scrolling_cases/text_40000_pixels_per_second" - }, - { - "duration": "9.344333449494947", - "name": "thread_times.tough_scrolling_cases/text_50000_pixels_per_second" - }, - { - "duration": "9.039353525252526", - "name": "thread_times.tough_scrolling_cases/text_60000_pixels_per_second" - }, - { - "duration": "8.806727313131312", - "name": "thread_times.tough_scrolling_cases/text_75000_pixels_per_second" - }, - { - "duration": "8.637646499999995", - "name": "thread_times.tough_scrolling_cases/text_90000_pixels_per_second" - }, - { - "duration": "17.830313131313126", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second" - }, - { - "duration": "16.559272767676767", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second" - }, - { - "duration": "13.911222272727269", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second" - }, - { - "duration": "12.56742427777778", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second" - }, - { - "duration": "11.141333323232319", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second" - }, - { - "duration": "10.640161611111107", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second" - }, - { - "duration": "10.13763637878788", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second" - }, - { - "duration": "9.867434358585857", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second" - }, - { - "duration": "9.55034346464646", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second" - }, - { - "duration": "9.458282833333334", - "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second" - }, - { - "duration": "15.934656560606062", - "name": "thread_times.tough_scrolling_cases/text_hover_05000_pixels_per_second" - }, - { - "duration": "14.77061612626263", - "name": "thread_times.tough_scrolling_cases/text_hover_10000_pixels_per_second" - }, - { - "duration": "12.5120403989899", - "name": "thread_times.tough_scrolling_cases/text_hover_15000_pixels_per_second" - }, - { - "duration": "11.235535338383837", - "name": "thread_times.tough_scrolling_cases/text_hover_20000_pixels_per_second" - }, - { - "duration": "10.06039392424242", - "name": "thread_times.tough_scrolling_cases/text_hover_30000_pixels_per_second" - }, - { - "duration": "9.483515136363637", - "name": "thread_times.tough_scrolling_cases/text_hover_40000_pixels_per_second" - }, - { - "duration": "9.163828257575753", - "name": "thread_times.tough_scrolling_cases/text_hover_50000_pixels_per_second" - }, - { - "duration": "8.836565681818183", - "name": "thread_times.tough_scrolling_cases/text_hover_60000_pixels_per_second" - }, - { - "duration": "8.574262636363637", - "name": "thread_times.tough_scrolling_cases/text_hover_75000_pixels_per_second" - }, - { - "duration": "8.537939429292932", - "name": "thread_times.tough_scrolling_cases/text_hover_90000_pixels_per_second" - }, - { - "duration": "10.713727277777776", + "duration": "11.0", "name": "tracing.tracing_with_background_memory_infra/Facebook" }, { - "duration": "11.191767717171716", + "duration": "11.0", "name": "tracing.tracing_with_background_memory_infra/Wikipedia" }, { - "duration": "9.35317175757576", + "duration": "10.0", "name": "tracing.tracing_with_background_memory_infra/http://www.amazon.com" }, { - "duration": "10.2252221969697", + "duration": "11.0", "name": "tracing.tracing_with_background_memory_infra/http://www.ask.com/" }, { - "duration": "9.806010101010106", + "duration": "10.0", "name": "tracing.tracing_with_background_memory_infra/http://www.bing.com/" }, { - "duration": "9.9939495", + "duration": "10.0", "name": "tracing.tracing_with_background_memory_infra/http://www.yahoo.com/" }, { - "duration": "11.74751515656566", + "duration": "12.0", "name": "tracing.tracing_with_background_memory_infra/http://www.youtube.com" }, { - "duration": "22.485686853535345", + "duration": "11.0", "name": "tracing.tracing_with_background_memory_infra/https://www.google.com/#hl=en&q=barack+obama" }, { - "duration": "13.11601014646465", + "duration": "14.0", "name": "tracing.tracing_with_background_memory_infra/https://www.google.com/calendar/" }, { - "duration": "0.0010001659", - "name": "v8.browsing_desktop-future/browse:media:flickr_infinite_scroll" - }, - { - "duration": "231.88872727272724", + "duration": "249.0", "name": "v8.browsing_desktop-future/browse:media:imgur" }, { - "duration": "80.89534339393943", + "duration": "77.0", "name": "v8.browsing_desktop-future/browse:media:pinterest" }, { - "duration": "84.93430303030304", + "duration": "140.0", "name": "v8.browsing_desktop-future/browse:media:tumblr" }, { - "duration": "96.28224242424241", + "duration": "96.0", "name": "v8.browsing_desktop-future/browse:media:youtube" }, { - "duration": "135.44675743434345", + "duration": "122.0", "name": "v8.browsing_desktop-future/browse:news:cnn" }, { - "duration": "0.00100002286", - "name": "v8.browsing_desktop-future/browse:news:flipboard" - }, - { - "duration": "9.999871E-4", - "name": "v8.browsing_desktop-future/browse:news:hackernews" - }, - { - "duration": "139.11240404040404", - "name": "v8.browsing_desktop-future/browse:news:nytimes" - }, - { - "duration": "87.88215151515152", - "name": "v8.browsing_desktop-future/browse:news:reddit" - }, - { - "duration": "58.09329290909093", + "duration": "60.0", "name": "v8.browsing_desktop-future/browse:search:google" }, { - "duration": "42.20118181818184", + "duration": "43.0", "name": "v8.browsing_desktop-future/browse:search:google_india" }, { - "duration": "98.05891923232323", + "duration": "99.0", "name": "v8.browsing_desktop-future/browse:social:facebook_infinite_scroll" }, { - "duration": "105.47064646464645", + "duration": "107.0", "name": "v8.browsing_desktop-future/browse:social:tumblr_infinite_scroll" }, { - "duration": "57.849323232323265", + "duration": "56.0", "name": "v8.browsing_desktop-future/browse:social:twitter" }, { - "duration": "119.28043444444444", - "name": "v8.browsing_desktop-future/browse:social:twitter_infinite_scroll" - }, - { - "duration": "110.93080808080808", + "duration": "113.0", "name": "v8.browsing_desktop-future/browse:tech:discourse_infinite_scroll" }, { - "duration": "105.05406064646465", + "duration": "104.0", "name": "v8.browsing_desktop-future/browse:tools:earth" }, { - "duration": "80.53191915151517", + "duration": "81.0", "name": "v8.browsing_desktop-future/browse:tools:maps" }, { - "duration": "0.0010000467", - "name": "v8.browsing_desktop/browse:media:flickr_infinite_scroll" - }, - { - "duration": "250.189606060606", + "duration": "247.0", "name": "v8.browsing_desktop/browse:media:imgur" }, { - "duration": "81.52414141414143", + "duration": "77.0", "name": "v8.browsing_desktop/browse:media:pinterest" }, { - "duration": "84.41895963636362", + "duration": "141.0", "name": "v8.browsing_desktop/browse:media:tumblr" }, { - "duration": "96.44750501010101", + "duration": "96.0", "name": "v8.browsing_desktop/browse:media:youtube" }, { - "duration": "132.24963612121212", + "duration": "121.0", "name": "v8.browsing_desktop/browse:news:cnn" }, { - "duration": "9.999275E-4", - "name": "v8.browsing_desktop/browse:news:flipboard" - }, - { - "duration": "9.999871E-4", - "name": "v8.browsing_desktop/browse:news:hackernews" - }, - { - "duration": "138.06498989898992", + "duration": "146.0", "name": "v8.browsing_desktop/browse:news:nytimes" }, { - "duration": "88.60219195959591", + "duration": "79.0", "name": "v8.browsing_desktop/browse:news:reddit" }, { - "duration": "58.15426258585859", + "duration": "58.0", "name": "v8.browsing_desktop/browse:search:google" }, { - "duration": "42.216141393939395", + "duration": "43.0", "name": "v8.browsing_desktop/browse:search:google_india" }, { - "duration": "97.3823837979798", + "duration": "97.0", "name": "v8.browsing_desktop/browse:social:facebook_infinite_scroll" }, { - "duration": "104.57660606060608", + "duration": "107.0", "name": "v8.browsing_desktop/browse:social:tumblr_infinite_scroll" }, { - "duration": "56.72188892929295", + "duration": "57.0", "name": "v8.browsing_desktop/browse:social:twitter" }, { - "duration": "115.95925252525245", - "name": "v8.browsing_desktop/browse:social:twitter_infinite_scroll" - }, - { - "duration": "110.61260606060605", + "duration": "113.0", "name": "v8.browsing_desktop/browse:tech:discourse_infinite_scroll" }, { - "duration": "106.01424250505049", + "duration": "105.0", "name": "v8.browsing_desktop/browse:tools:earth" }, { - "duration": "80.0400404040404", + "duration": "81.0", "name": "v8.browsing_desktop/browse:tools:maps" }, { - "duration": "0.00150001045", - "name": "wasm/AsmJsZenGarden" + "duration": "33.0", + "name": "v8.runtime_stats.top_25/AdsAMPAds_cold" }, { - "duration": "47.291363641414144", + "duration": "38.0", + "name": "v8.runtime_stats.top_25/AdsAMPAds_hot" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/AdsAMPAds_warm" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/AdsAdSenseAsyncAds_cold" + }, + { + "duration": "37.0", + "name": "v8.runtime_stats.top_25/AdsAdSenseAsyncAds_hot" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/AdsAdSenseAsyncAds_warm" + }, + { + "duration": "31.0", + "name": "v8.runtime_stats.top_25/AdsAsyncAdSenseImage_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/AdsAsyncAdSenseImage_hot" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/AdsAsyncAdSenseImage_warm" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/AdsDoubleClickAsyncAds_cold" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/AdsDoubleClickAsyncAds_hot" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/AdsDoubleClickAsyncAds_warm" + }, + { + "duration": "31.0", + "name": "v8.runtime_stats.top_25/AdsMultipleAdSlots_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/AdsMultipleAdSlots_hot" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/AdsMultipleAdSlots_warm" + }, + { + "duration": "31.0", + "name": "v8.runtime_stats.top_25/AdsOnScreenDetection_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/AdsOnScreenDetection_hot" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/AdsOnScreenDetection_warm" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/AdsSyncAdSenseImage_cold" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/AdsSyncAdSenseImage_hot" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/AdsSyncAdSenseImage_warm" + }, + { + "duration": "31.0", + "name": "v8.runtime_stats.top_25/AdsSyncLoadAsyncRenderAdSenseImage_cold" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/AdsSyncLoadAsyncRenderAdSenseImage_hot" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/AdsSyncLoadAsyncRenderAdSenseImage_warm" + }, + { + "duration": "44.0", + "name": "v8.runtime_stats.top_25/AdsViewOptimizedRendering_cold" + }, + { + "duration": "71.0", + "name": "v8.runtime_stats.top_25/AdsViewOptimizedRendering_hot" + }, + { + "duration": "57.0", + "name": "v8.runtime_stats.top_25/AdsViewOptimizedRendering_warm" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://edition.cnn.com_cold" + }, + { + "duration": "45.0", + "name": "v8.runtime_stats.top_25/http://edition.cnn.com_hot" + }, + { + "duration": "41.0", + "name": "v8.runtime_stats.top_25/http://edition.cnn.com_warm" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/http://hi.wikipedia.org/wiki/%E0%A4%AE%E0%A5%81%E0%A4%96%E0%A4%AA%E0%A5%83%E0%A4%B7%E0%A5%8D%E0%A4%A0_cold" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://hi.wikipedia.org/wiki/%E0%A4%AE%E0%A5%81%E0%A4%96%E0%A4%AA%E0%A5%83%E0%A4%B7%E0%A5%8D%E0%A4%A0_hot" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/http://hi.wikipedia.org/wiki/%E0%A4%AE%E0%A5%81%E0%A4%96%E0%A4%AA%E0%A5%83%E0%A4%B7%E0%A5%8D%E0%A4%A0_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://inbox.google.com_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/http://inbox.google.com_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://inbox.google.com_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://maps.google.co.jp/maps/search/restaurant+tokyo_cold" + }, + { + "duration": "40.0", + "name": "v8.runtime_stats.top_25/http://maps.google.co.jp/maps/search/restaurant+tokyo_hot" + }, + { + "duration": "37.0", + "name": "v8.runtime_stats.top_25/http://maps.google.co.jp/maps/search/restaurant+tokyo_warm" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/http://meta.discourse.org_cold" + }, + { + "duration": "39.0", + "name": "v8.runtime_stats.top_25/http://meta.discourse.org_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://meta.discourse.org_warm" + }, + { + "duration": "30.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?angular_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?angular_hot" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?angular_warm" + }, + { + "duration": "30.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?backbone_cold" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?backbone_hot" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?backbone_warm" + }, + { + "duration": "30.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?ember_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?ember_hot" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?ember_warm" + }, + { + "duration": "30.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?jquery_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?jquery_hot" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?jquery_warm" + }, + { + "duration": "30.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?vanilla_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?vanilla_hot" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/http://pollouer.muc/Speedometer/CustomRunner.html?vanilla_warm" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/http://reddit.musicplayer.io_cold" + }, + { + "duration": "39.0", + "name": "v8.runtime_stats.top_25/http://reddit.musicplayer.io_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://reddit.musicplayer.io_warm" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://weibo.com_cold" + }, + { + "duration": "40.0", + "name": "v8.runtime_stats.top_25/http://weibo.com_hot" + }, + { + "duration": "37.0", + "name": "v8.runtime_stats.top_25/http://weibo.com_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://world.taobao.com_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/http://world.taobao.com_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://world.taobao.com_warm" + }, + { + "duration": "31.0", + "name": "v8.runtime_stats.top_25/http://www.amazon.com/s/?field-keywords=v8_cold" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://www.amazon.com/s/?field-keywords=v8_hot" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/http://www.amazon.com/s/?field-keywords=v8_warm" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/http://www.baidu.com/s?wd=v8_cold" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://www.baidu.com/s?wd=v8_hot" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/http://www.baidu.com/s?wd=v8_warm" + }, + { + "duration": "31.0", + "name": "v8.runtime_stats.top_25/http://www.bing.com/search?q=v8+engine_cold" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://www.bing.com/search?q=v8+engine_hot" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://www.bing.com/search?q=v8+engine_warm" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://www.ebay.fr/sch/i.html?_nkw=v8_cold" + }, + { + "duration": "41.0", + "name": "v8.runtime_stats.top_25/http://www.ebay.fr/sch/i.html?_nkw=v8_hot" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/http://www.ebay.fr/sch/i.html?_nkw=v8_warm" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/http://www.instagram.com/archdigest_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/http://www.instagram.com/archdigest_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://www.instagram.com/archdigest_warm" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://www.msn.com/ar-ae_cold" + }, + { + "duration": "42.0", + "name": "v8.runtime_stats.top_25/http://www.msn.com/ar-ae_hot" + }, + { + "duration": "39.0", + "name": "v8.runtime_stats.top_25/http://www.msn.com/ar-ae_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://www.pinterest.com/categories/popular_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/http://www.pinterest.com/categories/popular_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://www.pinterest.com/categories/popular_warm" + }, + { + "duration": "67.0", + "name": "v8.runtime_stats.top_25/http://www.qq.com_cold" + }, + { + "duration": "76.0", + "name": "v8.runtime_stats.top_25/http://www.qq.com_hot" + }, + { + "duration": "69.0", + "name": "v8.runtime_stats.top_25/http://www.qq.com_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://www.reddit.com_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/http://www.reddit.com_hot" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://www.reddit.com_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://www.twitter.com/taylorswift13_cold" + }, + { + "duration": "39.0", + "name": "v8.runtime_stats.top_25/http://www.twitter.com/taylorswift13_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/http://www.twitter.com/taylorswift13_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://www.wikiwand.com/en/hill_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/http://www.wikiwand.com/en/hill_hot" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://www.wikiwand.com/en/hill_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://www.yahoo.co.jp_cold" + }, + { + "duration": "37.0", + "name": "v8.runtime_stats.top_25/http://www.yahoo.co.jp_hot" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://www.yahoo.co.jp_warm" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/http://yandex.ru/search/?text=v8_cold" + }, + { + "duration": "37.0", + "name": "v8.runtime_stats.top_25/http://yandex.ru/search/?text=v8_hot" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/http://yandex.ru/search/?text=v8_warm" + }, + { + "duration": "46.0", + "name": "v8.runtime_stats.top_25/https://adwords.google.com_cold" + }, + { + "duration": "59.0", + "name": "v8.runtime_stats.top_25/https://adwords.google.com_hot" + }, + { + "duration": "57.0", + "name": "v8.runtime_stats.top_25/https://adwords.google.com_warm" + }, + { + "duration": "30.0", + "name": "v8.runtime_stats.top_25/https://cdn.ampproject.org/c/www.bbc.co.uk/news/amp/37344292#log=3_cold" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/https://cdn.ampproject.org/c/www.bbc.co.uk/news/amp/37344292#log=3_hot" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/https://cdn.ampproject.org/c/www.bbc.co.uk/news/amp/37344292#log=3_warm" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/https://en.wikipedia.org/w/index.php?title=Barack_Obama&veaction=edit_cold" + }, + { + "duration": "41.0", + "name": "v8.runtime_stats.top_25/https://en.wikipedia.org/w/index.php?title=Barack_Obama&veaction=edit_hot" + }, + { + "duration": "43.0", + "name": "v8.runtime_stats.top_25/https://en.wikipedia.org/w/index.php?title=Barack_Obama&veaction=edit_warm" + }, + { + "duration": "32.0", + "name": "v8.runtime_stats.top_25/https://www.facebook.com/shakira_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/https://www.facebook.com/shakira_hot" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/https://www.facebook.com/shakira_warm" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/https://www.google.de/search?q=v8_cold" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/https://www.google.de/search?q=v8_hot" + }, + { + "duration": "33.0", + "name": "v8.runtime_stats.top_25/https://www.google.de/search?q=v8_warm" + }, + { + "duration": "34.0", + "name": "v8.runtime_stats.top_25/https://www.linkedin.com/m/_cold" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/https://www.linkedin.com/m/_hot" + }, + { + "duration": "36.0", + "name": "v8.runtime_stats.top_25/https://www.linkedin.com/m/_warm" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/https://www.youtube.com/watch?v=_kZsOISarzg_cold" + }, + { + "duration": "43.0", + "name": "v8.runtime_stats.top_25/https://www.youtube.com/watch?v=_kZsOISarzg_hot" + }, + { + "duration": "40.0", + "name": "v8.runtime_stats.top_25/https://www.youtube.com/watch?v=_kZsOISarzg_warm" + }, + { + "duration": "35.0", + "name": "v8.runtime_stats.top_25/https://www.youtube.com_cold" + }, + { + "duration": "41.0", + "name": "v8.runtime_stats.top_25/https://www.youtube.com_hot" + }, + { + "duration": "38.0", + "name": "v8.runtime_stats.top_25/https://www.youtube.com_warm" + }, + { + "duration": "16.0", "name": "wasm/WasmSpaceBuggy" }, { - "duration": "116.5097373737374", - "name": "wasm/WasmStylizedRenderer" - }, - { - "duration": "104.80597985858586", - "name": "wasm/WasmSunTemple" - }, - { - "duration": "58.15015152020203", + "duration": "18.0", "name": "wasm/WasmTanks" }, { - "duration": "114.43171709090916", + "duration": "34.0", "name": "wasm/WasmZenGarden" }, { - "duration": "68.14915151515152", + "duration": "35.0", "name": "webrtc/10s_datachannel_transfer" }, { - "duration": "21.731161616161614", + "duration": "22.0", "name": "webrtc/canvas_capture_peer_connection" }, { - "duration": "31.167606050505032", + "duration": "32.0", "name": "webrtc/codec_constraints_h264" }, { - "duration": "31.151949505050506", + "duration": "32.0", "name": "webrtc/codec_constraints_vp8" }, { - "duration": "31.11636367676769", + "duration": "32.0", "name": "webrtc/codec_constraints_vp9" }, { - "duration": "19.85481824242424", + "duration": "20.0", "name": "webrtc/hd_local_stream_10s" }, { - "duration": "57.42817169696971", + "duration": "53.0", "name": "webrtc/multiple_peerconnections" }, { - "duration": "72.67151521212121", + "duration": "57.0", "name": "webrtc/pause_play_peerconnections" } ] \ No newline at end of file
diff --git a/tools/perf/core/shard_maps/win10_shard_map.json b/tools/perf/core/shard_maps/win10_shard_map.json index 1a4c2f30..3562446 100644 --- a/tools/perf/core/shard_maps/win10_shard_map.json +++ b/tools/perf/core/shard_maps/win10_shard_map.json
@@ -8,8 +8,29 @@ "power.desktop": {}, "speedometer-future": {}, "blink_perf.owp_storage": {}, - "memory.desktop": {}, - "start_with_url.warm.startup_pages": {}, + "memory.desktop": { + "end": 1 + } + } + }, + "1": { + "benchmarks": { + "memory.desktop": { + "begin": 1, + "end": 5 + } + } + }, + "2": { + "benchmarks": { + "memory.desktop": { + "begin": 5 + }, + "start_with_url.warm.startup_pages": {} + } + }, + "3": { + "benchmarks": { "wasm": {}, "dummy_benchmark.histogram_benchmark_1": {}, "speedometer": {}, @@ -18,27 +39,65 @@ "dummy_benchmark.noisy_benchmark_1": {}, "blink_perf.svg": {}, "system_health.webview_startup": {}, - "speedometer2-future": {}, + "v8.browsing_mobile": {}, "jetstream": {}, "smoothness.tough_pinch_zoom_cases": {}, + "speedometer2-future": {}, "power.typical_10_mobile": {}, "v8.runtime_stats.top_25": { - "end": 83 + "end": 12 } } }, - "1": { + "4": { "benchmarks": { "v8.runtime_stats.top_25": { - "begin": 83 + "begin": 12, + "end": 47 + } + } + }, + "5": { + "benchmarks": { + "v8.runtime_stats.top_25": { + "begin": 47, + "end": 84 + } + } + }, + "6": { + "benchmarks": { + "v8.runtime_stats.top_25": { + "begin": 84, + "end": 124 + } + } + }, + "7": { + "benchmarks": { + "v8.runtime_stats.top_25": { + "begin": 124 }, "loading.mobile": {}, "speedometer2": {}, - "v8.browsing_desktop-future": {}, + "v8.browsing_desktop-future": { + "end": 15 + } + } + }, + "8": { + "benchmarks": { + "v8.browsing_desktop-future": { + "begin": 15 + }, "webrtc": {}, "blink_perf.shadow_dom": {}, "blink_perf.events": {}, - "blink_perf.layout": {}, + "blink_perf.layout": {} + } + }, + "9": { + "benchmarks": { "memory.long_running_idle_gmail_background_tbmv2": {}, "tab_switching.typical_25": {}, "blink_perf.dom": {}, @@ -46,60 +105,166 @@ "start_with_url.cold.startup_pages": {}, "blink_perf.bindings": {}, "system_health.memory_desktop": { - "end": 25 + "end": 6 } } }, - "2": { + "10": { "benchmarks": { "system_health.memory_desktop": { - "begin": 25 + "begin": 6, + "end": 20 + } + } + }, + "11": { + "benchmarks": { + "system_health.memory_desktop": { + "begin": 20, + "end": 41 + } + } + }, + "12": { + "benchmarks": { + "system_health.memory_desktop": { + "begin": 41, + "end": 53 + } + } + }, + "13": { + "benchmarks": { + "system_health.memory_desktop": { + "begin": 53, + "end": 62 + } + } + }, + "14": { + "benchmarks": { + "system_health.memory_desktop": { + "begin": 62 }, "media.desktop": {}, "smoothness.gpu_rasterization.tough_pinch_zoom_cases": {}, "rasterize_and_record_micro.partial_invalidation": {}, - "v8.browsing_desktop": {}, - "blink_perf.parser": {}, - "memory.top_10_mobile": {}, - "blink_perf.canvas": {}, - "loading.desktop": { - "end": 2 + "v8.browsing_desktop": { + "end": 10 } } }, - "3": { + "15": { + "benchmarks": { + "v8.browsing_desktop": { + "begin": 10 + }, + "blink_perf.parser": {}, + "memory.top_10_mobile": {}, + "blink_perf.canvas": { + "end": 14 + } + } + }, + "16": { + "benchmarks": { + "blink_perf.canvas": { + "begin": 14 + }, + "loading.desktop": { + "end": 36 + } + } + }, + "17": { "benchmarks": { "loading.desktop": { - "begin": 2 + "begin": 36, + "end": 67 + } + } + }, + "18": { + "benchmarks": { + "loading.desktop": { + "begin": 67, + "end": 96 + } + } + }, + "19": { + "benchmarks": { + "loading.desktop": { + "begin": 96 }, "dromaeo": {}, "kraken": {}, "oortonline_tbmv2": {}, "system_health.common_desktop": { - "end": 62 + "end": 16 } } }, - "4": { + "20": { "benchmarks": { "system_health.common_desktop": { - "begin": 62 + "begin": 16, + "end": 54 + } + } + }, + "21": { + "benchmarks": { + "system_health.common_desktop": { + "begin": 54 }, "rasterize_and_record_micro.top_25": {}, "dummy_benchmark.stable_benchmark_1": {}, "system_health.memory_mobile": {}, - "rendering.desktop": {}, + "rendering.desktop": { + "end": 5 + } + } + }, + "22": { + "benchmarks": { + "rendering.desktop": { + "begin": 5, + "end": 61 + } + } + }, + "23": { + "benchmarks": { + "rendering.desktop": { + "begin": 61, + "end": 121 + } + } + }, + "24": { + "benchmarks": { + "rendering.desktop": { + "begin": 121, + "end": 196 + } + } + }, + "25": { + "benchmarks": { + "rendering.desktop": { + "begin": 196 + }, "blink_perf.css": {}, - "v8.browsing_mobile": {}, "blink_perf.paint": {}, "tracing.tracing_with_background_memory_infra": {} } }, "extra_infos": { - "num_stories": 1832, - "predicted_min_shard_time": 13278.596959395232, - "predicted_min_shard_index": 4, - "predicted_max_shard_time": 13411.964187257567, + "num_stories": 1830, + "predicted_min_shard_time": 2528.0, + "predicted_min_shard_index": 3, + "predicted_max_shard_time": 3150.0, "predicted_max_shard_index": 1 } } \ No newline at end of file
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index b22494c..087009f 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -243,6 +243,8 @@ android_library("ui_full_java") { java_files = [ + "java/src/org/chromium/ui/AsyncViewStub.java", + "java/src/org/chromium/ui/AsyncViewProvider.java", "java/src/org/chromium/ui/DropdownAdapter.java", "java/src/org/chromium/ui/DropdownDividerDrawable.java", "java/src/org/chromium/ui/DropdownItem.java", @@ -339,12 +341,21 @@ ] } +android_resources("ui_javatest_resources") { + custom_package = "org.chromium.test.ui" + resource_dirs = [ "junit/res" ] +} + junit_binary("ui_junit_tests") { + package_name = "org.chromium.test.ui" java_files = [ + "junit/src/org/chromium/ui/AsyncViewStubTest.java", + "junit/src/org/chromium/ui/AsyncViewProviderTest.java", "junit/src/org/chromium/ui/base/ClipboardTest.java", "junit/src/org/chromium/ui/base/SelectFileDialogTest.java", "junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java", "junit/src/org/chromium/ui/text/SpanApplierTest.java", + "junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java", "junit/src/org/chromium/ui/shadows/ShadowAppCompatResources.java", "junit/src/org/chromium/ui/shadows/ShadowAppCompatResourcesTest.java", "junit/src/org/chromium/ui/shadows/ShadowAnimatedStateListDrawable.java", @@ -352,6 +363,7 @@ ] deps = [ ":ui_java", + ":ui_javatest_resources", "//base:base_java", "//base:base_java_test_support", "//base:base_junit_test_support",
diff --git a/ui/android/java/res/values/attrs.xml b/ui/android/java/res/values/attrs.xml index 06c3b266..61ae7c63 100644 --- a/ui/android/java/res/values/attrs.xml +++ b/ui/android/java/res/values/attrs.xml
@@ -20,4 +20,10 @@ <declare-styleable name="TextViewWithLeading"> <attr name="leading" format="reference|dimension"/> </declare-styleable> + <declare-styleable name="AsyncViewStub"> + <!-- Supply an identifier for the layout resource to inflate when the AsyncViewStub + becomes visible or when forced to do so. The layout resource must be a + valid reference to a layout. --> + <attr name="layout" format="reference" /> + </declare-styleable> </resources>
diff --git a/ui/android/java/src/org/chromium/ui/AsyncViewProvider.java b/ui/android/java/src/org/chromium/ui/AsyncViewProvider.java new file mode 100644 index 0000000..16547543 --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/AsyncViewProvider.java
@@ -0,0 +1,131 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui; + +import android.support.annotation.Nullable; +import android.view.View; + +import org.chromium.base.Callback; +import org.chromium.base.ThreadUtils; + +/** + * A provider that encapsulates a {@link View} that is in the view hierarchy to be inflated by + * an {@link AsyncViewStub}. + * @param <T> type of the {@link View} that this provider encapsulates. + */ +public class AsyncViewProvider<T extends View> implements Callback<View> { + private int mResId; + // Exactly one of mView and mViewStub is non-null at any point. + private T mView; + private AsyncViewStub mViewStub; + private boolean mDestroyed; + + private AsyncViewProvider(AsyncViewStub viewStub, int resId) { + assert viewStub != null; + mResId = resId; + mViewStub = viewStub; + } + + @SuppressWarnings("unchecked") + private AsyncViewProvider(View view) { + assert view != null; + mView = (T) view; + } + + /** + * Returns a provider for a view in the view hierarchy that is to be inflated by {@param + * viewStub}. + * @param viewStub the {@link AsyncViewStub} that will inflate the view hierarchy containing the + * {@link View}. + * @param resId The resource id of the view that this provider should provide/encapsulate. + * @return an {@link AsyncViewProvider} that encapsulates a view with id {@param resId}. + */ + public static <E extends View> AsyncViewProvider<E> of(AsyncViewStub viewStub, int resId) { + ThreadUtils.assertOnUiThread(); + if (viewStub.getInflatedView() != null) { + return new AsyncViewProvider<>(viewStub.getInflatedView().findViewById(resId)); + } + AsyncViewProvider<E> provider = new AsyncViewProvider<>(viewStub, resId); + viewStub.addOnInflateListener(provider); + return provider; + } + + /** + * Get a provider for a view with id {@param viewResId} that is (or going to be) in the view + * hierarchy inflated by the AsyncViewStub with id {@param viewStubResId}. + * @param root the {@link View} to use as the context for finding the View/ViewStub that the + * provider encapsulates. + * @param viewStubResId the resource id of the AsyncViewStub that inflates the view hierarchy + * where the encapsulated View lives. + * @param viewResId the resource id of the view that the provider should provide/encapsulate. + * @return an {@link AsyncViewProvider} that encapsulates a view with id {@param viewResId}. + */ + public static <E extends View> AsyncViewProvider<E> of( + View root, int viewStubResId, int viewResId) { + ThreadUtils.assertOnUiThread(); + View viewStub = root.findViewById(viewStubResId); + if (viewStub != null && viewStub instanceof AsyncViewStub) { + // view stub not yet inflated + return of((AsyncViewStub) viewStub, viewResId); + } + // view stub already inflated, return pre-loaded provider + return new AsyncViewProvider<>(root.findViewById(viewResId)); + } + + @Override + public void onResult(View view) { + mView = view.findViewById(mResId); + mViewStub = null; + } + + /** + * @return the {@link View} encapsulated by this provider or null (if the view has not been + * inflated yet). + */ + @Nullable + public T get() { + return mView; + } + + /** + * @param resId resource id of the {@link View} that the returned provider would + * encapsulate. + * @param <E> type of the {@link View} that the returned provider would encapsulate + * @return a provider for a {@link View} with resource id {@param resId} that is in the view + * hierarchy of the {@link View} encapsulated by this provider. + */ + public <E extends View> AsyncViewProvider<E> getChildProvider(int resId) { + if (mView != null) { + return new AsyncViewProvider<>(mView.findViewById(resId)); + } + return of(mViewStub, resId); + } + + /** + * Add a callback that would be run (on the UI thread) once the {@link View} encapsulated by + * this provider is inflated. The callback runs immediately (blocking) if the view has + * already been inflated. + */ + public void whenLoaded(Callback<T> callback) { + ThreadUtils.assertOnUiThread(); + if (mDestroyed) return; + if (mView != null) { + // fire right now if view already inflated. + callback.onResult(mView); + } else { + mViewStub.addOnInflateListener((View view) -> { + if (mDestroyed) return; + // listeners are called in order so mView should be set correctly at this point. + callback.onResult(mView); + }); + } + } + + public void destroy() { + mDestroyed = true; + mView = null; + mViewStub = null; + } +}
diff --git a/ui/android/java/src/org/chromium/ui/AsyncViewStub.java b/ui/android/java/src/org/chromium/ui/AsyncViewStub.java new file mode 100644 index 0000000..9451822 --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/AsyncViewStub.java
@@ -0,0 +1,153 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.support.annotation.NonNull; +import android.support.v4.view.AsyncLayoutInflater; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; + +import org.chromium.base.Callback; +import org.chromium.base.ObserverList; +import org.chromium.base.ThreadUtils; +import org.chromium.base.TraceEvent; + +/** + * An implementation of ViewStub that inflates the view in a background thread. Callbacks are still + * called on the UI thread. + */ +public class AsyncViewStub extends View implements AsyncLayoutInflater.OnInflateFinishedListener { + private int mLayoutResource; + private View mInflatedView; + + private static AsyncLayoutInflater sAsyncLayoutInflater; + + private final ObserverList<Callback<View>> mListeners = new ObserverList<>(); + + public AsyncViewStub(Context context, AttributeSet attrs) { + super(context, attrs); + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AsyncViewStub); + mLayoutResource = a.getResourceId(R.styleable.AsyncViewStub_layout, 0); + a.recycle(); + + setVisibility(GONE); + setWillNotDraw(true); + + if (sAsyncLayoutInflater == null) { + sAsyncLayoutInflater = new AsyncLayoutInflater(getContext()); + } + } + + /** + * Specifies the layout resource to inflate when {@link #inflate(boolean)} is invoked. The View + * created by inflating the layout resource is used to replace this AsyncViewStub in its parent. + * + * @param layoutResource A valid layout resource identifier (different from 0.) + */ + public void setLayoutResource(int layoutResource) { + mLayoutResource = layoutResource; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(0, 0); + } + + @SuppressLint("MissingSuperCall") + @Override + public void draw(Canvas canvas) {} + + @Override + protected void dispatchDraw(Canvas canvas) {} + + @Override + public void onInflateFinished(@NonNull View view, int resId, ViewGroup parent) { + mInflatedView = view; + replaceSelfWithView(view, parent); + callListeners(view, resId, parent); + } + + /** + * Starts background inflation for the stub, the AsyncViewStub must be attached to the window + * (ie have a parent) before you call inflate on it. Must be called on the UI thread. + * @param onBackgroundThread if inflation should be tried on a background thread first, this is + * used for A/B testing. + */ + public void inflate(boolean onBackgroundThread) { + try (TraceEvent te = TraceEvent.scoped("AsyncViewStub.inflate")) { + ThreadUtils.assertOnUiThread(); + final ViewParent viewParent = getParent(); + assert viewParent != null; + assert viewParent instanceof ViewGroup; + assert mLayoutResource != 0; + if (onBackgroundThread) { + // AsyncLayoutInflater uses its own thread and cannot inflate <merge> elements. It + // might be a good idea to write our own version to use our scheduling primitives + // and to handle <merge> inflations. + sAsyncLayoutInflater.inflate(mLayoutResource, (ViewGroup) viewParent, this); + } else { + ViewGroup inflatedView = + (ViewGroup) LayoutInflater.from(getContext()) + .inflate(mLayoutResource, (ViewGroup) viewParent, false); + onInflateFinished(inflatedView, mLayoutResource, (ViewGroup) viewParent); + } + } + } + + private void callListeners(View view, int resId, ViewGroup parent) { + try (TraceEvent te = TraceEvent.scoped("AsyncViewStub.callListeners")) { + ThreadUtils.assertOnUiThread(); + for (Callback<View> listener : mListeners) { + listener.onResult(view); + } + mListeners.clear(); + } + } + + /** + * This should only be used by {@link AsyncViewProvider}, use {@link + * AsyncViewProvider#whenLoaded} instead. + * + * Adds listener that gets called once the view is inflated and added to the view hierarchy. The + * listeners are called on the UI thread. This method can only be called on the UI thread. + * + * @param listener the listener to add. + */ + void addOnInflateListener(Callback<View> listener) { + ThreadUtils.assertOnUiThread(); + if (mInflatedView != null) { + listener.onResult(mInflatedView); + } else { + mListeners.addObserver(listener); + } + } + + /** + * @return the inflated view or null if inflation is not complete yet. + */ + View getInflatedView() { + return mInflatedView; + } + + private void replaceSelfWithView(View view, ViewGroup parent) { + try (TraceEvent te = TraceEvent.scoped("AsyncViewStub.replaceSelfWithView")) { + int index = parent.indexOfChild(this); + parent.removeViewInLayout(this); + final ViewGroup.LayoutParams layoutParams = getLayoutParams(); + if (layoutParams != null) { + parent.addView(view, index, layoutParams); + } else { + parent.addView(view, index); + } + } + } +}
diff --git a/ui/android/junit/res/layout/inflated_view.xml b/ui/android/junit/res/layout/inflated_view.xml new file mode 100644 index 0000000..bb5678a4 --- /dev/null +++ b/ui/android/junit/res/layout/inflated_view.xml
@@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> + +<TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/inflated_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + />
diff --git a/ui/android/junit/res/layout/main_view.xml b/ui/android/junit/res/layout/main_view.xml new file mode 100644 index 0000000..41549d83 --- /dev/null +++ b/ui/android/junit/res/layout/main_view.xml
@@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="horizontal" > + + <org.chromium.ui.AsyncViewStub + android:id="@+id/view_stub" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + /> + + <ImageView + android:id="@+id/pre_inflated_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + /> + +</LinearLayout>
diff --git a/ui/android/junit/src/org/chromium/ui/AsyncViewProviderTest.java b/ui/android/junit/src/org/chromium/ui/AsyncViewProviderTest.java new file mode 100644 index 0000000..17c07a0 --- /dev/null +++ b/ui/android/junit/src/org/chromium/ui/AsyncViewProviderTest.java
@@ -0,0 +1,130 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLooper; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.ui.shadows.ShadowAsyncLayoutInflater; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Tests logic in the AsyncViewProvider class. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowAsyncLayoutInflater.class}) +public class AsyncViewProviderTest { + private LinearLayout mRoot; + private AsyncViewStub mAsyncViewStub; + private AsyncViewProvider<View> mAsyncViewProvider; + private final AtomicInteger mEventCount = new AtomicInteger(); + private static final int MAIN_LAYOUT_RESOURCE_ID = org.chromium.test.ui.R.layout.main_view; + private static final int INFLATE_LAYOUT_RESOURCE_ID = + org.chromium.test.ui.R.layout.inflated_view; + private static final int STUB_ID = org.chromium.test.ui.R.id.view_stub; + private static final int INFLATED_VIEW_ID = org.chromium.test.ui.R.id.inflated_view; + private static final int PREINFLATED_VIEW_ID = org.chromium.test.ui.R.id.pre_inflated_view; + + @Before + public void setUp() { + mRoot = (LinearLayout) LayoutInflater.from(RuntimeEnvironment.application) + .inflate(MAIN_LAYOUT_RESOURCE_ID, null); + mAsyncViewStub = mRoot.findViewById(STUB_ID); + mAsyncViewStub.setLayoutResource(INFLATE_LAYOUT_RESOURCE_ID); + mAsyncViewProvider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID); + mAsyncViewStub.setId(STUB_ID); + mEventCount.set(0); + } + + @Test + public void testCreatesUnloadedProviderIfNotInflated() { + AsyncViewProvider provider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID); + assertNull(provider.get()); + } + + @Test + public void testCreatesLoadedProviderIfInflated() { + mAsyncViewStub.inflate(true); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + AsyncViewProvider provider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID); + assertNotNull(provider.get()); + } + + @Test + public void testCreatesUnloadedProviderUsingResourceIds() { + AsyncViewProvider provider = AsyncViewProvider.of(mRoot, STUB_ID, INFLATED_VIEW_ID); + assertNull(provider.get()); + } + + @Test + public void testCreatesLoadedProviderUsingResourceIds() { + mAsyncViewStub.inflate(true); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + AsyncViewProvider provider = AsyncViewProvider.of(mRoot, STUB_ID, INFLATED_VIEW_ID); + assertNotNull(provider.get()); + } + + @Test + public void testCreatesLoadedProviderUsingResourceIdsWithoutAsyncViewStub() { + AsyncViewProvider provider = AsyncViewProvider.of(mRoot, 0, PREINFLATED_VIEW_ID); + assertNotNull(provider.get()); + assertTrue(provider.get() instanceof ImageView); + } + + @Test + public void testRunsCallbackImmediatelyIfLoaded() { + mAsyncViewStub.inflate(true); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + AsyncViewProvider<View> provider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID); + assertEquals(mEventCount.get(), 0); + provider.whenLoaded((View v) -> { mEventCount.incrementAndGet(); }); + assertEquals(mEventCount.get(), 1); + provider.whenLoaded((View v) -> { mEventCount.incrementAndGet(); }); + assertEquals(mEventCount.get(), 2); + } + + @Test + public void testCallsListenersOnUiThread() { + mAsyncViewProvider.whenLoaded((View v) -> { + assertTrue(ThreadUtils.runningOnUiThread()); + mEventCount.incrementAndGet(); + }); + mAsyncViewStub.inflate(true); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + // ensure callback gets called. + assertEquals(mEventCount.get(), 1); + } + + @Test + public void testCallsListenersInOrder() { + mAsyncViewProvider.whenLoaded( + (View v) -> { assertEquals(mEventCount.incrementAndGet(), 1); }); + mAsyncViewProvider.whenLoaded( + (View v) -> { assertEquals(mEventCount.incrementAndGet(), 2); }); + mAsyncViewProvider.whenLoaded( + (View v) -> { assertEquals(mEventCount.decrementAndGet(), 1); }); + assertEquals(mEventCount.get(), 0); + mAsyncViewStub.inflate(true); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + assertEquals(mEventCount.get(), 1); + } +} \ No newline at end of file
diff --git a/ui/android/junit/src/org/chromium/ui/AsyncViewStubTest.java b/ui/android/junit/src/org/chromium/ui/AsyncViewStubTest.java new file mode 100644 index 0000000..4f343d8f --- /dev/null +++ b/ui/android/junit/src/org/chromium/ui/AsyncViewStubTest.java
@@ -0,0 +1,74 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLooper; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.ui.shadows.ShadowAsyncLayoutInflater; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Tests logic in the AsyncViewStub class. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowAsyncLayoutInflater.class}) +public class AsyncViewStubTest { + private AsyncViewStub mAsyncViewStub; + private final AtomicInteger mEventCount = new AtomicInteger(); + private static final int MAIN_LAYOUT_RESOURCE_ID = org.chromium.test.ui.R.layout.main_view; + private static final int INFLATE_LAYOUT_RESOURCE_ID = + org.chromium.test.ui.R.layout.inflated_view; + private static final int STUB_ID = org.chromium.test.ui.R.id.view_stub; + + @Before + public void setUp() { + LinearLayout mainView = (LinearLayout) LayoutInflater.from(RuntimeEnvironment.application) + .inflate(MAIN_LAYOUT_RESOURCE_ID, null); + mAsyncViewStub = mainView.findViewById(STUB_ID); + mAsyncViewStub.setLayoutResource(INFLATE_LAYOUT_RESOURCE_ID); + mEventCount.set(0); + } + + @Test + public void testCallsListenersOnUiThread() { + mAsyncViewStub.addOnInflateListener((View v) -> { + assertTrue(ThreadUtils.runningOnUiThread()); + mEventCount.incrementAndGet(); + }); + mAsyncViewStub.inflate(true); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + // ensure callback gets called. + assertEquals(mEventCount.get(), 1); + } + + @Test + public void testCallsListenersInOrder() { + mAsyncViewStub.addOnInflateListener( + (View v) -> { assertEquals(mEventCount.incrementAndGet(), 1); }); + mAsyncViewStub.addOnInflateListener( + (View v) -> { assertEquals(mEventCount.incrementAndGet(), 2); }); + mAsyncViewStub.addOnInflateListener( + (View v) -> { assertEquals(mEventCount.decrementAndGet(), 1); }); + assertEquals(mEventCount.get(), 0); + mAsyncViewStub.inflate(true); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + assertEquals(mEventCount.get(), 1); + } +} \ No newline at end of file
diff --git a/ui/android/junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java b/ui/android/junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java new file mode 100644 index 0000000..0eb8472 --- /dev/null +++ b/ui/android/junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java
@@ -0,0 +1,33 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.shadows; + +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.AsyncLayoutInflater; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +import org.chromium.base.ThreadUtils; + +/** + * Shadow implementation of AsyncLayoutInflater that inflates on the UI thread then posts the + * callback on the UI thread delayed. + */ +@Implements(AsyncLayoutInflater.class) +public class ShadowAsyncLayoutInflater { + @Implementation + public void inflate(@LayoutRes int resid, @Nullable ViewGroup parent, + @NonNull AsyncLayoutInflater.OnInflateFinishedListener callback) { + View inflatedView = LayoutInflater.from(parent.getContext()).inflate(resid, parent, false); + ThreadUtils.postOnUiThreadDelayed( + () -> callback.onInflateFinished(inflatedView, inflatedView.getId(), parent), 500); + } +} \ No newline at end of file
diff --git a/ui/aura/client/screen_position_client.h b/ui/aura/client/screen_position_client.h index a302d1c9..24e22be 100644 --- a/ui/aura/client/screen_position_client.h +++ b/ui/aura/client/screen_position_client.h
@@ -53,7 +53,7 @@ AURA_EXPORT ScreenPositionClient* GetScreenPositionClient( const Window* root_window); -} // namespace clients +} // namespace client } // namespace aura #endif // UI_AURA_SCREEN_POSITION_CLIENT_H_
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index 9786d36..47e7e52 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -1104,13 +1104,10 @@ InFlightBoundsChange bounds_change(this, window, bounds, local_surface_id); InFlightChange* current_change = GetOldestInFlightChangeMatching(bounds_change); - if (current_change) { + if (current_change) current_change->SetRevertValueFrom(bounds_change); - } else { - const gfx::Rect& window_bounds = window->GetWindow()->bounds(); - if (window_bounds != bounds) - SetWindowBoundsFromServer(window, bounds, local_surface_id); - } + else if (window->GetWindow()->GetBoundsInScreen() != bounds) + SetWindowBoundsFromServer(window, bounds, local_surface_id); } // There is currently no API to bulk set properties, so we iterate over each
diff --git a/ui/aura/mus/window_tree_host_mus_init_params.cc b/ui/aura/mus/window_tree_host_mus_init_params.cc index a882d81..6c876d4 100644 --- a/ui/aura/mus/window_tree_host_mus_init_params.cc +++ b/ui/aura/mus/window_tree_host_mus_init_params.cc
@@ -61,9 +61,8 @@ params.display_id = display::Screen::GetScreen()->GetDisplayMatching(bounds_in_screen).id(); } else { - // TODO(jamescook): This should probably be the display for new windows, - // but that information isn't available at this level. - params.display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + params.display_id = + display::Screen::GetScreen()->GetDisplayForNewWindows().id(); } // Pass |properties| to CreateWindowPortForTopLevel() so that |properties|
diff --git a/ui/aura/window_targeter.cc b/ui/aura/window_targeter.cc index c40ef77..fbf6f6f 100644 --- a/ui/aura/window_targeter.cc +++ b/ui/aura/window_targeter.cc
@@ -8,10 +8,13 @@ #include "ui/aura/client/capture_client.h" #include "ui/aura/client/event_client.h" #include "ui/aura/client/focus_client.h" +#include "ui/aura/client/screen_position_client.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_tree_host.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" #include "ui/events/event_target.h" #include "ui/events/event_target_iterator.h" @@ -120,8 +123,16 @@ if (consumer) return static_cast<Window*>(consumer); - // If the initial touch is outside the root window, target the root. - if (!root_window->bounds().Contains(event.root_location())) + // If the initial touch is outside the window's display, target the root. + // This is used for bezel gesture events (eg. swiping in from screen edge). + display::Display display = + display::Screen::GetScreen()->GetDisplayNearestWindow(root_window); + gfx::Point screen_location = event.root_location(); + if (client::GetScreenPositionClient(root_window)) { + client::GetScreenPositionClient(root_window) + ->ConvertPointToScreen(root_window, &screen_location); + } + if (!display.bounds().Contains(screen_location)) return root_window; }
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn index 73c038e3..319c2bd 100644 --- a/ui/file_manager/BUILD.gn +++ b/ui/file_manager/BUILD.gn
@@ -47,3 +47,9 @@ "video_player/js/cast:closure_compile", ] } + +group("unit_test_data") { + deps = [ + "gallery/js/image_editor:unit_tests", + ] +}
diff --git a/ui/file_manager/file_manager/foreground/js/directory_contents.js b/ui/file_manager/file_manager/foreground/js/directory_contents.js index ec78ae0..4807d02 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_contents.js +++ b/ui/file_manager/file_manager/foreground/js/directory_contents.js
@@ -429,6 +429,7 @@ */ this.lastHostedFilesDisabled_ = null; + this.hideAndroidDownload(); chrome.fileManagerPrivate.onPreferencesChanged.addListener( this.onPreferencesChanged_.bind(this)); this.onPreferencesChanged_(); @@ -535,6 +536,23 @@ }; /** + * Sets up a filter to hide /Download directory in 'Play files' volume. + * + * "Play files/Download" is an alias to Chrome OS's Downloads volume. It is + * convenient in Android file picker, but can be confusing in Chrome OS Files + * app. This function adds a filter to hide the Android's /Download. + */ +FileFilter.prototype.hideAndroidDownload = function() { + this.addFilter('android_download', entry => { + if (entry.filesystem && entry.filesystem.name === 'android_files' && + entry.fullPath === '/Download') { + return false; + } + return true; + }); +}; + +/** * @param {Entry} entry File entry. * @return {boolean} True if the file should be shown, false otherwise. */
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_dispatcher_mock_deps.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_dispatcher_mock_deps.js new file mode 100644 index 0000000..ebea153 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_dispatcher_mock_deps.js
@@ -0,0 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// importScripts is used in metadata_dispatcher.js which is designed to work +// inside SharedWorker. +function importScripts(arg1) {}
diff --git a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js index 1fb63e7..2dede3f 100644 --- a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js +++ b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js
@@ -135,6 +135,7 @@ VolumeManagerCommon.VolumeType.REMOVABLE, VolumeManagerCommon.VolumeType.ANDROID_FILES, VolumeManagerCommon.VolumeType.CROSTINI, + VolumeManagerCommon.VolumeType.MEDIA_VIEW, ]; /**
diff --git a/ui/file_manager/gallery/js/image_editor/BUILD.gn b/ui/file_manager/gallery/js/image_editor/BUILD.gn index 9a2e4a9..52fffc9 100644 --- a/ui/file_manager/gallery/js/image_editor/BUILD.gn +++ b/ui/file_manager/gallery/js/image_editor/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//ui/file_manager/js_unit_tests.gni") js_type_check("closure_compile") { deps = [ @@ -75,6 +76,7 @@ js_library("exif_encoder_unittest") { deps = [ ":exif_encoder", + ":test_util", "../../../file_manager/foreground/js/metadata:exif_parser", ] } @@ -145,6 +147,7 @@ js_library("image_encoder_unittest") { deps = [ ":image_encoder", + ":test_util", "../../../file_manager/common/js:unittest_util", "../../../file_manager/foreground/js/metadata:metadata_parser", ] @@ -216,3 +219,12 @@ "//ui/webui/resources/js/cr:event_target", ] } + +js_unit_tests("unit_tests") { + deps = [ + ":exif_encoder_unittest", + ":image_encoder_unittest", + ":image_view_unittest", + ] + mocks = [ "../../../file_manager/foreground/js/metadata/metadata_dispatcher_mock_deps.js" ] +}
diff --git a/ui/file_manager/gallery/js/image_editor/exif_encoder_unittest.html b/ui/file_manager/gallery/js/image_editor/exif_encoder_unittest.html deleted file mode 100644 index 3016f41..0000000 --- a/ui/file_manager/gallery/js/image_editor/exif_encoder_unittest.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!DOCTYPE html> -<!-- Copyright 2014 The Chromium Authors. All rights reserved. - -- Use of this source code is governed by a BSD-style license that can be - -- found in the LICENSE file. - --> -<html> -<body> - -<script type="text/javascript"> - // importScripts is used in metadata_dispatcher.js which is designed to work inside SharedWorker. - function importScripts(arg1) {} -</script> -<script src="../../../../webui/resources/js/assert.js"></script> - -<script src="../../../file_manager/foreground/js/metadata/byte_reader.js"></script> -<script src="../../../file_manager/foreground/js/metadata/metadata_parser.js"></script> -<script src="../../../file_manager/foreground/js/metadata/metadata_dispatcher.js"></script> -<script src="../../../file_manager/foreground/js/metadata/exif_parser.js"></script> -<script src="../../../file_manager/foreground/js/metadata/exif_constants.js"></script> - -<script src="image_encoder.js"></script> -<script src="exif_encoder.js"></script> - -<script src="test_util.js"></script> -<script src="exif_encoder_unittest.js"></script> - -</body> -</html>
diff --git a/ui/file_manager/gallery/js/image_editor/image_encoder_unittest.html b/ui/file_manager/gallery/js/image_editor/image_encoder_unittest.html deleted file mode 100644 index 0a527331..0000000 --- a/ui/file_manager/gallery/js/image_editor/image_encoder_unittest.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<!-- Copyright 2014 The Chromium Authors. All rights reserved. - -- Use of this source code is governed by a BSD-style license that can be - -- found in the LICENSE file. - --> -<html> -<body> - -<script src="../../../../webui/resources/js/assert.js"></script> - -<script src="../../../file_manager/common/js/unittest_util.js"></script> - -<script src="image_util.js"></script> -<script src="image_encoder.js"></script> - -<script src="test_util.js"></script> -<script src="image_encoder_unittest.js"></script> - -</body> -</html>
diff --git a/ui/file_manager/gallery/js/image_editor/image_view_unittest.html b/ui/file_manager/gallery/js/image_editor/image_view_unittest.html deleted file mode 100644 index f2a9eae..0000000 --- a/ui/file_manager/gallery/js/image_editor/image_view_unittest.html +++ /dev/null
@@ -1,48 +0,0 @@ -<!DOCTYPE html> -<!-- Copyright 2014 The Chromium Authors. All rights reserved. - -- Use of this source code is governed by a BSD-style license that can be - -- found in the LICENSE file. - --> -<html> -<body> - -<!-- Should be loaded before volume_manager.js --> -<script src="../../file_manager/common/js/volume_manager_common.js"></script> - -<!-- Viewport deps --> -<script src="../../../../webui/resources/js/assert.js"></script> -<script src="../../../../webui/resources/js/cr.js"></script> -<script src="../../../../webui/resources/js/cr/event_target.js"></script> - -<!-- MetadataModel deps --> -<script src="../../../file_manager/foreground/js/metadata/metadata_cache_set.js"></script> -<script src="../../../common/js/lru_cache.js"></script> -<script src="../../../common/js/unittest_util.js"></script> -<script src="../../../common/js/util.js"></script> -<script src="../../../file_manager/foreground/js/metadata/metadata_cache_item.js"></script> -<script src="../../../file_manager/foreground/js/metadata/metadata_item.js"></script> -<script src="../../../file_manager/foreground/js/metadata/metadata_model.js"></script> -<script src="../../../file_manager/foreground/js/metadata/metadata_provider.js"></script> -<script src="../../../file_manager/foreground/js/metadata/metadata_request.js"></script> - -<!-- Metrics deps --> -<script src="../../../file_manager/test/js/chrome_api_test_impl.js"></script> -<script src="../../../file_manager/common/js/metrics_base.js"></script> -<script src="../../../file_manager/common/js/metrics.js"></script> -<script src="../../../file_manager/foreground/js/metrics_start.js"></script> - -<!-- Others --> -<script src="../../../file_manager/common/js/file_type.js"></script> -<script src="../../../file_manager/common/js/mock_entry.js"></script> -<script src="../../../file_manager/foreground/js/thumbnail_loader.js"></script> - -<script src="../gallery_item.js"></script> -<script src="viewport.js"></script> -<script src="image_buffer.js"></script> -<script src="image_util.js"></script> -<script src="image_loader.js"></script> -<script src="image_view.js"></script> -<script src="image_view_unittest.js"></script> - -</body> -</html>
diff --git a/ui/file_manager/integration_tests/file_manager/delete.js b/ui/file_manager/integration_tests/file_manager/delete.js index 873f5b4..684672f 100644 --- a/ui/file_manager/integration_tests/file_manager/delete.js +++ b/ui/file_manager/integration_tests/file_manager/delete.js
@@ -6,25 +6,25 @@ * Tests that the Delete menu item is disabled if no entry is selected. */ testcase.deleteMenuItemNoEntrySelected = function() { + const contextMenu = '#file-context-menu:not([hidden])'; + testPromise(setupAndWaitUntilReady(null, RootPath.DOWNLOADS).then( function(results) { var windowId = results.windowId; - // Right click the list without selecting an item. - return remoteCall.callRemoteTestUtil( - 'fakeMouseRightClick', windowId, ['list.list'] - ).then(function(result) { - chrome.test.assertTrue(result); - - // Wait until the context menu is shown. - return remoteCall.waitForElement( - windowId, - '#file-context-menu:not([hidden])'); - }).then(function() { - // Assert that delete command is disabled. - return remoteCall.waitForElement( - windowId, - 'cr-menu-item[command="#delete"][disabled="disabled"]'); - }); + // Right click the list without selecting an entry. + return remoteCall + .callRemoteTestUtil('fakeMouseRightClick', windowId, ['list.list']) + .then(function(result) { + chrome.test.assertTrue(!!result, 'fakeMouseRightClick failed'); + // Wait until the context menu is shown. + return remoteCall.waitForElement(windowId, contextMenu); + }) + .then(function() { + // Assert the menu delete command is disabled. + const deleteDisabled = '[command="#delete"][disabled="disabled"]'; + return remoteCall.waitForElement( + windowId, contextMenu + ' ' + deleteDisabled); + }); })); }; @@ -51,35 +51,36 @@ function(results) { var windowId = results.windowId; // Confirm entries in the directory before the deletion. - // - // Ignore last modified time since file manager sometimes fails to get - // last modified time of files. - // TODO(yawano): Fix the root cause and remove this temporary fix. - return remoteCall.waitForFiles(windowId, beforeDeletion, - {ignoreLastModifiedTime: true}).then(function() { - // Select My Desktop Background.png - return remoteCall.callRemoteTestUtil( - 'selectFile', windowId, ['My Desktop Background.png']); - }).then(function(result) { - chrome.test.assertTrue(result); - - // Click delete button in the toolbar. - return remoteCall.callRemoteTestUtil( - 'fakeMouseClick', windowId, ['button#delete-button']); - }).then(function(result) { - chrome.test.assertTrue(result); - - // Confirm that the confirmation dialog is shown. - return remoteCall.waitForElement( - windowId, '.cr-dialog-container.shown'); - }).then(function() { - // Press delete button. - return remoteCall.callRemoteTestUtil( - 'fakeMouseClick', windowId, ['button.cr-dialog-ok']); - }).then(function() { - // Confirm the file is removed. - return remoteCall.waitForFiles(windowId, afterDeletion, - {ignoreLastModifiedTime: true}); - }); + return remoteCall + .waitForFiles( + windowId, beforeDeletion, {ignoreLastModifiedTime: true}) + .then(function() { + // Select My Desktop Background.png + return remoteCall.callRemoteTestUtil( + 'selectFile', windowId, ['My Desktop Background.png']); + }) + .then(function(result) { + chrome.test.assertTrue(result); + // Click delete button in the toolbar. + return remoteCall.callRemoteTestUtil( + 'fakeMouseClick', windowId, ['button#delete-button']); + }) + .then(function(result) { + chrome.test.assertTrue(result); + // Confirm that the confirmation dialog is shown. + return remoteCall.waitForElement( + windowId, '.cr-dialog-container.shown'); + }) + .then(function() { + // Press delete button. + return remoteCall.callRemoteTestUtil( + 'fakeMouseClick', windowId, ['button.cr-dialog-ok']); + }) + .then(function(result) { + chrome.test.assertTrue(!!result, 'fakeMouseClick failed'); + // Confirm the file is removed. + return remoteCall.waitForFiles( + windowId, afterDeletion, {ignoreLastModifiedTime: true}); + }); })); };
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js index 08da11a..86a90e0 100644 --- a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js +++ b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
@@ -121,19 +121,23 @@ * Clicks context menu item of id in directory tree. */ function clickDirectoryTreeContextMenuItem(windowId, path, id) { + const contextMenu = '#directory-tree-context-menu:not([hidden])'; + return remoteCall.callRemoteTestUtil('focus', windowId, - [`[full-path-for-testing="${path}"]`]).then(function() { + [`[full-path-for-testing="${path}"]`]).then(function(result) { + chrome.test.assertTrue(!!result, 'focus failed'); // Right click photos directory. return remoteCall.callRemoteTestUtil('fakeMouseRightClick', windowId, [`[full-path-for-testing="${path}"]`]); - }).then(function() { - // Wait for context menu. + }).then(function(result) { + chrome.test.assertTrue(!!result, 'fakeMouseRightClick failed'); + // Check: context menu item |id| should be shown enabled. return remoteCall.waitForElement(windowId, - `#directory-tree-context-menu > [command="#${id}"]:not([disabled])`); + `${contextMenu} [command="#${id}"]:not([disabled])`); }).then(function() { - // Click menu item. + // Click the menu item specified by |id|. return remoteCall.callRemoteTestUtil('fakeMouseClick', windowId, - [`#directory-tree-context-menu > [command="#${id}"]`]); + [`${contextMenu} [command="#${id}"]`]); }); }
diff --git a/ui/file_manager/integration_tests/file_manager/share_and_manage_dialog.js b/ui/file_manager/integration_tests/file_manager/share_and_manage_dialog.js index 6657ab6..0102473 100644 --- a/ui/file_manager/integration_tests/file_manager/share_and_manage_dialog.js +++ b/ui/file_manager/integration_tests/file_manager/share_and_manage_dialog.js
@@ -23,61 +23,37 @@ }, // Wait for the share button. function(result) { - chrome.test.assertTrue(result); + chrome.test.assertTrue(!!result); remoteCall.waitForElement(appId, '#share-menu-button:not([disabled])') .then(this.next); }, - // Open share options menu + // Click the share button to open share menu. function(result) { chrome.test.assertTrue(!!result); remoteCall.callRemoteTestUtil( 'fakeMouseClick', appId, ['#share-menu-button'], this.next); }, - // Wait until the "Share with others" item is shown. - function(result) { - chrome.test.assertTrue(result); - remoteCall - .waitForElement( - appId, 'cr-menu-item[command="#share"]:not([disabled]') - .then(this.next); - }, - // Invoke the share dialog. + // Check: the "Share with others" menu item should be shown enabled. function(result) { chrome.test.assertTrue(!!result); - remoteCall.callRemoteTestUtil( - 'fakeMouseClick', appId, ['cr-menu-item[command="#share"]'], - this.next); + const shareMenuItem = + '#share-menu:not([hidden]) [command="#share"]:not([disabled])'; + remoteCall.waitForElement(appId, shareMenuItem).then(this.next); }, - // Wait until the share dialog's contents are shown. + // Click the "Share with others" menu item to open the share dialog. function(result) { - chrome.test.assertTrue(result); + chrome.test.assertTrue(!!result); + const item = ['#share-menu [command="#share"]']; + remoteCall.callRemoteTestUtil('fakeMouseClick', appId, item, this.next); + }, + // Wait until the share dialog's (mocked) content is shown. + function(result) { + chrome.test.assertTrue(!!result); remoteCall.waitForElement(appId, '.share-dialog-webview-wrapper.loaded') .then(this.next); }, - function(result) { - chrome.test.assertTrue(!!result); - repeatUntil(function() { - return remoteCall - .callRemoteTestUtil( - 'queryAllElements', appId, - ['.share-dialog-webview-wrapper.loaded', ['width', 'height']]) - .then(function(elements) { - // TODO(mtomasz): Fix the wrong geometry of the share dialog. - // return elements[0] && - // elements[0].styles.width === '350px' && - // elements[0].styles.height === '250px' ? - // undefined : - // pending('Dialog wrapper is currently %j. ' + - // 'but should be: 350x250', - // elements[0]); - return elements[0] ? - undefined : - pending(caller, 'The share dialog is not found.'); - }); - }).then(this.next); - }, // Wait until the share dialog's contents are shown. - function(result) { + function() { remoteCall.callRemoteTestUtil( 'executeScriptInWebView', appId, [ @@ -122,7 +98,7 @@ }, // Wait for the file to be selected. function(result) { - chrome.test.assertTrue(result); + chrome.test.assertTrue(!!result); remoteCall.waitForElement(appId, '.table-row[selected]').then(this.next); }, // Right-click on the file. @@ -133,7 +109,7 @@ }, // Wait for the context menu to appear. function(result) { - chrome.test.assertTrue(result); + chrome.test.assertTrue(!!result); remoteCall.waitForElement(appId, '#file-context-menu:not([hidden])') .then(this.next); },
diff --git a/ui/file_manager/integration_tests/file_manager/tasks.js b/ui/file_manager/integration_tests/file_manager/tasks.js index ff29903..dce4de1 100644 --- a/ui/file_manager/integration_tests/file_manager/tasks.js +++ b/ui/file_manager/integration_tests/file_manager/tasks.js
@@ -194,13 +194,14 @@ 'fakeMouseClick', windowId, ['#tasks']); // Wait for dropdown menu to show. return remoteCall.waitForElement( - windowId, '#tasks-menu cr-menu-item'); + windowId, '#tasks-menu:not([hidden]) cr-menu-item'); }) .then(function(result) { + chrome.test.assertTrue(!!result); // Click on first menu item. remoteCall.callRemoteTestUtil( 'fakeMouseClick', windowId, - ['#tasks-menu cr-menu-item:nth-child(1)']); + ['#tasks-menu:not([hidden]) cr-menu-item:nth-child(1)']); // Wait dropdown menu to hide. return remoteCall.waitForElement(windowId, '#tasks-menu[hidden]'); })
diff --git a/ui/file_manager/integration_tests/file_manager/zip_files.js b/ui/file_manager/integration_tests/file_manager/zip_files.js index 9c014f2..b311ba2 100644 --- a/ui/file_manager/integration_tests/file_manager/zip_files.js +++ b/ui/file_manager/integration_tests/file_manager/zip_files.js
@@ -186,7 +186,8 @@ remoteCall.callRemoteTestUtil('fakeMouseClick', appId, [zip], this.next); }, // Check: a zip file should be created. - function() { + function(result) { + chrome.test.assertTrue(!!result, 'fakeMouseClick failed'); const files = getZipSelectionFileListRowEntries(); remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}) .then(this.next); @@ -233,7 +234,8 @@ remoteCall.callRemoteTestUtil('fakeMouseClick', appId, [zip], this.next); }, // Check: a zip file should be created. - function() { + function(result) { + chrome.test.assertTrue(!!result, 'fakeMouseClick failed'); const files = getZipSelectionFileListRowEntries(); remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}) .then(this.next); @@ -305,7 +307,8 @@ remoteCall.callRemoteTestUtil('fakeMouseClick', appId, [zip], this.next); }, // Check: a zip file should be created. - function() { + function(result) { + chrome.test.assertTrue(!!result, 'fakeMouseClick failed'); const files = getZipSelectionFileListRowEntries(); remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true}) .then(this.next);
diff --git a/ui/file_manager/js_unit_test.py b/ui/file_manager/js_unit_test.py new file mode 100644 index 0000000..351882f6 --- /dev/null +++ b/ui/file_manager/js_unit_test.py
@@ -0,0 +1,78 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +This script takes in a file created by js_library.py and any supplementary js +files to build an html file used for js unit tests. +""" + +from argparse import ArgumentParser + +def flatten(deps): + """ + Recursively follows a list of dep files and returns source files in + dependency order. Ignores externs. + """ + if len(deps) == 0: + return [] + sources = [] + moredeps = [] + for d in deps: + with open(d, "r") as depfile: + assert depfile.readline( + ) == 'sources:\n', "Depfile parse error (expected 'sources:')." + line = depfile.readline() + while line != 'deps:\n': + assert line != '', "Depfile parse error (expected 'deps:')." + sources.append(line[:-1]) + line = depfile.readline() + line = depfile.readline() + while line != 'externs:\n': + assert line != '', "Depfile parse error (expected 'externs:')." + moredeps.append(line[:-1]) + line = depfile.readline() + return flatten(moredeps) + sources + +def main(): + parser = ArgumentParser() + parser.add_argument('-i', '--input', + help='Input dependency file generated by js_library.py') + parser.add_argument('-m', '--mocks', nargs='*', default=[], + help='List of additional js files to load before others') + parser.add_argument('-o', '--output', + help='Generated html output with flattened dependencies') + args = parser.parse_args() + + alldeps = flatten([args.input]) + uniquedeps = [] + # No such thing as include guards, so do that here with a set. + seen = set() + for d in alldeps: + if d not in seen: + seen.add(d) + uniquedeps.append(d) + with open(args.output, 'w') as out: + out.write('<!DOCTYPE html>\n<html>\n<body>\n') + out.write( +""" +<script> +// Basic include checker. +window.addEventListener('error', function(e) { + if ((e.target instanceof HTMLScriptElement)) { + console.log('ERROR loading <script> element (does it exist?):\\n\\t' + + e.srcElement.src + '\\n\\tIncluded from: ' + + e.srcElement.baseURI); + } +}, true /* useCapture */); +</script> + +""") + for file in args.mocks: + out.write('<script src="%s"></script>\n' % (file)) + for file in uniquedeps: + out.write('<script src="%s"></script>\n' % (file)) + out.write('</body>\n</html>\n') + +if __name__ == '__main__': + main()
diff --git a/ui/file_manager/js_unit_tests.gni b/ui/file_manager/js_unit_tests.gni new file mode 100644 index 0000000..0e4fc30 --- /dev/null +++ b/ui/file_manager/js_unit_tests.gni
@@ -0,0 +1,58 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Describes a list of js_library targets that will each have an html file +# written listing all its (flattened) js dependencies, for loading as a test. +# Must be declared after the js_library targets it depends on. +# +# Variables: +# deps: +# List of js_library targets to depend on +# +# mocks: +# An optional list of .js files to load before any other scripts +# +# Example: +# js_unit_tests("folder_tests") { +# deps = [ +# ":foo_unittest", +# ":bar_unittest", +# ":baz_unittest", +# ] +# mocks = [ "my_mocks.js" ] +# } + +template("js_unit_tests") { + html_gen_target_name = target_name + "_html_gen" + action_foreach(html_gen_target_name) { + script_path = "//ui/file_manager" + script = "$script_path/js_unit_test.py" + forward_variables_from(invoker, + [ + "deps", + "mocks", + ]) + sources = [] + foreach(dep, deps) { + sources += get_target_outputs(dep) + } + + outputs = [ + "$target_gen_dir/{{source_name_part}}.html", + ] + args = [ "--output" ] + rebase_path(outputs, root_build_dir) + args += [ "--input" ] + [ "{{source}}" ] + + if (defined(mocks)) { + args += [ "--mocks" ] + rebase_path(mocks, root_build_dir) + data = mocks + } + } + group(target_name) { + data = get_target_outputs(":$html_gen_target_name") + deps = [ + ":$html_gen_target_name", + ] + } +}
diff --git a/ui/gfx/color_utils.cc b/ui/gfx/color_utils.cc index 3c7f114..c4ae1e2 100644 --- a/ui/gfx/color_utils.cc +++ b/ui/gfx/color_utils.cc
@@ -188,6 +188,12 @@ hsl->l = -1; } +bool IsHSLShiftMeaningful(const HSL& hsl) { + // -1 in any channel is no-op, but additionally 0.5 is no-op for S/L. + return hsl.h != -1 && hsl.s != -1 && hsl.s != 0.5 && hsl.l != -1 && + hsl.l != 0.5; +} + SkColor HSLShift(SkColor color, const HSL& shift) { SkAlpha alpha = SkColorGetA(color);
diff --git a/ui/gfx/color_utils.h b/ui/gfx/color_utils.h index 35d2748..747ecbb 100644 --- a/ui/gfx/color_utils.h +++ b/ui/gfx/color_utils.h
@@ -64,6 +64,10 @@ // special value which indicates 'no change'. GFX_EXPORT void MakeHSLShiftValid(HSL* hsl); +// Returns whether pasing |hsl| to HSLShift() would have any effect. Assumes +// |hsl| is a valid shift (as defined by MakeHSLShiftValid()). +GFX_EXPORT bool IsHSLShiftMeaningful(const HSL& hsl); + // HSL-Shift an SkColor. The shift values are in the range of 0-1, with the // option to specify -1 for 'no change'. The shift values are defined as: // hsl_shift[0] (hue): The absolute hue value - 0 and 1 map
diff --git a/ui/gfx/mac/display_icc_profiles.cc b/ui/gfx/mac/display_icc_profiles.cc index 45bbb4b..3e0c359 100644 --- a/ui/gfx/mac/display_icc_profiles.cc +++ b/ui/gfx/mac/display_icc_profiles.cc
@@ -35,6 +35,7 @@ void DisplayICCProfiles::UpdateIfNeeded() { if (!needs_update_) return; + needs_update_ = false; map_.clear(); // Always add Apple's sRGB profile.
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index 76fac948..1d4f863 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -780,6 +780,9 @@ } gfx::Rect KeyboardController::GetWorkspaceOccludedBounds() const { + if (!enabled()) + return gfx::Rect(); + const gfx::Rect visual_bounds_in_window(visual_bounds_in_screen_.size()); const gfx::Rect occluded_bounds_in_window = container_behavior_->GetOccludedBounds(visual_bounds_in_window);
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc index 607ba7c4..f68c257 100644 --- a/ui/message_center/views/message_popup_collection.cc +++ b/ui/message_center/views/message_popup_collection.cc
@@ -44,6 +44,8 @@ return; base::AutoReset<bool> reset(&is_updating_, true); + RemoveClosedPopupItems(); + if (animation_->is_animating()) { UpdateByAnimation(); return; @@ -93,6 +95,7 @@ { base::AutoReset<bool> reset(&is_updating_, true); + RemoveClosedPopupItems(); ResetHotMode(); state_ = State::IDLE; animation_->End(); @@ -118,6 +121,13 @@ Update(); } +void MessagePopupCollection::NotifyPopupClosed(MessagePopupView* popup) { + for (auto& item : popup_items_) { + if (item.popup == popup) + item.popup = nullptr; + } +} + void MessagePopupCollection::OnNotificationAdded( const std::string& notification_id) { Update(); @@ -131,6 +141,8 @@ void MessagePopupCollection::OnNotificationUpdated( const std::string& notification_id) { + RemoveClosedPopupItems(); + // Find Notification object with |notification_id|. const auto& notifications = MessageCenter::Get()->GetPopupNotifications(); auto it = notifications.begin(); @@ -462,7 +474,6 @@ if (!item.is_animating) continue; item.popup->Close(); - item.popup = nullptr; } RemoveClosedPopupItems(); } @@ -473,7 +484,6 @@ if (item.popup->GetOpacity() > 0.0) continue; item.popup->Close(); - item.popup = nullptr; removed = true; } RemoveClosedPopupItems(); @@ -486,7 +496,6 @@ if (work_area.Contains(item.bounds)) continue; item.popup->Close(); - item.popup = nullptr; } RemoveClosedPopupItems(); }
diff --git a/ui/message_center/views/message_popup_collection.h b/ui/message_center/views/message_popup_collection.h index 4d6faa82..2b05ea8d 100644 --- a/ui/message_center/views/message_popup_collection.h +++ b/ui/message_center/views/message_popup_collection.h
@@ -43,6 +43,9 @@ // Notify the popup size is changed. Called from MessagePopupView. void NotifyPopupResized(); + // Notify the popup is closed. Called from MessagePopupView. + void NotifyPopupClosed(MessagePopupView* popup); + // MessageCenterObserver: void OnNotificationAdded(const std::string& notification_id) override; void OnNotificationRemoved(const std::string& notification_id,
diff --git a/ui/message_center/views/message_popup_collection_unittest.cc b/ui/message_center/views/message_popup_collection_unittest.cc index 73dad0e4..b5046bd 100644 --- a/ui/message_center/views/message_popup_collection_unittest.cc +++ b/ui/message_center/views/message_popup_collection_unittest.cc
@@ -902,4 +902,19 @@ EXPECT_TRUE(work_area().Contains(r1)); } +TEST_F(MessagePopupCollectionTest, PopupWidgetClosedOutsideDuringFadeOut) { + std::string id = AddNotification(); + AnimateUntilIdle(); + + MessageCenter::Get()->MarkSinglePopupAsShown(id, false); + AnimateToMiddle(); + + // On Windows it might be possible that the widget is closed outside + // MessagePopupCollection? https://crbug.com/871199 + GetPopup(id)->GetWidget()->CloseNow(); + AnimateToEnd(); + + EXPECT_FALSE(IsAnimating()); +} + } // namespace message_center
diff --git a/ui/message_center/views/message_popup_view.cc b/ui/message_center/views/message_popup_view.cc index 774e063..06454c3 100644 --- a/ui/message_center/views/message_popup_view.cc +++ b/ui/message_center/views/message_popup_view.cc
@@ -62,26 +62,40 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); } -MessagePopupView::~MessagePopupView() = default; +MessagePopupView::~MessagePopupView() { + popup_collection_->NotifyPopupClosed(this); +} void MessagePopupView::UpdateContents(const Notification& notification) { + ui::AXNodeData old_data; + message_view_->GetAccessibleNodeData(&old_data); message_view_->UpdateWithNotification(notification); popup_collection_->NotifyPopupResized(); if (notification.rich_notification_data() .should_make_spoken_feedback_for_popup_updates) { - NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); + ui::AXNodeData new_data; + message_view_->GetAccessibleNodeData(&new_data); + if (old_data.GetStringAttribute(ax::mojom::StringAttribute::kName) != + new_data.GetStringAttribute(ax::mojom::StringAttribute::kName)) + NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); } } float MessagePopupView::GetOpacity() const { + if (!GetWidget() || GetWidget()->IsClosed()) + return 0.f; return GetWidget()->GetLayer()->opacity(); } void MessagePopupView::SetPopupBounds(const gfx::Rect& bounds) { + if (!GetWidget() || GetWidget()->IsClosed()) + return; GetWidget()->SetBounds(bounds); } void MessagePopupView::SetOpacity(float opacity) { + if (!GetWidget() || GetWidget()->IsClosed()) + return; GetWidget()->SetOpacity(opacity); } @@ -170,7 +184,7 @@ void MessagePopupView::OnWorkAreaChanged() { views::Widget* widget = GetWidget(); - if (!widget) + if (!widget || widget->IsClosed()) return; gfx::NativeView native_view = widget->GetNativeView();
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc index c298ac455..6c8dd7e 100644 --- a/ui/message_center/views/message_view.cc +++ b/ui/message_center/views/message_view.cc
@@ -74,7 +74,14 @@ // Create the opaque background that's above the view's shadow. background_view_ = new views::View(); - UpdateCornerRadius(0, 0); + + // ChromeOS rounds the corners of the message view. TODO(estade): should we do + // this for all platforms? + if (ShouldRoundMessageViewCorners()) + UpdateCornerRadius(kNotificationCornerRadius, kNotificationCornerRadius); + else + UpdateCornerRadius(0, 0); + AddChildView(background_view_); focus_painter_ = views::Painter::CreateSolidFocusPainter( @@ -246,16 +253,6 @@ // Background. background_view_->SetBoundsRect(content_bounds); - - // ChromeOS rounds the corners of the message view. TODO(estade): should we do - // this for all platforms? - if (ShouldRoundMessageViewCorners()) { - gfx::Path path; - constexpr SkScalar kCornerRadius = SkIntToScalar(kNotificationCornerRadius); - path.addRoundRect(gfx::RectToSkRect(background_view_->GetLocalBounds()), - kCornerRadius, kCornerRadius); - background_view_->set_clip_path(path); - } } const char* MessageView::GetClassName() const {
diff --git a/ui/views/cocoa/bridged_native_widget.h b/ui/views/cocoa/bridged_native_widget.h index 674a9b7..827da47 100644 --- a/ui/views/cocoa/bridged_native_widget.h +++ b/ui/views/cocoa/bridged_native_widget.h
@@ -13,11 +13,9 @@ #import "base/mac/scoped_nsobject.h" #include "base/macros.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" -#import "ui/accelerated_widget_mac/accelerated_widget_mac.h" #include "ui/accelerated_widget_mac/ca_transaction_observer.h" #include "ui/accelerated_widget_mac/display_ca_layer_tree.h" #include "ui/base/ime/input_method_delegate.h" -#include "ui/compositor/layer_owner.h" #import "ui/views/cocoa/bridged_native_widget_owner.h" #import "ui/views/cocoa/cocoa_mouse_capture_delegate.h" #import "ui/views/focus/focus_manager.h" @@ -31,7 +29,6 @@ namespace ui { class InputMethod; -class RecyclableCompositorMac; } namespace views { @@ -39,6 +36,7 @@ class BridgedNativeWidgetTestApi; } +class BridgedNativeWidgetHost; class CocoaMouseCapture; class CocoaWindowMoveLoop; class DragDropClientMac; @@ -50,12 +48,9 @@ // NativeWidgetMac to the Cocoa window. Behaves a bit like an aura::Window. class VIEWS_EXPORT BridgedNativeWidget : public ui::CATransactionCoordinator::PreCommitObserver, - public ui::LayerDelegate, - public ui::LayerOwner, public ui::internal::InputMethodDelegate, public CocoaMouseCaptureDelegate, public FocusChangeListener, - public ui::AcceleratedWidgetMacNSView, public BridgedNativeWidgetOwner, public DialogObserver { public: @@ -75,8 +70,8 @@ static gfx::Size GetWindowSizeForClientSize(NSWindow* window, const gfx::Size& size); - // Creates one side of the bridge. |parent| must not be NULL. - explicit BridgedNativeWidget(NativeWidgetMac* parent); + // Creates one side of the bridge. |host| and |parent| must not be NULL. + BridgedNativeWidget(BridgedNativeWidgetHost* host, NativeWidgetMac* parent); ~BridgedNativeWidget() override; // Initialize the bridge, "retains" ownership of |window|. @@ -176,8 +171,6 @@ // fullscreen or transitioning between fullscreen states. gfx::Rect GetRestoredBounds() const; - // Creates a ui::Compositor which becomes responsible for drawing the window. - void CreateLayer(ui::LayerType layer_type, bool translucent); // Updates |associated_views_| on NativeViewHost::Attach()/Detach(). void SetAssociationForView(const views::View* view, NSView* native_view); @@ -227,13 +220,24 @@ bool ShouldRunCustomAnimationFor( Widget::VisibilityTransition transition) const; - // ui::CATransactionCoordinator::PreCommitObserver implementation + // ui::CATransactionCoordinator::PreCommitObserver: bool ShouldWaitInPreCommit() override; base::TimeDelta PreCommitTimeout() override; - // Overridden from ui::internal::InputMethodDelegate: + // ui::internal::InputMethodDelegate: ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* key) override; + // views::BridgedNativeWidget: + // TODO(ccameron): Rename BridgedNativeWidget to BridgedNativeWidgetImpl, and + // make these methods be exposed via the BridgedNativeWidget interface. + // Initialize the view to display compositor output. This will send the + // current visibility and dimensions (and any future updates) to the + // BridgedNativeWidgetHost. + void InitCompositorView(); + + // Specify the content to draw in the NSView. + void SetCALayerParams(const gfx::CALayerParams& ca_layer_params); + private: friend class test::BridgedNativeWidgetTestApi; @@ -247,28 +251,17 @@ // coordinate transformations are required from AppKit coordinates. gfx::Size GetClientAreaSize() const; - // Creates an owned ui::Compositor. For consistency, these functions reflect - // those in aura::WindowTreeHost. - void CreateCompositor(); - void InitCompositor(); - void DestroyCompositor(); - // Installs the NSView for hosting the composited layer. void AddCompositorSuperview(); // Size the layer to match the client area bounds, taking into account display // scale factor. - void UpdateLayerProperties(); - - // Immediately return if there is a composited frame matching |size_in_dip|. - // Otherwise, asks ui::WindowResizeHelperMac to run tasks until a matching - // frame is ready, or a timeout occurs. - void MaybeWaitForFrame(const gfx::Size& size_in_dip); + void UpdateCompositorSizeAndScale(); // Show the window using -[NSApp beginSheet:..], modal for the parent window. void ShowAsModalSheet(); - // Overridden from CocoaMouseCaptureDelegate: + // CocoaMouseCaptureDelegate: void PostCapturedEvent(NSEvent* event) override; void OnMouseCaptureLost() override; NSWindow* GetWindow() const override; @@ -277,21 +270,13 @@ // Creates and attaches a new instance if not found. NSMutableDictionary* GetWindowProperties() const; - // Overridden from FocusChangeListener: + // FocusChangeListener: void OnWillChangeFocus(View* focused_before, View* focused_now) override; void OnDidChangeFocus(View* focused_before, View* focused_now) override; - // Overridden from ui::LayerDelegate: - void OnPaintLayer(const ui::PaintContext& context) override; - void OnDeviceScaleFactorChanged(float old_device_scale_factor, - float new_device_scale_factor) override; - - // Overridden from ui::AcceleratedWidgetMac: - void AcceleratedWidgetCALayerParamsUpdated() override; - - // Overridden from BridgedNativeWidgetOwner: + // BridgedNativeWidgetOwner: NSWindow* GetNSWindow() override; gfx::Vector2d GetChildWindowOffset() const override; bool IsVisibleParent() const override; @@ -303,9 +288,10 @@ // Set |layer()| to be visible or not visible based on |window_visible_|. If // the layer is not visible, then lock the compositor, so we don't draw any // new frames. - void UpdateLayerVisibility(); + void UpdateCompositorVisibility(); - views::NativeWidgetMac* native_widget_mac_; // Weak. Owns this. + BridgedNativeWidgetHost* const host_; // Weak. Owns this. + NativeWidgetMac* const native_widget_mac_; // Weak. Owns |host_|. base::scoped_nsobject<NSWindow> window_; base::scoped_nsobject<ViewsNSWindowDelegate> window_delegate_; base::scoped_nsobject<BridgedContentView> bridged_view_; @@ -317,13 +303,16 @@ std::unique_ptr<DragDropClientMac> drag_drop_client_; FocusManager* focus_manager_; // Weak. Owned by our Widget. Widget::InitParams::Type widget_type_; + bool is_translucent_window_ = false; BridgedNativeWidgetOwner* parent_; // Weak. If non-null, owns this. std::vector<BridgedNativeWidget*> child_windows_; + // The size of the most recently received compositor frame. Note that this + // may lag behind GetClientAreaSize. + gfx::Size compositor_frame_dip_size_; base::scoped_nsobject<NSView> compositor_superview_; std::unique_ptr<ui::DisplayCALayerTree> display_ca_layer_tree_; - std::unique_ptr<ui::RecyclableCompositorMac> compositor_; // Tracks the bounds when the window last started entering fullscreen. Used to // provide an answer for GetRestoredBounds(), but not ever sent to Cocoa (it
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm index 98fd9ba0..fcda74e 100644 --- a/ui/views/cocoa/bridged_native_widget.mm +++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -23,12 +23,12 @@ #include "ui/base/ime/input_method_factory.h" #include "ui/base/layout.h" #include "ui/base/ui_base_switches.h" -#include "ui/compositor/recyclable_compositor_mac.h" #include "ui/gfx/geometry/dip_util.h" #import "ui/gfx/mac/coordinate_conversion.h" #import "ui/gfx/mac/nswindow_frame_controls.h" #import "ui/native_theme/native_theme_mac.h" #import "ui/views/cocoa/bridged_content_view.h" +#import "ui/views/cocoa/bridged_native_widget_host.h" #import "ui/views/cocoa/cocoa_mouse_capture.h" #import "ui/views/cocoa/cocoa_window_move_loop.h" #import "ui/views/cocoa/drag_drop_client_mac.h" @@ -36,7 +36,6 @@ #import "ui/views/cocoa/views_nswindow_delegate.h" #import "ui/views/cocoa/widget_owner_nswindow_adapter.h" #include "ui/views/view.h" -#include "ui/views/views_delegate.h" #include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_aura_utils.h" @@ -222,8 +221,10 @@ return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect)); } -BridgedNativeWidget::BridgedNativeWidget(NativeWidgetMac* parent) - : native_widget_mac_(parent), +BridgedNativeWidget::BridgedNativeWidget(BridgedNativeWidgetHost* host, + NativeWidgetMac* parent) + : host_(host), + native_widget_mac_(parent), focus_manager_(nullptr), widget_type_(Widget::InitParams::TYPE_WINDOW), // Updated in Init(). parent_(nullptr), @@ -248,12 +249,13 @@ DCHECK(child_windows_.empty()); SetFocusManager(nullptr); SetRootView(nullptr); - DestroyCompositor(); } void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, const Widget::InitParams& params) { widget_type_ = params.type; + is_translucent_window_ = + params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW; DCHECK(!window_); window_.swap(window); @@ -432,7 +434,7 @@ // If this is ever false, the compositor will need to be properly torn down // and replaced, pointing at the new view. - DCHECK(!view || !compositor_); + DCHECK(!view || !compositor_superview_); drag_drop_client_.reset(); [bridged_view_ clearView]; @@ -744,11 +746,7 @@ // purposes of detecting a window move. gfx::Size new_size = GetClientAreaSize(); native_widget_mac_->GetWidget()->OnNativeWidgetSizeChanged(new_size); - if (layer()) { - UpdateLayerProperties(); - if ([window_ inLiveResize]) - MaybeWaitForFrame(new_size); - } + UpdateCompositorSizeAndScale(); } void BridgedNativeWidget::OnPositionChanged() { @@ -790,24 +788,11 @@ [parent_->GetNSWindow() removeChildWindow:window_]; } - // TODO(tapted): Investigate whether we want this for Mac. This is what Aura - // does, and it is what tests expect. However, because layer drawing is - // asynchronous (and things like deminiaturize in AppKit are not), it can - // result in the compositor producing a blank frame during the time that the - // layer is not visible. Avoid this by locking the compositor (preventing any - // new frames) in UpdateLayerVisibility whenever the layer is hidden. - if (layer()) { - UpdateLayerVisibility(); - layer()->SchedulePaint(gfx::Rect(GetClientAreaSize())); - - // For translucent windows which are made visible, recalculate shadow when - // the frame from the compositor arrives. - if (![window_ isOpaque]) - invalidate_shadow_on_frame_swap_ = window_visible_; - } - + // Inform the compositor of the view's size before making it visible. + if (window_visible_) + UpdateCompositorSizeAndScale(); + UpdateCompositorVisibility(); NotifyVisibilityChangeDown(); - native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged( window_visible_); @@ -823,8 +808,7 @@ } void BridgedNativeWidget::OnBackingPropertiesChanged() { - if (layer()) - UpdateLayerProperties(); + UpdateCompositorSizeAndScale(); } void BridgedNativeWidget::OnWindowKeyStatusChangedTo(bool is_key) { @@ -889,34 +873,16 @@ return gfx::ScreenRectFromNSRect([window_ frame]); } -void BridgedNativeWidget::CreateLayer(ui::LayerType layer_type, - bool translucent) { - DCHECK(bridged_view_); - DCHECK(!layer()); +void BridgedNativeWidget::InitCompositorView() { + AddCompositorSuperview(); - CreateCompositor(); - DCHECK(compositor_); - - SetLayer(std::make_unique<ui::Layer>(layer_type)); - // Note, except for controls, this will set the layer to be hidden, since it - // is only called during Init(). - UpdateLayerVisibility(); - layer()->set_delegate(this); - - InitCompositor(); - - // Transparent window support. - layer()->GetCompositor()->SetBackgroundColor(translucent ? SK_ColorTRANSPARENT - : SK_ColorWHITE); - layer()->SetFillsBoundsOpaquely(!translucent); - - // Use the regular window background for window modal sheets. The layer() will + // Use the regular window background for window modal sheets. The layer will // still paint over most of it, but the native -[NSApp beginSheet:] animation // blocks the UI thread, so there's no way to invalidate the shadow to match // the composited layer. This assumes the native window shape is a good match // for the composited NonClientFrameView, which should be the case since the // native shape is what's most appropriate for displaying sheets on Mac. - if (translucent && !native_widget_mac_->IsWindowModalSheet()) { + if (is_translucent_window_ && !native_widget_mac_->IsWindowModalSheet()) { [window_ setOpaque:NO]; [window_ setBackgroundColor:[NSColor clearColor]]; @@ -930,7 +896,10 @@ DCHECK(!ca_transaction_sync_suppressed_); } - UpdateLayerProperties(); + UpdateCompositorSizeAndScale(); + // Note, except for controls, this will set the layer to be hidden, since it + // is only called during initialization. + UpdateCompositorVisibility(); } void BridgedNativeWidget::SetAssociationForView(const views::View* view, @@ -1032,9 +1001,9 @@ return false; if (ca_transaction_sync_suppressed_) return false; - if (!compositor_) + if (!compositor_superview_) return false; - return !compositor_->widget()->HasFrameOfSize(GetClientAreaSize()); + return GetClientAreaSize() != compositor_frame_dip_size_; } base::TimeDelta BridgedNativeWidget::PreCommitTimeout() { @@ -1090,34 +1059,22 @@ } //////////////////////////////////////////////////////////////////////////////// -// BridgedNativeWidget, LayerDelegate: +// TODO(ccameron): Update class names to: +// BridgedNativeWidgetImpl, BridgedNativeWidget: -void BridgedNativeWidget::OnPaintLayer(const ui::PaintContext& context) { - native_widget_mac_->GetWidget()->OnNativeWidgetPaint(context); -} - -void BridgedNativeWidget::OnDeviceScaleFactorChanged( - float old_device_scale_factor, - float new_device_scale_factor) { - native_widget_mac_->GetWidget()->DeviceScaleFactorChanged( - old_device_scale_factor, new_device_scale_factor); -} - -//////////////////////////////////////////////////////////////////////////////// -// BridgedNativeWidget, AcceleratedWidgetMac: - -void BridgedNativeWidget::AcceleratedWidgetCALayerParamsUpdated() { +void BridgedNativeWidget::SetCALayerParams( + const gfx::CALayerParams& ca_layer_params) { // Ignore frames arriving "late" for an old size. A frame at the new size // should arrive soon. - if (!compositor_->widget()->HasFrameOfSize(GetClientAreaSize())) + gfx::Size frame_dip_size = gfx::ConvertSizeToDIP(ca_layer_params.scale_factor, + ca_layer_params.pixel_size); + if (GetClientAreaSize() != frame_dip_size) return; + compositor_frame_dip_size_ = frame_dip_size; // Update the DisplayCALayerTree with the most recent CALayerParams, to make // the content display on-screen. - const gfx::CALayerParams* ca_layer_params = - compositor_->widget()->GetCALayerParams(); - if (ca_layer_params) - display_ca_layer_tree_->UpdateCALayerTree(*ca_layer_params); + display_ca_layer_tree_->UpdateCALayerTree(ca_layer_params); if (ca_transaction_sync_suppressed_) ca_transaction_sync_suppressed_ = false; @@ -1237,54 +1194,6 @@ return gfx::Size(NSWidth(content_rect), NSHeight(content_rect)); } -void BridgedNativeWidget::CreateCompositor() { - DCHECK(!compositor_); - DCHECK(ViewsDelegate::GetInstance()); - - ui::ContextFactory* context_factory = - ViewsDelegate::GetInstance()->GetContextFactory(); - DCHECK(context_factory); - ui::ContextFactoryPrivate* context_factory_private = - ViewsDelegate::GetInstance()->GetContextFactoryPrivate(); - - AddCompositorSuperview(); - - compositor_ = ui::RecyclableCompositorMacFactory::Get()->CreateCompositor( - context_factory, context_factory_private); - compositor_->widget()->SetNSView(this); -} - -void BridgedNativeWidget::InitCompositor() { - TRACE_EVENT0("ui", "BridgedNativeWidget::InitCompositor"); - DCHECK(layer()); - float scale_factor = GetDeviceScaleFactorFromView(compositor_superview_); - gfx::Size size_in_dip = GetClientAreaSize(); - compositor_->UpdateSurface(ConvertSizeToPixel(scale_factor, size_in_dip), - scale_factor); - compositor_->compositor()->SetRootLayer(layer()); - compositor_->Unsuspend(); -} - -void BridgedNativeWidget::DestroyCompositor() { - if (layer()) { - // LayerOwner supports a change in ownership, e.g., to animate a closing - // window, but that won't work as expected for the root layer in - // BridgedNativeWidget. - DCHECK_EQ(this, layer()->owner()); - layer()->CompleteAllAnimations(); - layer()->SuppressPaint(); - layer()->set_delegate(nullptr); - } - DestroyLayer(); - - if (!compositor_) - return; - compositor_->widget()->ResetNSView(); - compositor_->compositor()->SetRootLayer(nullptr); - ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor( - std::move(compositor_)); -} - void BridgedNativeWidget::AddCompositorSuperview() { DCHECK(!compositor_superview_); compositor_superview_.reset( @@ -1314,18 +1223,18 @@ [bridged_view_ addSubview:compositor_superview_]; } -void BridgedNativeWidget::UpdateLayerProperties() { - DCHECK(layer()); - DCHECK(compositor_superview_); +void BridgedNativeWidget::UpdateCompositorSizeAndScale() { + // Avoid transient updates during initialization by waiting until after + // |compositor_superview_| is created. + if (!compositor_superview_) + return; float scale_factor = GetDeviceScaleFactorFromView(compositor_superview_); gfx::Size size_in_dip = GetClientAreaSize(); - gfx::Size size_in_pixel = ConvertSizeToPixel(scale_factor, size_in_dip); if (!ca_transaction_sync_suppressed_) ui::CATransactionCoordinator::Get().Synchronize(); - layer()->SetBounds(gfx::Rect(size_in_dip)); - compositor_->UpdateSurface(size_in_pixel, scale_factor); + host_->SetCompositorSize(size_in_dip, scale_factor); // For a translucent window, the shadow calculation needs to be carried out // after the frame from the compositor arrives. @@ -1333,37 +1242,13 @@ invalidate_shadow_on_frame_swap_ = true; } -void BridgedNativeWidget::MaybeWaitForFrame(const gfx::Size& size_in_dip) { - return; // TODO(https://crbug.com/682825): Delete this during cleanup. - if (!layer()->IsDrawn() || compositor_->widget()->HasFrameOfSize(size_in_dip)) - return; - - const int kPaintMsgTimeoutMS = 50; - const base::TimeTicks start_time = base::TimeTicks::Now(); - const base::TimeTicks timeout_time = - start_time + base::TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS); - - ui::WindowResizeHelperMac* resize_helper = ui::WindowResizeHelperMac::Get(); - for (base::TimeTicks now = start_time; now < timeout_time; - now = base::TimeTicks::Now()) { - if (!resize_helper->WaitForSingleTaskToRun(timeout_time - now)) - return; // Timeout. - - // Since the UI thread is blocked, the size shouldn't change. - DCHECK(size_in_dip == GetClientAreaSize()); - if (compositor_->widget()->HasFrameOfSize(size_in_dip)) - return; // Frame arrived. - } -} - void BridgedNativeWidget::ShowAsModalSheet() { // -[NSApp beginSheet:] will block the UI thread while the animation runs. // So that it doesn't animate a fully transparent window, first wait for a // frame. The first step is to pretend that the window is already visible. window_visible_ = true; - UpdateLayerVisibility(); + UpdateCompositorVisibility(); native_widget_mac_->GetWidget()->OnNativeWidgetVisibilityChanged(true); - MaybeWaitForFrame(GetClientAreaSize()); NSWindow* parent_window = parent_->GetNSWindow(); DCHECK(parent_window); @@ -1390,12 +1275,12 @@ return properties; } -void BridgedNativeWidget::UpdateLayerVisibility() { - layer()->SetVisible(window_visible_); - if (window_visible_) - compositor_->Unsuspend(); - else - compositor_->Suspend(); +void BridgedNativeWidget::UpdateCompositorVisibility() { + // Avoid transient updates during initialization by waiting until after + // |compositor_superview_| is created. + if (!compositor_superview_) + return; + host_->SetCompositorVisibility(window_visible_); } } // namespace views
diff --git a/ui/views/cocoa/bridged_native_widget_host.h b/ui/views/cocoa/bridged_native_widget_host.h index 084d58c..a489871b 100644 --- a/ui/views/cocoa/bridged_native_widget_host.h +++ b/ui/views/cocoa/bridged_native_widget_host.h
@@ -14,6 +14,13 @@ class VIEWS_EXPORT BridgedNativeWidgetHost { public: virtual ~BridgedNativeWidgetHost() = default; + + // Update the ui::Compositor and ui::Layer's size. + virtual void SetCompositorSize(const gfx::Size& size_in_dip, + float scale_factor) = 0; + + // Update the ui::Compositor and ui::Layer's visibility. + virtual void SetCompositorVisibility(bool visible) = 0; }; } // namespace views
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.h b/ui/views/cocoa/bridged_native_widget_host_impl.h index 85777048..72c1176 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.h +++ b/ui/views/cocoa/bridged_native_widget_host_impl.h
@@ -8,8 +8,15 @@ #include <memory> #include "base/macros.h" +#include "ui/accelerated_widget_mac/accelerated_widget_mac.h" +#include "ui/compositor/layer_owner.h" #include "ui/views/cocoa/bridged_native_widget_host.h" #include "ui/views/views_export.h" +#include "ui/views/widget/widget.h" + +namespace ui { +class RecyclableCompositorMac; +} namespace views { @@ -20,7 +27,10 @@ // communicates to the BridgedNativeWidget, which interacts with the Cocoa // APIs, and which may live in an app shim process. class VIEWS_EXPORT BridgedNativeWidgetHostImpl - : public BridgedNativeWidgetHost { + : public BridgedNativeWidgetHost, + public ui::LayerDelegate, + public ui::LayerOwner, + public ui::AcceleratedWidgetMacNSView { public: // Creates one side of the bridge. |parent| must not be NULL. explicit BridgedNativeWidgetHostImpl(NativeWidgetMac* parent); @@ -31,12 +41,34 @@ // with methods that may be sent across processes. BridgedNativeWidget* bridge() const { return bridge_.get(); } + // Initialize the ui::Compositor and ui::Layer. + void CreateCompositor(const Widget::InitParams& params); + private: + void DestroyCompositor(); + + // Overridden from views::BridgedNativeWidgetHost: + void SetCompositorSize(const gfx::Size& size_in_dip, + float scale_factor) override; + void SetCompositorVisibility(bool visible) override; + + // Overridden from ui::LayerDelegate: + void OnPaintLayer(const ui::PaintContext& context) override; + void OnDeviceScaleFactorChanged(float old_device_scale_factor, + float new_device_scale_factor) override; + + // Overridden from ui::AcceleratedWidgetMacNSView: + void AcceleratedWidgetCALayerParamsUpdated() override; + + views::NativeWidgetMac* const native_widget_mac_; // Weak. Owns |this_|. + // TODO(ccameron): Rather than instantiate a BridgedNativeWidget here, // we will instantiate a mojo BridgedNativeWidget interface to a Cocoa // instance that may be in another process. std::unique_ptr<BridgedNativeWidget> bridge_; + std::unique_ptr<ui::RecyclableCompositorMac> compositor_; + DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetHostImpl); };
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm index 46841d8..ba1677d 100644 --- a/ui/views/cocoa/bridged_native_widget_host_impl.mm +++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -4,14 +4,125 @@ #include "ui/views/cocoa/bridged_native_widget_host_impl.h" +#include "ui/compositor/recyclable_compositor_mac.h" +#include "ui/gfx/geometry/dip_util.h" #include "ui/views/cocoa/bridged_native_widget.h" +#include "ui/views/views_delegate.h" +#include "ui/views/widget/native_widget_mac.h" namespace views { BridgedNativeWidgetHostImpl::BridgedNativeWidgetHostImpl( NativeWidgetMac* parent) - : bridge_(new BridgedNativeWidget(parent)) {} + : native_widget_mac_(parent), + bridge_(new BridgedNativeWidget(this, parent)) {} -BridgedNativeWidgetHostImpl::~BridgedNativeWidgetHostImpl() {} +BridgedNativeWidgetHostImpl::~BridgedNativeWidgetHostImpl() { + // Destroy the bridge first to prevent any calls back into this during + // destruction. + // TODO(ccameron): When all communication from |bridge_| to this goes through + // the BridgedNativeWidgetHost, this can be replaced with closing that pipe. + bridge_.reset(); + DestroyCompositor(); +} + +void BridgedNativeWidgetHostImpl::CreateCompositor( + const Widget::InitParams& params) { + DCHECK(!compositor_); + DCHECK(!layer()); + DCHECK(ViewsDelegate::GetInstance()); + + // "Infer" must be handled by ViewsDelegate::OnBeforeWidgetInit(). + DCHECK_NE(Widget::InitParams::INFER_OPACITY, params.opacity); + bool translucent = params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW; + + // Create the layer. + SetLayer(std::make_unique<ui::Layer>(params.layer_type)); + layer()->set_delegate(this); + layer()->SetFillsBoundsOpaquely(!translucent); + + // Create the compositor and attach the layer to it. + ui::ContextFactory* context_factory = + ViewsDelegate::GetInstance()->GetContextFactory(); + DCHECK(context_factory); + ui::ContextFactoryPrivate* context_factory_private = + ViewsDelegate::GetInstance()->GetContextFactoryPrivate(); + compositor_ = ui::RecyclableCompositorMacFactory::Get()->CreateCompositor( + context_factory, context_factory_private); + compositor_->widget()->SetNSView(this); + compositor_->compositor()->SetBackgroundColor( + translucent ? SK_ColorTRANSPARENT : SK_ColorWHITE); + compositor_->compositor()->SetRootLayer(layer()); + + // The compositor is initially locked (prevented from producing frames), and + // is only unlocked when the BridgedNativeWidget calls back via + // SetCompositorVisibility. + bridge_->InitCompositorView(); +} + +void BridgedNativeWidgetHostImpl::DestroyCompositor() { + if (layer()) { + // LayerOwner supports a change in ownership, e.g., to animate a closing + // window, but that won't work as expected for the root layer in + // BridgedNativeWidget. + DCHECK_EQ(this, layer()->owner()); + layer()->CompleteAllAnimations(); + layer()->SuppressPaint(); + layer()->set_delegate(nullptr); + } + DestroyLayer(); + if (!compositor_) + return; + compositor_->widget()->ResetNSView(); + compositor_->compositor()->SetRootLayer(nullptr); + ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor( + std::move(compositor_)); +} + +//////////////////////////////////////////////////////////////////////////////// +// BridgedNativeWidgetHostImpl, views::BridgedNativeWidgetHost: + +void BridgedNativeWidgetHostImpl::SetCompositorSize( + const gfx::Size& size_in_dip, + float scale_factor) { + layer()->SetBounds(gfx::Rect(size_in_dip)); + compositor_->UpdateSurface(ConvertSizeToPixel(scale_factor, size_in_dip), + scale_factor); +} + +void BridgedNativeWidgetHostImpl::SetCompositorVisibility(bool window_visible) { + layer()->SetVisible(window_visible); + if (window_visible) { + compositor_->Unsuspend(); + layer()->SchedulePaint(layer()->bounds()); + } else { + compositor_->Suspend(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// BridgedNativeWidgetHostImpl, LayerDelegate: + +void BridgedNativeWidgetHostImpl::OnPaintLayer( + const ui::PaintContext& context) { + native_widget_mac_->GetWidget()->OnNativeWidgetPaint(context); +} + +void BridgedNativeWidgetHostImpl::OnDeviceScaleFactorChanged( + float old_device_scale_factor, + float new_device_scale_factor) { + native_widget_mac_->GetWidget()->DeviceScaleFactorChanged( + old_device_scale_factor, new_device_scale_factor); +} + +//////////////////////////////////////////////////////////////////////////////// +// BridgedNativeWidgetHostImpl, AcceleratedWidgetMac: + +void BridgedNativeWidgetHostImpl::AcceleratedWidgetCALayerParamsUpdated() { + const gfx::CALayerParams* ca_layer_params = + compositor_->widget()->GetCALayerParams(); + if (ca_layer_params) + bridge_->SetCALayerParams(*ca_layer_params); +} } // namespace views
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc index 76ad9a512..0f37029 100644 --- a/ui/views/mus/desktop_window_tree_host_mus.cc +++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -539,7 +539,7 @@ } void DesktopWindowTreeHostMus::SetSize(const gfx::Size& size) { - // Use GetBounds() as the origin of window() is always at 0, 0. + // Use GetBoundsInPixels(), as the origin of window() is always at (0, 0). gfx::Rect screen_bounds = gfx::ConvertRectToDIP(GetScaleFactor(), GetBoundsInPixels()); screen_bounds.set_size(size); @@ -588,11 +588,7 @@ } gfx::Rect DesktopWindowTreeHostMus::GetWindowBoundsInScreen() const { - gfx::Point display_origin = GetDisplay().bounds().origin(); - gfx::Rect bounds_in_dip = - gfx::ConvertRectToDIP(GetScaleFactor(), GetBoundsInPixels()); - bounds_in_dip.Offset(display_origin.x(), display_origin.y()); - return bounds_in_dip; + return gfx::ConvertRectToDIP(GetScaleFactor(), GetBoundsInPixels()); } gfx::Rect DesktopWindowTreeHostMus::GetClientAreaBoundsInScreen() const { @@ -622,10 +618,7 @@ } gfx::Rect DesktopWindowTreeHostMus::GetWorkAreaBoundsInScreen() const { - // TODO(sky): GetDisplayNearestWindow() should take a const aura::Window*. - return display::Screen::GetScreen() - ->GetDisplayNearestWindow(const_cast<aura::Window*>(window())) - .work_area(); + return GetDisplay().work_area(); } void DesktopWindowTreeHostMus::SetShape(
diff --git a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc index d077d45..85bfbad 100644 --- a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc +++ b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
@@ -423,11 +423,12 @@ Widget widget2; Widget::InitParams params2(Widget::InitParams::TYPE_WINDOW); params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params2.bounds = gfx::Rect(0, 0, 100, 100); + params2.bounds = gfx::Rect(800, 0, 100, 100); widget2.Init(params2); - aura::WindowTreeHostMus::ForWindow(widget2.GetNativeWindow()) - ->set_display_id(kSecondDisplayId); EXPECT_EQ(gfx::Rect(800, 0, 100, 100), widget2.GetWindowBoundsInScreen()); + EXPECT_EQ(kSecondDisplayId, + aura::WindowTreeHostMus::ForWindow(widget2.GetNativeWindow()) + ->display_id()); } // WidgetDelegate implementation that allows setting window-title and whether
diff --git a/ui/views/mus/remote_view/remote_view_provider_unittest.cc b/ui/views/mus/remote_view/remote_view_provider_unittest.cc index f87a320..bf3a202d 100644 --- a/ui/views/mus/remote_view/remote_view_provider_unittest.cc +++ b/ui/views/mus/remote_view/remote_view_provider_unittest.cc
@@ -14,6 +14,7 @@ #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/mus/test_window_tree.h" #include "ui/aura/window.h" +#include "ui/aura/window_tracker.h" #include "ui/gfx/geometry/rect.h" #include "ui/views/mus/remote_view/remote_view_provider_test_api.h" @@ -159,11 +160,15 @@ aura::Window* embedder = SimulateEmbed(); ASSERT_TRUE(embedder); + aura::WindowTracker window_tracker; + window_tracker.Add(embedder); SimulateEmbedderClose(embedder); + // SimulateEmbedderClose() should delete |embedder|. + EXPECT_TRUE(window_tracker.windows().empty()); aura::Window* new_embedder = SimulateEmbed(); + // SimulateEmbed() should create a new window. ASSERT_TRUE(new_embedder); - EXPECT_NE(new_embedder, embedder); } } // namespace views
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index 3fe4565..a8bd55b 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -147,10 +147,7 @@ bridge()->SetFocusManager(focus_manager); } - // "Infer" must be handled by ViewsDelegate::OnBeforeWidgetInit(). - DCHECK_NE(Widget::InitParams::INFER_OPACITY, params.opacity); - bool translucent = params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW; - bridge()->CreateLayer(params.layer_type, translucent); + bridge_host_->CreateCompositor(params); } void NativeWidgetMac::OnWidgetInitDone() { @@ -202,12 +199,13 @@ } const ui::Compositor* NativeWidgetMac::GetCompositor() const { - return bridge() && bridge()->layer() ? bridge()->layer()->GetCompositor() - : nullptr; + return bridge_host_ && bridge_host_->layer() + ? bridge_host_->layer()->GetCompositor() + : nullptr; } const ui::Layer* NativeWidgetMac::GetLayer() const { - return bridge() ? bridge()->layer() : nullptr; + return bridge_host_ ? bridge_host_->layer() : nullptr; } void NativeWidgetMac::ReorderNativeViews() { @@ -583,8 +581,8 @@ target_rect.origin.y = NSHeight(client_rect) - target_rect.origin.y - NSHeight(target_rect); [GetNativeView() setNeedsDisplayInRect:target_rect]; - if (bridge() && bridge()->layer()) - bridge()->layer()->SchedulePaint(rect); + if (bridge_host_ && bridge_host_->layer()) + bridge_host_->layer()->SchedulePaint(rect); } void NativeWidgetMac::SetCursor(gfx::NativeCursor cursor) {
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm index b079f64..9ae776f 100644 --- a/ui/views/widget/native_widget_mac_unittest.mm +++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -103,15 +103,11 @@ // Simulate a frame swap from the compositor. void SimulateFrameSwap(const gfx::Size& size) { const float kScaleFactor = 1.0f; - ui::CALayerFrameSink* ca_layer_frame_sink = - ui::CALayerFrameSink::FromAcceleratedWidget( - bridge_->compositor_->widget()->accelerated_widget()); gfx::CALayerParams ca_layer_params; ca_layer_params.is_empty = false; ca_layer_params.pixel_size = size; ca_layer_params.scale_factor = kScaleFactor; - ca_layer_frame_sink->UpdateCALayerTree(ca_layer_params); - bridge_->AcceleratedWidgetCALayerParamsUpdated(); + bridge_->SetCALayerParams(ca_layer_params); } NSAnimation* show_animation() {